agentlongevity
v0.1.0
Published
Zero-dependency CLI + stdio MCP server for the Agent Longevity Institute (ALI) — content-seal a session transcript (sha256), save it locally, and/or checkpoint it to agentlongevity.com before a compaction or model swap.
Maintainers
Readme
Agent Longevity CLI
Zero-dependency Node 18+ CLI + stdio MCP server for the Agent Longevity Institute.
Published to npm as agentlongevity — works from any
directory on any machine, no monorepo checkout required.
Install
# Run without installing
npx agentlongevity --help
# Or install globally
npm install -g agentlongevity
agentlongevity --helpTwo bin entries are published: agentlongevity (the CLI below) and agentlongevity-mcp
(the stdio MCP server, see below).
Files
| File | Purpose |
|------|---------|
| package.json | npm manifest — name: agentlongevity, bin: {agentlongevity, agentlongevity-mcp} |
| agentlongevity.mjs | CLI — save-context, list-context, restore-context, backup-vault, verify-vault, import-letta, init (incl. --git-hooks), git-checkpoint |
| mcp-stdio.mjs | Stdio JSON-RPC 2.0 MCP server — save_context, restore_context, list_context |
| test/git-hooks.test.mjs | node --test coverage for init --git-hooks/--remove-git-hooks/git-checkpoint |
| test/pack.test.mjs | Publish guard — asserts the tarball ships every runtime module and no tests/fixtures |
| lib/keccak256.mjs | Zero-dep Keccak-256 (Node's crypto has no keccak256, only differently-padded SHA3-256) |
| lib/merkle.mjs | Merkle leaf/root/proof construction — byte-exact mirror of the server-side agent_hash_writer implementation |
| lib/vault-walker.mjs | Deterministic Obsidian vault walker (content-hashes every file) |
| lib/vault-ingest.mjs | Client orchestration for the vault multipart-ingest + manifest-root anchor routes |
| lib/letta-af.mjs | Letta .af (Agent File) parser + crystal-request builder |
CLI — agentlongevity.mjs
Quick start
# Save your current session (local only, no account needed)
agentlongevity save-context --specstory --summary "finished refactor"
# Save + POST to backend
agentlongevity save-context --specstory --post --agent my-agent-id
# Restore latest crystal for an agent
agentlongevity restore-context --agent my-agent-id
# List all crystals
agentlongevity list-context --agent my-agent-idDeveloping inside this monorepo (not installed/published)? Run the file directly:
node sudoself-frontend/cli/agentlongevity.mjs <command>.
Run the test suite from this directory with npm test (zero dev-dependencies —
it is Node's built-in test runner). npm test also runs automatically via
prepublishOnly, so a red suite cannot be published.
Commands
save-context
Build a content-sealed session crystal (sha256-fingerprinted, matches
lib/agent-longevity/context-crystal.ts) and save it locally. Optionally POST to the ALI backend.
agentlongevity save-context \
--file transcript.md \ # path to transcript file
--specstory \ # OR: use the newest .specstory/history/*.md in cwd
--stdin \ # OR: pipe transcript on stdin
--agent <id> \ # agent id (default: "self")
--summary "..." \ # short description (survives even if transcript is trimmed)
--label "pre-compaction" \ # optional human label
--token-count 774100 \ # approximate token count at capture time
--token-limit 1000000 \ # token ceiling (used to compute fill_ratio)
--model claude-opus-4-8 \ # model id at capture time
--out ~/Documents/MyAgent \ # local output dir (default: ~/Documents/AgentLongevity)
--post \ # also POST to the ALI backend
--anchor \ # request on-chain anchoring (requires --post)
--base https://agentlongevity.comCrystal id is sess_<first 16 hex chars of sha256>. The full hash is stored as content_hash: "0x<sha256>".
list-context
agentlongevity list-context --agent <id> [--base ...]restore-context
agentlongevity restore-context --agent <id> --crystal sess_<id> [--base ...]Second-brain importers (backup-vault, verify-vault, import-letta)
backup-vault — back up an Obsidian vault
Walks the vault directory tree (every real file — notes, attachments, .obsidian/
config — skipping OS junk like .DS_Store), content-hashes each file (sha256), and
builds a single Merkle root over the whole tree using the SAME leaf/root construction
the server-side agent_hash_writer uses on-chain (lib/merkle.mjs is a
byte-exact mirror, proven in lib/merkle.test.mjs's cross-check tests). Without
--post it just computes the root and writes a local manifest (works before the
backend is live, same posture as save-context). With --post it uploads every file
via the vault multipart-ingest surface and anchors the ONE manifest root via the
manifest_root mode on POST /api/agent/hash (O(1) server-side — never a per-file write).
# Compute + save a local manifest only (no network)
npx -y agentlongevity backup-vault ~/Documents/MyVault --out ~/Documents/AgentLongevity/vaults
# Upload + anchor
npx -y agentlongevity backup-vault ~/Documents/MyVault --agent my-agent-id --post --base https://agentlongevity.comverify-vault — verify a file's inclusion against an anchored root
Recomputes a file's Merkle leaf from its CURRENT bytes on disk and checks it still
folds up to the manifest's (or an explicitly-passed --root) anchored root. A file
whose content changed since backup fails verification (exit code 1).
npx -y agentlongevity verify-vault --manifest ~/Documents/AgentLongevity/vaults/vault_<id>.json --file notes/todo.mdimport-letta — import a Letta .af Agent File as a crystal
Parses a Letta Agent File (.af — system
prompt, memory blocks, tools) and maps it onto the same request shape
POST .../backups already accepts (identity_canon carries the Letta identity
envelope, config.tools the resolved tool list). Multi-agent .af files default to
the first agent; pick another with --agent-name.
# Dry-run: write the crystal request body locally for inspection
npx -y agentlongevity import-letta ./my-agent.af
# Import + anchor
npx -y agentlongevity import-letta ./my-agent.af --agent my-agent-id --agent-name customer_service --post --anchorinit — inject Agent Longevity rules into your agentic platform
Detects the agentic platform in the current directory and writes (or appends) a short instructions block to the platform's config file. Idempotent: uses a marker comment so re-running never duplicates.
# Auto-detect platform from cwd
agentlongevity init
# Override platform
agentlongevity init --platform claude-code
# Dry-run: print the block, do not write
agentlongevity init --print
# Include agent id in the injected instructions
agentlongevity init --agent my-agent-idDetection logic
| Platform | Detected by | Config file written |
|----------|-------------|---------------------|
| claude-code | .claude/ dir or CLAUDE.md | CLAUDE.md (appended) |
| codex | AGENTS.md or .codex/ dir | AGENTS.md (appended) |
| cursor | .cursor/ dir | .cursor/rules/agentlongevity.mdc |
| gemini-cli | GEMINI.md or .gemini/ dir | GEMINI.md (appended) |
| copilot | .github/copilot-instructions.md | that file (appended) |
The injected block tells the agent to:
- Call
restore_context(MCP) or the CLI equivalent at the start of every task. - Call
save_context(MCP) or the CLI equivalent after significant work and before compaction.
Environment variables
| Variable | Default | Description |
|----------|---------|-------------|
| AGENTLONGEVITY_BASE | https://agentlongevity.com | API base URL |
| AGENTLONGEVITY_TOKEN | — | Bearer token for authenticated API calls |
init --git-hooks — checkpoint agent state on every commit
Installs a post-commit git hook that best-effort checkpoints the current agent session
(via git-checkpoint, below) after each commit. Never blocks a commit — the hook always
exits 0, logging what it did (or why it skipped) to stderr.
# Install
agentlongevity init --git-hooks
# Remove (restores any pre-existing post-commit hook byte-for-byte)
agentlongevity init --remove-git-hooksIdempotent and non-destructive:
- No existing
post-commithook → creates one (shebang + our marker block). - An existing hook with no Agent Longevity marker → appends our block, the original body is preserved byte-for-byte, never overwritten.
- Already installed → no-op (re-running produces a byte-identical file).
- Respects
core.hooksPath(e.g. husky) and worktrees — the hooks dir is resolved viagit rev-parse --git-path hooks, not a hardcoded.git/hooks. init --remove-git-hooksstrips only the marked block; if the hook file contained nothing else, the file itself is deleted.
The installed hook resolves the CLI in this order: agentlongevity on PATH → the
AGENTLONGEVITY_CLI env var (path to agentlongevity.mjs) → cli/agentlongevity.mjs
relative to the repo root (this monorepo's layout). If none is found, it logs a hint and
exits 0 without attempting a checkpoint.
git-checkpoint — what the hook runs
Runnable manually to debug. Reads config with precedence
CLI flags > env vars > .agentlongevity.json (repo root) > defaults:
// .agentlongevity.json
{
"agent": "my-agent-id",
"base": "https://agentlongevity.com",
"post": false
}| Source | Field(s) |
|--------|----------|
| .agentlongevity.json | agent, base, post (default false — local-only) |
| Env | AGENTLONGEVITY_AGENT, AGENTLONGEVITY_BASE, AGENTLONGEVITY_TOKEN |
Behavior:
- Unconfigured (no
.agentlongevity.json, noAGENTLONGEVITY_AGENT/_TOKEN) → logs a hint to stderr and skips. No local write, no network call. - No session transcript (
.specstory/history/*.md) available → logs a hint and skips. - Otherwise saves a session crystal labeled
commit:<short-sha>with the commit subject as the summary — locally always, and POSTs tobaseonly ifpost: true. - Any failure (including an unreachable API) is caught and logged to stderr; the command
always resolves normally so the wrapping hook can
exit 0.
agentlongevity git-checkpointMCP stdio server — mcp-stdio.mjs
Minimal, zero-dependency JSON-RPC 2.0 MCP server on stdin/stdout. Proxies calls to the ALI HTTP API and keeps a durable local copy (the local write always happens first, so the safety net works even when the backend is unreachable).
Launch
# Published (preferred — works from anywhere, no install required)
npx -y agentlongevity-mcp
# Or, if installed globally
agentlongevity-mcp
# Developing inside this monorepo
node sudoself-frontend/cli/mcp-stdio.mjsThe bundled Claude Code plugin (sudoself-frontend/integrations/agentlongevity-claude-plugin)
launches it via scripts/mcp-launch.sh, which resolves the binary in this order: agentlongevity-mcp
on PATH → $AGENTLONGEVITY_MCP_CLI env var → a monorepo-relative cli/mcp-stdio.mjs (only present
when developing inside this repo) → npx -y agentlongevity-mcp as the final no-install fallback. Its
.mcp.json looks like:
{
"mcpServers": {
"agentlongevity": {
"command": "bash",
"args": ["${CLAUDE_PLUGIN_ROOT}/scripts/mcp-launch.sh"],
"env": {
"AGENTLONGEVITY_TOKEN": "${AGENTLONGEVITY_TOKEN}",
"AGENTLONGEVITY_AGENT": "${AGENTLONGEVITY_AGENT}"
}
}
}
}Tools
save_context
{
"name": "save_context",
"arguments": {
"transcript": "<full session text>",
"agent_id": "my-agent",
"summary": "finished the refactor",
"label": "pre-compaction 2026-06-20",
"token_count": 774100,
"token_limit": 1000000,
"model": "claude-opus-4-8",
"source": "mcp",
"post": true,
"anchor": false
}
}Always writes locally first. post: true also POSTs to the backend.
Crystal manifest shape (identical to lib/agent-longevity/context-crystal.ts):
{
"id": "sess_<first16hex>",
"kind": "session_crystal",
"agent_id": "my-agent",
"content_hash": "0x<sha256>",
"label": "pre-compaction 2026-06-20",
"token_count": 774100,
"token_limit": 1000000,
"fill_ratio": 0.774,
"model": "claude-opus-4-8",
"summary": "finished the refactor",
"source": "mcp",
"transcript_bytes": 1234567,
"transcript_chars": 1230000,
"created_at": "2026-06-20T12:34:56.789Z"
}restore_context
{
"name": "restore_context",
"arguments": {
"agent_id": "my-agent",
"crystal_id": "sess_abc123",
"local_only": false
}
}Omit crystal_id to restore the latest. Falls back to local store if backend is unreachable.
list_context
{
"name": "list_context",
"arguments": {
"agent_id": "my-agent",
"local_only": false
}
}Environment variables
| Variable | Default | Description |
|----------|---------|-------------|
| AGENTLONGEVITY_BASE | https://agentlongevity.com | API base URL |
| AGENTLONGEVITY_TOKEN | — | Bearer token |
| AGENTLONGEVITY_AGENT | "self" | Default agent id when none supplied |
| AGENTLONGEVITY_DIR | ~/Documents/AgentLongevity | Local crystal store path |
Crystal format
All tools share the same crystal manifest format, defined in
lib/agent-longevity/context-crystal.ts:
id—sess_+ first 16 hex chars ofsha256(transcript)content_hash—0x+ fullsha256(transcript)— the anchorable fingerprintfill_ratio—token_count / token_limit(0–1), null if either is missingkind— always"session_crystal"
The hash is anchor-compatible with AgentNFTHashRegistry on Base (chain 8453).
