跳到正文

CCManager

一个终端菜单,同时看着若干个编码 agent——每个占一个 git worktree:它显示谁在忙、谁在等你、谁空着,负责创建与合并这些 worktree,并且能在崩溃之后把整批会话重新拉起来。

Screenshot of CCManager
编辑截图, 29 Sep 2026CCManager ↗

这是什么

一个围绕 git worktree 做的编码 agent 会话管理器。它跑在终端里,把一个仓库里的每个 worktree 连同挂在它上面的 agent 列出来,并显示那个会话是忙、在等输入还是空着,于是几个 agent 可以并行干活而不必再开第二个终端窗口。worktree 的创建、合并与删除都在它里面完成,项目运行所需的 gitignore 文件可以带进新 worktree,而上一次退出或崩溃时还开着的会话可以在下次启动时重新拉起。它支持八种助手——Claude Code、Gemini CLI、Codex CLI、Cursor Agent、Copilot CLI、Cline CLI、OpenCode 与 Kimi CLI——每一种都有自己的状态判定规则,且可配置。

谁做的按他自己的说法,一位日本软件工程师;账号 2019 年注册,68 个公开仓库,94 个关注者。770 次提交里 566 次是他写的;一个工作流机器人占 145 次,另有约二十位其他人贡献过代码,其中几位相当稳定。

它是怎么搭起来的

组成 · 6

一层终端界面加一个会话编排器,工作单位是 git worktree。每个会话是一个被启动并被监管的进程,菜单是所有会话当前状态的渲染,而状态本身按助手用可配置的规则推断出来,不假定各家一致。两个后果塑造了代码:因为在大仓库里创建工作树可能要几分钟,它被当作一个不许阻塞输入的长时操作;又因为会话比界面活得久,正在运行的记录是持续写而不是退出时写,于是工具可以在自己死掉之后提出把同一批拉回来。worktree 由程序内部管理而不是手工操作,这正是为什么这么大一部分表面积是 git 管道——创建工作树、合并、include 文件、detached head 状态——也是为什么界面必须在一张列表里把十几个会话的状态讲清楚。

src/
62 个 service 文件干实事——会话编排、worktree 操作、状态判定、配置、钩子,以及那个可选的批准校验器——其上是 45 个组件的界面层(其中一个 42 KB 的应用外壳),另有 35 个工具函数、六个 hook、类型与常量目录,以及两个端到端测试。
.kiro/specs/ 与 .kiro/steering/
那套规格流程:两个功能各有需求与设计两份文档,另有三份 steering 文档讲产品、代码结构与技术选型。这是一个属于某种工具的目录格式,却由另一种工具来填写和驱动。
.claude/commands/kiro/
十个命令文件驱动那套流程,从规格初始化,到需求、设计、任务拆解、实现,再到状态、设计校验与缺口检查,外加两条 steering 命令——最大的那个设计命令有 20 KB。
docs/ 与 AGENTS.md
十三个文档,领头的是一份 11 KB 的错误处理迁移方案和一份 worktree 钩子参考,另有自动批准(带自己的 JSON schema)、devcontainer 用法、多项目模式、项目与命令配置、状态钩子,以及 include 文件与工作树目录的约定。AGENTS.md 只有九字节:一个指向别处的链接,而不是文档。
npm/ 与 plugins/
五个平台目录——Apple 芯片与 Intel 的 macOS、x64 与 arm64 的 Linux、以及 Windows——于是安装时拿到的是匹配的预编译二进制,而不需要工具链;这也是为什么发布工作流只有 2.9 KB、持续集成文件只有 801 字节。
配置面
键盘快捷键、带后备的命令预设、按助手区分的状态判定策略、在会话状态改变时触发的状态钩子、devcontainer 设置,以及一份带 schema 的批准配置——全部由文件驱动,这正是让八种习惯不同的助手共用同一个菜单的前提。

取舍,以及它替代了什么

  • 用 worktree,而不是在同一个检出里开多个会话 替代 让这些助手并排工作在同一个工作树里

    并行 agent 改同一份检出会撞车,所以每个会话分到自己的 worktree——而程序把创建、合并与删除的责任接下来,而不是留给用户。仓库里大多数管道代码都是这个选择的后果。

  • 恢复会话只是重跑命令,仅此而已 替代 连上一次的终端输出与对话一起恢复

    连被否掉的替代方案一起写明:复刻对话记录意味着要为每一种助手维护一套格式,而每种助手本来就有自己的恢复方式。恢复做的事是在同一个 worktree 里跑同一条命令,而会话记录在它们来来去去时持续写入,所以崩溃也弄不丢它。

  • 采纳 .worktreeinclude 这个约定 替代 一个项目专属的 include 文件

    一个放在仓库根、用 gitignore 语法的文件已经被 Claude Code、Codex、Conductor 和一个独立工具读取,所以沿用同样的名字与语义,意味着用户已经维护着的那份文件原样可用,不必再写第二份配置描述同一件事。

  • 用校验来放行,而不是把确认整个关掉 替代 一个对所有问题都答「是」的自动确认模式

    README 在和一个同类工具比较时写道,对方「绕过了 Claude Code 内置的安全确认——不推荐用于安全操作」。这个项目对等的能力是实验性的,并且把决定交给一次针对有文档、有 schema 的配置所做的 AI 校验;它还给退出加了一步确认——焦点默认在取消——因为那个退出键与「杀掉所有在跑的会话」之间原本只隔一次误触。

  • 给布局一个宽度预算,而不是一套固定菜单 替代 永远按对齐方式排

    对齐布局是逐列表选择的:调用方传入行标签可占用的列数,排不下时状态标签退回接在名字后面。这样既留下了改进,也没有把菜单从窄终端上拿走。

依据.kiro/specs/loading-spinner-async-operations/design.md、.kiro/specs/result-pattern-error-handling-2/design.md、.kiro/steering/*、README.md(19,070 字符)、docs/auto-approval.md、各 pull request 正文,以及完整的 232 个文件树及其体积。

制作过程

7 个阶段
  1. 01

    一个管八种助手的菜单,和一年稳定的发版节奏

    仓库建于 2025-06-07,有 770 次提交,而它的曲线对一个个人项目来说罕见地平稳:第一个月为了把它做出来提交了 205 次,此后每个月都在 6 到 81 次之间,包括 2026 年那些本档案多数对象正处在第一波冲刺里的月份。它发了 163 个 release,从 2025 年 6 月早期的 0.0.4 到 2026 年 9 月的 v4.4.4——版本线中途被重启过,编号至今还留着痕迹。周围还有 1,256 个星、93 个 fork、276 个 pull request、58 个 issue,以及作者之外的约二十位贡献者,其中一位落地了十七处改动。306 条共同作者尾注里最大的一群是只写「Claude」的那 187 条,其次是 Opus 4.5 的四十四条。

  2. 02

    工作单位是 worktree,而真正难的是创建它

    这个工具要解决的问题是两个 agent 改同一份检出会撞车,所以每个会话分到自己的一份 git worktree——而这个选择的余波全写在 pull request 里。其中一条(编号 337)讲的就是创建工作树:这个操作会把用户按在加载页上直到每一步跑完,而那些慢步骤是同步执行的,于是它们运行期间界面完全无法响应。分支名生成、git worktree add、复制会话数据与 include 文件、以及创建前后的钩子现在都改成异步;在加载页按回车会退回菜单,创建继续进行,菜单则列出正在进行的创建及其已用时间。作者自己在那条改动上写的一句话比功能本身更值钱:自动检查跑过了,但他还没有在真实终端里手动走过这条流程。另一条较小(332)讲的是「怎么读这个菜单」:状态标签原本直接接在分支名后面,于是每一行都从不同的横向位置开始,想扫出哪个会话卡住了,就得逐行读到名字结束的地方。现在它有自己的列;而窄终端付不起这个宽度,所以调用方会把一行的宽度预算传进来,排不下时就退回原来的排法。

  3. 03

    那个只在 Num Lock 打开时才出现的 bug

    这个仓库里最好的一处修复,是没人能清楚报告的那种。有用户发现 Ctrl+E——退回菜单的快捷键——在已接入的会话里毫无反应,而且只在部分机器上。原因在扩展键盘协议报告按键的方式:修饰键被编码成一个数字,而这个数字同时携带键盘的锁定状态——Caps Lock 加 64、Num Lock 加 128,叠加在真正按住的修饰键之上。快捷键匹配器拿收到的字节和「修饰键字段硬编码为 Ctrl」的预置字符串比对,于是一个带着锁定位的 Ctrl+E 谁都匹配不上,直接掉进「把原始字节写进子进程」那条路——没有报错、没有反馈,界面上也没有任何东西能解释它。它之所以看起来像某台机器的毛病,是因为笔记本即便没有小键盘,开机时内部也常常开着 Num Lock。修法是匹配时忽略锁定位——这种更正只能来自去读规范,而不是照着症状猜。

  4. 04

    恢复会话时刻意不恢复的东西

    退出这个工具会杀掉它启动的那些助手进程,所以下一次启动原本会看到一个空菜单。修法是维护一份打开的会话记录——在会话来来去去时写,而不是退出时写,所以崩溃、强杀或直接关掉终端都不会让它丢失——并在启动时提出重新拉起它们。有意思的是作者划下并写出来的那条边界:恢复的意思是在各自的 worktree 里重新跑一遍那个启动命令,而上一次的终端输出和助手内部的对话是刻意不恢复的。复制那些东西被认真考虑过并放弃了,因为那意味着要为每一种助手维护一套自己的记录格式,而每种助手本来就有自己的恢复方式。这个区分还因为一处「故意的不一致」而更锋利:另有一个独立功能确实会把 Claude Code 的会话数据在工作树之间复制,好让对话上下文跟着走——而它是作为一个显式动作提供的,不属于自动路径。

  5. 05

    采纳一个既有约定,而不是发明一个自己的

    新建的 git worktree 只包含被跟踪的文件,于是项目真正跑起来需要的东西——本地的环境变量文件、证书、夹具——都不会跟着过去。显而易见的答案是定义一个自己的配置键,而作者选了另一条路:支持那些在意 worktree 的工具已经收敛到的那个文件名。.worktreeinclude,一个放在仓库根、用 gitignore 语法的文件,已经被 Claude Code、Codex、Conductor 以及一个独立的命令行工具读取,所以实现同样的名字和同样的语义,意味着用户为那些工具已经维护着的那份文件在这里原样可用,而不必再写第二份配置去描述同一件事。那条 pull request 列出了它本可以另立门户的替代方案,并用「用户现有的设置」而不是「项目的方便」来说明好处。

  6. 06

    两种「让会话别再问」的方式,以及这一种为什么不同

    README 用一个同类工具来立论,开篇先劝用 tmux 的人留在原地,然后列出三点不同。其中一点是安全论证:对方的自动确认功能「绕过了 Claude Code 内置的安全确认——不推荐用于安全操作」。这个项目用另一条路提供同样的能力,并把它标为实验性:自动批准是用 AI 校验来决定要不要放行的,配一份自己的配置文档和一份 schema;而决定「等待」是什么意思的状态判定规则按助手分别可配,因为每种 CLI 宣告自己的方式都不同。同一种直觉也出现在更小的决定上——退出前加了一步确认,焦点默认落在「取消」,对话框还会说明有多少个会话会被终止;此前那个退出快捷键与「杀掉所有在跑的会话」之间只隔一次误触。

  7. 07

    规格写在一种工具里,却由另一种工具驱动

    有两个功能各自带一整套规格目录:一份需求文档加一份设计文档,一对是 34 KB,另一对是 52 KB。旁边还放着三份 steering 文档,分别讲产品、代码结构与技术选型。让这件事值得记下来的是这套流程由谁驱动:.claude/commands/ 下有十个斜杠命令——初始化、需求、设计、任务拆解、实现、状态,外加两个校验器和两个 steering 命令——用另一种 agent 工具去跑那套原本属于某一种工具的目录格式。仓库层面的 agent 材料按本档案的标准算克制:docs/ 下十三个文档(含一份 11 KB 的错误处理迁移方案和自动批准的配置),一个给助手插件系统用的插件目录,以及一个只有九字节的 AGENTS.md——那是一个链接,不是文件。

相关档案

全部档案 →