I used claude-mem (opens in a new tab) (відкриється в новій вкладці) because it removed a dull ritual from coding sessions:
explaining the last session before starting the next one. Its hooks made memory
feel immediate. I liked that continuity, but I did not like keeping a Claude
subscription in the loop when most of my work now happens in Codex through my
ChatGPT plan.
Codex Memories cannot replace claude-mem turn for turn because it works on a
slower schedule. It does not save an observation after every turn. Once an
earlier task has been idle long enough, Codex can extract useful material during
a later root-session startup and then attempt to consolidate it into local
Markdown. I use that memory for recall and keep mandatory rules in AGENTS.md
and checked-in documentation.
OpenAI's Memories documentation (opens in a new tab) (відкриється в новій вкладці)
draws the same boundary, and the
tagged pipeline documentation (opens in a new tab) (відкриється в новій вкладці)
describes the two background phases.
How the local memory pipeline works
In Codex, a rollout is a saved task or thread, not an individual message. The memory pipeline runs asynchronously during a later root-session startup:
A previous task becomes idle, a later root task starts the background pipeline, and Codex attempts extraction then consolidation for future tasks.
Use plus and minus to zoom, arrow keys to move around the diagram when zoomed, and Home to reset.
Phase 1 selects recent tasks once they have been idle long enough and no other worker has claimed them. For each useful task, the model produces a detailed raw memory, a compact rollout summary, and optionally a short slug. Codex redacts secrets from those generated fields and saves the result in its state database.
Phase 2 selects eligible outputs ranked by prior use and recency, then refreshes
the files under $CODEX_HOME/memories/, which is ~/.codex/memories/ by default.
On my machine the main workspace currently contains MEMORY.md,
memory_summary.md, raw_memories.md, rollout_summaries/, and skills/. Codex
generates and manages that state. I inspect the directory when I need to trace a
recalled detail, but I do not hand-edit it during ordinary work.
A successful extraction may not trigger consolidation during the same startup. Phase 2 has its own coordination, retry, and cooldown checks, so a startup can finish Phase 1 and skip consolidation. The tagged Phase 2 implementation (opens in a new tab) (відкриється в новій вкладці) contains those checks.
I kept the tagged six-hour idle default. It lets memories become eligible sooner, although a comment in the tagged configuration source recommends more than 12 hours when avoiding premature extraction matters more. Memory from a finished session may still be unavailable in the next session I open five minutes later.
My exact configuration
This is the memory section in my global ~/.codex/config.toml:
[features]
memories = true
[memories]
generate_memories = true
use_memories = true
dedicated_tools = true
disable_on_external_context = false
min_rate_limit_remaining_percent = 10
min_rollout_idle_hours = 6
max_rollout_age_days = 30
max_rollouts_per_startup = 8
max_unused_days = 90The feature flag turns the system on. generate_memories allows new tasks to
become inputs for later extraction, while use_memories allows Codex to inject
existing memory into future tasks. I keep both lines explicit even though they
default to true in 0.145.0.
I leave extract_model and consolidation_model unset. Codex can choose the
models intended for those jobs, and I have no measurement showing that an
override would improve my memories.
Defaults versus my values
| Setting | 0.145.0 default | Mine | Why I set it |
|---|---|---|---|
dedicated_tools | false | true | Expose native list, search, read, and note tools |
disable_on_external_context | false | false | Keep MCP, web, and tool-search sessions eligible |
min_rate_limit_remaining_percent | 25 | 10 | Skip fewer background passes when quota is still usable |
min_rollout_idle_hours | 6 | 6 | Keep the tagged default and accept earlier extraction |
max_rollout_age_days | 10 | 30 | Give an unprocessed task more time to enter the pipeline |
max_rollouts_per_startup | 2 | 8 | Let one startup pass claim up to eight candidates |
max_unused_days | 30 | 90 | Retain context for projects I revisit monthly |
The
tagged 0.145.0 configuration source (opens in a new tab) (відкриється в новій вкладці)
defines those defaults. The
current configuration reference (opens in a new tab) (відкриється в новій вкладці)
now says 30 days and 16 rollouts for two of the same fields, rather than
10 and 2. I treat defaults as versioned behavior and pin the values that
matter to me. If I upgrade Codex, I check the installed version and the current
reference again.
Why I changed the scheduling knobs
With my configuration, a task enters the candidate pool when it is at least six
hours idle and no more than 30 days old. max_rollouts_per_startup then limits
Codex to eight claimed candidates during that startup pass.
Suppose I finish task A at 10:00. A new root task at noon will not select it for extraction because only two hours have passed. If I start another root task at 17:00, task A is old enough to qualify. If eight newer eligible tasks are already ahead of it, a later startup can pick it up, provided it has not aged beyond 30 days.
max_rollouts_per_startup = 8 lets one background pass process up to eight prior
rollout candidates. Prompt construction is separate, so Codex does not inject all
eight transcripts into every task.
max_unused_days = 90 controls how long a Phase 1 output stays eligible after
Codex cites it. If Codex has never cited it, 0.145.0 uses the source task's last
update time. The same setting lets startup prune stale, unselected database rows.
This setting does not directly expire the generated Markdown files. I kept the
longer window because I switch between projects. I accept that it may also
preserve an old decision for longer.
The tagged memory runtime (opens in a new tab) (відкриється в новій вкладці)
contains those selection and pruning rules.
I verify the current state before relying on a memory.
A failed quota check does not block startup
min_rate_limit_remaining_percent = 10 does not reserve 10 percent of my quota.
When Codex obtains a backend rate-limit snapshot, every reported primary or
secondary window must clear the threshold before the memory pass starts. If
Codex cannot check the snapshot, 0.145.0 still allows startup to continue.
The tagged rate-limit guard (opens in a new tab) (відкриється в новій вкладці)
shows that check.
I lowered the default from 25 because I prefer to run more memory passes while
each reported rate-limit window remains above 10 percent. The setting cannot
guarantee that the same amount remains after extraction and consolidation
finish.
Tool-heavy sessions stay eligible
Most of my useful coding tasks use MCP, web search, or tool search. With
disable_on_external_context = false, those tasks can still contribute to
memory. Setting it to true marks the whole task polluted and excludes it from
memory generation. Codex does not filter only the external snippets.
The tagged external-context handling (opens in a new tab) (відкриється в новій вкладці)
shows that thread-level behavior.
I keep the global value false and use /memories for exceptions. If a task is
sensitive, noisy, or disposable, I can prevent that task from becoming memory
input without discarding every tool-heavy session.
With this setting, external tool output can influence generated memory. OpenAI says Codex redacts secrets from generated memory fields, but also warns users not to put secrets in memory and to review the local files before sharing them.
Dedicated memory tools
With the memories feature and use_memories enabled, dedicated_tools = true
adds four tools to Codex's native extension surface:
| Tool | What I use it for |
|---|---|
memories.list | Browse the local memory workspace |
memories.search | Find substring matches across memory files |
memories.read | Read the relevant file or line range |
memories.add_ad_hoc_note | Record an explicit remember, update, or forget request |
The tagged memory-tool registry (opens in a new tab) (відкриється в новій вкладці) defines all four. They are local, namespaced Codex tools, not MCP tools. I do not install a server or manage another process.
Normally I ask in plain language:
Search your memories for the Vercel deployment issue we solved,
then read the most relevant result.For an explicit update:
Remember that this repository validates MDX with bun run mdx:check.The tool description tells Codex to use this operation only after an explicit
request to remember, update, or forget something. The handler requires a
timestamp-shaped Markdown filename and refuses to overwrite an existing file. It
does not rewrite MEMORY.md in place. A later consolidation pass can incorporate
the note.
The tagged note-tool implementation (opens in a new tab) (відкриється в новій вкладці)
defines the agent-facing instruction, while the
local note backend (opens in a new tab) (відкриється в новій вкладці)
enforces new-file creation.
The 0.145.0 configuration type includes this flag, and it works in my installed
build. The public configuration reference did not list it on July 23, 2026, so I
would recheck it after an upgrade rather than treat it as a permanent contract.
Memory in my workflow
I give each kind of context one home:
| Layer | What belongs there |
|---|---|
AGENTS.md and project docs | Required commands, conventions, architecture, and review rules |
| Codex Memories | Prior decisions, useful evidence, failures, preferences, and task history |
| Skills | Repeatable workflows such as research, review, or prose editing |
| MCP, apps, and live tools | Current external state from GitHub, calendars, deployment systems, and docs |
| Fresh verification | Versions, runtime output, repository state, and other facts that can drift |
With this split, I am less likely to mistake a remembered preference for a repository rule or an old deployment result for current state.
At the start of a task, I let the injected memory summary provide broad context. If the request depends on an earlier decision, I ask Codex to search and read the supporting memory instead of guessing from the summary. During ordinary work, I do not create a note after every turn. I leave that volume to the background extractor.
I reserve explicit notes for facts an automatic summary might miss, such as a personal preference or a recurring failure. I also use one when a decision changes. Hard project requirements go into the repository instead.
Results so far
While writing this post, I used the injected memory to recover the Blog's earlier Humanizer workflow and bilingual parity rules. I then inspected the repository and found a route-specific end-to-end test that would fail when the new article became featured. I avoided reconstructing that context by hand and read the local Markdown to check the evidence behind the summary.
I still give up the fine-grained observation timeline I had with claude-mem.
Codex memory can arrive hours later, the dedicated search is substring-based, and
a 90-day consolidation window can bring back stale context. ChatGPT web memory
also remains separate, so this is not one universal memory across every OpenAI
surface.
I am not ready to claim a productivity percentage from this setup. I judge it by
whether I spend less time reconstructing decisions and whether Codex avoids
repeating failures it already solved. If old context becomes noisy, I will lower
max_unused_days to 60 before adding another memory system.
Sources
- OpenAI: Memories (opens in a new tab) (відкриється в новій вкладці)
- OpenAI: Codex configuration reference (opens in a new tab) (відкриється в новій вкладці)
-
Codex
0.145.0memory settings and defaults (opens in a new tab) (відкриється в новій вкладці) -
Codex
0.145.0memory pipeline documentation (opens in a new tab) (відкриється в новій вкладці) -
Codex
0.145.0memory runtime (opens in a new tab) (відкриється в новій вкладці) -
Codex
0.145.0consolidation implementation (opens in a new tab) (відкриється в новій вкладці) -
Codex
0.145.0rate-limit guard (opens in a new tab) (відкриється в новій вкладці) -
Codex
0.145.0external-context handling (opens in a new tab) (відкриється в новій вкладці) -
Codex
0.145.0memory-tool registry (opens in a new tab) (відкриється в новій вкладці) -
Codex
0.145.0substring-search tool (opens in a new tab) (відкриється в новій вкладці) -
Codex
0.145.0ad-hoc note tool (opens in a new tab) (відкриється в новій вкладці) -
Codex
0.145.0local note backend (opens in a new tab) (відкриється в новій вкладці) -
claude-memrepository (opens in a new tab) (відкриється в новій вкладці)