In this article

🧭 What a Codex session is and where it lives

A session in Codex CLI is the complete record of a conversation: my prompts, the model's replies, tool calls and their results. As I work, the CLI keeps writing it to a JSONL file under ~/.codex/sessions/. Saving is always on: there is no save command, because none is needed.

The important detail is that resuming is anchored to the working directory: by default codex resume considers the sessions started from the current folder. Each project therefore has its own history, and when I resume the latest session I get the one from this repo, not the last thing I did somewhere else.

There are three entry points: codex resume from the terminal, /resume from inside an already open session, and codex exec resume for non-interactive runs. I use all of them, at different moments of the day.

The ways to pick a session back up
# reopens the latest session of the current folder
codex resume --last

# opens the interactive session picker
codex resume

# resumes a session by name or by ID
codex resume auth-refactor

# from inside an active session: switch conversation
/resume

Official docs Β· Codex CLI reference β†—

The CLI entry points: from the terminal, from inside a session, or in scripts.

πŸ” --last, the picker, and resuming by name: how I choose

codex resume --last is the daily gesture: it reopens the most recent session of the folder I am in, with no IDs to remember and no questions asked. It is the equivalent of Claude Code's --continue, and for single-thread work it covers 90% of the cases.

When the latest session is not the right one, I run codex resume with no arguments and the picker opens: a list of recent sessions with date and preview, which I navigate with the arrow keys and confirm with Enter. By default I see the sessions of the current directory; with --all I widen the search to those started from any folder.

The third way is direct resumption: codex resume <id-or-name> accepts both the session ID (a UUID) and the session's name, and if the argument parses as a UUID, the ID wins. The name is also what I use with codex archive, codex unarchive and codex delete to keep the list tidy: finished sessions get archived, useless ones deleted.

How I find an old session with the picker
  1. 01
    Open the pickercodex resume with no arguments, or /resume from inside an active session.
  2. 02
    Widen if neededBy default I see the current folder; --all includes sessions from any directory.
  3. 03
    Pick from the listEach row shows the date and a transcript preview: I move with the arrow keys.
  4. 04
    Resume with EnterThe session reopens with its full history; new replies are appended there.

Source: official Codex CLI documentation β€” developer commands.

πŸ“‚ Different folder? The role of tui.resume_cwd

A case that happens often: I resume a session from a directory different from the one it started in. Codex notices and asks me which folder to use β€” the current one or the one saved in the session. It is a sensible question, because the folder determines what the sandbox is allowed to write.

If the answer is always the same, I pin it in config.toml with tui.resume_cwd: "current" to always use the directory I launch from, "session" to always go back to the original one. An explicit --cd (or -C) on the command line still wins over the configuration.

A handy detail: codex resume accepts the same global flags as codex, so I can resume a session while changing model or sandbox on the fly β€” for instance reopening in read-only a session that started in workspace-write, just to ask it questions.

Pinning the behaviour in config.toml
# ~/.codex/config.toml

[tui]
# "current"  β†’ use the directory I launch codex resume from
# "session"  β†’ go back to the session's original directory
resume_cwd = "current"
The folder choice is configured once; the -C flag overrides it when needed.

🌿 codex fork and /side: experimenting without losing the thread

When I am at a good point and want to try a different route β€” another library, a more aggressive approach β€” I do not sacrifice the conversation that got me there: I use codex fork, which duplicates a previous session into a new thread while leaving the original transcript intact. From inside an active session I do the same with /fork.

For short detours there is /side: it opens a throwaway side conversation without leaving the main task. I use it for sanity checks β€” "does this approach have an obvious problem?" β€” before returning to the main thread, without polluting the session's context.

The distinction to keep in mind is the same as with any tool of this kind: the fork duplicates the conversation, not the files. Code changes made in a branch are real and shared by any session working in the same folder: for files, the restore point remains Git.

resume or fork: how I choose

codex resume

  • Continues the same session: replies are appended
  • The daily gesture with --last, or from the picker
  • Also resumes by name or by session ID
  • With --all it reaches sessions from other folders

codex fork

  • Duplicates the session into a new thread and diverges
  • The original stays intact in the picker
  • For experiments I might want to throw away
  • From inside the session: /fork, or /side for detours

πŸ€– exec resume: picking up non-interactive runs too

The part I use most in scripts is codex exec resume: the non-interactive mode has its own dedicated resumption, with the same logic as the TUI. codex exec resume --last re-attaches the most recent run of the current folder, codex exec resume <session-id> a specific one, and in both cases I can pass the follow-up prompt right away.

It is the piece that makes codex exec incremental: the first run builds the context β€” it understands the repo, does the heavy lifting β€” and the following ones reuse it instead of starting from scratch. In a pipeline, each step picks up the previous step's context by passing the same session.

With --json I get JSONL events line by line, easy to process in scripts; --all widens the search for the most recent run to every directory. These are the same building blocks I use for overnight automations: one long run in the evening, targeted follow-ups in the morning.

Resuming a non-interactive run
# first run: builds the context
codex exec "analyse the repo and propose a refactor plan"

# follow-up on the same context, no restart
codex exec resume --last "apply step 1 of the plan"

# targeted resumption by session ID, with JSONL output
codex exec resume <session-id> --json "update the tests"
The dedicated resumption of codex exec: same session, context already built.

⚠️ The limits worth knowing: transcript, not model state

Resuming rebuilds the context by re-reading the transcript, not by restoring the model's internal state. For long sessions this means two things: reopening takes a moment, and a very long transcript can get close to the context limits before the whole history is reloaded. After resuming a task interrupted midway, two lines from me β€” "we were at X, the current state is Y" β€” reorient the model faster than letting it infer everything from the log.

Watch out for commands that look harmless too: /clear does not clean the screen, it starts a new conversation; to clear the view while keeping the context you use Ctrl+L. Mixing them up means ending up in a blank session without meaning to β€” recoverable via the picker, but it is an extra trip.

Finally, persistence covers the conversation, not the project's rules. Conventions, architectural decisions and constraints every session must know belong in AGENTS.md, which Codex reads at every start: the session is for "continue what I was doing", the project file is for "understand this project".

βœ… The flow I follow to never lose work

Put together, these commands become a single habit: I never close a piece of work hoping to remember it, I leave it in a session I know how to find again. The mini-flow I follow, in order:

  • I resume with *--last* for daily single-thread work, and switch to the picker only when there is more than one thread.
  • I fork before taking risks: a codex fork costs nothing and saves the good route if the experiment does not hold up.
  • I use /side for detours: sanity-check questions must not pollute the main task's context.
  • In scripts I chain runs with codex exec resume --last, so each step reuses the previous step's context.
  • I archive and delete with codex archive and codex delete: a short picker is a useful picker.

Frequently asked questions about codex resume

What is the difference between codex resume and codex fork?

codex resume continues the same session: new replies are appended to the existing transcript. codex fork duplicates the session into a new thread and diverges, leaving the original intact. I resume to carry on a piece of work, I fork to experiment down a route I might want to throw away.

Where are Codex CLI sessions stored?

In ~/.codex/sessions/, one JSONL file per session with prompts, replies and tool calls. Saving is always on: there is no save command. The format is internal to the CLI and can change between versions, so to extract content it is better to process it with tools like jq rather than rely on its structure.

Can I resume a session started from another folder?

Yes: codex resume --all includes sessions from any directory in the picker. If the current folder differs from the saved one, Codex asks which to use; the answer can be pinned in config.toml with tui.resume_cwd = "current" or "session", and an explicit -C on the command line wins over everything.

How do I resume a codex exec run in scripts?

With the dedicated resumption: codex exec resume --last "prompt" re-attaches the folder's most recent run, codex exec resume <session-id> a specific one. Each follow-up reuses the context already built instead of starting over, and with --json I get JSONL events that are easy to process in pipelines.

Does resume restore exactly the state I left the model in?

No: it restores the transcript, and the model rebuilds the context by re-reading it. The conversation is all there, but the internal working state has to be inferred from the history β€” which is why after a resume it pays to reorient it with a line like "we were at X, the current state is Y", especially on long sessions.

Let's talk

If this topic is relevant to you, write to me: comparing notes on code and AI is always time well spent.

All articles