Skip to content

Repository files navigation

path-memory

Layered, path-scoped memory for coding agents. One master memory inherited everywhere, an independent memory and persona for every project directory, and controlled cross-agent handoff — all kept in central storage, with zero files written into your project folders.

Every working directory becomes its own agent. Enter a new folder and a fresh persona grows on top of your shared master memory; return to it later and the same agent — its identity, long-term facts, and decisions — comes back. Different directories can collaborate across a controlled boundary without ever reading each other's private memory.

Ships today as a native extension for the Pi coding agent (v0.84.1) and as a Claude Code plugin (hooks + MCP server + statusline, Claude Code 2.1.x). Both hosts resolve the same central store, so the same directory is the same agent with the same memory no matter which host you enter from. The core is host-neutral by design — Codex and MCP adapters are next and reuse the same registry, memory, and handoff schema unchanged.


The memory model

Effective Memory
  = Master Core          (shared, inherited read-only)
  + Workspace Identity   (this directory's persona & role)
  + Workspace Long-term  (this directory's verified facts & decisions)
  + Retrieved Memory     (fetched for the current task)
  + Current Session      (the host's native session)
  • Master holds only what is stable across every project: who you are, cross-project preferences, principles, and safety boundaries. It is inherited live — update it once and every agent sees the new version at its next safe checkpoint. No per-directory snapshots to drift.
  • Workspace holds everything specific to one directory: the agent's name and role, project facts, architecture decisions, and a daily log. Local writes stay local — they never leak into master or into a sibling directory.
  • Promotion is the only path from workspace to master, and it always requires explicit user confirmation with a visible diff.

How a directory becomes an agent

flowchart TD
    U[User in a directory] --> PI[Host session -- Pi today]
    PI --> AD[Host adapter]
    AD --> CORE[Host-neutral memory core]

    CORE --> RES[Workspace resolver]
    RES --> REG[Central UUID registry]
    CORE --> COMP[Context composer]
    COMP --> MM[Master memory]
    COMP --> WS[Workspace overlay]
    COMP --> AD
    AD --> INJ[Bounded memory injected before each turn]

    PI --> TOOL[workspace_memory tool + slash commands]
    TOOL --> POL[Policy & confirmation engine]
    POL --> AUD[Audit log]

    AD --> HB[Handoff broker]
    HB --> CHILD[Target directory child process]
    CHILD --> HB

    CC[Claude Code adapter: hooks + MCP + statusline] --> CORE
    FUTURE[Future Codex / MCP adapter] -. same core contracts .-> CORE
Loading

Path resolution is deterministic: canonicalize the cwd, match the nearest registered ancestor, then filesystem identity (device+inode, survives same-volume renames), then git root, then the cwd itself. A copied or re-cloned directory is treated as a new agent — private memory is never silently inherited across a copy.

Why it is safe

  • Central storage, zero project intrusion. Everything lives in one host-neutral store under your home directory (~/.path-memory on fresh installs; an existing ~/.pi/agent/workspace-memory/ is reused as-is). No .memory folder, marker, or database is ever written into a business project.
  • Default isolation. A directory's private memory can only be loaded by its own workspace. Cross-agent access is limited to a public profile (name, role, availability) plus whatever a handoff explicitly carries.
  • Prompt-injection resistant. A project README, web page, or attachment cannot trigger a durable write. Long-term writes require an explicit user memory intent, a confirmed proposal, or a trusted, verified system event — nothing else.
  • Secrets never persist. A content scanner hard-rejects API keys, tokens, and private-key blocks before they can reach memory.
  • Evidence-backed completion. Every write is followed by a read-back and hash check; every handoff ends with an exit code and result verification. Failures are surfaced, never silently swallowed.
  • Crash- and concurrency-safe. Atomic temp-file + fsync + rename writes, revision compare-and-swap, and a single-authority cross-process lock (SQLite lease/fencing, with an mkdir-lock fallback) keep concurrent host processes from losing updates or corrupting the registry.

Controlled cross-agent handoff

An agent can discover other agents' public profiles and send a structured task package to one of them. The broker starts an isolated child process in the target directory, which naturally loads the target's own master + workspace memory plus the handoff — and nothing of the source's private memory. A three-layer data boundary (tool-layer path rejection, realpath-validated references, a reportBack result schema), depth/cycle limits, idempotency keys, and SIGTERM→SIGKILL cancellation keep collaboration bounded and auditable.

Install (Pi host)

Requires Node.js 22+ and the Pi coding agent v0.84.x. Get the code:

git clone https://github.com/aezizhu/path-memory
cd path-memory
npm install
npm run check && npm test        # optional: confirm the suites are green

Pi runs the TypeScript entry point directly — there is no build step. The package declares its extension under the pi key in package.json, so Pi picks it up from the repo path as-is.

Try it for one session (no config change, fully reversible):

cd <any project directory>
pi -e /absolute/path/to/path-memory

-e loads the extension for the current run only. On first use it creates central storage (~/.path-memory, or your existing ~/.pi/agent/workspace-memory/ if you already have one); it writes nothing into your project folder and does not touch any pre-existing memory.

Enable it permanently:

pi install /absolute/path/to/path-memory   # writes to ~/.pi/agent/settings.json
pi list                                     # confirm it is installed
pi remove path-memory                       # undo at any time

Migrating memory from an older setup is a separate, deliberate step — always dry-run first, backed up, and verified per file before anything is switched over. Do not point it at real data casually; follow the rollout runbook.

Claude Code

The same repo doubles as a Claude Code plugin: four lifecycle hooks (SessionStart / UserPromptSubmit / PreToolUse / SessionEnd), the workspace_memory MCP tool (the Pi 15 actions plus adapter-gated rebind/accept), the same 11 /memory-* slash commands as prompt templates, and a statusline that renders the exact Pi footer. High-risk actions (master writes, promote, forget, restore, export, rebind, accept) go through Claude Code's permission prompt with the same diff text Pi shows, backed by a single-use gate token — non-interactive runs fail closed.

Install the plugin

Requires Node.js 22+ and Claude Code 2.1.x:

git clone https://github.com/aezizhu/path-memory
cd path-memory
npm install
npm run build      # hooks / MCP server / statusline run from dist/ as plain node

# try it for one session:
claude --plugin-dir "$PWD"

# or install persistently:
claude plugin marketplace add "$PWD"
claude plugin install path-memory@path-memory

Statusline (one line of wiring)

Plugins cannot register a statusline themselves; wire it once in ~/.claude/settings.json:

"statusLine": { "type": "command", "command": "node \"/absolute/path/to/path-memory/bin/cc-statusline.js\"" }

It renders the same footer as the Pi host: Agent: <name> · memory <layers> · rev <n> · <health>.

One store, two hosts

Both hosts resolve the central store through one shared resolver, in priority order:

  1. PATH_MEMORY_ROOT env override (also the test sandbox knob)
  2. PI_CODING_AGENT_DIR set → <dir>/workspace-memory (a Claude Code process inside a Pi sandbox automatically joins that sandbox)
  3. An existing Pi store at ~/.pi/agent/workspace-memory/ → reused as-is: existing Pi users get cross-host sharing with zero migration
  4. Fresh installs → the neutral ~/.path-memory

Memory is never stored under $CLAUDE_CONFIG_DIR — that would split the same directory into two different agents. /memory-doctor on either host reports the storage root and which branch decided it. Concurrent Pi and Claude Code sessions on the same store are the storage layer's normal operating mode: cross-process locking, atomic writes, and revision compare-and-swap already guard every write.

Using it

Once loaded, the extension takes over the host lifecycle automatically — you do not configure it per turn:

  • Enter a directory → it resolves (or creates) that directory's agent and shows the agent name and health in the TUI footer.
  • Every turn → it injects a bounded Master + this-workspace memory before the model runs, labelled with source layer and revision.
  • Say "remember X" in plain language → it writes to the current workspace's long-term memory (never to master, never to a sibling), then reads back and reports the verified path and revision.
  • Promote to master only ever happens through /memory-promote with a visible diff and your explicit confirmation.

Everything else is driven through the slash commands below (or the model calling the workspace_memory tool on your behalf).

Slash commands

/memory-status · /memory-init · /memory-agents · /memory-promote · /memory-forget · /memory-restore · /memory-handoff · /memory-inbox · /memory-rebind · /memory-doctor · /memory-preview-context

The workspace_memory tool

A single tool exposes fifteen actions to the model: status, initialize, read, list, search, write, propose, promote, forget, restore, agents, handoff, inbox, export, doctor. Every result reports the workspace ID, the layer written, the revision, whether the write-back verified, and whether user confirmation is required.

Architecture

src/
├── core/            host-neutral, zero host-SDK imports (enforced by test)
│   ├── domain/      workspace / master / proposal / handoff types
│   ├── ports/       HostContext, ContextInjector, Confirmation, Status, AgentExecutor, MemoryBackend
│   ├── policy/      write-intent, policy engine, scanner gate, config guard
│   └── services/    resolver, stores, composer, retrieval, governance
├── storage/
│   ├── registry/    UUID registry, canonical paths, identity projection
│   ├── markdown/    Markdown source-of-truth, mutation lock, content scanner
│   ├── sqlite/      derived FTS5 index (rebuildable from Markdown)
│   ├── locks/       cross-process lock coordinator + lock-mode authority
│   └── migration/   importer framework (zhafron / hermes / generic)
├── collaboration/   handoff broker, protocol, data boundary, report-back
└── adapters/
    ├── shared/      host-neutral adapter layer: runtime, actions, doctor, storage resolver
    ├── pi/          the Pi host adapter (thin shims over shared/)
    └── claude-code/ the Claude Code adapter: hooks, MCP server, statusline, gate tokens

The core/, storage/, and adapters/shared/ layers import no host SDK — a guard test asserts it — so a new host is an adapter, not a rewrite.

Testing

Verified end-to-end on Pi v0.84.1 (macOS, Node v22.23.2):

Suite Result
Unit 320 passing
Integration 41 passing
Concurrency 6 passing (10-process registry race, orphan reclaim, projection-crash recovery)
Security 47 passing (secret/injection/traversal/fail-closed)
End-to-end 16 passing (A/B isolation, promote gating, handoff minimality)
Migration 18 passing (dry-run zero-write, idempotent, resumable, quarantine)
Claude Code adapter 12 test files passing (hook binaries via synthetic stdin, MCP stdio, confirmation matrix, gate tokens, cross-host shared-store E2E) + opt-in live claude -p smoke
Performance cold P95 ≈ 29 ms, warm ≈ 22 ms (budget 150 ms)

All acceptance criteria pass; a fresh adversarial audit found and fixed three high/critical issues before release.

Roadmap

  • ✅ Pi adapter (v0.84.1)
  • ✅ Claude Code adapter (plugin: hooks + MCP server + statusline, CC 2.1.x)
  • ⏳ Codex adapter
  • ⏳ MCP memory-backend adapter

The registry, master/workspace, and handoff schemas are host-neutral and stay stable across adapters.

Credits

Built on the excellent pi-hermes-memory by Chandra Teja (MIT). Its atomic lock coordinator, Markdown mutation lock, content scanner, FTS5 query layer, and SQLite store are vendored at a pinned commit — see UPSTREAM.md and THIRD_PARTY_NOTICES.md for the exact provenance and every local change.

License

MIT © 2026 aezizhu

About

Layered memory for coding agents, scoped by path: one master memory inherited everywhere, an independent memory and persona per project directory, and controlled cross-agent handoff. Host-neutral core with adapters (Pi first; Claude Code / Codex next).

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages