don't let the agent forget the goal.
codex exec resumes a transcript but never restates why. codex‑goal is a small wrapper that stores one objective per project outside Codex's own workspace, and hands it back as plain context on every new or resumed run — built anyway after upstream closed the request.
One line on your email: used only to reach you about codex-goal, never sold, never shared. The CLI below stays free no matter what you pick.
the matchup
Same two commands, two sessions apart. One remembers the assignment; one doesn't.
$ codex exec "migrate billing to new schema" … session ends, summarized … $ codex exec resume --last "continue" > continuing. what's the task again? (transcript survived. the point of it didn't.)
Resume brings back messages, not the objective that framed them.
$ codex_goal.py set "migrate billing to new schema" $ codex_goal.py run > [codex-goal] persisted objective: migrate billing… … session ends … $ codex_goal.py run --last > [codex-goal] persisted objective: migrate billing… (re-injected before Codex sees anything else.)
Every new or resumed run gets the same goal text, re-stated, every time.
instant replay
Real, runnable output from demo.py — a disposable project dir, a disposable $CODEX_GOAL_HOME, and a deterministic stand-in for the real codex binary (no network, no account, nothing billed). Two separate process runs see the same goal; a kill -9 mid-run doesn't touch it.
$ python3 codex_goal.py set -C $PROJECT 'Ship codex-goal's two-run persistence demo'
codex-goal: saved goal g-a2c8350ac309 for myapp-58cda05ecfff4ec2
[exit 0] goal saved
$ python3 codex_goal.py run -C $PROJECT --codex-bin tests/fake_codex.py
[exit 0] run 1 done ← fresh session, goal injected
$ python3 codex_goal.py run -C $PROJECT --last --codex-bin tests/fake_codex.py
[exit 0] run 2 done ← resumed, SAME goal injected again
$ (background run) ; kill -9 35478
[killed] simulated crash ← mid-run, hard kill
$ python3 codex_goal.py show -C $PROJECT --json
{
"current": {
"text": "Ship codex-goal's two-run persistence demo",
"goal_id": "g-a2c8350ac309"
}
}
ASSERTION PASSED: goal text identical before and after the crash.
how it scores
- 01 Goal state lives under
~/.codex-goal— outside the directory Codex's own sandbox lets it write to.setis a human command; the wrapper never calls it on Codex's behalf. - 02 Every
setis versioned: the previous goal moves to a capped history instead of being silently overwritten. - 03 Writes are atomic (temp file + rename) under an exclusive file lock — a crash mid-write can't leave torn JSON.
- 04
runnever edits the goal. It only appends one line to a separate run-log, after the child exits, with the real exit code. - 05 Codex is spawned via an argv list, never a shell string — a goal containing
; rm -rf / #is one opaque argument, not a command. - 06 Ctrl‑C / SIGTERM sent to the wrapper is forwarded to the Codex child, so cancellation behaves exactly like calling
codexdirectly. The wrapper's exit code is the child's.
game passes
Free tier works offline, forever. Paid tiers are founding-price early access — there is no checkout yet.
- Full CLI, source, tests, demo
- Unlimited local projects
- No account, no telemetry
- Hosted goal + run-log viewer
- Cross-machine goal sync
- Email digest on run failures
- Shared goals, per-teammate run history
- Slack alert when a run fails
- Audit log export
rules of the game
- 1 goal One objective per project at a time. Not a task list, not a scheduler, not a replacement for your issue tracker.
- no force The injected text is plain, visible user context — it carries no special authority inside Codex. A model can still choose to ignore it, same as any other instruction.
- no grading This only guarantees the goal is faithfully re-stated every run. It does not inspect diffs or grade progress — pair it with finishline-supervisor for that.
- plain json
$CODEX_GOAL_HOMEis ordinary local storage with your file permissions, no encryption. Don't put secrets in goal text. - local lock Locking is advisory and local-filesystem only — it doesn't coordinate over NFS/SMB or across machines.
- your flags
runforwards whatevercodex execflags you give it, including dangerous ones if you ask for them. This wrapper adds or removes none of Codex's own safety behavior.