Codex Memory Plugin
Equip Codex with persistent memory across sessions. Install it once, and your OpenViking profile and memory index are loaded at session start, relevant memories are recalled with every prompt, new turns are captured after each response, and sessions are committed before compaction. The plugin also connects Codex to OpenViking's /mcp endpoint, enabling the model to call tools such as find, search, read, and remember directly.
Source: examples/codex-memory-plugin | Blog: Motivation & demo
Install
Claude Code and Codex share one installer. It asks for your language (English/中文), which harnesses to install, the download source, and your OpenViking credentials; every step is idempotent.
bash <(curl -fsSL https://raw.githubusercontent.com/volcengine/OpenViking/main/examples/memory-plugin-shared/install.sh)TraeCode CLI 2.0 accepts this Codex-format plugin directly. Its default installer entry is --harness trae-cli:
bash <(curl -fsSL https://raw.githubusercontent.com/volcengine/OpenViking/main/examples/memory-plugin-shared/install.sh) \
--harness trae-cliIn regions where GitHub is hard to reach, run the same installer from the Volcengine TOS mirror (or pick "TOS mirror" at the download-source prompt). Codex installs from a TOS-hosted git repo and keeps remote update support:
bash <(curl -fsSL https://ovrelease.tos-cn-beijing.volces.com/memory-plugin-shared/install.sh)No shell wrapper is needed anymore — the plugin ships a stdio MCP proxy that reads ~/.openviking/ovcli.conf (or OPENVIKING_* env vars) at runtime, same as the hooks. After installing:
codex # First run: approve hooks once when prompted via /hooksManual setup
Prerequisites: Node.js >= 22, Codex >= 0.130.0, and the plugin_hooks feature enabled.
Configure the connection — write
~/.openviking/ovcli.conf(url,api_key, optionalaccount/user), or run the bundled wizardnode <plugin-dir>/scripts/setup.mjsafter installing.Install the plugin from the remote marketplace:
bashcodex plugin marketplace add volcengine/OpenViking codex plugin add openviking-memory@openvikingThen enable plugin hooks in
~/.codex/config.tomlif your build doesn't already:[features]→plugin_hooks = true. Update later withcodex plugin marketplace upgrade openviking.
Verify
Launch codex; on the first prompt of a session, the SessionStart hook should load your profile, and the plugin should then recall relevant memories for every prompt. Set OPENVIKING_DEBUG=1 to write events to ~/.openviking/logs/codex-hooks.log. For TraeCode CLI 2.0, launch trae-cli and use trae-cli plugin list to confirm the plugin is enabled.
How it works
The plugin integrates with Codex's lifecycle by hooking into key events. On SessionStart (startup, clear, or resume), it injects profile.md plus URI and abstract indexes for preferences/ and entities/ through the same shared, CJK-aware profile builder used by the other coding-agent integrations. It then searches OpenViking and injects relevant memories before every prompt (UserPromptSubmit), appends new turns to the session after each response (Stop), commits the full transcript before compaction (PreCompact), and commits the session when the thread shuts down (SessionEnd) so memory extraction processes the entire conversation. Upon starting a fresh session, it also sweeps any orphaned sessions left by previous runs. A resumed session may combine the fixed profile block with its latest archive digest.
Known limitation:
SessionEndrequires Codex 0.145 or newer, and it only fires on a graceful exit (/quit,/exit, doubleCtrl-C, EOF, end of acodex execrun). It does not fire onSIGTERM, a closed terminal,kill -9, or a crash, and it is deferred when the TUI runs against acodex app-serverdaemon. Those sessions — and every session on Codex older than 0.145, and any TraeCode CLI build without it — are recovered by the idle-TTL sweep (30 minutes) at the nextSessionStart.
Tool calls and results are captured as dedicated tool parts, and tool_output is reported verbatim. Truncation is the server's job: output larger than tool_output_externalization.threshold_chars (default 20000) is written to the session's tool-result store, and the part keeps a synopsis stub plus tool_output_ref, so the original stays readable through /api/v1/sessions/{id}/tool-results.
Configuration
Credential source: env vars win by default — when any OPENVIKING_* credential env var (OPENVIKING_URL/OPENVIKING_BASE_URL, OPENVIKING_BEARER_TOKEN/OPENVIKING_API_KEY, OPENVIKING_ACCOUNT, OPENVIKING_USER, OPENVIKING_PEER_ID) is set, its value takes precedence over the active ovcli.conf. Only when none of them are set does the active ovcli.conf (OPENVIKING_CLI_CONFIG_FILE or ~/.openviking/ovcli.conf) drive hooks, MCP proxy, and child ov commands together, so ov config switch <name> takes effect on the next launch. Set OPENVIKING_CREDENTIAL_SOURCE=cli to force the active ovcli config even while credential env vars are present. Fields not covered by either fall back to ovcli.conf, then ov.conf, then built-in defaults.
| Env Var | Default | Description |
|---|---|---|
OPENVIKING_URL / OPENVIKING_BASE_URL | — | Full server URL |
OPENVIKING_API_KEY | — | API key (sent as Authorization: Bearer) |
OPENVIKING_CLI_CONFIG_FILE | ~/.openviking/ovcli.conf | Active CLI config to use for hooks, MCP, and child ov commands |
OPENVIKING_CREDENTIAL_SOURCE | auto | auto prefers env-var credentials when any are set; cli forces the active ovcli config, env forces env vars |
OPENVIKING_NO_AUTO_INJECT | false | Disable fixed session-start profile/background injection without disabling per-prompt recall |
OPENVIKING_PROFILE_TOKEN_BUDGET | 10000 | CJK-aware token budget for profile.md plus preferences/ and entities/ indexes |
OPENVIKING_CODEX_IDLE_TTL_MS | 1800000 | SessionStart idle-TTL sweep threshold |
OPENVIKING_CODEX_LOCK_WAIT_MS | 120000 (SessionEnd), 40000 (PreCompact) | How long a capture hook waits for the per-session state lock |
OPENVIKING_CODEX_COMMITTED_TTL_MS | 2592000000 | How long a committed session's transcript cursor is kept before its state file is retired |
OPENVIKING_RECALL_QUERY_FILTERS | "" | CSV of sed-style regex rules applied to the prompt before it becomes a query (grammar and examples) |
OPENVIKING_CAPTURE_FILTERS | "" | CSV of sed-style regex rules applied to every captured turn (same grammar) |
OPENVIKING_DEBUG | false | Write logs to ~/.openviking/logs/codex-hooks.log |
Most of these knobs can also live in ovcli.conf under plugin — see Plugin Settings. The two filter knobs are better written there, as JSON arrays, because the environment form is split on commas.
If recall latency matters most, see Low-latency recall for the environment-variable and ovcli.conf settings that disable query expansion and Codex's local result compression.
Additional tuning options (e.g., OPENVIKING_RECALL_LIMIT, OPENVIKING_CAPTURE_ASSISTANT_TURNS) are documented in the plugin README.
Workspace peer
Memories are filed under a peer derived from the repository you are working in, so one project keeps one memory across clones, worktrees, and subdirectories. The default peer.source: "git" uses the repository's normalized origin URL — with origin [email protected]:volcengine/OpenViking.git, the peer is github.com-volcengine-openviking — falling back to the repository root path; outside a repository no peer is sent at all, and what is remembered there goes to your user-level space at viking://user/<you>/memories. A fork has its own origin, so it stays a separate peer.
Change it with OPENVIKING_PEER_SOURCE, with plugin.peerSource in ovcli.conf, or with peer.source in the workspace's .openviking/config.json (a "version": 1 file the team can commit): "cwd" restores the previous behavior — the working directory with every non-alphanumeric character replaced by - — "none" sends no peer, and a template such as "team-{dir}" builds your own. To give a directory that is not a repository its own memory, create .openviking/config.json in it containing {"version": 1, "peer": {"id": "my-project"}}. Memories written under the earlier cwd-derived peer are still recalled, so nothing needs migrating. The layer precedence and the full workspace-file schema are in Client Configuration → Workspace Configuration.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| MCP tool calls fail with an auth error | The active ovcli config has no valid api_key for an authenticated server | Fix ~/.openviking/ovcli.conf (or run node <plugin-dir>/scripts/setup.mjs) and restart Codex; the stdio proxy re-reads it on launch and after auth failures. |
| MCP tool calls fail with a connection error | Server unreachable or the URL is wrong | Check the endpoint: curl "$(jq -r '.url' ~/.openviking/ovcli.conf)/health" |
4 hooks need review | Security review on first launch | Run /hooks within Codex and approve the hooks. |
Plugin still targets an old server after ov config switch | Codex keeps the proxy process from the previous session | Restart Codex; the proxy resolves credentials at startup. |
| Hooks use one server, MCP another | Stale OPENVIKING_* credential env vars in one context (env vars override ovcli.conf by default) | Unset the stale env vars (ovcli.conf then drives both), set OPENVIKING_CREDENTIAL_SOURCE=cli, or make the env vars consistent. |
See also
- Capability Reference
- Blog: OpenViking in Claude Code / Codex — Motivation, architecture overview, and demo.
- Plugin README — Full environment variable list and architecture diagram.
- DESIGN.md — Commit decision tree.
- MCP Clients — MCP protocol, tools, and other clients.
- Deployment Guide → CLI —
ovcli.confsetup instructions.
