# PAXM: Provider-Neutral Memory for Codex, Claude Code and Other Coding Agents

> PAXM is a Go CLI and plugin set that stores decisions and conventions in SQLite or a remote provider and replays them into later coding-agent sessions. The cross-agent recall is the interesting part; the sandbox and hook-trust rules are where it gets fiddly.

**pax-beehive/paxm** — Persistent, provider-neutral memory for Codex, Claude Code, OpenCode, Pi, and MCP coding agents.

- Repository: https://github.com/pax-beehive/paxm
- Stars: 421 · Forks: 21
- Language: Go
- License: Apache-2.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/pax-beehive-paxm

## The problem PAXM targets: context that dies with the session

Every coding-agent session starts cold. The architecture decision you explained on Monday, the deployment rule that production only ships through GitHub Actions, the naming convention the team settled on: none of it survives into Tuesday's session, so you type it again. PAXM's README frames the product as a fix for exactly that, with the line "Stop re-explaining your project to every new coding-agent session."

The intended audience is narrow and specific. It is people who already use Codex, Claude Code, OpenCode, Pi, Cursor, TRAE, Kimi Code, ZCode, Kiro, Cline or a generic MCP client, and who switch between at least two of them on the same codebase. The README's second bullet is the one that matters: a decision captured from Codex can be recalled from Claude Code, OpenCode, Pi, or any MCP client. A single-agent user gets less out of this, because the agent's own session files already cover part of the ground.

The project is written in Go, licensed Apache-2.0, and the last push to the default branch was on 2026-08-28. The most recent release listed is v0.2.6 from 2026-07-26, so the version line is still in the 0.2 range.

## How the memory loop actually works

There are two paths into the store, and the README separates them clearly. The explicit path is the CLI: paxm remember writes a memory, paxm recall queries one back, paxm history lists what happened. The passive path is hook-driven. With passive integration enabled, the README states that paxm recalls relevant context before the agent responds and durably captures completed turns afterward, and that provider delays or failures do not block the coding session.

The Claude Code plugin registers five lifecycle hooks by name: SessionStart, UserPromptSubmit, PostToolUse, PostToolUseFailure, and Stop. That is the clearest view of the mechanism. Session start injects the configured user, agent, and session identity along with the current local time and time zone. UserPromptSubmit is where recall happens. The two PostToolUse hooks and Stop are where completed turns get written back. Codex, Claude Code, and Pi use their session-start events; OpenCode performs the same bootstrap before the first message in a session.

There is a small detail worth noticing: if a later user input arrives more than 12 hours after the preceding turn activity, paxm refreshes the local-time context before the agent handles that input. That is a deliberate choice to stop a stale timestamp from being treated as current, and it suggests the injected time is used for reasoning about relative dates.

Storage sits behind a provider abstraction. SQLite is the default and needs no account, API key, embeddings, or extra memory-layer model calls. Zep, Mem0, MemOS, and OpenViking are the named remote providers, and examples/jsonrpc-provider/ in the repository shows the JSON-RPC route for a private provider. The go.mod lists github.com/getzep/zep-go/v3 and modernc.org/sqlite, which matches the README's claim that the SQLite driver is pure Go rather than cgo.

## Installing PAXM and getting a first recall back

The shortest documented path is the Codex plugin, which the README calls the shortest path to a complete active-and-passive memory loop. It is three commands plus setup. The marketplace add pins a ref, and the installer pulls the latest published binary.

```bash
codex plugin marketplace add pax-beehive/paxm --ref paxm-memory-v0.1.4
codex plugin add paxm-memory@pax-agent-nexus
curl -fsSL https://github.com/pax-beehive/paxm/releases/latest/download/install.sh | bash
paxm setup --integration codex-plugin
```

After that you start a new Codex task and trust the Pax Agent neXus hooks when /hooks asks. The README is explicit about the division of labour: the plugin registers active-memory skills and owns the passive Codex hooks after setup, and it never installs a binary, writes credentials, or bypasses hook trust on its own. The installer is what puts the binary on disk.

Before you rely on passive memory, verify the loop end to end. Four commands, and the second and third are a matched pair: you write a sentinel string and then query for it.

```bash
paxm config doctor
paxm remember --profile stm --text "PAXM_FIRST_RECALL_OK"
paxm recall --query "PAXM_FIRST_RECALL_OK"
paxm history --days 1
```

If recall returns the sentinel, the store and the query path work. If it does not, the problem is in configuration or storage, not in the agent integration, which is a useful thing to know before you start debugging hooks.

For OpenCode, Pi, the CLI, or MCP, the path is shorter because there is no plugin. Install the release and run interactive setup:

```bash
curl -fsSL https://github.com/pax-beehive/paxm/releases/latest/download/install.sh | bash
paxm setup
paxm config doctor
```

paxm setup asks two questions: which providers to enable and which agents get passive memory. Agents found on the machine are pre-selected and marked (detected), and cloud provider API keys are masked as they are typed. Everything else uses defaults. Fine-tuning of paths, profiles, routing policy, and per-hook behaviour lives in the config file rather than the wizard, and docs/config.md is where the README points for that. Scripts can skip the prompts with repeatable flags:

```bash
paxm setup --provider sqlite --agent codex --agent claude
```

For non-interactive runs there are also --user-id and --team-id flags, and the README gives the example paxm setup --user-id todd --team-id pax-core, which creates durable write profiles such as team-pax-core. Set PAXM_VERSION before installation if you want a reproducible version or a rollback target.

## The SQLite sandbox trap and the duplicate-hook trap

Two failure modes are called out in the README, and both are the kind of thing that wastes an afternoon.

The first is SQLite health checks in a sandbox. SQLite health checks must be allowed to create WAL/SHM files beside the configured database. A sandbox that can read the database but cannot write its parent directory may report SQLite error 14. The README's guidance is to use an isolated writable SQLite path for sandboxed evaluations, and it notes that the same configuration may be healthy in the real agent process. That is a real constraint, not a bug: WAL mode needs write access to the directory, and a read-only mount will not provide it.

The second is hook duplication. When Codex is using the bundled paxm-memory plugin, the README says to let the plugin own Codex's hooks so paxm does not register a duplicate global hook. The README text on this point is a fragment rather than a full procedure, so if you have previously installed the global hook and then add the plugin, the exact cleanup is not spelled out. Check which side is registering hooks before you assume the passive path is broken.

There is a third boundary that is easy to miss. Active recall skills remain user-installed. The plugin gives you the passive loop; the active skills are a separate install step, and the README does not describe it beyond saying they remain user-installed. If you expected the plugin to bring both, you will find half the loop missing.

Finally, provider credentials remain user-managed, and the README states that paxm never writes the Team Memory secret to config.yaml. That is a sensible design, but it also means credential setup is your problem, not the tool's.

## Where PAXM is the wrong tool

PAXM is a local-first memory layer for a single developer or a small team working on the same repositories. It is not a knowledge base, and it is not a hosted service. The README describes the storage as user-owned, and the default SQLite provider is a file on your machine. If you need memory shared across a distributed team with per-user access control, the local default does not give you that, and the README does not describe an access-control model for the SQLite path.

It is also the wrong tool if you use exactly one agent and that agent already keeps durable project notes. The cross-agent recall is the differentiator; without a second agent in the picture, you are adding a hook layer and a provider abstraction to solve a problem your agent's own context mechanism may already handle.

And it is the wrong tool in a locked-down CI or container where the parent directory of the SQLite file is read-only. The README's own note about SQLite error 14 applies. You can point the database at a writable path, but if the environment forbids that entirely, the default provider will not work and you would need a remote provider instead.

Rollback is documented only as the PAXM_VERSION environment variable for pinning an install, and there is no documented data export path. If either matters to you, that is a gap to raise upstream rather than something to assume exists.

## How it differs from Zep and Mem0, which it also supports

The obvious comparison is with the remote memory providers PAXM itself integrates: Zep and Mem0. The difference is architectural, not feature-by-feature.

Zep and Mem0 are services. You send them content, they handle storage and retrieval, and the retrieval typically involves embeddings or a managed model in the loop. PAXM treats them as backends behind its provider interface. The README's promise is that you can change memory providers later without rewiring every agent, and that SQLite works without an API key while remote providers such as Zep, Mem0, MemOS, and OpenViking require connection details during setup.

That means the two are not really competitors at the layer that matters. If you want a managed memory service with its own retrieval quality work, you can use Zep or Mem0 directly and skip PAXM. What PAXM adds on top is the agent-side plumbing: the hooks, the session bootstrap, the identity injection, the cross-agent recall, and a provider switch that does not require touching every agent's configuration. The go.mod dependency on github.com/getzep/zep-go/v3 confirms the Zep integration is a first-class client rather than a wrapper around a generic HTTP call.

The trade-off is that you inherit PAXM's abstraction. When a provider gains a feature that does not fit the common interface, PAXM has to expose it, and the README does not describe how provider-specific capabilities are surfaced. For a local-first setup this rarely bites. For a team leaning on a remote provider's advanced retrieval, it might.

## Maintenance, licence and what the 0.2 line implies

The project is at v0.2.6, released on 2026-07-26, with v0.2.5 and v0.2.4 landing in the two days before that. The last push to main was on 2026-08-28, roughly three weeks after the most recent release listed. The repository is not archived. On the available evidence, the project is being worked on, but the 0.2 version number is the honest signal: interfaces and config keys can still move between releases, and the README's own emphasis on rollback via PAXM_VERSION suggests the authors expect people to pin.

The licence is Apache-2.0. That is a permissive licence with an explicit patent grant, and it does not impose copyleft obligations on code that merely calls the CLI or talks to the MCP server. It does require preserving notices and the licence text when you redistribute the software or a modified version. None of this is legal advice; if you are embedding PAXM in a product, have counsel read the LICENSE file rather than a summary.

Upgrade cost is concentrated in two places. First, the config file: fine-tuning of paths, profiles, routing policy, and per-hook behaviour lives there, and the README points to docs/config.md for the details, so a schema change lands on you. Second, the hook registration: the Claude Code plugin registers five named lifecycle hooks, and the Codex plugin owns Codex's hooks, so an upgrade that changes hook behaviour can alter what your agent does without any change on your side. Pinning with PAXM_VERSION and re-running paxm config doctor after each bump is the cheap insurance the README itself implies.

## Conclusion

Adopt PAXM if you run two or more of the supported agents on the same repositories and keep re-stating the same architectural decisions, and you are comfortable with the plugin owning your Codex hooks. Do not adopt it if you need a hosted, multi-user memory service with an access-control story, or if your agent runs in a sandbox that cannot write beside the SQLite file. Verify first with paxm config doctor and a remember/recall round trip, and confirm that only one of the plugin and the global hook installation is registering Codex hooks.

## FAQ

### Does PAXM need an API key or an account to start?

No. The default SQLite provider makes the adaptor usable without first creating an account or API key, and SQLite works without an API key. Remote providers such as Zep, Mem0, MemOS, and OpenViking require connection details during setup.

### Can a memory written from Codex be recalled from Claude Code?

Yes, that is the stated design goal. The README says a decision captured from Codex can be recalled from Claude Code, OpenCode, Pi, or any MCP client, because all of them read through the same provider.

### Why does paxm config doctor report SQLite error 14 in a sandbox?

SQLite health checks must be allowed to create WAL/SHM files beside the configured database. A sandbox that can read the database but cannot write its parent directory may report SQLite error 14, and the README suggests using an isolated writable SQLite path for sandboxed evaluations.

### Should the Codex plugin or the global hook install own Codex's hooks?

When Codex is using the bundled paxm-memory plugin, the README says to let the plugin own Codex's hooks so paxm does not register a duplicate global hook. The cleanup procedure is not described if both are already registered.

## Sources

- [Issues](https://github.com/pax-beehive/paxm/issues)
- [License: Apache-2.0](https://github.com/pax-beehive/paxm/blob/main/LICENSE)
- [pax-beehive/paxm on GitHub](https://github.com/pax-beehive/paxm)
- [README](https://github.com/pax-beehive/paxm/blob/main/README.md)
- [Releases](https://github.com/pax-beehive/paxm/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pax-beehive-paxm
