Cross-platform launcher and crash recovery for Codex sessions. csg run supervises a Codex-compatible launcher, records its Session ID, and keeps a recoverable record when the terminal, process tree, or computer stops unexpectedly.
CSG is opt-in. Running codex or spine-codex directly does not install a wrapper, create a record, or change how that command resolves.
- Explicit monitoring through
csg runonly - Live status listing plus Session ID based recovery and deletion
- Windows Job Objects for CMD/BAT and descendant process supervision
- Linux and macOS process-group supervision with one foreground supervisor per session
- Crash-safe run records with PID and process-start identity checks
- Launcher-agnostic recovery: the original launcher is used again
- Transactional install, upgrade, rollback, and ownership-checked uninstall
- Windows, Linux, and macOS CI coverage
pwsh ./scripts/install.ps1
csg doctorsh ./scripts/install.sh
csg doctorThe installers place csg and codex-session-guard in ~/.local/bin (or %USERPROFILE%\.local\bin on Windows). They do not replace the user's codex command.
Start a monitored session with the launcher you normally use:
csg run spine-codex.cmd
csg run imba_codex --profile work
csg run .\tools\foo-codex.cmd --model fastOn Linux or macOS:
csg run spine-codex --profile work
csg run ./tools/foo-codex.shInspect every session currently tracked by CSG:
csg list
The list reports four states:
| Status | Meaning |
|---|---|
RUNNING |
The monitored session is active. A pending (waiting for first turn) Session value means the launcher has not supplied a Session ID yet. A prebound; waiting for Hook confirmation value means CSG already knows an explicit resume UUID and is waiting for the Hook to confirm it. |
UNKNOWN |
Process liveness could not be verified safely; the session is not treated as recoverable. |
CRASHED |
The monitored process tree stopped unexpectedly and the session can be resumed. |
Sessions that exit normally or through a user interrupt are removed instead of being retained as history. To resume a crashed session:
csg resume <SESSION_ID>
To discard a recovery record:
csg delete <SESSION_ID>
resume and delete accept a complete Session ID only. They do not accept list positions or --all. Deleting a record removes CSG metadata only; Codex transcripts and session history are untouched.
Other commands:
csg doctor
csg version
csg help
The first launcher's extra arguments are used only for that launch. They are not stored or replayed during recovery, which avoids persisting prompts or secrets. Recovery returns to the recorded working directory and invokes the original launcher with resume <SESSION_ID>.
csg runwrites a run record before starting the requested launcher and passes a random run ID through the environment.- The Codex
SessionStartHook binds the exact Session ID, transcript path, working directory, and source to that record. - The supervisor waits for the complete process tree, including a script that exits before its child Codex process.
- A normal exit or user interrupt removes the record. An abrupt stop leaves it on disk for the next
csg list. csg listchecks PID plus process-start identity and reports active and crashed sessions without mistaking a reused PID for the old process.csg resumeatomically claims the record, pre-binds the known UUID before starting the original launcher, and lets the new Hook confirm it and enrich the record.
Session records are written atomically before the target starts. This lets a reboot or power interruption leave a recoverable record without requiring a background service. Explicit resume <SESSION_ID> arguments are pre-bound before launch, so a resumed session does not need a first user turn before it can be recovered again. New sessions and name-based resume still wait for the SessionStart Hook to provide the resolved UUID.
The target launcher must preserve the CSG run ID environment variable, pass through the Hook-related arguments, and support resume <SESSION_ID>. CSG recognizes only a valid UUID after the structured resume command for pre-binding; it never treats a session name as an ID. CSG does not parse the internals of CMD, BAT, or shell scripts.
Windows CMD/BAT launchers cannot receive arguments containing newlines through the Windows command-line syntax. Use a native executable when multiline arguments are required.
Processes deliberately moved to an external service, scheduled task, or escaped process group are outside the supervision boundary. Records are platform-specific and are not automatically executable after being copied to another operating system.
On Unix, if the CSG supervisor alone is forcibly killed while the target process group remains healthy, the group may continue running because no separate daemon is retained to kill it. Terminal close and computer failure remain covered by the process group and durable run record; Windows Job Object supervision still terminates the tree when the supervisor disappears.
State directories:
- Windows:
%LOCALAPPDATA%\CodexSessionGuard - macOS:
~/Library/Application Support/CodexSessionGuard - Linux:
$XDG_STATE_HOME/codex-session-guard, or~/.local/state/codex-session-guard
The installer updates only the CSG-managed SessionStart and SessionEnd Hook entries and their trust records. Existing user hooks, Codex settings, backups, and PATH entries are preserved. Upgrading from an older CSG version removes legacy codex wrappers only when the recorded installation hash proves CSG ownership.
Prerequisite: Go 1.22 or newer.
Run the unit tests and static checks from the repository root:
go test ./...
go test -race ./...
go vet ./...Build and run the isolated integration suite:
pwsh ./scripts/build.ps1
pwsh ./scripts/test-integration.ps1sh ./scripts/build.sh
sh ./scripts/test-integration.shThe GitHub Actions matrix runs native tests on Windows, Ubuntu, and macOS. Build artifacts are written to dist/ and are intentionally ignored by Git.
cmd/csg/ Go application, platform backends, and tests
scripts/ Build, install, uninstall, and integration entry points
testdata/ Small launcher fixtures used by integration tests
.github/ Continuous integration workflow
Windows:
pwsh ./scripts/uninstall.ps1Linux and macOS:
sh ./scripts/uninstall.shUninstall removes only CSG-owned binaries, hooks, and trust records. It preserves the user's codex command, PATH entries, recovery records, and installation backups.