Skip to main content

Codex

View Changelog →

Persistent memory for Codex CLI using Hindsight. Three Python hook scripts automatically recall relevant context before each prompt and retain conversations after each turn — no changes to your Codex workflow required.

Quick Start

curl -fsSL https://hindsight.vectorize.io/get-codex | bash

The installer will guide you through choosing local or cloud mode and configuring your connection. Once installed, start a new Codex session — memory is live.

To uninstall:

curl -fsSL https://hindsight.vectorize.io/get-codex | bash -s -- --uninstall

Features

  • Auto-recall — on every user prompt, queries Hindsight for relevant memories and injects them as additionalContext (invisible to the transcript, visible to Codex)
  • Auto-retain — after each Codex response, stores the conversation transcript to Hindsight for future recall
  • Dynamic bank IDs — supports per-project memory isolation based on the working directory
  • Session-level upsert — uses the session ID as the document ID so re-running the same session updates rather than duplicates stored content
  • Zero dependencies — pure Python stdlib, no pip install required

Architecture

The plugin uses three Codex hook events:

HookEventPurpose
session_start.pySessionStartWarm up — verify Hindsight is reachable
recall.pyUserPromptSubmitAuto-recall — query memories, inject as additionalContext
retain.pyStopAuto-retain — extract transcript, POST to Hindsight (async)

On UserPromptSubmit, the hook reads the prompt, queries Hindsight for the most relevant memories, and outputs a hookSpecificOutput.additionalContext block. Codex prepends this to the conversation before sending it to the model:

<hindsight_memories>
Relevant memories from past conversations...
Current time - 2026-03-27 09:14

- Project uses FastAPI with asyncpg — not SQLAlchemy [world] (2026-03-26)
- Preferred testing framework: pytest with pytest-asyncio [experience] (2026-03-26)
</hindsight_memories>

On Stop, the hook reads the session transcript, strips previously injected memory tags (to prevent feedback loops), and POSTs the conversation to Hindsight asynchronously.

Connection Modes

Connect to a running Hindsight server (cloud or self-hosted):

{
"hindsightApiUrl": "https://api.hindsight.vectorize.io",
"hindsightApiToken": "hsk_your_token"
}

2. Local Daemon

Run hindsight-embed locally. The session_start.py hook will detect it on apiPort (default 9077). The daemon is not auto-started by the Codex plugin — start it separately:

uvx hindsight-embed

Then leave hindsightApiUrl empty in your config and the plugin will connect to http://localhost:9077.

Configuration

Settings are loaded from ~/.hindsight/codex.json. Every setting can also be overridden via environment variable.

Loading order (later entries win):

  1. Built-in defaults
  2. Plugin settings.json (at ~/.hindsight/codex/settings.json)
  3. User config (~/.hindsight/codex.json)
  4. Environment variables

Connection

SettingEnv VarDefaultDescription
hindsightApiUrlHINDSIGHT_API_URL""URL of the Hindsight API server. Required.
hindsightApiTokenHINDSIGHT_API_TOKENnullAPI token for authentication. Required for Hindsight Cloud.
apiPortHINDSIGHT_API_PORT9077Port for the local hindsight-embed daemon.

Memory Bank

SettingEnv VarDefaultDescription
bankIdHINDSIGHT_BANK_ID"codex"The bank to read from and write to. All sessions share this bank unless dynamicBankId is enabled.
bankMissionHINDSIGHT_BANK_MISSIONcoding assistant promptDescribes the agent's purpose. Sent when creating or updating the bank.
retainMissionextraction promptInstructions for Hindsight's fact extraction — what to extract from coding conversations.
dynamicBankIdHINDSIGHT_DYNAMIC_BANK_IDfalseWhen true, derives a unique bank ID from dynamicBankGranularity fields — useful for per-project isolation.
dynamicBankGranularity["agent", "project"]Which fields to combine for dynamic bank IDs. "project" = working directory, "agent" = agent name.
bankIdPrefix""Prefix prepended to all bank IDs.
agentNameHINDSIGHT_AGENT_NAME"codex"Agent name used in dynamic bank ID derivation.

Auto-Recall

SettingEnv VarDefaultDescription
autoRecallHINDSIGHT_AUTO_RECALLtrueMaster switch for auto-recall.
recallBudgetHINDSIGHT_RECALL_BUDGET"mid"Search depth: "low" (fast), "mid" (balanced), "high" (thorough).
recallMaxTokensHINDSIGHT_RECALL_MAX_TOKENS1024Max tokens in the recalled memory block.
recallTypes["world", "experience"]Memory types to retrieve.
recallContextTurnsHINDSIGHT_RECALL_CONTEXT_TURNS1Prior turns to include when building the recall query. 1 = latest prompt only.
recallMaxQueryCharsHINDSIGHT_RECALL_MAX_QUERY_CHARS800Max characters in the query sent to Hindsight.
recallRoles["user", "assistant"]Which roles to include when building a multi-turn query.
recallPromptPreamblebuilt-inText placed above the recalled memories in the injected context block.

Auto-Retain

SettingEnv VarDefaultDescription
autoRetainHINDSIGHT_AUTO_RETAINtrueMaster switch for auto-retain.
retainModeHINDSIGHT_RETAIN_MODE"full-session""full-session" sends the full transcript per session (upserted by session ID). "chunked" sends sliding windows every N turns.
retainEveryNTurns10Retain fires every N turns. 1 = every turn. Higher values reduce API calls.
retainOverlapTurns2Extra turns included from the previous chunk (chunked mode only).
retainRoles["user", "assistant"]Which roles to include in the retained transcript.
retainTags["{session_id}"]Tags attached to the stored document. {session_id} is replaced at runtime.
retainMetadata{}Arbitrary key-value metadata attached to the stored document.
retainContext"codex"Label identifying the source integration. Useful when multiple integrations write to the same bank.

Debug

SettingEnv VarDefaultDescription
debugHINDSIGHT_DEBUGfalseEnable verbose logging to stderr. All log lines are prefixed with [Hindsight].

Per-Project Memory

To give each project its own isolated memory bank, enable dynamic bank IDs:

{
"dynamicBankId": true,
"dynamicBankGranularity": ["agent", "project"]
}

With this config, running Codex in ~/projects/api and ~/projects/frontend stores and recalls memories separately. Bank IDs are derived from the working directory path.

Troubleshooting

Hooks not firing: Check that ~/.codex/config.toml contains codex_hooks = true under [features]. Re-run the installer to fix this automatically.

No memories recalled: Recall returns results only after something has been retained. Either complete one Codex session first, or seed your bank manually using the cookbook example.

Memory not being stored: retainEveryNTurns defaults to 10 — retain only fires every 10 turns. While testing, add "retainEveryNTurns": 1 to ~/.hindsight/codex.json.

Debug mode: Add "debug": true to ~/.hindsight/codex.json to see what Hindsight is doing on each turn:

[Hindsight] Recalling from bank 'codex', query length: 42
[Hindsight] Injecting 3 memories
[Hindsight] Retaining to bank 'codex', doc 'sess-abc123', 2 messages, 847 chars

High latency on recall: Use "recallBudget": "low" or reduce recallMaxTokens to speed up recall queries.