配置驱动、与语言/技术栈无关的 git worktree 槽位 + 端口编排器——为多服务并行开发而生。
一个功能来了,先占一个槽位 N,用到哪个服务就在哪个服务开一个 worktree 挂进这个槽。每个服务有自己的端口段,同槽的各服务都取段里的第 N 个端口(服务基址 + N)、各自独立进程,前端自动接上同槽的后端。工具替你管好 worktree 路径、端口分配、依赖、.env 注入与回收。
在 monorepo / 多仓工作区里并行开发多个功能时,git worktree 能隔离代码,但隔离不了运行时——端口会撞、依赖要重装、前端连不上你本地起在偏移端口的后端。worktree-bay 在 worktree 之上补一层「功能 = 槽位」的编排:
- 端口不撞:每个服务有自己的端口段,功能占槽
N→ 各服务用自己的基址 + N,与主 dev(槽 0)和其它槽天然错开。 - 免重装:依赖从主 checkout 拷贝(或按服务自定义安装命令),不必每个 worktree 从头装。
- 前端自接后端:前端按「同槽上游服务」自动把 api base 指向本槽后端端口。
- 不泄漏:槽位占用从文件系统派生;
gc合并感知回收(已并入主分支且干净才删,保守不误删)。
npm i -g worktree-bay需要 Node ≥ 20。
输出语言按系统区域自动切换中/英(识别不出时默认中文)。可用环境变量
WORKTREE_BAY_LANG=zh|en强制指定。
# 一条命令起整个功能:自动占槽 + 在 api/lms 上开 worktree(分支默认 = 功能名)
# -d 记录这个槽的用途,写进槽账本,ls 会显示、重入时参考(up/add/claim 都支持)
worktree-bay up drill-fix api lms -d "修演练页 bug"
# 看占用
worktree-bay ls
# 在服务运行体里跑命令(透传)
worktree-bay run drill-fix api test
# 拆除整个功能(默认查脏/未推保护,-f 强删)
worktree-bay down drill-fix
# 回收已合并的(默认 dry-run,--apply 实际执行)
worktree-bay gc运行体随起随停(不动 worktree/代码):
worktree-bay stop drill-fix停掉(docker 容器 + dev server 一起)、start起回来、restart重启。更细的控制:
claim <feature>单独占槽、add <feature> <service> [branch]单加一个服务(branch 可自定义,省略则用功能名)、down <feature> <service>只拆某个服务(省略服务则拆整功能)。dev server 起不来或报错?
worktree-bay logs <feature>(--tail N调行数、--prev看上一轮)直接看日志尾部排障——日志每次启动滚动,当前文件只含本轮。
在工作区根放一份 worktree-bay.config.json,集中声明所有服务。工具运行时自下而上查找它(或用环境变量 WORKTREE_BAY_CONFIG 指定)。
| 原语 | 说明 |
|---|---|
port(必填) |
本服务端口段基址(= 主 dev/槽0);槽 N 端口 = port + N;各服务的段 [port, port+maxSlots] 互不重叠 |
repo |
仓库目录名(相对 workspaceRoot),默认 = 服务名 |
vars |
自定义模板变量 |
copy |
从主 checkout 递归拷贝的文件/目录(含依赖目录) |
env |
按文件合并 dotenv 键值,文件不存在则建 |
upstream |
声明依赖的上游服务,产出 {upstreamBase} |
setup / teardown |
建立 / 销毁运行体的 shell(up 时 setup、down 时 teardown) |
start |
长进程 dev server(如 pnpm dev),up 时自动后台启动、日志落 .worktree-bay/logs/,由 start/stop/restart 控制 |
stop |
停止 infra 运行体的 shell(如 docker compose stop),供 stop/restart 用(让 docker 停而不毁) |
exec |
透传命令模板(argv 数组,{cmd...} splice) |
run |
命名命令(argv 数组),供 worktree-bay run <feature> <service> <name> |
{slot} {port} {slug} {worktree} {repo} {upstreamBase} {cmd...},以及 vars 里自定义的。
- 按服务分段:每个服务有自己的端口段(基址
port= 主 dev/槽0),功能占槽N(1..maxSlots)→ 该服务用port + N。服务数量无上限,各段不重叠即可。 - 占用从文件系统派生:槽是否被占,看各服务
<repo>/.worktrees/s<N>-*目录是否存在;.worktree-bay-slots.json只是「功能名 → 槽号」的标签账本(预约)。删了 worktree,槽自动空出。 - 并发安全:
claim/add/rm/gc全程持工作区原子锁。 - 前端自接:前端有
upstream时,若同槽已起该上游服务的 worktree,就把 api base 指向本槽端口;否则用fallback。 - 合并感知回收:
gc先git fetch,用merge-base --is-ancestor判断是否并入主分支;只在「已合并 + 工作区干净 + 无未推」时才自动删,判不准一律保守不删、只标记。
一条命令装好(自动探测 shell、幂等写入对应 rc;fish 直接写补全目录):
worktree-bay completion install执行 source ~/.bashrc(或重开终端)即可 tab 补全子命令、功能名、服务名。也可手动:worktree-bay completion bash(打印脚本,自行接入)。
内置一个 MCP 服务,让 AI(Claude Code 等)通过 MCP 调用 worktree-bay 完成并行开发,并内置工作流指导(三层模型 + 何时用 doctor/up/path/run/start-stop-restart/down/gc)。
启动:worktree-bay mcp(stdio)。在 Claude Code 里注册(项目级 .mcp.json 或全局,跨平台、无需写死路径):
{
"mcpServers": {
"worktree-bay": { "command": "worktree-bay", "args": ["mcp"] }
}
}服务在哪个工作区目录启动,就用哪个目录的
worktree-bay.config.json(cwd 自动向上查找,无需写死路径;也可设WORKTREE_BAY_CONFIG)。暴露的工具:worktree_bay_doctor / ls / up / claim / add / path / run / start / stop / restart / down / logs / gc / init / skill(doctor列出全部服务名,lsJSON 返回各 worktree 路径与▸run,path给某功能某服务目录,start/stop/restart控制运行体,down可只拆单个服务,logs看 dev server 日志排障,skill取完整指南)。MCP 调用时自动以非交互模式运行(输出不含颜色/进度控制符)。
{ "workspaceRoot": "/path/to/workspace", "maxSlots": 9, "services": { "api": { "port": 6001, // 端口段基址(= 主 dev/槽0),槽 N 用 6001+N "vars": { "project": "myapi-{slug}" }, "copy": [".env", "vendor"], // 从主 checkout 递归拷文件/目录 "env": { ".env": { "APP_PORT": "{port}" } }, // 合并键值进 dotenv(保留其它键) "setup": "docker compose -p {project} up -d", // up 时执行(建运行体) "stop": "docker compose -p {project} stop", // stop/restart 时执行(停而不毁) "teardown": "docker compose -p {project} down -v", // down 时执行(销毁) "exec": ["docker", "exec", "-i", "{project}-app-1", "{cmd...}"], // 透传模板(argv) "run": { "test": ["composer", "run", "test"] } // 命名命令 }, "lms": { "port": 6011, // 与 api 段不重叠(间距 > maxSlots) "upstream": { "service": "api", "fallback": "http://localhost:6001" }, // → {upstreamBase} "env": { ".env.dev.local": { "VITE_API_BASE_URL": "{upstreamBase}" } }, "setup": "pnpm install", "start": "pnpm dev --port {port}" // 长进程 dev server:up 时自动后台启动 } } }