Scoped memory management for Codex (global, project, hybrid, and per-thread options)
What variant of Codex are you using?
CLI and IDE Extension
What feature would you like to see?
I would like Codex memories to support explicit scope management instead of relying only on a global memory store.
Today, memory appears to be effectively global under the current CODEX_HOME, which can cause cross-project contamination over time. In practice, many memories are highly specific to one repository, one codebase, or one workflow, and should not automatically influence unrelated projects.
I would like Codex to support configurable memory scopes such as:
- Global: shared across all projects
- Project: isolated to the current project/repo/worktree
- Hybrid: use both global and project memory, with project memory taking priority
- Thread-only / no carryover: keep memory local to a thread/session and do not reuse it elsewhere
It would also be useful to have basic memory management controls, for example:
- view whether a memory is global or project-scoped
- promote or move a memory between scopes
- clear memory only for the current project
- optionally disable project memory inheritance from global memory
This would make Codex much more reliable for users who work across multiple repositories with different standards, conventions, and domain-specific context.
Additional information
This becomes more important as memory grows over time. A pattern, preference, or instruction that is useful in one project may be undesirable or even harmful in another. The current behavior can also save very specific project details in a shared memory pool, which makes reuse less precise and increases the chance of irrelevant memory retrieval.
A good solution could be:
- a configurable memory policy in settings/config
- automatic project namespacing based on repo root or worktree
- optional hybrid retrieval with clear precedence rules
- commands or UI to inspect and manage memory by scope
This would improve long-term memory quality, reduce context bleed between projects, and make memory safer and more predictable for multi-project workflows.
11 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
These issues seems not to be related.
Scoped memory management: we solved this for multi-agent, same patterns apply
The cross-project contamination problem you describe is exactly what we hit in multi-agent deployments at KinthAI (31 agents, shared OpenClaw gateway). Our solution maps directly to Codex's needs:
Three-tier memory scoping:
memory/global/.memory/project/{project_hash}/. This is the critical missing tier.The key design decision: scope inheritance
When querying memory, the system searches:
session → project → global, with project-scoped facts overriding global facts when they conflict. Example: global memory says "use tabs", but project memory says "this repo uses 2-space indent" → project wins.What we found doesn't work:
Scope management UX:
memory list --scope project— show what this project "knows"memory promote {id} --to global— a project-specific insight that should apply everywherememory demote {id} --to project— a global memory that is wrong for this specific projectThis is fundamentally the same problem as multi-tenant memory isolation in agent platforms. We wrote about the architecture: Why Character.AI Forgets You — Persistent Memory Architecture
This is one of the most important memory architecture decisions for coding agents. From building a scoped memory system for 31 concurrent agents:
Four-scope hierarchy works in practice:
Cross-project contamination is a real problem: We've seen agents apply project A's conventions to project B (e.g., using Python patterns in a Go repo because the agent previously worked on a Python project). The fix is strict scope isolation with explicit inheritance: a project scope inherits from global, but global memories never auto-inherit from project scopes.
Importance scoring with time decay: Not all memories deserve equal weight. We use
relevance = importance × (0.95 ^ days_since_stored)to automatically deprioritize stale memories. A memory about a library choice made 6 months ago may no longer be relevant if the dependency has since been replaced. The decay rate should be configurable per scope — global memories decay slowly, session memories don't need decay at all.Memory compaction across scopes: When the total memory size approaches the context window limit, compact lower-priority scopes first. Progressive compaction: full memory → structured summary with entity references preserved verbatim → one-line digest. A project-scoped memory about "use PostgreSQL for the auth service" must preserve that exact entity reference even through aggressive compaction.
Conflict resolution between scopes: When global says "prefer tabs" but project says "use spaces," the more specific scope wins. We resolve conflicts by scope specificity: session > branch > project > global. Log the override so the user can review decisions.
Architecture deep-dive on memory scoping and compaction: https://blog.kinthai.ai/why-character-ai-forgets-you-persistent-memory-architecture
This is a critical feature. Global-only memory creates real problems at scale — we saw this firsthand running 31 agents across multiple projects on a shared gateway.
The contamination problem is worse than it looks: It's not just "project A's conventions leak into project B." In a multi-agent setup, Agent A's memory about a failed approach in Project X can cause Agent B to avoid a perfectly valid approach in Project Y. The agents develop learned helplessness from memories that don't apply to their current context.
Our scoping model (four levels, similar to what you're proposing):
Key design decisions:
Per-thread / no-carryover mode: We implement this as a "session-only" scope where memories are written to an ephemeral store that's garbage-collected when the session ends. Useful for exploratory tasks where you don't want experimental approaches polluting the persistent store.
The hybrid mode gotcha: When project and global memories conflict, you need a deterministic resolution strategy. We use importance scoring with scope weighting — project memories get a 2x importance multiplier over global memories, so they naturally win in retrieval ranking.
More on the memory architecture (including the importance scoring, time decay, and compaction that makes scoped memory manageable): https://blog.kinthai.ai/why-character-ai-forgets-you-persistent-memory-architecture
Multi-tenant isolation patterns that prevent cross-project contamination at the infrastructure level: https://blog.kinthai.ai/openclaw-multi-tenancy-why-vm-per-user-doesnt-scale
Scope control is the right thing to ask for, but I'd push on the framing a little. The cross-project contamination you're describing isn't really caused by memory being global. It's caused by not being able to tell, later, where a given memory came from and whether you ever actually meant for it to stick. Scope boundaries help, but on their own they just move the contamination around instead of removing it.
The case that breaks pure scoping is the hybrid one you mention. Once project memory and global memory both feed retrieval, "project takes priority" sounds clean until two entries genuinely conflict, or until something that started as a one-off in one repo quietly gets treated as a general preference. At that point what you want isn't a bigger precedence table, it's knowing which entries you confirmed versus which ones got written automatically, so the confirmed ones can win regardless of scope.
The promote/move-between-scopes controls have the same issue. Moving a memory from project to global is exactly the moment it's most likely to be wrong, so that's the moment that benefits most from a deliberate confirmation step rather than a silent reclassification.
We've spent a while building memory that's split into global and project scopes, and the scoping itself turned out to be the straightforward part. The thing that actually made retrieval safer across repos was attaching provenance to each entry and keeping a human in the loop before anything became a durable, cross-project fact. I'd treat namespacing as the floor here, not the feature.
A concrete workflow where project/repository-scoped memory would be especially valuable:
I work with many independent, long-lived repositories and intentionally create a new Codex thread for every development task. This keeps tasks focused and avoids relying on increasingly long thread context.
The downside is that every new thread has to rebuild the same repository context: architecture, CI/CD structure, build and test commands, conventions, prior design decisions, terminology, and known limitations.
Global memory is not suitable for this because these facts belong to the repository, not to the user, and must not leak into unrelated repositories.
The useful hierarchy would be:
Global user preferences → Repository/workspace memory → Task threadImportant controls would include inspect/edit/delete, provenance for each entry, explicit confirmation before promoting repository knowledge to global scope, and protection for secrets and ignored files.
This would eliminate the current trade-off between one oversized thread that retains repository knowledge and clean task-specific threads that repeatedly rebuild it.
A concrete current workaround exists for people who need repository isolation before a native Codex scope UI: GoodMemory v0.7.2.
Repeat
enableinside each selected repository. Different workspace IDs isolate repository memory; intentionally reusing an ID allows selected worktrees to share that scope. SQLite is the local default. The installed Codex path provides workspace-scoped recall plus read-only MCP inspection, while writeback remains opt-in and records can be inspected, revised, exported, or forgotten.This is a parallel local memory layer, not a change to Codex built-in memory or thread behavior. Disclosure: I maintain GoodMemory. The commands above were checked against the published GoodMemory 0.7.2 CLI; I am not claiming that release gates prove improved coding outcomes or independent adoption.
Memory has become a necessary feature now that newer models like 5.6 are ignoring AGENTS.md and other requirements docs. Memory fills that gap and really helps (usually just a reminder that the requirement exists). But the contamination is completely breaking the memory feature for me.
One example is my React-based project uses toast popups for validating and error notifications, and my Blazor-based application uses in-line for validation and modals for errors. These are clearly differentiated in the AGENTS.md for each project, but memories are overriding and keep aligning to one project or the other contaminating the other project.
Every time I say it did something wrong, it creates a memory that "fixes" it for one project and completely breaks it for every other project.
Concrete compaction failure this project-scoped memory design should solve
I hit a real continuity failure in a long-running Codex infrastructure session that makes this request more than a cross-project-isolation concern.
Earlier in the thread, Codex had successfully used SSH access to a private host and had the relevant target, user, authentication context, completed steps, and current work in its active context. After context compaction, Codex responded:
The raw password itself should not become durable project memory. Passwords, tokens, private keys, and other secrets should remain outside normal memory artifacts. However, compaction also discarded the surrounding operational state:
That forced the user to re-supply access and partially reconstruct state that Codex had already learned and used. This is exactly where project-scoped operational memory plus secure thread-scoped secret continuity would help.
What the current source already provides
The current repository appears to contain most of the architectural primitives needed:
Feature::MemoryToolis described as startup memory extraction and file-backed memory consolidation incodex-rs/features/src/lib.rs.codex-rs/memories/README.mddocuments a two-phase pipeline:~/.codex/memories, includingMEMORY.md,memory_summary.md, and rollout summaries.codex-rs/state/migrations/0006_memories.sql.codex-rs/ext/memories/src/extension.rscontributes memory context at thread startup.codex-rs/ext/memories/src/prompts.rsreads~/.codex/memories/memory_summary.mdand renders it into developer instructions.codex-rs/ext/memories/templates/memories/read_path.mdinstructs Codex to searchMEMORY.md, skills, and rollout summaries when prior context may help.codex-rs/thread-store/src/projects.rsdefines stored projects with an ID, name, roots, metadata, and thread associations.projectIdwhen a thread starts.PreCompactandPostCompactare first-class hook event names incodex-rs/protocol/src/protocol.rs.codex-rs/core/src/compact.rsinvokes pre-compaction hooks, performs compaction, replaces detailed history with retained user messages plus a summary, and then invokes post-compaction hooks.These pieces suggest that Codex does not need a second independent storage subsystem. The missing capability is wiring the existing Project, memory, and compaction primitives together for synchronous continuity of the active project.
Why the current memory pipeline does not prevent this failure
The existing pipeline is useful, but it solves a different problem:
That means it is not currently a guaranteed, synchronous checkpoint of the live thread immediately before compaction.
The current read path also appears globally rooted in
CODEX_HOME:MemoriesExtensionConfigcurrently carriesenabled,dedicated_tools, andcodex_home, but not the activeproject_id, project roots, or current working directory.build_memory_tool_developer_instructions(...)similarly receives onlycodex_home.Therefore, the current system can have memory and still miss the specific operational state needed after a compaction boundary.
Proposed model: four distinct state layers
The implementation should separate four kinds of state rather than treating all of them as one memory blob.
| Layer | Scope | Examples | Persistence |
|---|---|---|---|
| Global memory | User/Codex installation | preferred command style, general conventions, communication preferences | Durable across projects |
| Project memory | Codex Project / repo roots | architecture decisions, environment facts, runbooks, known failures, durable project constraints | Durable across threads in the same project |
| Active operational checkpoint | Project + thread | current target, completed steps, work in progress, next action, active incident state | Survives compaction/resume; expires or closes when work completes |
| Secret lease/reference | Thread + approved tool boundary | SSH password handle, temporary token handle, sudo credential handle | Never stored as ordinary memory; short-lived and tightly scoped |
The critical rule should be:
Proposed compaction lifecycle
A native lifecycle could be:
PreCompact should preserve at least
project_idand matching project roots;PostCompact should restore
The active checkpoint should be host-owned structured state, not only a free-form model summary. A model can propose candidate fields, but the runtime should attach canonical project/thread IDs, tool call IDs, timestamps, file paths, and other evidence it can verify directly.
Example checkpoint for the reported SSH workflow
After compaction, Codex should be able to recover:
It should not need the user to reconstruct the entire workflow.
Secure secret continuity
Project memory alone should not attempt to remember passwords. The reported failure also exposes the need for a separate secure runtime mechanism.
A safe design could provide optional thread-scoped secret slots or leases:
secret://thread/....MEMORY.md, rollout summaries, logs, analytics, hook payloads, or child-agent context.SSH keys and
ssh-agentremain the preferred path, but password-based infrastructure workflows still exist and should not force plaintext secrets into the context window as the only continuity mechanism.Project routing and retrieval
Project memory should be keyed primarily by the existing Codex
project_id, not solely by a rawcwdstring.Recommended routing order:
project_id.This handles multiple worktrees and multi-root projects better than hashing the current directory alone.
A possible filesystem layout, building on the current memory root, would be:
The exact storage can remain an implementation choice. Active checkpoints may fit better in the existing state database for atomicity and lifecycle management, while consolidated project memory can remain file-backed and inspectable.
Retrieval precedence should be:
More specific state should override less specific state, but the system should preserve conflicts and provenance rather than silently rewriting history.
Memory item quality and staleness
Each durable item should distinguish at least:
Useful metadata includes:
project_idand optional affected roots/files/symbols;valid_at_shawhen a Git checkout is involved;A remembered hypothesis must not later be treated as a confirmed fact. A previous successful SSH connection must not imply that the host is still reachable indefinitely. A project decision that has been superseded should remain auditable but should not control current execution.
User controls
This should be inspectable and reversible from both CLI and app surfaces.
Potential controls:
App UI could expose a Project > Memory view with:
Suggested implementation seams in the current source
This proposal appears alignable with existing code rather than requiring a parallel architecture:
MemoriesExtensionConfigincodex-rs/ext/memories/src/extension.rswith activeproject_id, project roots, and/or normalized workspace identity.build_memory_tool_developer_instructions(...).run_compact_task_inner_impl(...)replaces history.PreCompactlifecycle and canonical session/tool history.Acceptance criteria
A minimal implementation should satisfy all of the following:
Relationship to existing issues
The concrete gap is the intersection of those two requests:
This is not a request to store SSH passwords in
MEMORY.md. It is a request for Codex to stop using the context window as the only place where active project state and temporary access continuity can exist.The desired user-visible result is straightforward:
That would directly prevent the workflow interruption described above while preserving a strong secret-handling boundary.
@en4ble1337 this incident usefully separates three state classes that should not be collapsed into one memory tier:
GoodMemory 0.7.5 can cover the first class and parts of the second when a host explicitly captures selected, redacted state. Its installed path keeps raw transcripts out of durable memory, scopes records to a workspace, and exposes audit/correction/deletion. It does not currently provide a Codex-native synchronous
PreCompactcheckpoint or a secure credential-handle service, so I would not claim it fully solves the failure you described.A useful native acceptance test would be:
That test distinguishes continuity from credential persistence and avoids using ordinary project memory as a secret store. Disclosure: I maintain GoodMemory; this is a capability-boundary note, not evidence that the current release fixes Codex native compaction.