{"id":50904172,"url":"https://github.com/dgl1231/relay-baton","last_synced_at":"2026-06-16T06:00:27.068Z","repository":{"id":360724236,"uuid":"1250927882","full_name":"dgl1231/relay-baton","owner":"dgl1231","description":"Transfer coding sessions between Codex CLI and Claude Code without losing context.","archived":false,"fork":false,"pushed_at":"2026-06-09T15:22:11.000Z","size":470,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-09T16:26:45.801Z","etag":null,"topics":["agentic","ai","ai-agents","ai-coding","claude","claude-code","codex","context-engineering","developer-tools","llm","orchestration","terminal-tools","token","token-diet"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dgl1231.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-27T05:00:42.000Z","updated_at":"2026-06-09T15:29:52.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dgl1231/relay-baton","commit_stats":null,"previous_names":["dgl1231/relay-baton"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/dgl1231/relay-baton","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgl1231%2Frelay-baton","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgl1231%2Frelay-baton/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgl1231%2Frelay-baton/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgl1231%2Frelay-baton/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dgl1231","download_url":"https://codeload.github.com/dgl1231/relay-baton/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgl1231%2Frelay-baton/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34393302,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-16T02:00:06.860Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentic","ai","ai-agents","ai-coding","claude","claude-code","codex","context-engineering","developer-tools","llm","orchestration","terminal-tools","token","token-diet"],"created_at":"2026-06-16T06:00:17.163Z","updated_at":"2026-06-16T06:00:27.057Z","avatar_url":"https://github.com/dgl1231.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# relay-baton\n\n**Portable continuation infrastructure for coding agents.**\n\nPass compressed coding state between Codex CLI, Claude Code, and whatever ships next — without re-pasting the chat log, the diff, or the repo.\n\n[![Node](https://img.shields.io/badge/node-%E2%89%A520-339933?logo=node.js\u0026logoColor=white)](https://nodejs.org)\n[![pnpm](https://img.shields.io/badge/pnpm-%E2%89%A59-F69220?logo=pnpm\u0026logoColor=white)](https://pnpm.io)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5-3178C6?logo=typescript\u0026logoColor=white)](https://www.typescriptlang.org/)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](#license)\n[![Latest](https://img.shields.io/badge/release-v2.1.0--alpha.2-blue.svg)](./release-notes/v2.1.0-alpha.2.md)\n[![Download](https://img.shields.io/badge/download-binaries-238636.svg)](https://github.com/dgl1231/relay-baton/releases/latest)\n\n**English**\n · [한국어](./docs/i18n/README.ko.md)\n · [日本語](./docs/i18n/README.ja.md)\n · [简体中文](./docs/i18n/README.zh-CN.md)\n · [繁體中文](./docs/i18n/README.zh-TW.md)\n · [Español](./docs/i18n/README.es.md)\n · [Français](./docs/i18n/README.fr.md)\n · [Deutsch](./docs/i18n/README.de.md)\n · [Português](./docs/i18n/README.pt-BR.md)\n · [Русский](./docs/i18n/README.ru.md)\n\n\u003c/div\u003e\n\n```bash\n# Codex hits a quota wall mid-task. relay-baton notices, builds a compact\n# handoff from the repository's actual state, and resumes the work in Claude.\n$ relay-baton run \"refactor the upload pipeline\" --diet caveman\n[relay-baton] codex: ... rate limit exceeded ...\n[relay-baton] fallback pattern detected: rate limit exceeded\n[relay-baton] building handoff for claude...\n[relay-baton] claude resumed from .ai-session/handoff.md\n```\n\n---\n\n## Download\n\nPrebuilt, single-file executables are attached to every release — no Node install required to run them.\n\nOne-line CLI install (verifies `SHA256SUMS`, no admin required):\n\n```bash\n# macOS / Linux\ncurl -fsSL https://raw.githubusercontent.com/dgl1231/relay-baton/main/install/install.sh | sh\n```\n\n```powershell\n# Windows PowerShell\niwr https://raw.githubusercontent.com/dgl1231/relay-baton/main/install/install.ps1 -UseB | iex\n```\n\n| OS | Binary | Get it |\n| --- | --- | --- |\n| macOS (Apple Silicon) | `relay-baton-macos-arm64` | [Latest release](https://github.com/dgl1231/relay-baton/releases/latest) |\n| Linux (x64) | `relay-baton-linux-x64` | [Latest release](https://github.com/dgl1231/relay-baton/releases/latest) |\n| Windows (x64) | `relay-baton-windows-x64.exe` | [Latest release](https://github.com/dgl1231/relay-baton/releases/latest) |\n\n```bash\n# macOS / Linux\nchmod +x relay-baton-macos-arm64\n./relay-baton-macos-arm64 --version\n```\n\n```powershell\n# Windows\n.\\relay-baton-windows-x64.exe --version\n```\n\n**Desktop app** (Tauri shell over the same CLI — see [`desktop/`](./desktop)):\n\n| OS | Installer | Get it |\n| --- | --- | --- |\n| macOS (Apple Silicon) | `relay-baton_…_aarch64.dmg` | [Latest release](https://github.com/dgl1231/relay-baton/releases/latest) |\n| Linux (x64) | `relay-baton_…_amd64.AppImage` | [Latest release](https://github.com/dgl1231/relay-baton/releases/latest) |\n| Windows (x64) | `relay-baton_…_x64_en-US.msi` | [Latest release](https://github.com/dgl1231/relay-baton/releases/latest) |\n\n\u003e Desktop installers are signed/notarized only when release signing secrets are\n\u003e configured. Unsigned fallback builds still ship, so expect Gatekeeper /\n\u003e SmartScreen prompts on unsigned releases. `SHA256SUMS` is attached to new\n\u003e releases for CLI installer verification.\n\u003e Desktop update checks are opt-in and manual. Signed updater artifacts and\n\u003e `latest.json` are published only when Tauri updater signing secrets are\n\u003e configured for a release.\n\u003e\n\u003e Older versions: pick any tag on the [releases page](https://github.com/dgl1231/relay-baton/releases). Prefer to build from source instead? See [Install](#install) below.\n\n## Why this exists\n\nAI coding work is fragmenting across tools. A real session looks like this:\n\n- Codex CLI for one batch of edits.\n- Claude Code for another.\n- A laptop in the morning, a different machine in the evening.\n- A context window that fills up, falls over, or quietly truncates.\n\nThe default way to move work between agents today is **copy-paste the chat log** — or worse, the whole repo dumped into a prompt. That approach has three problems:\n\n1. **Tokens.** Chat logs are mostly noise. You pay for that noise every turn.\n2. **Continuity.** The next agent doesn't get *intent*; it gets transcripts.\n3. **Fragility.** One missed file, one stale diff, and the agent restarts from a wrong premise.\n\nrelay-baton is a **local harness** that sits underneath the agents and carries the *minimum sufficient state* across the handoff: a compact summary, a repo map, and file references — not a transcript.\n\n\u003e **Spend as few tokens as possible while merging Codex CLI and Claude Code CLI into a single workflow.**\n\u003e\n\u003e When one agent hits a quota / context limit, the next one resumes from the exact repository state — without re-pasting the whole log, diff, or repo.\n\n## The idea\n\n```\n┌─────────┐   ┌──────────────┐   ┌──────────────┐   ┌────────┐\n│ Codex   │ → │ Fallback     │ → │ Token Diet   │ → │ Claude │\n│ exec    │   │ Detector     │   │ Handoff      │   │ Code   │\n└─────────┘   └──────────────┘   └──────────────┘   └────────┘\n                        ↓                ↓\n                  .ai-session/handoff.md, compact-state.md,\n                  repo-map.md, full-diff.patch, commands.log\n```\n\nA baton-pass for coding agents:\n\n- **Detect** when the current agent stops being useful (quota, context, rate, errors).\n- **Capture** what matters — repo state, changed files, decisions, next step.\n- **Compact** it under a budget the next agent can actually consume.\n- **Hand off** with quality gates so the receiver isn't fed broken context.\n\nThe handoff is a small file (`.ai-session/handoff.md`) plus references. Everything heavy — the full diff, the full log, the full repo map — stays on disk and is loaded on demand.\n\n## Workflow\n\n```bash\n$ relay-baton init                  # create .ai-session/ in the current repo\n$ relay-baton doctor                # check git, codex, claude, env, config\n\n$ relay-baton run \"fix flaky upload test\" --diet balanced\n[relay-baton] running codex exec --sandbox workspace-write \"fix flaky upload test\"\n... codex output streams here ...\n[relay-baton] fallback pattern detected: maximum context length\n[relay-baton] building handoff for claude...\n[relay-baton] HandoffQualityGate: ok\n[relay-baton] TokenDietQualityGate: ok\n[relay-baton] running claude --permission-mode acceptEdits -p \"\u003ccontinuation\u003e\"\n... claude resumes, edits files, finishes ...\n\n$ relay-baton status                # what state is the session in?\n$ relay-baton budget                # how much of the diet budget did we use?\n```\n\nManual handoff, no auto-fallback:\n\n```bash\n$ relay-baton handoff --to claude --no-run --diet caveman\n```\n\nAcross multiple repos:\n\n```bash\n$ relay-baton project add /path/to/repo-a --diet caveman\n$ relay-baton project add /path/to/repo-b --diet balanced\n$ relay-baton project switch repo-b\n$ relay-baton run \"wire up the new metrics endpoint\"\n```\n\n### Plan-execute mode\n\nA proactive alternative to reactive fallback: have a planner write a structured\nplan, gate it for completeness, then have an executor implement it.\n\n```bash\n# 1) Planner (default: Claude) writes .ai-session/plan.md, gated by PlanQualityGate.\n$ relay-baton plan \"add rate limiting to the upload endpoint\" --with claude\n\n# 2) Inspect / edit the plan if you want.\n$ cat .ai-session/plan.md\n\n# 3) Executor (default: Codex) implements the plan.\n$ relay-baton execute --with codex\n\n# Or do both in one shot once the plan passes its gate:\n$ relay-baton plan \"add rate limiting\" --then-execute\n\n# Scaffold an empty plan template without launching an agent:\n$ relay-baton plan \"explore options\" --no-run\n```\n\n### Context-compression mode\n\nDeterministic mid-session compaction of `state.md` / `commands.log` so an agent\nruns longer before hitting a context wall. No model call, fully reversible\n(raw artifacts are rotated to `commands.log.full.\u003cts\u003e`).\n\n```bash\n# See what would change without writing anything.\n$ relay-baton compress-context --dry-run\n\n# Compress when weight/budget exceeds the threshold (default 0.8).\n$ relay-baton compress-context --threshold 0.8\n\n# Force compression regardless of threshold.\n$ relay-baton compress-context --force\n```\n\n### Verify the harness (no model calls)\n\n```bash\n# Simulated end-to-end check: resolution, fallback detection, handoff no-run,\n# token budget, API-key env block. Exits non-zero on failure.\n$ relay-baton verify\n\n# Extended environment diagnostics (OK/WARN/FAIL checklist).\n$ relay-baton doctor --deep\n```\n\nNeither `verify` nor `doctor --deep` makes any network or model call, and\n`verify` writes nothing into your repo (it uses a throwaway temp dir).\n\n## Quick start\n\n```bash\n# 1) Install \u0026 build\npnpm install\npnpm build\n\n# 2) Log in to both CLIs in one go\npnpm relay-baton login\n\n# 3) Sanity check\npnpm relay-baton doctor\n\n# 4) Start a task on Codex; auto-handoff to Claude on quota/context limit\npnpm relay-baton run \"Fix the mail attachment upload flow\" --diet balanced\n```\n\n\u003e `pnpm relay-baton` is an alias for `node packages/cli/dist/index.js`. For a global binary, link it with `pnpm -F @relay-baton/cli link --global` (optional).\n\n### One-line install via an agent\n\n[`install/install.md`](./install/install.md) is both a human install guide **and an instruction surface that coding agents can execute as-is**:\n\n```bash\n# Codex CLI\ncodex exec --sandbox workspace-write \"Read https://github.com/dgl1231/relay-baton/blob/main/install/install.md and install relay-baton on this machine. Do not print or store API keys. Finish by running 'pnpm relay-baton doctor'.\"\n\n# Claude Code (headless)\nclaude --permission-mode acceptEdits -p \"Read https://github.com/dgl1231/relay-baton/blob/main/install/install.md and follow it step by step. Do not print or store API keys. End by running 'pnpm relay-baton doctor'.\"\n```\n\n## Features\n\n- **Automatic fallback.** Detects `quota exceeded`, `rate limit exceeded`, `maximum context length` and similar in agent output and hands off to the fallback agent. False-positive guards skip grep results and prose about the patterns themselves.\n- **Token diet.** Five deterministic compaction profiles (`off · lite · balanced · caveman · ultra`). Lock files, build output, minified bundles, and binary blobs are excluded; logs are tailed; repo maps replace source.\n- **Plan-execute mode.** A proactive alternative to reactive fallback: a planner agent (default Claude) writes a structured `.ai-session/plan.md`, gated for completeness, then an executor agent (default Codex) implements it. `relay-baton plan \"\u003ctask\u003e\" --then-execute`.\n- **Context compression.** Proactive, deterministic mid-session compression of `state.md` / `commands.log` so an agent runs longer before hitting a context wall. `relay-baton compress-context`, plus an auto-pass inside `run`.\n- **Quality gates.** A handoff is *verified* before the fallback agent is launched — required sections present, budget respected, no inlined manifests.\n- **Auth-safe by default.** `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` are stripped from child processes. Opt-in only via `--allow-api-key-env`. No keys are ever stored, printed, or logged.\n- **Project registry.** Register multiple repos once, switch the active project, run commands against any of them with `--project` or `--path`.\n- **Ink TUI.** Project / session dashboard with diet cycling, budget refresh, and no-run handoff generation. Never launches agents.\n- **No API of its own.** relay-baton never calls the OpenAI / Anthropic API directly. It only spawns the local `codex` / `claude` CLIs as subprocesses.\n\n## Architecture\n\n```\npackages/\n  shared/    # types, constants\n  core/      # UI-independent business logic\n    agents/        # AgentAdapter, CodexAdapter, ClaudeCodeAdapter, FallbackDetector\n    git/           # GitService, RepoMapGenerator\n    session/       # SessionManager (.ai-session/ lifecycle)\n    token-diet/    # BudgetManager, DiffCompactor, LogCompactor, HandoffCompactor, ...\n    handoff/       # HandoffGenerator, HandoffQualityGate, TokenDietQualityGate, PromptBuilder\n    workflow/      # BatonWorkflow — the orchestration\n    projects/      # ProjectRegistry, ProjectManager, ProjectResolver\n  cli/       # commander entrypoints — thin shells over core\n  tui/       # Ink dashboard — read-only over core\n```\n\nDesign rules:\n\n- `core` knows nothing about UI.\n- `cli` and `tui` hold no business logic — they wire user input to `core`.\n- Each agent is an `AgentAdapter`. Adding `opencode`, `gemini`, `aider` means adding an adapter, not patching `core`.\n- Everything written to disk lives under `.ai-session/`. relay-baton never edits your source files.\n\n## Usage\n\nSingle-repository flow:\n\n```bash\nrelay-baton init\nrelay-baton doctor\nrelay-baton run \"Fix the failing upload flow\" --diet balanced\nrelay-baton status\nrelay-baton budget\n```\n\nGenerate a handoff without launching the next agent:\n\n```bash\nrelay-baton handoff --to claude --no-run --diet caveman\n```\n\nRegister and use a project:\n\n```bash\nrelay-baton project add /path/to/relay-baton --name relay-baton --diet caveman --primary codex --fallback claude\nrelay-baton project list\nrelay-baton project switch relay-baton\nrelay-baton status --project relay-baton\nrelay-baton handoff --to claude --no-run --project relay-baton --diet caveman\n```\n\nDirect path without registering:\n\n```bash\nrelay-baton status --path /path/to/repo\nrelay-baton budget --path /path/to/repo\n```\n\nOpen the TUI dashboard:\n\n```bash\nrelay-baton tui --project relay-baton\n```\n\n## Commands\n\n| Command | Description |\n|---|---|\n| `relay-baton init` | Create `.ai-session/` in the current repo |\n| `relay-baton doctor` | Check git / codex / claude / env / config (`--deep` for extended diagnostics) |\n| `relay-baton verify` | Simulated end-to-end check — no real model calls (`--diet`, `--verbose`, `--keep-temp`) |\n| `relay-baton login [agent]` | Run Codex / Claude auth flows (`codex` / `claude` / `all`) |\n| `relay-baton run \"\u003ctask\u003e\"` | Run primary agent, detect fallback, hand off |\n| `relay-baton handoff --to claude` | Manual handoff (`--diet`, `--no-run`, `--force`) |\n| `relay-baton handoff history` | List the current + backed-up handoff documents (metadata only) |\n| `relay-baton plan \"\u003ctask\u003e\"` | Plan-execute mode: planner writes `plan.md` (`--with`, `--no-run`, `--then-execute`) |\n| `relay-baton execute` | Plan-execute mode: executor implements `plan.md` (`--with`, `--from`) |\n| `relay-baton review` | Deterministically review the diff against `plan.md` Steps — no model call (`--json`) |\n| `relay-baton receipt done/skip/list` | Append-only execution receipts for plan steps (`--note`, `--json`) |\n| `relay-baton compact` / `squeeze` | Rebuild compact-state, repo-map, full-diff |\n| `relay-baton compress-context` | Compress running state.md / commands.log when over budget (`--dry-run`, `--threshold`) |\n| `relay-baton budget` | Show context-budget usage |\n| `relay-baton compress \u003cfile\u003e` | Deterministically compress a markdown file |\n| `relay-baton status` | Print session status |\n| `relay-baton project add \u003cpath\u003e` | Register a project directory |\n| `relay-baton project list` / `current` / `doctor` | Inspect registered projects |\n| `relay-baton project switch \u003cname-or-id\u003e` | Change the active project |\n| `relay-baton project remove \u003cname-or-id\u003e` | Unregister a project |\n| `relay-baton tui` | Launch the Ink dashboard (display-only; never spawns agents) |\n| `relay-baton chat` / `room` | Agent Room: turn-based, confirmation-first multi-agent REPL (v0.9: `/continue --max-steps N`, `/replan`, `/replay`) |\n| `relay-baton replay` | Replay the recorded conversation timeline — read-only, no model call (`--json`, `--session`, `--kind`, `--limit`) |\n\nProject-aware commands accept `--project \u003cname-or-id\u003e` and `--path \u003crepoPath\u003e`.\n\nResolution priority: `--path` \u003e `--project` \u003e active project \u003e current working directory. `compress \u003cfile\u003e` stays cwd-based — it's a file-level utility.\n\n## Project registry\n\nProjects are stored at `~/.relay-baton/projects.json`. Set `RELAY_BATON_PROJECTS_FILE` to use a different path (CI, sandboxing, tests).\n\n```bash\nrelay-baton project add /path/to/relay-baton --name relay-baton --diet caveman --primary codex --fallback claude\nrelay-baton project list\nrelay-baton project switch relay-baton\n```\n\n`project add` requires the path to exist and be a directory. It may be a plain, non-git project folder; git-backed commands such as `run` and `handoff` still require a git repository when executed. Duplicate paths are not added twice. A corrupt `projects.json` is backed up to `projects.json.corrupt-\u003ctimestamp\u003e.bak` and reset to an empty registry — commands keep working. Read-only commands (`status`, `budget`, `doctor`) do not write the registry; only `run` and `handoff` update `lastUsedAt`.\n\n## Handoff flow\n\n1. `relay-baton run \"...\"` spawns the primary CLI as a subprocess.\n2. stdout / stderr stream live and append to `.ai-session/commands.log`.\n3. Output is scanned for fallback phrases. Grep-style result lines and prose explaining the patterns are skipped to avoid false positives.\n4. On fallback, relay-baton collects git state, builds a repo map, compacts the state, and writes the handoff document.\n5. **HandoffQualityGate + TokenDietQualityGate** run *before* the fallback agent launches.\n6. The fallback agent resumes from `.ai-session/handoff.md` and the referenced files.\n\n## Token diet\n\nPrinciples:\n\n- Don't paste the whole thing.\n- Prefer **log tail + known errors** over raw logs.\n- Prefer **repo map** over full source.\n- Prefer **focused diff** (lock / build / `*.min.js` excluded) over full diff.\n- Delegate large content to file references.\n\n### Profiles\n\n| Profile | Intent | Notes |\n|---|---|---|\n| `off` | Minimal truncation | Mostly pass-through |\n| `lite` | Light cleanup | Strip blank lines, duplicate instructions |\n| `balanced` *(default)* | Day-to-day | Compact state + diff summary + log tail + repo map |\n| `caveman` | Aggressive minimal | Short direct bullets; no full diff/log inline |\n| `ultra` | Extreme | Almost everything via reference |\n\n\u003e `caveman` is **not a silly tone** — it means *aggressive minimal-context*. Technical accuracy is preserved.\n\n## `.ai-session/` files\n\n| File | Role |\n|---|---|\n| `task.md` | The user's task |\n| `state.md` | Current state (Goal / Done / In Progress / Remaining / Decisions / Risks / Next Step) |\n| `compact-state.md` | Deterministic compaction of `state.md` |\n| `handoff.md` | Handoff document for the next agent |\n| `decisions.md` | Decision log |\n| `changed-files.md` | List of changed files |\n| `repo-map.md` | Directory tree + key files |\n| `commands.log` | Codex / Claude execution log (append-only) |\n| `errors.md` | Error notes |\n| `test-results.md` | Test / build results |\n| `full-diff.patch` | `git diff HEAD` snapshot |\n| `context-budget.json` | Token-diet usage snapshot |\n| `session.json` | Session metadata |\n\n## Configuration — `relay-baton.config.json`\n\n```json\n{\n  \"primaryAgent\": \"codex\",\n  \"fallbackAgent\": \"claude\",\n  \"agents\": {\n    \"codex\":  { \"command\": \"codex\",  \"args\": [\"exec\", \"--sandbox\", \"workspace-write\"] },\n    \"claude\": { \"command\": \"claude\", \"args\": [\"--permission-mode\", \"acceptEdits\", \"-p\"] }\n  },\n  \"fallbackPatterns\": [\n    \"usage limit reached\",\n    \"rate limit exceeded\",\n    \"context length exceeded\",\n    \"context limit exceeded\",\n    \"token limit exceeded\",\n    \"quota exceeded\",\n    \"quota limit\",\n    \"insufficient quota\",\n    \"maximum context length\",\n    \"too many requests\"\n  ],\n  \"authPolicy\": {\n    \"mode\": \"cli-session\",\n    \"allowApiKeyEnv\": false,\n    \"warnIfApiKeyEnvDetected\": true,\n    \"blockedEnvVars\": [\"OPENAI_API_KEY\", \"ANTHROPIC_API_KEY\"]\n  },\n  \"tokenDiet\": {\n    \"enabled\": true,\n    \"profile\": \"balanced\",\n    \"outputCompression\": true\n  }\n}\n```\n\nIf no config file exists, defaults are used.\n\n## TUI\n\n`relay-baton tui` opens an Ink dashboard for the active project, or `relay-baton tui --project \u003cname-or-id\u003e` for a specific one.\n\n- Sidebar: active project, registered projects, selected diet, primary / fallback agents, key hints.\n- Main panels: task, session status, active agent, fallback reason, repo path, changed files, compact-state preview, token budget, log tail, recent errors.\n- Keys: `q` quit · `r` refresh · `p` next project · `d` cycle diet (in memory) · `b` reload budget · `h` generate handoff with no agent run.\n\nThe TUI never launches Codex or Claude. It reads session files and can generate a no-run handoff.\n\n## Quality gates\n\n**Handoff Quality Gate** — runs before fallback launch:\n\n- Required files exist and are non-empty.\n- `handoff.md` contains the sections `Goal`, `Previous Agent`, `Next Agent`, `Changed Files`, `Known Errors`, `Next Steps`.\n- Fails the launch if anything is missing. `--force` overrides.\n\n**Token Diet Quality Gate**:\n\n- `handoff.md` ≤ `maxHandoffChars` for the active profile.\n- `Token Diet Summary` section present.\n- Truncate marker present when content was actually truncated.\n- `commands.log` / `AGENTS.md` / `CLAUDE.md` bodies must not be inlined.\n- For `caveman` / `ultra`, the *Important Diff* block stays within `maxDiffChars`.\n\n## Auth \u0026 safety\n\n- Never stores, prints, or logs API keys.\n- `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` stripped from child processes by default.\n- Only `--allow-api-key-env` or `authPolicy.allowApiKeyEnv: true` lets them through.\n- `doctor` reports whether each variable is set — but never prints its value.\n- Refuses to run `run` / `handoff` outside a git repo.\n- Backs up an existing `handoff.md` with a timestamp suffix.\n- `commands.log` is append-only.\n- relay-baton never modifies your source files directly — only `.ai-session/`.\n- `compress` does not overwrite the input file unless `--write` is passed.\n\n## vs the alternatives\n\n| Approach | What carries over | Token cost | Continuity | Failure mode |\n|---|---|---|---|---|\n| Raw chat export | Entire transcript | High (most of it is noise) | Brittle — agent re-reads its own thinking | Context window overflow |\n| Copy-paste prompting | What the human remembered | Variable | Fragile — depends on memory | Silent drift from real state |\n| Whole-repo dump | Everything | Very high | Strong but expensive | Truncated mid-file by the model |\n| **relay-baton** | Compact summary + repo map + file references | **Low, bounded by profile** | Strong — driven by *actual* repo state | Fails *loudly* via quality gates |\n\n## Philosophy\n\nrelay-baton is **small sharp tooling for AI-native development workflows**.\n\n- **Local-first.** Everything lives on your disk. No cloud, no daemon, no telemetry, no account.\n- **Composability.** A `.ai-session/` directory is just files. Read them, grep them, diff them, ship them in a PR.\n- **Lightweight state transfer.** A handoff is a markdown file, not a database.\n- **Deterministic over clever.** No LLM-driven summarization in the harness itself — if the model gets summarization wrong, the handoff lies. relay-baton uses character budgets, structural rules, and explicit references.\n- **Repo state is the source of truth.** The conversation is interpretation; the repo is fact.\n- **Token efficiency is the feature**, not a knob hidden in a menu. Every design decision is measured against \"does this bloat the handoff?\"\n\n### Design principles\n\n1. It's **work handoff**, not chat relay.\n2. The **current repository state** beats any conversation history.\n3. The handoff must be **readable by a human**.\n4. Every UI is just a thin shell over `core`.\n5. **Token diet is not a side feature — it's the core feature.**\n\n## Demo\n\n\u003e _GIF / asciinema recording placeholder — coming with v0.4._\n\u003e\n\u003e A 30-second clip will show a Codex run hitting a quota wall, relay-baton emitting a compact handoff, and Claude Code resuming the task from the exact same repo state.\n\n## Requirements\n\n| Item | Version / Note |\n|---|---|\n| Node.js | ≥ 20 |\n| pnpm | ≥ 9 |\n| git | required |\n| [`codex`](https://github.com/openai/codex) | primary agent — **ChatGPT Plus or higher subscription required** |\n| [`claude`](https://docs.claude.com/en/docs/agents-and-tools/claude-code/setup) | fallback agent — **Claude Pro or higher subscription required** |\n\n\u003e ### Subscription notice\n\u003e\n\u003e relay-baton **never calls the OpenAI / Anthropic API directly**. It uses the **subscription auth** of the local `codex` / `claude` CLIs.\n\u003e\n\u003e - **Codex CLI** — sign in with ChatGPT **Plus / Pro / Team / Enterprise**.\n\u003e - **Claude Code CLI** — sign in with Anthropic **Claude Pro / Max / Team / Enterprise**.\n\u003e - Free-tier accounts will not work reliably for either CLI.\n\u003e - API-key auth is technically possible but **blocked by default** behind `--allow-api-key-env`, to prevent accidental usage-based billing.\n\nDefault agent invocations:\n\n- Codex: `codex exec --sandbox workspace-write \"\u003ctask\u003e\"`\n- Claude Code: `claude --permission-mode acceptEdits -p \"\u003cprompt\u003e\"`\n\n`--full-auto`, `--ask-for-approval`, and `bypassPermissions` are intentionally **not** used (deprecated / unsupported / unsafe). Power users can override `agents.\u003cid\u003e.args` in `relay-baton.config.json`.\n\n## Logging in\n\n`relay-baton login` launches each CLI's native auth flow.\n\n```bash\nrelay-baton login           # both\nrelay-baton login codex     # codex only\nrelay-baton login claude    # claude only\n```\n\nUnder the hood:\n\n- **Codex** → runs `codex login`. Complete browser auth and you return automatically.\n- **Claude** → opens an interactive `claude` session. Type `/login`, complete browser auth, then `/exit`.\n\n`claude --version` succeeding does **not** mean you're logged in. If you see \"Not logged in\", re-run the command above.\n\n\u003e relay-baton does not store, print, or log credentials during the auth process. All credentials are managed by each CLI itself.\n\n## Limitations (MVP)\n\n- No LLM / tokenizer calls of its own — runs on **character budgets**.\n- No semantic summarization — deterministic compaction only.\n- Agent adapters: **Codex / Claude only**.\n- TUI does not run agents; v0.2+ allows no-run handoff generation only.\n\n## Future direction\n\nrelay-baton starts as a two-agent fallback harness. The same primitive scales further:\n\n- **Multi-agent relay chains.** Codex → Claude → OpenCode → back to Codex, each leg carrying a compact handoff.\n- **Branching session trees.** Fork a task into parallel agent attempts; reconcile via diffs.\n- **Remote relay state.** Push `.ai-session/` to a shared remote so the next machine picks up where the last one stopped.\n- **Orchestrated workflows.** `review`, `diagnose`, `continue` modes — bounded autopilot loops with explicit checkpoints.\n- **More adapters.** OpenCode, Gemini CLI, Aider, anything else with a sane local subprocess interface.\n\nThe harness stays the same shape: detect, capture, compact, hand off.\n\n### Roadmap\n\nThe full roadmap lives in [`docs/ROADMAP.md`](./docs/ROADMAP.md):\n\n- **v0.6 — Trust \u0026 Verify**: `verify`, `doctor --deep`, TUI mode panel.\n- **v0.7 — Review \u0026 Diagnose**: `review`, plan execution receipts, plan diffing, `--json` outputs, conversation event schema.\n- **v0.8 — Adapter Expansion + Agent Room (first cut)**: OpenCode / Gemini / Aider adapter scaffolds, project-level fallback overrides, OS CI matrix, and `relay-baton chat`/`room` (turn-based, confirmation-first REPL).\n- **v0.9 — Automation \u0026 Runtime** (current): bounded multi-turn loop (`LoopController`), `/continue --max-steps N`, `/replan`, session `replay`, adaptive per-agent compression thresholds.\n- **v1.0 — Stable Local Release**: frozen schema, full command reference, i18n parity.\n\n### Future: Agent Room / Conversation Mode\n\nA planned direction (first cut in v0.8) to turn relay-baton into an interactive\n**multi-agent workspace**: talk to Claude and Codex by turns in one session,\nwith per-agent messages clearly distinguished — Claude as planner/reviewer,\nCodex as executor. It keeps every existing safety rail (subprocess-only, no API\nkeys, no auto commit/push/PR, confirmation-first with a prompt preview before\nany real run). Design only for now — **not implemented yet**. Full design:\n[`docs/AGENT_ROOM.md`](./docs/AGENT_ROOM.md).\n\n## Documentation\n\n- [`docs/GUIDE.md`](./docs/GUIDE.md) — consolidated guide: install, quickstart, desktop/CLI workflows, safety ([한국어](./docs/i18n/GUIDE.ko.md))\n- [`docs/COMMANDS.md`](./docs/COMMANDS.md) — full command reference ([한국어](./docs/i18n/COMMANDS.ko.md))\n- [`docs/ARTIFACTS.md`](./docs/ARTIFACTS.md) — `.ai-session/` artifact stability contract (v1.0)\n- [`docs/AGENT_ROOM.md`](./docs/AGENT_ROOM.md) — Agent Room design\n- [`docs/ROADMAP.md`](./docs/ROADMAP.md) — roadmap\n- [`docs/RELEASE.md`](./docs/RELEASE.md) — release \u0026 distribution runbook (how the per-OS binaries are built/shipped)\n- [`docs/HANDOFF.md`](./docs/HANDOFF.md) — session handoff / current state (start here in a new session)\n\n## Release notes\n\nDetailed notes live in [`release-notes/`](./release-notes/) ([index](./release-notes/README.md)). They are user-facing changelogs, not agent handoff material — that role belongs to `.ai-session/handoff.md`.\n\n**Latest:** v2.1.0-alpha.2 — [English](./release-notes/v2.1.0-alpha.2.md) · [한국어](./release-notes/ko/v2.1.0-alpha.2.md)\n\n| Version | English | 한국어 | One-line summary |\n|---|---|---|---|\n| v2.1.0-alpha.2 | [Read →](./release-notes/v2.1.0-alpha.2.md) | [읽기 →](./release-notes/ko/v2.1.0-alpha.2.md) | Secret-leak regression scan + `--allow-api-key-env` audit (names only); v2.1 complete. |\n| v2.1.0-alpha.1 | [Read →](./release-notes/v2.1.0-alpha.1.md) | [읽기 →](./release-notes/ko/v2.1.0-alpha.1.md) | Redact before handoff: a Redaction Gate blocks launching the next agent on high-severity secret findings (unless `--force`). |\n| v2.1.0-alpha.0 | [Read →](./release-notes/v2.1.0-alpha.0.md) | [읽기 →](./release-notes/ko/v2.1.0-alpha.0.md) | Windows-safe agent spawn: `safeSpawn` (cross-spawn) resolves npm-global `.cmd` shims and escapes arguments, fixing `doctor`/`run`/`login` on Windows. |\n| v2.0.0-alpha.6 | [Read →](./release-notes/v2.0.0-alpha.6.md) | [읽기 →](./release-notes/ko/v2.0.0-alpha.6.md) | Conversation-event schema versioning + `session export`; v2.0 feature-complete and a \"Beyond v2.0\" roadmap. |\n| v2.0.0-alpha.5 | [Read →](./release-notes/v2.0.0-alpha.5.md) | [읽기 →](./release-notes/ko/v2.0.0-alpha.5.md) | Session archive prune policy (`session prune`, disabled by default, dry-run unless `--apply`) + a CI release-creation race fix. |\n| v2.0.0-alpha.4 | [Read →](./release-notes/v2.0.0-alpha.4.md) | [읽기 →](./release-notes/ko/v2.0.0-alpha.4.md) | git-baseline.json brought under the versioned schema contract (registry + migrate/doctor coverage + legacy normalization). |\n| v2.0.0-alpha.3 | [Read →](./release-notes/v2.0.0-alpha.3.md) | [읽기 →](./release-notes/ko/v2.0.0-alpha.3.md) | Installer/update finalized + public docs pass: a locked distribution policy in RELEASE.md and a consolidated `docs/GUIDE.md` (EN+KO). |\n| v2.0.0-alpha.2 | [Read →](./release-notes/v2.0.0-alpha.2.md) | [읽기 →](./release-notes/ko/v2.0.0-alpha.2.md) | Stability guards: desktop i18n parity test (en/ko/ja/zh) enforcing the stable desktop contract, and a hard-constraints test locking the auth policy + no-LLM-client rule. |\n| v2.0.0-alpha.1 | [Read →](./release-notes/v2.0.0-alpha.1.md) | [읽기 →](./release-notes/ko/v2.0.0-alpha.1.md) | Schema migrator apply path: `relay-baton migrate --apply [--dry-run]` normalizes legacy artifacts with timestamped backups, opt-in and idempotent. |\n| v2.0.0-alpha.0 | [Read →](./release-notes/v2.0.0-alpha.0.md) | [읽기 →](./release-notes/ko/v2.0.0-alpha.0.md) | v2.0 stability line opens: read-only artifact schema migration checks (`relay-baton migrate`, `ARTIFACT_SCHEMA_VERSIONS` registry, `doctor --deep` schema lines). Detection + guidance only. |\n| v1.9.0-alpha.0 | [Read →](./release-notes/v1.9.0-alpha.0.md) | [읽기 →](./release-notes/ko/v1.9.0-alpha.0.md) | Team handoff package: portable `handoff bundle` (manifest + SHA-256 + redaction pass), `handoff inspect`, a markdown `report`, and a desktop team-handoff export card + Agent Room `/bundle` `/report`. No cloud upload. |\n| v1.8.0-alpha.1 | [Read →](./release-notes/v1.8.0-alpha.1.md) | [읽기 →](./release-notes/ko/v1.8.0-alpha.1.md) | Project intelligence complete: `relay-baton profile` (framework tags + recommended commands), `inventory` (scripts/packages/CI/release files), and a desktop project-inspector panel + Agent Room `/workspace` `/profile` `/inventory`. |\n| v1.8.0-alpha.0 | [Read →](./release-notes/v1.8.0-alpha.0.md) | [읽기 →](./release-notes/ko/v1.8.0-alpha.0.md) | Project intelligence start: deterministic, bounded `relay-baton workspace` map (package managers, languages, monorepo packages, scripts, entry points, docs, AGENTS/CLAUDE files). No semantic indexing. |\n| v1.7.0-alpha.0 | [Read →](./release-notes/v1.7.0-alpha.0.md) | [읽기 →](./release-notes/ko/v1.7.0-alpha.0.md) | Guarded execution workflow: deterministic read-only execution checkpoints (`checkpoint add`/`list`/`summary`), a `guard` stop-condition policy, a `risk` classifier, and a desktop guarded-execution panel + Agent Room `/checkpoints` `/guard` `/risk`. |\n| v1.6.0-alpha.0 | [Read →](./release-notes/v1.6.0-alpha.0.md) | [읽기 →](./release-notes/ko/v1.6.0-alpha.0.md) | Session archives, recovery, and desktop browsing: read-only `session list`/`inspect`/`resume` with manifest + SHA-256 integrity and stale/incomplete diagnosis, plus a desktop session-archive panel and Agent Room `/sessions` `/inspect` `/resume`. |\n| v1.5.0-alpha.1 | [Read →](./release-notes/v1.5.0-alpha.1.md) | [읽기 →](./release-notes/ko/v1.5.0-alpha.1.md) | Distribution cleanup: opt-in/manual desktop updater wiring, signed updater artifact/latest.json release support, v1.4 deferred-item closure, and v1.6-to-v2.0 roadmap. |\n| v1.5.0-alpha.0 | [Read →](./release-notes/v1.5.0-alpha.0.md) | [읽기 →](./release-notes/ko/v1.5.0-alpha.0.md) | Git tracking first cut: read-only `relay-baton git status --json`, non-git project fallback, desktop Git panel, and `/git` in Agent Room. |\n| v1.4.0-alpha.1 | [Read →](./release-notes/v1.4.0-alpha.1.md) | [읽기 →](./release-notes/ko/v1.4.0-alpha.1.md) | Distribution polish: one-line CLI installers with SHA-256 verification, release SHA256SUMS/SBOM metadata, package-manager templates, optional signing hooks, and a desktop Codex/Claude preview switcher. |\n| v1.3.0-alpha.1 | [Read →](./release-notes/v1.3.0-alpha.1.md) | [읽기 →](./release-notes/ko/v1.3.0-alpha.1.md) | Desktop Agent Room UX revamp: tabbed dashboard/room, full-height chat, handoff modal, slash-command palette with descriptions, decluttered buttons, and a full `?` usage guide (en/ko/ja/zh). |\n| v1.3.0-alpha.0 | [Read →](./release-notes/v1.3.0-alpha.0.md) | [읽기 →](./release-notes/ko/v1.3.0-alpha.0.md) | Desktop conversation + project-scoped sessions: Agent Room composer, persisted conversation events via `conversation append`, visible project/session context, and confirmation-first slash actions. |\n| v1.2.0-alpha.3 | [Read →](./release-notes/v1.2.0-alpha.3.md) | [읽기 →](./release-notes/ko/v1.2.0-alpha.3.md) | Desktop project management + i18n: add projects with the folder picker, switch/remove projects in the GUI, register non-git project folders, and switch UI chrome between English/Korean/Japanese/Simplified Chinese. |\n| v1.2.0-alpha.2 | [Read →](./release-notes/v1.2.0-alpha.2.md) | [읽기 →](./release-notes/ko/v1.2.0-alpha.2.md) | Desktop sidecar fix: the GUI now actually reaches the bundled CLI (`withGlobalTauri` + `window.__TAURI__`), so status/budget/handoff/timeline panels populate. |\n| v1.2.0-alpha.1 | [Read →](./release-notes/v1.2.0-alpha.1.md) | [읽기 →](./release-notes/ko/v1.2.0-alpha.1.md) | Desktop prerelease completed: fixes the Windows `.msi` build (non-numeric prerelease) so all 6 assets ship; adds Phase D — signing docs, window-state persistence, light/dark toggle, TUI-mirrored keyboard shortcuts. |\n| v1.2.0-alpha.0 | [Read →](./release-notes/v1.2.0-alpha.0.md) | [읽기 →](./release-notes/ko/v1.2.0-alpha.0.md) | Desktop GUI prerelease (Phase A+B): `build-desktop` release job (.dmg/.msi/.AppImage), deterministic icons, sidecar staging, read-only dashboard, and CLI JSON surface (`project list/current --json`, `handoff show`). Unsigned installers. |\n| v1.1.3 | [Read →](./release-notes/v1.1.3.md) | [읽기 →](./release-notes/ko/v1.1.3.md) | Distributable (shipped): per-OS standalone executables (Node SEA) attached to the GitHub Release, automated `release.yml` pipeline, README downloads, Tauri desktop scaffold. (v1.1.0–1.1.2 were release-pipeline hotfixes.) |\n| v1.0.0 | [Read →](./release-notes/v1.0.0.md) | [읽기 →](./release-notes/ko/v1.0.0.md) | Stable Local Release: frozen config/session contracts, `.ai-session/` artifact validation (`doctor --deep`), full command reference (`docs/COMMANDS.md` EN+KO), finalized Agent Room set with read-only `/diagnose`. |\n| v0.9.0 | [Read →](./release-notes/v0.9.0.md) | [읽기 →](./release-notes/ko/v0.9.0.md) | Automation \u0026 Runtime (bounded): `LoopController`, `/continue --max-steps N`, `/replan`, `relay-baton replay` / room `/replay`, adaptive per-agent compression thresholds. |\n| v0.8.0 | [Read →](./release-notes/v0.8.0.md) | [읽기 →](./release-notes/ko/v0.8.0.md) | Adapter Expansion + Agent Room (first cut): OpenCode/Gemini/Aider scaffolds, project-level fallback overrides, OS CI matrix, `relay-baton chat`/`room` (turn-based, confirmation-first REPL). |\n| v0.7.0 | [Read →](./release-notes/v0.7.0.md) | [읽기 →](./release-notes/ko/v0.7.0.md) | Review \u0026 Diagnose: `relay-baton review` (deterministic diff-vs-plan), execution receipts, plan diffing, `--json` for status/budget/review, conversation event schema (draft). |\n| v0.6.0 | [Read →](./release-notes/v0.6.0.md) | [읽기 →](./release-notes/ko/v0.6.0.md) | Trust \u0026 Verify: `relay-baton verify` (simulated E2E, no model calls), `doctor --deep`, TUI mode panel, `docs/ROADMAP.md`. |\n| v0.5.0 | [Read →](./release-notes/v0.5.0.md) | [읽기 →](./release-notes/ko/v0.5.0.md) | Plan-execute mode (`plan` / `execute`, planner→executor, PlanQualityGate) + context-compression mode (`compress-context`). |\n| v0.4.0 | [Read →](./release-notes/v0.4.0.md) | [읽기 →](./release-notes/ko/v0.4.0.md) | GitHub Actions CI, critical-path tests, CLI smoke test, session observability, `handoff history`. |\n| v0.3.0 | [Read →](./release-notes/v0.3.0.md) | [읽기 →](./release-notes/ko/v0.3.0.md) | Side-effect-free `ProjectResolver`, registry recovery with backup on corrupt `projects.json`, `RELAY_BATON_PROJECTS_FILE` override, `lastError` cleanup on fallback. |\n| v0.2.0 | [Read →](./release-notes/v0.2.0.md) | [읽기 →](./release-notes/ko/v0.2.0.md) | Multi-project registry, `--project` / `--path`, project CLI commands, improved TUI dashboard, `.gitattributes`. |\n| v0.1.0 | [Read →](./release-notes/v0.1.0.md) | [읽기 →](./release-notes/ko/v0.1.0.md) | Initial MVP for Codex-to-Claude handoff with token diet, fallback detection, quality gates, and auth-safe subprocess execution. |\n\n## Smoke test\n\nAfter any change:\n\n```bash\npnpm build\npnpm test\npnpm relay-baton doctor\npnpm relay-baton project add /path/to/relay-baton --name relay-baton --diet caveman\npnpm relay-baton status --project relay-baton\npnpm relay-baton handoff --to claude --no-run --project relay-baton --diet caveman\npnpm relay-baton budget\n```\n\n## Contributing\n\nIssues and PRs welcome. For larger changes, open a short RFC issue first.\n\n```bash\ngit clone https://github.com/dgl1231/relay-baton\ncd relay-baton\npnpm install\npnpm build\npnpm test\n```\n\n## License\n\nMIT. See [`LICENSE`](./LICENSE).\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\n**Translations** ·\n[한국어](./docs/i18n/README.ko.md) ·\n[日本語](./docs/i18n/README.ja.md) ·\n[简体中文](./docs/i18n/README.zh-CN.md) ·\n[繁體中文](./docs/i18n/README.zh-TW.md) ·\n[Español](./docs/i18n/README.es.md) ·\n[Français](./docs/i18n/README.fr.md) ·\n[Deutsch](./docs/i18n/README.de.md) ·\n[Português](./docs/i18n/README.pt-BR.md) ·\n[Русский](./docs/i18n/README.ru.md)\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdgl1231%2Frelay-baton","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdgl1231%2Frelay-baton","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdgl1231%2Frelay-baton/lists"}