Persistent Honcho memory for OpenAI Codex sessions, wired through Codex lifecycle hooks. It captures your prompts and the assistant's responses into Honcho and injects relevant memory back at the start of a session — so context carries across sessions and projects.
This is the Codex counterpart to the Claude Code plugin (claude-honcho); both use the same Honcho memory model (one user peer, per-project sessions) so your identity and project context stay consistent across tools.
The plugin registers five Codex lifecycle hooks (hooks/hooks.json), each running scripts/honcho_codex_hook.py:
| Hook | What it does |
|---|---|
SessionStart |
Injects memory: the session summary (project-scoped) + your peer card (global identity). Flushes any queued writes. |
UserPromptSubmit |
Saves your prompt to Honcho. Optionally injects context (off by default). |
Stop |
Saves the assistant's final response for the turn. |
PreCompact |
Flushes the queued-writes buffer. |
PostCompact |
Flushes the queued-writes buffer after compaction completes, without re-injecting memory. |
Tool calls are intentionally not saved (MVP scope).
- In-process REST transport. Reads/writes go directly to the Honcho v3 REST API over the Python standard library (
urllib) from inside the hook process — seescripts/honcho_codex/rest.py(HonchoClient). There is no runtime dependency: the hook runs on the barepython3Codex invokes (no SDK, nouv, no virtualenv). ThehonchoCLI is not required at runtime — it is only used by the setup/status skill for diagnostics. - Ensure-cache.
workspace/peer/sessionare created lazily (get-or-create) and the result is cached on disk (~/.honcho/codex/ensured.json, 24h TTL) so they are not re-created on every event. This is the main latency win versus shelling out to the CLI per call. - Local write queue + dedup. Messages are queued locally (
~/.honcho/codex/queue.jsonl) and deduplicated by key (~/.honcho/codex/state.json) so a transient failure retries on the next event instead of losing or duplicating a write. - Self-healing writes. If a cached session was deleted server-side, a write returns 404; the client evicts the stale cache entry, recreates, and retries once.
| Concept | Value | Notes |
|---|---|---|
| Workspace | workspace config (default default) |
one workspace per person |
| User peer | userPeer config (default $USER) |
you — global identity across projects |
| Assistant peer | assistantPeer config (default codex) |
the assistant |
| Session | <userPeer>-<dir> (when sessionPeerPrefix=true) |
one session per project directory |
Session name formula: the current directory's base name is sanitized (lower-cased; any character outside a-z 0-9 _ - becomes -). With sessionPeerPrefix=true (default) it is prefixed with the user peer:
/home/me/repos/route-converter-se→me-route-converter-se- with
sessionPeerPrefix=false→route-converter-se
codex plugin marketplace add rafachavantes/honcho-codex
codex plugin add honcho-codex@honcho-codex
# restart CodexSet your API key (the plugin reads it from the environment or the config file):
export HONCHO_API_KEY=hcho_...Settings resolve in this order: environment variable > config file > default.
The config file is ~/.honcho/codex/config.json (camelCase keys).
| Config key | Environment variable | Default | What it does |
|---|---|---|---|
apiKey |
HONCHO_API_KEY |
— (required) | Your Honcho API key. Without it the hooks skip silently (no memory). |
baseUrl |
HONCHO_BASE_URL |
https://api.honcho.dev |
Honcho API base URL. Change only for self-hosted/staging. |
workspace |
HONCHO_WORKSPACE |
default |
The Honcho workspace — one per person; holds all your peers and sessions. |
userPeer |
HONCHO_USER_PEER |
$USER → else user |
Your identity (the "user" peer). Keep it stable so memory follows you across projects. |
assistantPeer |
HONCHO_ASSISTANT_PEER |
codex |
The assistant's peer id. |
sessionPeerPrefix |
HONCHO_SESSION_PEER_PREFIX |
true |
If true, session names are prefixed with the user peer (<userPeer>-<dir>); if false, just <dir>. |
sessionStrategy |
HONCHO_SESSION_STRATEGY |
per-directory |
How sessions are derived. Only per-directory (one session per project folder) is implemented. |
injectUserPromptContext |
HONCHO_INJECT_USER_PROMPT_CONTEXT |
false |
If true, injects memory on every prompt, not just at SessionStart. More context, more latency per turn. |
injectOnCompact |
HONCHO_INJECT_ON_COMPACT |
slim |
Injection after the CLI compacts context: slim injects a one-line pointer, off injects nothing, full re-injects the whole memory package (legacy behavior; can re-trigger compaction). |
saveUserMessages |
HONCHO_SAVE_USER_MESSAGES |
true |
Whether your prompts are saved to memory. |
saveAssistantMessages |
HONCHO_SAVE_ASSISTANT_MESSAGES |
true |
Whether the assistant's responses are saved to memory. |
saveToolCalls |
HONCHO_SAVE_TOOL_CALLS |
false |
Whether tool calls are saved (off in the MVP — kept for parity). |
maxMessageChars |
HONCHO_MAX_MESSAGE_CHARS |
12000 |
Messages longer than this are truncated before upload. |
contextTokens |
HONCHO_CONTEXT_TOKENS |
4000 |
Token budget for the memory/summary injected at session start. |
Example ~/.honcho/codex/config.json:
{
"workspace": "rafa",
"userPeer": "rafa",
"assistantPeer": "assistant",
"sessionPeerPrefix": true,
"injectUserPromptContext": false,
"injectOnCompact": "slim",
"contextTokens": 4000
}Note: the Codex plugin reads
HONCHO_USER_PEERfor the user peer — notHONCHO_PEER_NAME(which belongs to the Claude Code plugin). To make the user peer explicit and avoid depending on the$USERfallback, setuserPeerin the config file.
Important — API key in remote/non-interactive sessions: if you set
HONCHO_API_KEYonly as a shell environment variable, sessions that don't inherit your interactive shell environment (the mobile/remote app, cron, CI, a non-login shell) won't see it, and the hooks skip silently withmissing api_key(check~/.honcho/codex/logs.jsonl). To make memory work everywhere, put the key in the config file instead:{ "apiKey": "hcho_...", "workspace": "rafa", "userPeer": "rafa", "assistantPeer": "assistant" }The hooks read the config file on every event, so the next turn is captured without restarting the session. Keep the file private:
chmod 600 ~/.honcho/codex/config.json.
HONCHO_ENABLED=0 stops both the hooks and the MCP tools for a single invocation,
without touching any persisted setting:
HONCHO_ENABLED=0 codex exec "..." # this run only: hooks record nothing, tools refuse too
codex exec "..." # absent = enabled, the normal behaviorThe variable exists only in the process that sets it, so there is nothing to undo
afterwards. .mcp.json passes it through to the MCP server via env_vars, so both sides
see it. When it is off, the hooks return the host's expected empty-success response and
stop there: no config read, no API call, no state written. Every MCP tool call answers
{"ok": false, "error": "Honcho is disabled for this run (HONCHO_ENABLED=0)."} before
touching the network. One subtlety survives: a session started with the switch off
never gets a session-map entry (the hook that would write it never runs), so even after
the switch is back on, the tools in that session have nothing to scope themselves to and
refuse with "Could not determine the Honcho session" until a normal prompt is sent.
To see the resolved settings the plugin will actually use (config file + environment variables + defaults merged), run:
cd plugins/honcho-codex
HONCHO_API_KEY=$HONCHO_API_KEY PYTHONPATH=scripts python3 scripts/honcho_codex/config.pyIt prints the effective workspace, userPeer, assistantPeer, injectUserPromptContext, etc., plus an exampleSession showing the session name for the current directory — a quick way to confirm a change took effect before relying on it. A typical change-and-verify loop:
- Edit
~/.honcho/codex/config.json(or export aHONCHO_*variable). - Re-run the command above and check the value changed.
- Restart Codex so the hooks pick up the new config.
All under ~/.honcho/codex/:
config.json— settings (see above)queue.jsonl— pending writes (retried until delivered)state.json— dedup state (sent message keys)ensured.json— get-or-create cache (24h TTL)sessions.json— session id → session name map, written by the hooks and read by the MCP toolslogs.jsonl— error log for diagnostics
Besides injecting memory at session start, the plugin exposes six tools the model can call mid-conversation, all scoped to the current project's session:
| Tool | What it does |
|---|---|
search |
Semantic search over this project's stored messages. Returns the closest matches, which are not necessarily relevant. |
chat |
Asks Honcho about the user — preferences, habits, working style. |
get_briefing |
The session-start package on demand: session summary plus peer card. |
get_config |
Resolved settings, the session name in use, and whether an API key is configured. |
create_conclusion |
Stores one durable fact about the user or the project. |
set_config |
Writes one setting to ~/.honcho/codex/config.json. Fields that rename or repoint memory require confirm: true. |
The session is resolved from a map the hooks record (~/.honcho/codex/sessions.json).
In a brand-new session, send one prompt before the tools can tell which project they
are in — they refuse rather than guess.
The plugin code lives under plugins/honcho-codex/. Tests run with uv (no project virtualenv needed):
cd plugins/honcho-codex
PYTHONPATH=scripts uv run --with pytest python -m pytest tests/ -qExercise a hook directly with a simulated Codex event:
cd plugins/honcho-codex
echo '{"hook_event_name":"Stop","cwd":"/tmp/proj","last_assistant_message":"hello"}' \
| HONCHO_API_KEY=$HONCHO_API_KEY HONCHO_WORKSPACE=my-ws PYTHONPATH=scripts python3 scripts/honcho_codex_hook.pyDesign notes and the REST-transport implementation plan live under docs/superpowers/.
MIT