Working Notes on Agent Systems/Brad Zhang

Project dossier

fireworks-terminal-sessions

Exact tmux session recovery for Codex, Claude Code, and Kimi Code

Python · 3 stars / 0 forks · Active Sep 24, 2026 · GitHub

What this repository answers

<p align="center"> <img src="assets/icon.png" width="160" alt="Fireworks Terminal Sessions icon: a luminous terminal and recovery loop"> </p> <h1 align="center">Fireworks Terminal Sessions</h1> <p align="center">Put each Codex, Claude Code, Kimi Code, or Pi...

README

Fireworks Terminal Sessions icon: a luminous terminal and recovery loop

Fireworks Terminal Sessions

Put each Codex, Claude Code, Kimi Code, or Pi conversation back in its named tmux window.

简体中文 · How it works · Architecture SVG · Recovery flow SVG

If you work through Codex, Claude Code, Kimi Code, or Pi, ask your agent:

Install https://github.com/yizhiyanhua-ai/fireworks-terminal-sessions as a skill and install its local CLI. Run terminal-sessions doctor, detect my tmux server name, capture the current Codex/Claude/Kimi/Pi windows, and show me the recovery plan. Do not start a new conversation or replace a running window.

For a later recovery:

My terminal windows disappeared. Use the fireworks-terminal-sessions skill to show the exact saved window-to-conversation mapping, restore only missing sessions, and tell me which ones were already running or blocked. Match each tmux name to its task. On Wave Terminal, run reopen to recreate every window in one step.

The agent should read SKILL.md and show the plan before running restore. The same commands work by hand.

Architecture diagram: live tmux panes, exact identity capture, private journal, and guarded native resume

Quick start

Requires macOS or Linux, Python 3.10+, tmux, ps, pgrep, and lsof. Install Codex, Claude Code, Kimi Code, or Pi separately for the sessions you want to recover. Automatic periodic capture currently uses macOS launchd; Linux users can run capture from their own scheduler.

git clone https://github.com/yizhiyanhua-ai/fireworks-terminal-sessions.git
cd fireworks-terminal-sessions
./install.sh
~/.local/bin/terminal-sessions doctor

To expose the instructions as an agent skill, ask your Codex or Claude Code agent to install this repository as a skill, or use a compatible Skills CLI:

npx skills add yizhiyanhua-ai/fireworks-terminal-sessions

For a regular tmux server, use --server default. For a named server started with tmux -L work, use --server work consistently:

terminal-sessions capture --server work
terminal-sessions plan --server work
terminal-sessions restore --server work
tmux -L work attach -t api-backend

If you are already inside tmux, attach from a terminal outside it, or run TMUX= tmux -L work attach -t api-backend. The CLI restores detached windows; it does not take over your current terminal.

On macOS, opt in to automatic capture every two minutes:

terminal-sessions auto-install --server work
terminal-sessions auto-status --server work

The job runs capture through the existing tmux server. This matters when the server has access to volumes or files that a newly started background process cannot read. The installer never restarts tmux or any AI CLI.

Common scenarios

Every scenario below assumes the same setup: you run coding agents — Codex, Claude Code, Kimi Code, or Pi — inside named tmux windows, one task per window, and you want each conversation back in its own window after something breaks.

1. Morning check: is everything still there?

$ terminal-sessions status
server: work
  snapshot: 2026-09-24T08:58:03+08:00 (2m ago), 6 entries
  api-backend: live
  billing-fix: live
  release-notes: live
  docs-site: live
  data-pipeline: live
  smoke-tests: live
  auto-capture: loaded
  server started: 2026-09-23 21:14:52+08:00 (pid 8120), probe: ok

One line per window: live or missing, plus snapshot age, the auto-capture job state, and a server health line. Add --server work to check one server only.

2. The terminal app crashed (or you closed the window by mistake)

You had six windows: api-backend and billing-fix running Codex, release-notes and docs-site running Claude Code, data-pipeline and smoke-tests running Kimi Code. Open a fresh terminal and look at the plan:

$ terminal-sessions plan --server work
target tmux server: work
server started: 2026-09-23 21:14:52+08:00 (pid 8120), probe: ok
  api-backend: codex 123e4567-e89b-42d3-a456-426614174000 -> ready
  billing-fix: codex 123e4567-e89b-42d3-a456-426614174002 -> ready
  release-notes: claude 123e4567-e89b-42d3-a456-426614174001 -> already-running
  docs-site: claude 123e4567-e89b-42d3-a456-426614174003 -> ready
  data-pipeline: kimi a1b2c3d4-window-two -> ready
  smoke-tests: kimi a1b2c3d4-window-six -> blocked: native session already active outside target window

(IDs above are illustrative.) ready means the exact native record was verified and the window can be relaunched. already-running means the conversation is still alive, so it is skipped. blocked means something needs your eyes first — here, the same Kimi conversation appears to be running somewhere else, so restoring it would create a duplicate.

terminal-sessions restore --server work   # launches the ready windows, skips the rest
tmux -L work attach -t api-backend        # reattach to any restored window

Running restore a second time skips everything, because each window is now either live or verified running.

If the terminal app itself died but tmux survived — the classic Wave Terminal crash — one command recreates every window:

terminal-sessions reopen --server work

reopen checks server health first (a fossil server aborts; run restore --fresh-server instead), restores any missing sessions with the exact same preflight as restore, then opens a Wave block per window through wsh run -- "$(command -v tmux)" -S <socket> attach -t <name>. The absolute tmux path matters: a freshly restarted Wave runs blocks with a minimal environment where a bare tmux is not found. Windows that already have a client attached report already-open and are skipped, so re-running it never spawns duplicates (--attach-all overrides). On other terminal emulators, reopen --print just prints the attach commands to run by hand.

reopen demo: three windows live, the tmux server is killed, reopen restores every session and reopens its window, and status shows all live again

The recording runs against an isolated demo harness with a stub CLI and stub wsh (docs/demo/reopen.tape); no real model session is involved.

3. Windows restore but fail immediately (macOS fossil server)

On macOS, a privacy-permission change (Full Disk Access granted, a removable volume remounting, and similar events) can strand the old tmux server: it still answers tmux commands, but every window it spawns loses filesystem access and fails with Operation not permitted. Restoring into it looks fine and breaks on the first write. Check before you restore:

$ terminal-sessions server-health --server work
server pid: 8120
started: 2026-09-23 21:14:52+08:00
socket: /private/tmp/tmux-501/work
probe path: /path/to/project
probe: denied
context-stale (probe write denied)

context-stale means the server is a fossil. Rebuild onto a fresh server so restored windows inherit the current security context:

terminal-sessions restore --fresh-server --server work

This kills the old tmux server first, so it lists any sessions still at risk and refuses; review the list and add --force only when you accept that. If server-health reports healthy, a plain restore is enough.

4. One window shows unresolved

When an ID cannot be observed automatically, the window is marked unresolved instead of guessed. Check the CLI's own session list (codex resume picker, claude --resume, or the Kimi session list inside that project), then bind the exact ID:

terminal-sessions bind --server work --name release-notes \
  --tool claude --session-id 123e4567-e89b-42d3-a456-426614174001 \
  --cwd /path/to/project
terminal-sessions plan --server work

5. Housekeeping: one window only, and stale sockets

terminal-sessions restore --server work --only api-backend   # recover a single window
terminal-sessions forget --server work --name api-backend    # retire a mapping; history stays
terminal-sessions clean                                      # list dead tmux sockets (dry run)
terminal-sessions clean --apply                              # actually remove them

What recovery verifies

CLI Capture evidence Before resume Post-launch evidence
Codex Open rollout file or exact CLI argument Rollout metadata contains the saved ID Matching process and open rollout
Claude Code Open project transcript or exact CLI argument Saved transcript exists Matching CLI process / ID when observable
Kimi Code Exact CLI argument, or a manually verified binding Native session list matches ID and workspace Matching CLI process / ID when observable
Pi Single session file matching the process working directory (exact match), or a manually verified binding Session file header contains the saved ID and working directory Matching CLI process

Pi rewrites its process command line and never holds its session file open, so capture can only match a session file by its recorded working directory — a directory with several Pi conversations stays unresolved and needs an explicit bind.

Codex capture and exact resume have been exercised with a real tmux integration canary using a stub CLI. Claude, Kimi, and Pi command syntax and native-store checks are implemented, but an end-to-end real-provider recovery has not been verified for this release. The tool never sends a model prompt to prove recovery. If the native identity cannot be established, it stops instead of guessing from “most recent”.

Principles and limits

  • The journal holds window name, CLI, exact native ID, working directory, source path, and capture time. It does not copy prompts, transcripts, terminal output, or credentials. It is local, append-only, and owner-readable (0600); the state directory is 0700.
  • capture retains the last verified mapping if a window vanishes. plan checks native records, cwd, executable, tmux name occupancy, and possible duplicate live processes. A blocker prevents that restore batch from launching. Each ready item is checked again immediately before launch.
  • Recovery is per named tmux server. FTS_STATE_DIR chooses a private state directory; FTS_TMUX_SERVER changes the default server. macOS state defaults to ~/Library/Application Support/fireworks-terminal-sessions; Linux uses $XDG_STATE_HOME/fireworks-terminal-sessions or ~/.local/state/fireworks-terminal-sessions.
  • There is no cloud account, daemon, model call, transcript parser, or automatic deletion. It cannot recover a provider conversation if that provider's native session record is gone.

See how it works for the detection and restore algorithm, security for the local data boundary, and contributing for development.

Recovery flow: observe, resolve, preserve, preflight, then branch to already running, blocked, or ready

MIT licensed. Icon and diagrams are included in the repository.