{"slug": "show-hn-agent-hop-a-rust-tui-that-hops-a-live-claude-code-chat-into-codex", "title": "Show HN: Agent-hop – a Rust TUI that hops a live Claude Code chat into Codex", "summary": "Developer hetpatel-11 released agent-hop 0.1.3, an open-source Rust TUI runtime that lets users run Claude Code, Codex, OpenCode, Pi, and Grok in one terminal and hop a live chat session between them without leaving the terminal or starting over. The tool indexes all local chat history for hybrid BM25/MiniLM search and supports cross-harness resume by translating turns into each tool's native session format, with binaries available for macOS, Linux, and Windows via GitHub Releases, npm, or a curl installer.", "body_md": "## agent-hop.mp4\n\ndemo\n\n**A runtime for coding-agent harnesses.** Run Claude Code, Codex, OpenCode, Pi, and Grok inside one terminal, hop a live session between them, and search or resume any local chat.\n\n`ah`\n\nis the process you start. The harness runs inside it.\n\nClaude Code, Codex, OpenCode, Pi, and Grok each have their own CLI, their own session files, and their own idea of \"resume.\" None of them can take over a conversation another one just had. `agent-hop`\n\nis the runtime around those harnesses: a native Rust binary that opens the real agent in a pty, keeps a strip of chrome `ah`\n\nowns, and can move the live thread into the next harness without you leaving the terminal or starting over.\n\nYou work the way you already do. `claude`\n\nis still `claude`\n\n. Codex is still Codex. `ah`\n\ndoes not reimplement them, proxy their APIs, or invent a new agent. It is the runtime around them — PTY, Ghostty's VT engine, hop, search.\n\nWhen you hop Claude Code → Grok → Pi → OpenCode → Codex, the runtime finds the session the current harness just wrote for this project, translates the actual turns into the next harness's native format, and launches that harness's own resume command. Tool calls (shell, file edits, MCP) and attachments (images, PDFs) go with the thread. It is not a pasted summary.\n\nSearch and resume are part of the same runtime, not a separate product. Every harness writes history to disk in its own shape. `ah`\n\nindexes all of it locally — BM25 as you type, MiniLM when you pause — so you can pull up a thread you remember by topic, not by which tool or folder held it. `Ctrl+R`\n\nresumes in the same harness. A hop, or `ah resume -r`\n\n, continues it in a different one.\n\n**Runtime, not a wrapper UI**— you launch`ah`\n\n; it spawns the real harness in a pty and renders it with Ghostty's terminal engine. The agent is unmodified.**Live hop between harnesses**—`Ctrl+B n/p/a`\n\n,`Alt+↑/↓`\n\n, or click the bottom bar. The next tool gets the real conversation in its own session format. Native compact/recap (and the local digest when a thread is cut) stay in model context, not as a chat bubble.**Tabs and workspaces**— several agents in one`ah`\n\nprocess. Prefix chords (`Ctrl+B c/w/o/i/[ /]/1–9/x`\n\n) or click the sidebar and tab strip.`Ctrl+B q`\n\nleaves`ah`\n\n; the next`ah`\n\nrestores those workspaces and resumes each chat. When an agent exits, that tab closes. Last tab also leaves`ah`\n\n.**Pane CLI**— from inside a live tab,`ah tab`\n\n,`ah hop`\n\n,`ah close`\n\n,`ah focus`\n\n, and`ah workspace`\n\ntalk to the parent mux (never your own pane for hop/close).**Search every local chat**— one picker over Claude Code, Codex, OpenCode, Pi, and Grok. Hybrid lexical + semantic search, all on your machine.** Resume the real session**— same-harness resume uses that tool's own files and resume command. Cross-harness resume writes a native session the target would have written itself.**Interactive or scripted**— humans stay in the TUI. Agents and CI call`ah resume`\n\nwithout a picker.**Sessions never leave disk**— hop and search read the same files the harnesses already write. Telemetry, if left on, is aggregate usage only.\n\nmacOS or Linux, no Node required:\n\n```\ncurl -fsSL https://raw.githubusercontent.com/hetpatel-11/agent-hop/main/install.sh | bash\n```\n\nThat pulls `ah`\n\nfrom the [GitHub Release](https://github.com/hetpatel-11/agent-hop/releases/latest) (npm tarball as fallback) into `~/.local/bin`\n\n. Override with `AH_BIN_DIR`\n\n. Pin a version with `AH_VERSION=0.1.3`\n\n.\n\nOr download a binary from the [releases page](https://github.com/hetpatel-11/agent-hop/releases/latest): `ah-darwin-arm64`\n\n, `ah-darwin-x64`\n\n, `ah-linux-x64`\n\n, `ah-linux-arm64`\n\n, `ah-windows-x64.exe`\n\n.\n\nOr via npm / bun, if you already use them:\n\n```\nnpm install -g agent-hop\n# or\nbun install -g agent-hop\n```\n\nnpm is a binary CDN here, not a JavaScript app. The package is a tiny Node shim that execs the same Rust binary GitHub Releases and the curl installer ship.\n\nSupported prebuilds: macOS arm64/x64, Linux x64/arm64, Windows x64.\n\n`ah`\n\nis the runtime, not an installer. The harness you hop into must already be on your `PATH`\n\n.\n\nAnonymous usage telemetry is on by default (no queries, paths, or chat content). Turn it off with `ah telemetry off`\n\nor `AH_TELEMETRY=0`\n\n. Details: [https://agent-hop.com/telemetry](https://agent-hop.com/telemetry)\n\n```\nah\n```\n\nReopens the workspaces and tabs from last time, each on that harness's own resume of the chat. First run — or after you start with `ah claude`\n\n/ `ah resume`\n\n— you pick a harness. That harness is a child process; `ah`\n\nwraps it:\n\n| Shortcut | What it does |\n|---|---|\n`Ctrl+B` then `n` / `p` |\nHop this tab to the next / previous installed agent |\n`Ctrl+B` then `a` |\nOpen the agent picker (or click the bottom bar) |\n`Ctrl+B` then `c` |\nNew tab in this workspace |\n`Ctrl+B` then `w` |\nNew workspace (folder), then pick an agent |\n`Ctrl+B` then `o` / `i` |\nNext / previous tab |\n`Ctrl+B` then `[` / `]` |\nPrevious / next workspace |\n`Ctrl+B` then `1` –`9` |\nFocus that tab |\n`Ctrl+B` then `x` |\nClose this tab |\n`Ctrl+B` then `q` |\nLeave `ah` . Next `ah` restores these workspaces and chats |\n`Ctrl+B` then `?` |\nShow every `ah` shortcut |\n`Alt+↑` / `Alt+↓` |\nHop next / previous (where the terminal sends those keys) |\n`Ctrl+R` |\nSearch local history and resume a session in the same agent |\n\nLaunch straight into a tool:\n\n```\nah claude\nah codex\nah opencode\nah pi\nah grok\n```\n\nSearch and resume outside the live TUI:\n\n```\nah resume\nah resume \"auth migration\"\nah resume \"auth migration\" --agent claude\nah resume \"auth migration\" --agent claude --resume-in codex\n```\n\n| Flag | Description |\n|---|---|\n`-a, --agent <tool>` |\nOnly search this agent (`claude` , `codex` , `opencode` , `pi` , `grok` ) |\n`-r, --resume-in <tool>` |\nConvert the picked session into this agent's format, then launch it |\n\n`Ctrl+R`\n\nand bare `ah resume`\n\nstay on the same agent. Cross-agent is the hop (`Ctrl+B`\n\n/ `Alt+↑↓`\n\n) or `-r`\n\nfor scripts.\n\nWithout a TTY (another agent or a script), a query is required and the top match is auto-picked:\n\n```\nah resume \"adobe premiere mcp setup\" --agent codex --resume-in opencode\n```\n\nBe specific. A vague query like `\"adobe\"`\n\ncan resume the wrong chat.\n\n```\nah telemetry          # status\nah telemetry off\nah telemetry on\nah feedback \"the hop bar is hard to see\"\n```\n\nFrom inside a live pane (`AH_SOCK`\n\nis set; macOS and Linux), agents and you can drive the mux without targeting the pane that issued the command:\n\n```\nah tab                  # new tab (picker)\nah tab codex            # new tab, skip picker\nah hop grok             # hop the other tab (omit --tab if there is exactly one other)\nah hop grok --tab 2\nah close --tab 2        # never closes the calling pane\nah focus 2\nah workspace            # new workspace\nah workspace next\nah workspace prev\n```\n\n`Ctrl+B q`\n\nleaves `ah`\n\nthe way herdr's `prefix+q`\n\ndoes. Agents are not kept running in the background: the layout is saved, and the next `ah`\n\nreopens those folders and resumes each chat. When the last agent in a tab exits, that tab closes. If it was the last tab, `ah`\n\nexits. `Ctrl+B x`\n\ncloses a tab the same way.\n\n`ah`\n\nis a runtime: run the real harness, search the history those harnesses already wrote, translate a live session into another harness's format, and stay out of the way.\n\n```\nyou ──► ah (picker / TUI chrome)\n          │\n          ├─ portable-pty ──► claude | codex | opencode | pi | grok\n          │                      ▲\n          │                      │ native resume command\n          │\n          ├─ libghostty-vt ──► render the agent's own terminal\n          │\n          ├─ adapters ──► read/write each tool's files on disk\n          │      │\n          │      └─ Turn[] (shared IR) ──► hop / ah resume -r\n          │\n          └─ search ──► BM25 + MiniLM (local ONNX) over ~/.agent-hop\n```\n\n**TUI shell ( src/tui.rs, src/picker.rs)** — Starts the agent you picked inside a pty (\n\n`portable-pty`\n\n) and keeps a toggle bar `ah`\n\nowns. The agent never draws into that bar. Hop, search, and help are overlays on top of the still-running agent, not a separate app.**Terminal engine ( src/vt.rs, libghostty-vt)** — Ghostty's embeddable VT parser, linked at build time. The agent is a real TUI (Kitty keyboard protocol, OSC 133 prompt marks, truecolor). We render what it would draw in Ghostty, instead of reimplementing a half-compatible terminal. End users never need Zig; only people building from source do.\n\n**Hop ( src/adapters/mod.rs)** — On\n\n`Ctrl+B n/p/a`\n\nor `Alt+↑/↓`\n\n, `ah`\n\nfinds the session the current agent just wrote for this project, reads it, trims it to a 200k-character budget, writes it as the next agent's native session, and launches that agent's own resume command. If the source already stored a compact/recap (Claude user compact, Grok `session_recap`\n\n), that text is reserved first and hidden from the target TUI as a bubble; Codex compact is encrypted and unused. Anything else that still doesn't fit gets a local digest, also hidden. Fast path: `find_latest_for_path`\n\nso a hop does not scan every session on disk.**Mux ( src/tui.rs, src/control.rs)** — Tabs live in workspaces (folders). Chrome is a full-height sidebar plus a tab strip on the pane. Pane commands go over a unix socket (\n\n`$AH_SOCK`\n\n/ `$AH_TAB_ID`\n\n) so a child cannot hop or close itself. `ah feedback`\n\nposts to the same worker as telemetry.**Adapters ( src/adapters/<tool>.rs)** — One module per agent. Each implements:\n\n`list_sessions()`\n\n— cheap metadata for search`read()`\n\n— that tool's files →`Turn[]`\n\n`write()`\n\n—`Turn[]`\n\n→ a new session in that tool's format`resume_cmd()`\n\n— the argv to exec (`claude --resume …`\n\n,`codex resume …`\n\n, …)\n\nAdding an agent is one new adapter. The TUI and search do not change.\n\n**Shared IR ( Turn)** — Every hop goes through one shape: role, text, structured tool calls (name / input / output), attachments (mime, base64, filename). Tool calls are not flattened into prose. Each writer emits the target's real blocks (\n\n`tool_use`\n\n/ `function_call`\n\n/ `ToolPart`\n\n/ …), the same records that agent would have written itself.**Search ( src/search.rs, src/fuzzy.rs, src/resume.rs)** — Two stages, same index:\n\n**Lexical, every keystroke**— BM25 over local sessions. Exact phrases first, then fuzzy (BK-tree), prefix (`ux`\n\n→`uxp`\n\n), and compound tokens (`agenthop`\n\n→`agent hop`\n\n), with a recency boost.**Semantic, after you pause**—`all-MiniLM-L6-v2`\n\n(384-d, mean-pooled) refines ranking. First use downloads the quantized ONNX model plus ONNX Runtime into`~/.agent-hop/`\n\nand keeps them. Later searches are local.\n\nThe incremental vector index lives under `~/.agent-hop/`\n\n. New sessions are indexed by a detached `ah __background-index`\n\nso the picker never blocks on a full rebuild.\n\n**Standalone resume ( ah resume)** — Same ranker and picker as\n\n`Ctrl+R`\n\n, without wrapping a live agent first. `-r`\n\nis the scripted hop. Non-interactive mode skips the TUI entirely and execs the target agent's resume command with inherited stdio.**Telemetry ( src/telemetry.rs)** — Opt-out, self-hosted (\n\n`telemetry.agent-hop.com`\n\n). Sends aggregate usage (command, version, OS). Never queries, paths, project names, session ids, or chat content. Disabled by `AH_TELEMETRY=0`\n\n, `DO_NOT_TRACK=1`\n\n, or `ah telemetry off`\n\n.**Distribution** — CI builds one `ah`\n\nper platform and ships it twice: a [GitHub Release](https://github.com/hetpatel-11/agent-hop/releases) (what `install.sh`\n\nprefers) and npm `optionalDependencies`\n\n(`agent-hop-darwin-arm64`\n\n, …). `bin/ah.js`\n\nis only a resolver. Same artifact, two front doors.\n\n`ah`\n\nreads and writes what each tool already uses:\n\n| Agent | On disk | Notes |\n|---|---|---|\n| Claude Code | `~/.claude/projects/<encoded-cwd>/*.jsonl` |\nDirectory name replaces every non-alphanumeric with `-` , not just `/` . |\n| Codex | `~/.codex/sessions/YYYY/MM/DD/*.jsonl` |\n`response_item` continues the model; `event_msg` is what the TUI replays. |\n| OpenCode | official `opencode export` / `opencode import` |\nNo raw SQLite writes. Part IDs must be unique or OpenCode silently drops the insert. |\n| Pi | `~/.pi/agent/sessions/--<encoded-cwd>--/` |\nOnly `/` is encoded; `_` and `.` stay. |\n| Grok | `chat_history.jsonl` + `summary.json` per session |\n`updates.jsonl` is also written so the TUI can replay, not only continue. |\n\nLong threads are cut to the most recent slice that fits (`CONVERSION_CHAR_BUDGET`\n\n, 200k characters) rather than handed to a target that cannot load them.\n\n| Agent | Same-tool resume | Hop / write into this format |\n|---|---|---|\n| Claude Code | yes | yes |\n| Codex | yes | yes |\n| OpenCode | yes | yes |\n| Pi | yes | yes |\n| Grok | yes | yes |\n\nPrebuilt installs do not need this. Building from source does: a current Rust toolchain, Zig 0.15.2 (for `libghostty-vt`\n\n), and libclang (for bindgen).\n\n```\ngit clone https://github.com/hetpatel-11/agent-hop.git\ncd agent-hop\ncargo build --release\n# binary: target/release/ah\n```\n\n`npm run build`\n\nis the same `cargo build --release`\n\n. Do not copy the binary over a Homebrew/npm shim on macOS — Gatekeeper will kill a detached copy; symlink `~/.cargo/bin/ah`\n\nor `target/release/ah`\n\ninstead.\n\n```\ncargo test --release\n```\n\n", "url": "https://wpnews.pro/news/show-hn-agent-hop-a-rust-tui-that-hops-a-live-claude-code-chat-into-codex", "canonical_source": "https://github.com/hetpatel-11/agent-hop", "published_at": "2026-08-26 23:03:54+00:00", "updated_at": "2026-08-26 23:18:32.526613+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools", "ai-agents"], "entities": ["hetpatel-11", "agent-hop", "Claude Code", "Codex", "OpenCode", "Pi", "Grok", "Ghostty"], "alternates": {"html": "https://wpnews.pro/news/show-hn-agent-hop-a-rust-tui-that-hops-a-live-claude-code-chat-into-codex", "markdown": "https://wpnews.pro/news/show-hn-agent-hop-a-rust-tui-that-hops-a-live-claude-code-chat-into-codex.md", "text": "https://wpnews.pro/news/show-hn-agent-hop-a-rust-tui-that-hops-a-live-claude-code-chat-into-codex.txt", "jsonld": "https://wpnews.pro/news/show-hn-agent-hop-a-rust-tui-that-hops-a-live-claude-code-chat-into-codex.jsonld"}}