为Codex和ClaudeCode开发了本地控制台AgentConsole,不重建统一前端,而是扫描已持久化会话按工作区分组并归为四种状态,保留原生界面。采用Rust编写,通过独立守护进程管理PTY,避免关闭面板终止agent。模型仅用于生成会话摘要,终端模拟模块最大。支持macOS、Linux和Windows,可跨会话管理多个codingagent。
只开一个 coding agent 的时候,一个终端标签就是最好的界面。

长期稳定更新的攒劲资源: >>>点此立即查看<<<
但开到五个、十个,散落在几个项目里,问题就变了。你不再是一个 Agent 对话,而是在管理一组处于不同状态的工作:一个还在跑,一个在等你确认,一个已经失败,还有一个十分钟前就跑完了,但那个标签页被压在最后面。
解决问题的核心其实很具体:在不改变 Codex 和 Claude Code 使用方式的前提下,拿到一个跨会话的视图。
Agent Console 没有做统一聊天前端。它扫描 provider 已持久化的会话,按 workspace 分组,归一化成 working / waiting / idle / failed 四种状态,需要进入时调用 provider 自己的 resume 流程。进去之后,你面对的仍然是原生的 Codex 或 Claude Code 终端界面。
这个边界很重要。统一前端看起来整齐,但它会落后于 provider 的新能力,并且把 resume 行为、快捷键、审批流、渲染细节都变成第二套兼容层。而原生界面之上那一层——发现、状态、提醒、搜索、导航——小到可以做对。
Rust 这边刻意保守:ratatui 渲染,portable-pty 管子进程,vt100 做保留 pane 的终端模拟,rusqlite 存状态,完全没有 async runtime。整个程序就是一个同步循环,加上若干持有 PTY 的线程。
两家都没有「列出我的会话」这种 API,但都会持久化 transcript。所以发现会话意味着去读 ~/.codex/sessions/**/rollout-*.jsonl 和 ~/.claude/projects/**/,从一堆从没打算当公开接口的记录里反推结构。
当观测通道可以,当契约就很糟——provider 每次发版都可能挪字段。应对办法是:除了一张表,任何地方都不再按 provider 分支。
pub struct ProviderAdapter {pub kind: AgentKind,pub accepts: fn(&Path) -> bool,pub parse: fn(&Path) -> io::Result发现逻辑遍历这张表,而不是在五个地方 match 枚举:
for adapter in providers::enabled() {let root = paths.root(adapter.kind);let files = provider_files(root, adapter.accepts);let mut parsed = parse_cached_files(files, adapter, cache);if let Some(enrich) = adapter.enrich {enrich(root, &mut parsed);}sessions.extend(parsed);
}用裸 fn 指针而不是 Box,是为了让这张表能是 const——加一个 provider 就是加一条表项,零分配。AGENT_CONSOLE_PROVIDERS=codex 可以在运行时裁剪同一张表,这在两家都开始自带多会话视图、某一侧可能变成重复劳动的当下挺有用。
最在意的失败模式是:这个变量打错字,绝不能变成一个静悄悄的空面板。所以无法识别的值会记录原因并保持全部 provider 启用。
最直觉的设计是从 TUI 进程里 spawn agent。那样关掉面板就杀掉所有 agent——而这恰恰是让人宁愿开十二个终端标签的原因。
所以托管的 PTY 放在一个独立的常驻 daemon 里。关闭或崩溃 TUI 只是 detach,新的 TUI 重连并回放一段有界的 tail。不依赖 tmux,也不强制 git worktree——会话就在原地跑。
原地跑意味着两个面板可能同时 resume 同一个 provider 会话、写坏同一份 transcript,所以每个 provider session ID 都由跨进程 lease 保护,带持有者信息、安全拒绝和显式强制接管。这块恰恰是 Rust 帮助最小的地方:类型系统对「同一台机器上的第二个进程」无话可说,靠的是进程卫生。
working / waiting / failed 来自 provider 的 hook 事件和进程状态,用固定优先级确定性归约。模型只负责把长对话压成一眼能扫的任务摘要,它走会话自己的 provider、在 coding conversation 之外运行,并且能用 AGENT_CONSOLE_SUMMARIZER=off 完全关掉。
还有一个只有真跑起来才会暴露的细节:alert 是「运行期观测到的状态跃迁」,不是「状态」。面板启动时就已经在 waiting 的会话,不算新消息。这个区分搞错,提醒列表一天之内就会变成噪音。
pty.rs 有 6,600 行——是最大的模块,比 discovery、状态机和整个 UI 加起来还大。每个 pane 的保留回滚、给需要的 provider 做鼠标上报、alternate screen 处理、选择与剪贴板、resize、重连回放,每一项看起来都很小,实际都不小。
两个具体教训。托管的 Codex 会话用 --no-alt-screen 启动,这样 workspace pane 在 Codex 的任何状态下都能保留并滚动 transcript。以及——在 Codex 和 Claude Code 各自占掉自己的键之后,真正空闲的 Ctrl 组合只剩三个:Ctrl-`、Ctrl-^、Ctrl-Q,其余全部原样转发给子进程。
v0.0.11,支持 Codex 和 Claude Code,提供 macOS / Linux / Windows 包,macOS 二进制已签名并通过 notarization。
cargo install agent-console
agent-console doctor
# 检查 provider、hook、剪贴板、daemon、权限
agent-consoleMIT OR Apache-2.0 双授权。
还很早期。当前关注的核心问题比「再加十个 provider 图标」更基础:状态是否可信、提醒是否真的减少了切换、Shell 是否留在正确的 workspace、原生 resume 是否足够顺滑。
如果你每天同时跑好几个 coding agent——跨会话控制层应该给你看什么,又绝不该接管什么?
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述