Status: research + design proposal (2026-07-02; plugin paths refreshed
2026-07-03).
Goal: make Codex CLI and Cursor use the TraceDecay holographic fact store
(tracedecay_fact_store add/search/probe/reason, memory_facts table, HRR
vectors + trust scores) as their agent memory for both recall (facts reach
the model at the right moment) and storage (new durable facts get written),
instead of — or layered on top of — each agent's native memory mechanism.
Current plugin source lives under the shared plugin/ tree: shared skills in
plugin/skills/, Claude commands in plugin/commands/, shared agents in
plugin/agents/, and Cursor-only surfaces in plugin/overlays/cursor/.
~/.codex/config.toml has:
[features]
memories = true # experimental per `codex features list`Codex's memories feature is a background extract-and-consolidate pipeline that
materializes plain-markdown files under ~/.codex/memories/ (a git repo):
| File | Role |
|---|---|
memory_summary.md |
Stage-2 consolidated "user profile + preferences + what's in memory" digest — the primary artifact injected into new sessions |
MEMORY.md |
Task-group organized durable entries (per-repo task groups, user preferences, reusable knowledge, failure post-mortems) with pointers into rollout summaries |
raw_memories.md |
Stage-1 per-thread raw memory records (thread id, cwd, rollout path, keywords) |
rollout_summaries/*.md |
One summary file per eligible past session (rollout) |
extensions/ad_hoc/ |
Ad-hoc memory extension entries |
Mechanics (per developers.openai.com/codex/memories and the config reference):
- Generation is asynchronous: after a thread has been idle
≥
memories.min_rollout_idle_hours(default 6h), Codex extracts a per-thread memory (memories.extract_model), then periodically consolidates raw memories intoMEMORY.md/memory_summary.md(memories.consolidation_model). Short-lived/active sessions are skipped; secrets are redacted. - Recall is controlled by
memories.use_memories(defaulttrue): Codex injects existing memories into future sessions at startup. There is no per-prompt retrieval — it is session-start injection of the consolidated summary plus a search-over-MEMORY.mdaffordance (the summary explicitly tells the model to "SearchMEMORY.mdfirst for …"). memories.generate_memories(defaulttrue) gates whether new threads become generation inputs.memories.disable_on_external_context(defaultfalse) can exclude threads that used MCP/web-search from memory generation. Since tracedecay's MCP server is active in most sessions here, native memory generation currently does consume MCP-heavy threads (both systems learn from the same sessions — duplication risk, see §5).- Managed via
/memoriesin the TUI andcodex debug clear-memories. [features.memories] custom_tools = true(nested form) additionally exposes memories read/retrieval tools to the model — i.e. Codex is moving toward model-invocable memory reads, which is exactly the slot atracedecay_fact_storeMCP tool already occupies.
AGENTS.md— project-doc mechanism, auto-loaded from repo root (and parent/~/.codex/AGENTS.mdglobal variant). Stable, always read.- Skills (
~/.codex/skills/, plus plugin-bundled skills) — frontmatter name/description always visible; body lazy-loaded on match. - Plugins (
~/.codex/plugins/cache/<marketplace>/<name>/<version>/) — bundle MCP servers, skills, and lifecycle hooks. - Rules (
~/.codex/rules/default.rules) — command prefix allow/deny rules only, not a prompt-context surface (unlike Cursor rules).
Codex hooks are stable (codex features list → hooks stable true) and are
declared in a plugin's hooks/hooks.json (Claude-style schema: event →
matcher → command). Events used/verified by the tracedecay plugin
(~/.codex/plugins/cache/personal/tracedecay/0.0.23/hooks/hooks.json, trusted
hashes recorded under [hooks.state] in config.toml):
| Event | Payload includes | Output contract | Context injection? |
|---|---|---|---|
SessionStart |
session id, cwd, source (compact for post-compaction restarts) |
hookSpecificOutput.additionalContext |
Yes |
UserPromptSubmit |
session id, cwd, prompt text | hookSpecificOutput.additionalContext |
Yes — per prompt |
SubagentStart |
session id, agent type | hookSpecificOutput.additionalContext |
Yes |
PostToolUse |
tool name, command | (used for ingest/steering) | Yes |
PostCompact |
rollout path | side effects (summary replacement) | Indirect |
Key asymmetry vs Cursor: Codex's UserPromptSubmit hook receives the
prompt text and can inject additionalContext — a true per-prompt memory
recall channel. TraceDecay already exploits this channel for tool-routing
hints (src/hooks/codex.rs::hook_codex_user_prompt_submit →
codex_user_prompt_submit_context_for_event →
codex_additional_context_json("UserPromptSubmit", …)), just not for facts.
- Auto-generated short rules derived from chats, produced by a background sidecar model (hybrid with agent tool-calls for explicit "remember this"), scoped per project, stored server-side on the Cursor account (not in a user-inspectable local file). Managed in Settings → Rules → Memories (review/approve/edit/delete). Requires Privacy Mode disabled; toggle is "Generate Memories".
- Injected into agent context automatically alongside rules. There is no local file, no CLI, and no hook that exposes or intercepts the memory read/write path. Cursor memories are a black box: not interceptable, only disableable.
Precedence: Team Rules → Project Rules → User Rules, merged.
- Project rules:
.cursor/rules/*.mdc(frontmatteralwaysApply,globs,description). - Plugin rules: plugins under
~/.cursor/plugins/local/<name>/rules/*.mdcare injected as always-applied workspace rules — this is how tracedecay'stracedecay.mdcrule reaches every session today. AGENTS.mdat repo root; User Rules in settings.- Community + Cursor-staff consensus (forum, 2026): "
.cursor/ruleswithalwaysApply: trueis the most reliable way to inject context into every prompt today."
Hooks live in ~/.cursor/hooks.json, project .cursor/hooks.json, or plugin
hooks/hooks.json (tracedecay uses the plugin variant, verified at
~/.cursor/plugins/local/tracedecay/hooks/hooks.json). Events (per
cursor.com/docs/hooks): sessionStart/sessionEnd, preToolUse/postToolUse/
postToolUseFailure, subagentStart/subagentStop, beforeShellExecution/
afterShellExecution, beforeMCPExecution/afterMCPExecution,
beforeReadFile/afterFileEdit, beforeSubmitPrompt, preCompact, stop,
afterAgentResponse/afterAgentThought, workspaceOpen.
Context-injection capability per event (verified against docs + forum + the
comment in src/hooks/cursor.rs::hook_cursor_before_submit_prompt):
| Event | Injection field | Notes |
|---|---|---|
sessionStart |
additional_context (+ env) |
Documented "added to the conversation's initial system context". Known reliability bugs (forum reports of injected context being dropped due to a timing gap) — treat as best-effort |
postToolUse |
additional_context |
Works; also has reported plumbing gaps |
beforeSubmitPrompt |
none — output schema is {continue, user_message} only |
Receives the prompt + attachments, but cannot add context or modify the prompt (updated_input silently stripped). Per-prompt recall injection is architecturally impossible in Cursor today; there is an open feature request |
stop / sessionEnd / afterAgentResponse |
none | Observation only — good for storage side-effects, not recall |
preCompact |
none | Observation only |
So for Cursor: recall must ride on sessionStart.additional_context
(best-effort), an always-applied rule file (reliable), or model-initiated MCP
tool calls (reliable but discretionary). Storage interception rides on
stop/sessionEnd/transcript ingest — which TraceDecay already does.
Writes the Cursor projection of the shared plugin bundle
(src/agents/plugin_bundle.rs::cursor_files) to
~/.cursor/plugins/local/tracedecay/:
mcp.json— stdio servertracedecay serve --path ${workspaceFolder}(all fact-store/memory/graph tools available to the model).hooks/hooks.json— 9 hooks:sessionStart,beforeSubmitPrompt,postToolUse,afterFileEdit,afterShellExecution,preCompact,sessionEnd,stop,workspaceOpen, each shelling totracedecay hook-cursor-*(dispatch:src/hook_cmd.rs, impls:src/hooks/).rules/tracedecay.mdc— always-applied rule; its Recall bullet steers models totracedecay_message_search/tracedecay_fact_storesearch and theproject-memoryskill.skills/— shared model-invocable skills, excluding thetracedecay-*dispatcher skills that Cursor exposes as native commands.commands/— Cursor-native workflow commands fromplugin/overlays/cursor/commands/.agents/— Cursor agent definitions fromplugin/overlays/cursor/agents/.
What the hooks currently do (all fail-open):
sessionStart(hook_cursor_session_start) — catch-up transcript ingest, then emitsadditional_contextbuilt bybuild_cursor_session_context(src/hooks/steering.rs): index status + skill list + tokens-saved counter. No facts. SetsTRACEDECAY_PROJECT_ROOTenv.beforeSubmitPrompt— hot transcript ingest only; emits{"continue": true}(no context possible, see §2.3).postToolUse— tool-routing hints viaadditional_context(cursor_post_tool_use_decision).stop/sessionEnd/preCompact— transcript ingest into the LCM store, pre-compaction summary nodes. This is the storage-side raw material: every Cursor session ends up searchable viatracedecay_message_searchand becomes evidence for the session_reflector.
Installs the Codex projection of the shared plugin bundle
(src/agents/plugin_bundle.rs::codex_files) to
~/.codex/plugins/cache/personal/tracedecay/<version>/ plus a personal
marketplace entry (install_codex_marketplace_entry) and
[plugins."tracedecay@personal"] enabled = true in config.toml:
.mcp.json(codex_plugin_mcp,src/agents/codex.rs:563) — same stdio tracedecay server.hooks/hooks.json(codex_plugin_hooks,src/agents/codex.rs:582) —SessionStart,UserPromptSubmit,SubagentStart,PostToolUse(matcherBash|apply_patch),PostCompact(matcherauto|manual). Hooks require one-time/hookstrust (print_hook_trust_guidance); trusted hashes live in[hooks.state].skills/— shared skills fromplugin/skills/plus theagent-managed/overlay.- No rule surface exists in Codex, so the steering text Cursor gets via
tracedecay.mdcis injected throughSessionStart/UserPromptSubmitadditionalContextinstead (build_codex_session_context,codex_user_prompt_submit_context_for_event— index status + skills + tool hints. No facts.). PostCompactreplaces encrypted compaction placeholders with LCM-backed summaries via acodex app-serverchild.
Codex transcripts (rollouts under ~/.codex/sessions/) are ingested into the
LCM store as well (session-recall skills cover "Cursor/Codex/agent
transcripts"), so Codex sessions also feed reflection.
- Per-project holographic store (
memory_facts+ entities, HRR dim 2048, 4 banks, amari_fhrr algebra;src/memory/{store,retrieval,trust,types}.rs).tracedecay_memory_statuson this repo: 9 facts, 113 entities, trust all ≥ 0.75. - MCP/CLI surface:
tracedecay_fact_storewith actions add/search/probe/related/reason/contradict/get/update/remove/list, write-time near-duplicate & conflict detection, secret rejection, trust calibration guidance;tracedecay_fact_feedback(helpful/unhelpful trust deltas);tracedecay_memory_status. Cross-project reads viaproject_id/project_pathselectors (read-only actions). - Retrieval API (
src/memory/retrieval.rs::FactRetriever):search,probe,related,reason,contradict— directly callable in-process from the hook binary (the hooks are the sametracedecaybinary; no MCP round-trip needed).
src/automation/{runner,session_reflector,fact_proposals}.rs:
- Scheduler-driven task (
AgentTaskKind::SessionReflector,src/automation/scheduler.rs:301) gathers LCM session evidence, prompts an automation backend (build_session_reflector_prompt), and validates returned fact proposals against evidence citations (validate_fact_proposals— each proposal must cite raw messages / store ids / summary nodes; trust bounded byproposal_trust_value). - Accepted proposals are recorded to the dashboard proposal store
(
fact_proposals.rs::record_session_fact_proposals) for human approval in the curation UI, or auto-applied whenauto_apply_memory_ops && !require_dashboard_approval. - Defaults are conservative:
AutomationConfig::default()hasenabled: false,backend: Disabled,require_dashboard_approval: true,auto_apply_memory_ops: false(src/automation/config.rs:101-113). So the write path from transcripts → facts exists but is off unless the user enables automation.
src/automation/hermes_bridge.rs is a read-only projection of
Hermes-owned skill lifecycle state (skills dir, pending write approvals,
usage, curator config) for dashboards/MCP. Skill deployment to agents goes
through the managed-skill overlay (managed_skills.rs, skill_targets.rs,
install_*_managed_skill_overlay) — agent-authored skills land in the
agent-managed/ skill dir of each installed plugin. Relevant here only as
the template for "TraceDecay materializes generated content into agent
surfaces on a schedule," which design D reuses for memory.
| Stage | Codex | Cursor |
|---|---|---|
| Facts stored | ✅ fact store (9 facts here) + LCM transcripts | same store |
| Model can recall | ✅ MCP tracedecay_fact_store search + skill |
✅ same |
| Model is told to recall | project-memory skill matches only when the model thinks "recall" |
tracedecay.mdc; same skill-match dependency |
| Facts pushed into context | ❌ none — hook context is index status + hints only | ❌ none |
| Automatic storage | project-memory guardrail) |
same |
| Native memory overlap | features.memories=true), learning from the same threads in parallel |
Unknown toggle state; server-side, uninspectable |
The delta is precisely: nothing proactively retrieves facts at session/prompt time, and nothing writes facts without an explicit user request or a (disabled) automation run. Recall depends entirely on the model electing to call an MCP tool; storage depends on the user saying "remember this."
Codex is the lowest-effort path because UserPromptSubmit carries the prompt
text and honors hookSpecificOutput.additionalContext, and the hook binary is
tracedecay with in-process store access (no MCP hop, fits the 5s timeout).
SessionStart: incodex_session_context_for_event(src/hooks/codex.rs), after workspace status, runFactRetriever::search/listfor the top-K high-trust project facts (e.g. K=8,min_trust0.6, category-diverse, newest-first tiebreak) and append a compact## Project memoryblock with fact ids ("rate with tracedecay_fact_feedback, correct with fact_store update"). Reuse the token-budget discipline the context builders already have.UserPromptSubmit: incodex_user_prompt_submit_context_for_event(src/hooks/codex.rs), embed the prompt (prompt_like_text) via the existing HRR encoder and inject only facts above a similarity × trust threshold, deduped per session the same way tool hints are deduped (deduped_codex_hintpattern,remember_hint_in_process). Empty result → inject nothing (most prompts).SubagentStart: optionally include the same session-start block so subagents inherit memory.
Implementation pointers: src/hooks/codex.rs, src/hooks/cursor.rs,
src/hooks/steering.rs, and shared helpers in src/hooks/mod.rs,
src/memory/retrieval.rs (FactRetriever::search/probe), analytics via
record_hint_analytics so injection quality is measurable. No plugin schema
change; hook hashes change → users re-trust via /hooks (already documented
in the Codex plugin README).
Per-prompt injection is impossible in Cursor (§2.3), so combine the two channels that exist:
sessionStart.additional_context— extendbuild_cursor_session_context/cursor_session_context_for_root(src/hooks/steering.rs,src/hooks/cursor.rs) with the same top-K fact block as design A. Cheap, but treat as best-effort given the open forum bugs about droppedadditional_context.- Materialized always-applied memory rule — generate
~/.cursor/plugins/local/tracedecay/rules/tracedecay-memory.mdc(alwaysApply: true) from the fact store: a "Project memory (generated — curate via tracedecay_fact_store / dashboard)" section listing top-K high-trust facts with ids. This is the reliable channel per Cursor's own guidance. Refresh triggers:workspaceOpen/sessionStarthooks (rewrite if stale > N minutes — hooks already have write access to the plugin dir) and/or a scheduler task. Keep it small (facts are one-liners; cap ~1–2 KB) and deterministic (sorted) so diffs are reviewable.
Implementation pointers: add the managed rule to the Cursor projection in
src/agents/plugin_bundle.rs / src/agents/cursor.rs, refresh it from
hook_cursor_workspace_open (src/hooks/cursor.rs), and mark it managed the
same way generated skills are marked (managed_skill_format.rs) so uninstall
and doctor checks cover it.
Today project-memory's guardrail says add facts "only when the
user asks" — the opposite of agent-memory behavior. Change the instruction
(rule Recall bullet in plugin/overlays/cursor/rules/tracedecay.mdc + the
plugin/skills/project-memory/SKILL.md skill, shared across every host) to:
- Recall: "before starting non-trivial work, search
tracedecay_fact_storefor prior decisions" (currently phrased as fallback, not default). - Storage: "when you learn a durable preference, decision, or pitfall
(user corrections especially), store it with
fact_store addwith calibrated trust" — the add-path already defends against junk (near_duplicate / possible_conflict / secret rejection, §3.3).
This mirrors Cursor's hybrid design (sidecar + tool calls), with the tool-call half pointed at TraceDecay.
session_reflector is the background sidecar analog: transcripts (both agents, already ingested by the hooks) → evidence-cited fact proposals → dashboard approval → store. The work is activation, not construction:
- Surface a one-command enable (
tracedecay automation enable session-reflector) that picks a backend and leavesrequire_dashboard_approval: true; document the graduation path toauto_apply_memory_opsonce proposal quality is trusted. - Wire a nudge into
doctor/memory_statuswhen transcripts accumulate but automation is disabled ("N sessions ingested, 0 reflected").
Pointers: src/automation/config.rs (defaults/validation),
src/automation/runner.rs::run_session_reflector_with_backend,
dashboard curation UI (concurrent work in dashboard/ — coordinate, don't
touch).
With features.memories = true, Codex builds a parallel memory in
~/.codex/memories/ from the same sessions. Options:
- Coexist (default, zero change): native memories keep user-level cross-repo profile; fact store owns per-project durable facts. Acceptable but two sources of truth drift.
- Prefer TraceDecay: recommend
memories.use_memories = false(stop injection, keep generation) orfeatures.memories = falsein install docs/doctor output once design A ships — A's injection replaces it with curated, trust-scored, per-project recall. Do not silently edit the user'sconfig.toml; make it a doctor suggestion. - Harvest: one-way import of
~/.codex/memories/raw_memories.md+rollout_summaries/*.mdinto fact proposals (they're clean markdown with cwd/thread metadata — easy to parse intoAddFactRequests routed through the same proposal/approval path as D). Gives the fact store Codex's already-consolidated knowledge on day one.
For Cursor: native Memories can't be intercepted or exported; the only lever
is the Settings toggle. Once B+C are live, recommend users disable "Generate
Memories" to keep one memory system (document in KIRO-INTEGRATION.md-style
agent doc; can't be automated).
Scheduled materialization of facts into files agents read natively without
any tool call: a ## Memory (generated by tracedecay) fenced section in repo
AGENTS.md, or a ~/.codex/memories/extensions/tracedecay/ entry (Codex
reads the memories dir natively when the feature is on). Compared to B2 this
reaches every agent (Claude, Gemini, etc. — src/agents/ has 15
integrations) via one artifact, but it edits user/repo-owned files (needs
fenced-section ownership, .gitignore questions, merge conflicts) and its
freshness is only as good as the schedule. Recommend only as the
generalization step after A–C prove out, implemented as an automation task
alongside D and reusing the managed-file conventions from the skill overlay.
- Cursor
beforeSubmitPromptrecall injection — output schema is{continue, user_message}only;updated_input/additional_contextare silently stripped (confirmed by Cursor staff on the forum; open feature request). Revisit if Cursor ships the field. - Rewriting the user prompt via
user_message—user_messageis a user-facing notice, not model context; abusing it shows UI noise. - Intercepting Cursor native Memories — server-side, no local artifact, no hook. Only the on/off toggle exists.
- Codex
notifymechanism — fire-and-forget desktop notification hook; no context channel.
- A + B1 (hook-based injection, both agents) — one PR across
src/hooks/src/memory/retrieval.rshelpers; measurable via existing hook analytics.
- B2 + C (materialized Cursor memory rule + proactive storage wording) —
one PR in
src/agents/plugin_bundle.rs,src/agents/cursor.rs, and plugin rule/skill text (shared skill text underplugin/skills/). - D (reflector enablement UX) — config/doctor/dashboard nudge.
- E (coexistence policy + optional Codex-memories harvest importer).
- F (generalized AGENTS.md materialization across all 15 agent integrations) — only if A–C leave recall gaps for agents without hook surfaces.