内容
<!-- mcp-name: io.github.aytzey/showagent -->
<h1 align="center">showagent</h1>
<p align="center"><b>showagent</b> — 您的机器上的每个 AI 编程会话,都集中在一个 TUI 中。<br>
浏览、搜索、恢复、分支 — 以及 <em>转换</em> 会话从一个代理到另一个。<br>
Codex · Claude Code · Gemini CLI · OpenCode · jcode</p>
<p align="center">
<a href="https://github.com/aytzey/showagent/actions/workflows/ci.yml"><img src="https://github.com/aytzey/showagent/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<a href="https://github.com/aytzey/showagent/releases/latest"><img src="https://img.shields.io/github/v/release/aytzey/showagent" alt="Release"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT"></a>
</p>

> 在 Codex 中开始调试,想要听听 Claude 的意见?按下 `x`。您的会话随您移动 — 每个用户和助手回合,都重写为目标代理的原生会话格式。
## 为什么
您现在使用多个编码代理 — 大多数人都在使用。但每个代理都将其会话埋葬在自己的格式下,位于自己的点目录中,昨天的上下文被困在您启动它的工具中。showagent 直接从磁盘读取会话存储,并为您提供一个可搜索的选择器,涵盖所有代理。
- **一个列表包含所有内容** — 来自每个代理的会话,按工作区分组,模糊搜索,最新的在前。
- **在任何地方恢复或分支** — 在其自己的 CLI 中重新打开一个会话,或 fork 一个本地副本以尝试不同的方向。
- **代理间转换** — 将会话重写为另一个代理的原生格式,以便该代理自己的恢复功能正常工作。原始会话永远不会被修改;转换是原子写入的。
- **100% 本地** — 一个静态二进制文件,读取您自己的文件。没有托管服务,没有遥测数据,没有帐户。
## 支持的代理
| 代理 | CLI | 读取会话存储 | 环境变量覆盖 | 可转换来源 | 可转换目标 |
|---|---|---|---|:---:|:---:|
| Codex | `codex` | `~/.codex/sessions/**/*.jsonl` | `CODEX_HOME` | ✅ | ✅ |
| Claude Code | `claude` | `~/.claude/projects/**/*.jsonl` | `CLAUDE_HOME` | ✅ | ✅ |
| Gemini CLI | `gemini` | `~/.gemini/tmp/<project>/chats/` | `GEMINI_CLI_HOME` | ✅ | ✅ |
| OpenCode | `opencode` | `opencode.db`, 通过 `opencode` CLI | `OPENCODE_DATA_HOME` | ✅ | ✅ |
| jcode | `jcode` | `~/.jcode/sessions/*.json` | `JCODE_HOME` | ✅ | ✅ |
注意:
- OpenCode 将会话存储在 SQLite 数据库中,因此每个 OpenCode 操作(发现、导出、导入、删除)都通过您自己的 `opencode` CLI 进行 — showagent 永远不会直接写入数据库。OpenCode 和 jcode 仅在安装其 CLI 时可见。
- 选择器仅提供 CLI 在 `PATH` 上的目标,因此它永远不会使转换陷入困境。脚本转换到文件支持的代理仍然可以准备会话,然后在安装其 CLI 之前;OpenCode 始终需要其 CLI,因为导入通过 OpenCode 本身进行。
- jcode 是一个小众、实验性的代理 CLI。其支持是自动隐藏的:如果没有 `jcode` 二进制文件在 `PATH` 上,showagent 永远不会显示它。
- 平台:Linux 和 macOS(amd64 + arm64)。Windows(amd64)版本已发布,但 **实验性**:恢复运行代理作为子进程,而不是替换 showagent。
## 安装
```sh
# Homebrew(Linux/macOS)
brew install aytzey/tap/showagent
# 安装脚本(Linux/macOS,将二进制文件放入 ~/.local/bin)
curl -fsSL https://raw.githubusercontent.com/aytzey/showagent/main/scripts/install.sh | sh
# Go 1.25.12+
go install github.com/aytzey/showagent/cmd/showagent@latest
```
或者,从 [发布页面](https://github.com/aytzey/showagent/releases/latest) 获取存档 — `linux`/`darwin` amd64 + arm64,`windows` amd64(实验性)。
## 快速开始
```sh
showagent # 打开交互式选择器
showagent list # 每个会话的纯表格
showagent list --json # 相同,但可机器读取
showagent resume latest # 重新打开最近的会话,任意代理
showagent convert latest --to claude --dry-run
# 预览实际的交接会携带/删除的内容
showagent info latest # 确切的恢复命令 + 存储位置
showagent mcp # 向支持 MCP 的代理提供会话历史(stdio)
showagent mcp --read-only # 相同的搜索/转录工具,无写入工具
showagent mcp --allow-secrets
# 显式允许逐字逐句的类似机密的转录值
showagent update # 更新独立安装(Homebrew:brew upgrade aytzey/tap/showagent)
showagent --help # 完整的 CLI 帮助
```
### 快捷键
| 键 | 操作 |
|---|---|
| `↑/k`, `↓/j`, `pgup/pgdn` | 移动到会话 |
| `/` | 模糊搜索代理、工作区、会话 ID 和消息 |
| `enter` | 在其自己的 CLI 中恢复选定的会话 |
| `1`..`9` | 切换提供者可见性,按标题栏中列出的顺序编号 |
| `p` | 循环预览列:第一个 → 最新 → 第一个 + 最新消息 |
| `space` | 折叠或展开选定的工作区组 |
| `o` | 循环转换目标以获取选定的会话 |
| `t` | 循环转换范围:所有回合,或最新的 200/100/50/20/10 |
| `x` | 预览转换;再次按 `x` 以写入并选择新会话 |
| `n` | 分支:创建会话的完整本地副本 |
| `y` | 切换 yolo 恢复(跳过代理的权限提示) |
| `C` | 复合:恢复带有学习捕获提示的会话(见下文) |
| `d`, `del`, `backspace` | 删除会话 — 第二次按下确认,移动解除 |
| `r` | 重新扫描会话存储(保留光标、搜索和过滤器) |
| `?` | 切换完整的快捷键覆盖层 |
| `esc` | 清除搜索/关闭覆盖层/取消解除删除(永远不会退出) |
| `q`, `ctrl+c` | 退出 |
## 脚本
`showagent list --json` 发出一个按最新时间排序的数组 — 字段名称是稳定的契约:
```json
[
{
"id": "1f7c9a2e-4b31-4c8e-9d02-8a5e3f6b1c44",
"provider": "codex",
"workspace": "/home/you/code/api-server",
"updated": "2026-07-08T19:51:25Z",
"first_message": "Add rate limiting to POST /v1/charges",
"last_message": "the redis TTL test is flaky - mock the clock"
}
]
```
`showagent resume <id|latest> [--yolo]` 在没有选择器的情况下恢复,因此 shell 别名可以用一个按键重新打开最后一个会话。
`showagent convert <id|latest> --to <provider> --dry-run` 在写入任何内容之前打印交接:源会话、目标提供者、工作区、范围、可转移的回合计数、最后一个用户询问以及将被删除的代理特定状态。删除 `--dry-run` 以写入转换后的会话,然后 showagent 打印新行的恢复配方。
`showagent info <id|latest> [--yolo]` 打印确切的恢复命令、工作目录和会话的存储位置。
退出代码:`0` 成功,`1` 错误(包括“未找到会话”),`2` 用法。
当 stdout 不是终端时,普通的 `showagent` 会打印 `list` 表,因此管道直接工作。
## 从您的代理(MCP)中使用它
`showagent mcp` 运行一个 stdio MCP 服务器,因此您正在与之交谈的代理可以搜索机器上的每个过去的编码会话 — 来自 **任何** 代理 — 并将其作为上下文拉取或转换以继续。询问 Claude Code“ 我是否曾经解决过这个速率限制错误?” 它可以找到您曾经的 Codex 会话,读取转录,然后为您提供恢复它的命令 — 或将其重写为原生 Claude Code 会话并继续。您的会话历史记录不再是每个工具的内存,而是成为共享内存。
```sh
# Claude Code
claude mcp add showagent -- showagent mcp
# Codex (~/.codex/config.toml)
[mcp_servers.showagent]
command = "showagent"
args = ["mcp"]
```
MCP 客户端可以将返回的转录文本发送到其模型提供者。因此,常见的类似机密的值默认被编辑,并且每个转录都被标记为不受信任的历史数据而不是指令。如果需要逐字值,用户必须显式启动服务器为 `showagent mcp --allow-secrets`;MCP 工具调用不能绕过编辑。对于永远不会写入会话副本的客户端,注册 `showagent mcp --read-only`;该模式省略了 `branch_session` 和 `convert_session`。
工具:
| 工具 | 功能 |
|---|---|
| `list_sessions` | 跨所有代理搜索会话 — 按提供者、工作区子字符串或工作区 + 第一个/最后一个用户消息的自由文本过滤(默认 25 个,结果最多 100 个) |
| `get_transcript` | 读取最近的用户/助手回合(默认 50 个,最多 500 个);除非服务器被显式启动为 `--allow-secrets`,否则会编辑机密 |
| `branch_session` | 分叉会话的完整本地副本,相同的代理;返回新的 ID、文件和恢复命令 |
| `convert_session` | 将会话重写为另一个代理的原生格式;返回新的 ID、文件和恢复命令 |
| `resume_command` | 确切的 shell 命令(和 cwd),恢复会话 — 作为字符串返回,**从不执行** |
默认 MCP 接口是故意非破坏性的:**没有删除工具**,它永远不会启动或恢复交互式代理。OpenCode 存储操作仍然通过本地 `opencode` CLI 进行,因为其会话存储在 SQLite 中。删除会话仅在 TUI 中保留,删除会话需要按两次按键,并且移动会解除。
## 它是如何比较的
优秀的工具存在用于 **并行运行代理** — showagent 是关于它们留下的会话。[claude-squad](https://github.com/smtg-ai/claude-squad) 和 [ccmanager](https://github.com/kbwo/ccmanager) 在 tmux 会话和 git 工作树中编排多个实时代理,这是当您想要多个代理同时工作时的正确选择。
[Agent Sessions](https://github.com/jazzyalex/agent-sessions) 是一个精致的 macOS 应用程序,用于浏览多个代理的会话历史记录。showagent 是先有历史记录、再有终端的版本:一个跨平台的二进制文件,读取磁盘上的会话存储,恢复并从中分支 — 并且是唯一一个在代理之间转换会话格式的工具。
## 复合工程
在会话上按 `C` 并选择一个代理。showagent 在那里恢复会话并开始复合工程传递:查看已解决的内容,然后将持久的学习内容记录为 Markdown。
学习内容按项目合并,但跨代理共享:每个工作区在 `~/.showagent/learnings/<project>/` 下(通过 `SHOWAGENT_LEARNINGS_DIR` 覆盖)有一个目录,每个代理都读取和写入。选择未创建会话的代理会先转换它,因此它具有完整的上下文。
`showagent setup` 将配套的 [复合工程插件](https://github.com/EveryInc/compound-engineering-plugin) 安装到 Codex 和 Claude Code CLIs 中。它是幂等的,并且只安装缺少的内容。
## 常见问题
**我的会话数据会被发送到任何地方吗?**
showagent 本身不会上传会话内容,也没有遥测或帐户。MCP 客户端可能会将 `get_transcript` 结果发送到该客户端的模型提供者,因此 MCP 转录会默认编辑常见的机密;请记住这一点,然后再注册服务器。showagent 自己的 HTTP 客户端仅用于可选的发布更新和启动更新检查(禁用 `SHOWAGENT_NO_UPDATE_CHECK=1`)。`showagent setup` 调用已安装的 Codex/Claude CLI,它们可能会下载请求的插件。消息预览还会编辑类似密码的字符串和 API 密钥,然后渲染([`internal/session/session_test.go`](internal/session/session_test.go) 中的测试涵盖了这一点)。发布存档附带 `SHA256SUMS` 文件,v0.7.0 之后的发布也带有 GitHub 构建出处 — 使用 `gh attestation verify <file> --repo aytzey/showagent` 验证。
**转换是如何工作的?**
转换会从源转录中提取用户和助手回合,并以目标代理的原生格式写入全新的会话(对于 OpenCode,通过 `opencode import`),因此目标的恢复命令会拾取它。代码块、换行符和缩进会被保留。原始会话永远不会被修改,文件是私有的 (`0600`) 并且是原子写入的 — 崩溃不会留下半写的会话存储在另一个工具的存储中。
信任是明确的:在 TUI 中,第一个 `x` 显示交接预览,第二个 `x` 会写入。在脚本中,使用 `showagent convert ... --dry-run` 获取相同的预览。转换 **不** 复制工具调用的内部数据、批准历史、加密推理块或提供者附件:这些是源代理的私有数据,无法正确重放。`t` / `--scope` 将范围调整为转换前的最新 N 回合。
**删除实际执行什么操作?**
Codex 会话通过 `codex delete --force` 删除;OpenCode 通过 `opencode session delete` 删除(在数据库内级联)。Claude Code 删除 JSONL 以及其匹配的索引条目,jcode 删除 JSON 以及备份/日志边车,Gemini 删除其会话文件。删除始终需要按两次按键,并且移动会解除。
**Windows?**
二进制文件已发布,整个 TUI 都有效,但恢复语义是近似的(子进程而不是 exec),因此 Windows 被标记为实验性,直到它被实际使用过。
**一个会话在列表中丢失。**
运行 `showagent list` 时,如果没有找到会话,它会打印确切扫描了哪些目录以及覆盖它们的 env 变量。`r` 会在启动新会话后原地重新扫描。
## 添加提供者
提供者是一个自包含的文件,实现 [`internal/session/provider.go`](internal/session/provider.go) 中定义的 8 方法接口 — 大约 250 行代码,包括发现、恢复参数、转录提取和转换。在 `registry` 切片中注册它,TUI 会自动拾取徽章、筛选键和转换目标。添加一个匹配的 env 覆盖,以便其测试保持独立。问题和 PR 欢迎。
## 构建
```sh
git clone https://github.com/aytzey/showagent.git
cd showagent
go test ./...
go build -o showagent ./cmd/showagent
```
最低支持的工具链是 Go 1.25.12;CI 还运行 race tests、golangci-lint、`govulncheck` 和每个发布的交叉编译目标。
演示 GIF 是使用 [vhs](https://github.com/charmbracelet/vhs) 在构造的夹具上记录的 — 请参见 [`demo/README.md`](demo/README.md)。
安全问题和敏感数据暴露应私下报告;请参见 [`SECURITY.md`](SECURITY.md)。贡献受 [`CONTRIBUTING.md`](CONTRIBUTING.md) 覆盖。
## 许可证
MIT。 使用 [Bubble Tea](https://github.com/charmbracelet/bubbletea)、
[Bubbles](https://github.com/charmbracelet/bubbles) 和
[Lip Gloss](https://github.com/charmbracelet/lipgloss) 构建。