An open API service indexing awesome lists of open source software.

https://github.com/hughcube/worktree-bay

配置驱动的 git worktree 槽位 + 端口编排器,多服务并行开发利器
https://github.com/hughcube/worktree-bay

cli developer-tools git-worktree monorepo nodejs orchestration ports typescript

Last synced: about 1 month ago
JSON representation

配置驱动的 git worktree 槽位 + 端口编排器,多服务并行开发利器

Awesome Lists containing this project

README

          

# worktree-bay

[![npm version](https://img.shields.io/npm/v/worktree-bay.svg)](https://www.npmjs.com/package/worktree-bay)
[![license](https://img.shields.io/npm/l/worktree-bay.svg)](./LICENSE)

> 配置驱动、与语言/技术栈无关的 **git worktree 槽位 + 端口编排器**——为多服务并行开发而生。

一个功能来了,先**占一个槽位 `N`**,用到哪个服务就在哪个服务开一个 worktree 挂进这个槽。每个服务有自己的**端口段**,同槽的各服务都取段里的第 `N` 个端口(`服务基址 + N`)、各自独立进程,前端自动接上同槽的后端。工具替你管好 worktree 路径、端口分配、依赖、`.env` 注入与回收。

## 为什么

在 monorepo / 多仓工作区里并行开发多个功能时,git worktree 能隔离代码,但隔离不了运行时——端口会撞、依赖要重装、前端连不上你本地起在偏移端口的后端。`worktree-bay` 在 worktree 之上补一层「**功能 = 槽位**」的编排:

- **端口不撞**:每个服务有自己的端口段,功能占槽 `N` → 各服务用 `自己的基址 + N`,与主 dev(槽 0)和其它槽天然错开。
- **免重装**:依赖从主 checkout 拷贝(或按服务自定义安装命令),不必每个 worktree 从头装。
- **前端自接后端**:前端按「同槽上游服务」自动把 api base 指向本槽后端端口。
- **不泄漏**:槽位占用从文件系统派生;`gc` 合并感知回收(已并入主分支且干净才删,保守不误删)。

## 安装

```bash
npm i -g worktree-bay
```

需要 Node ≥ 20。

> 输出语言按系统区域自动切换中/英(识别不出时默认中文)。可用环境变量 `WORKTREE_BAY_LANG=zh|en` 强制指定。

## 快速上手

```bash
# 一条命令起整个功能:自动占槽 + 在 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 ` 单独占槽、`add [branch]` 单加一个服务(branch 可自定义,省略则用功能名)、`down ` 只拆某个服务(省略服务则拆整功能)。
>
> dev server 起不来或报错?`worktree-bay logs `(`--tail N` 调行数、`--prev` 看上一轮)直接看日志尾部排障——日志每次启动滚动,当前文件只含本轮。

## 配置

在工作区根放一份 `worktree-bay.config.json`,集中声明所有服务。工具运行时自下而上查找它(或用环境变量 `WORKTREE_BAY_CONFIG` 指定)。

```jsonc
{
"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 时自动后台启动
}
}
}
```

### 原语

| 原语 | 说明 |
|---|---|
| `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 ` |

### 模板变量

`{slot}` `{port}` `{slug}` `{worktree}` `{repo}` `{upstreamBase}` `{cmd...}`,以及 `vars` 里自定义的。

## 工作原理

- **按服务分段**:每个服务有自己的端口段(基址 `port` = 主 dev/槽0),功能占槽 `N`(1..`maxSlots`)→ 该服务用 `port + N`。服务数量无上限,各段不重叠即可。
- **占用从文件系统派生**:槽是否被占,看各服务 `/.worktrees/s-*` 目录是否存在;`.worktree-bay-slots.json` 只是「功能名 → 槽号」的标签账本(预约)。删了 worktree,槽自动空出。
- **并发安全**:`claim/add/rm/gc` 全程持工作区原子锁。
- **前端自接**:前端有 `upstream` 时,若同槽已起该上游服务的 worktree,就把 api base 指向本槽端口;否则用 `fallback`。
- **合并感知回收**:`gc` 先 `git fetch`,用 `merge-base --is-ancestor` 判断是否并入主分支;**只在「已合并 + 工作区干净 + 无未推」时才自动删**,判不准一律保守不删、只标记。

## Shell 补全

一条命令装好(自动探测 shell、幂等写入对应 rc;fish 直接写补全目录):

```bash
worktree-bay completion install
```

执行 `source ~/.bashrc`(或重开终端)即可 tab 补全子命令、功能名、服务名。也可手动:`worktree-bay completion bash`(打印脚本,自行接入)。

## MCP(让 AI 直接用)

内置一个 MCP 服务,让 AI(Claude Code 等)通过 MCP 调用 worktree-bay 完成并行开发,并内置工作流指导(三层模型 + 何时用 doctor/up/path/run/start-stop-restart/down/gc)。

启动:`worktree-bay mcp`(stdio)。在 Claude Code 里注册(项目级 `.mcp.json` 或全局,跨平台、无需写死路径):

```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` 列出全部服务名,`ls` JSON 返回各 worktree 路径与 `▸run`,`path` 给某功能某服务目录,`start/stop/restart` 控制运行体,`down` 可只拆单个服务,`logs` 看 dev server 日志排障,`skill` 取完整指南)。MCP 调用时自动以非交互模式运行(输出不含颜色/进度控制符)。

## 许可证

[MIT](./LICENSE)