{"id":50846807,"url":"https://github.com/hughcube/worktree-bay","last_synced_at":"2026-06-14T10:30:23.376Z","repository":{"id":362742658,"uuid":"1260634194","full_name":"hughcube/worktree-bay","owner":"hughcube","description":"配置驱动的 git worktree 槽位 + 端口编排器，多服务并行开发利器","archived":false,"fork":false,"pushed_at":"2026-06-05T19:07:22.000Z","size":81,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-05T19:11:03.354Z","etag":null,"topics":["cli","developer-tools","git-worktree","monorepo","nodejs","orchestration","ports","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/worktree-bay","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hughcube.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-05T17:49:43.000Z","updated_at":"2026-06-05T19:07:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/hughcube/worktree-bay","commit_stats":null,"previous_names":["hughcube/worktree-bay"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/hughcube/worktree-bay","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hughcube%2Fworktree-bay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hughcube%2Fworktree-bay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hughcube%2Fworktree-bay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hughcube%2Fworktree-bay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hughcube","download_url":"https://codeload.github.com/hughcube/worktree-bay/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hughcube%2Fworktree-bay/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34318523,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-14T02:00:07.365Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","developer-tools","git-worktree","monorepo","nodejs","orchestration","ports","typescript"],"created_at":"2026-06-14T10:30:22.757Z","updated_at":"2026-06-14T10:30:23.371Z","avatar_url":"https://github.com/hughcube.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# worktree-bay\n\n[![npm version](https://img.shields.io/npm/v/worktree-bay.svg)](https://www.npmjs.com/package/worktree-bay)\n[![license](https://img.shields.io/npm/l/worktree-bay.svg)](./LICENSE)\n\n\u003e 配置驱动、与语言/技术栈无关的 **git worktree 槽位 + 端口编排器**——为多服务并行开发而生。\n\n一个功能来了，先**占一个槽位 `N`**，用到哪个服务就在哪个服务开一个 worktree 挂进这个槽。每个服务有自己的**端口段**，同槽的各服务都取段里的第 `N` 个端口（`服务基址 + N`）、各自独立进程，前端自动接上同槽的后端。工具替你管好 worktree 路径、端口分配、依赖、`.env` 注入与回收。\n\n## 为什么\n\n在 monorepo / 多仓工作区里并行开发多个功能时，git worktree 能隔离代码，但隔离不了运行时——端口会撞、依赖要重装、前端连不上你本地起在偏移端口的后端。`worktree-bay` 在 worktree 之上补一层「**功能 = 槽位**」的编排：\n\n- **端口不撞**：每个服务有自己的端口段，功能占槽 `N` → 各服务用 `自己的基址 + N`，与主 dev（槽 0）和其它槽天然错开。\n- **免重装**：依赖从主 checkout 拷贝（或按服务自定义安装命令），不必每个 worktree 从头装。\n- **前端自接后端**：前端按「同槽上游服务」自动把 api base 指向本槽后端端口。\n- **不泄漏**：槽位占用从文件系统派生；`gc` 合并感知回收（已并入主分支且干净才删，保守不误删）。\n\n## 安装\n\n```bash\nnpm i -g worktree-bay\n```\n\n需要 Node ≥ 20。\n\n\u003e 输出语言按系统区域自动切换中/英（识别不出时默认中文）。可用环境变量 `WORKTREE_BAY_LANG=zh|en` 强制指定。\n\n## 快速上手\n\n```bash\n# 一条命令起整个功能：自动占槽 + 在 api/lms 上开 worktree（分支默认 = 功能名）\n# -d 记录这个槽的用途，写进槽账本，ls 会显示、重入时参考（up/add/claim 都支持）\nworktree-bay up drill-fix api lms -d \"修演练页 bug\"\n\n# 看占用\nworktree-bay ls\n\n# 在服务运行体里跑命令（透传）\nworktree-bay run drill-fix api test\n\n# 拆除整个功能（默认查脏/未推保护，-f 强删）\nworktree-bay down drill-fix\n\n# 回收已合并的（默认 dry-run，--apply 实际执行）\nworktree-bay gc\n```\n\n\u003e 运行体随起随停（不动 worktree/代码）：`worktree-bay stop drill-fix` 停掉（docker 容器 + dev server 一起）、`start` 起回来、`restart` 重启。\n\u003e\n\u003e 更细的控制：`claim \u003cfeature\u003e` 单独占槽、`add \u003cfeature\u003e \u003cservice\u003e [branch]` 单加一个服务（branch 可自定义，省略则用功能名）、`down \u003cfeature\u003e \u003cservice\u003e` 只拆某个服务（省略服务则拆整功能）。\n\u003e\n\u003e dev server 起不来或报错？`worktree-bay logs \u003cfeature\u003e`（`--tail N` 调行数、`--prev` 看上一轮）直接看日志尾部排障——日志每次启动滚动，当前文件只含本轮。\n\n## 配置\n\n在工作区根放一份 `worktree-bay.config.json`，集中声明所有服务。工具运行时自下而上查找它（或用环境变量 `WORKTREE_BAY_CONFIG` 指定）。\n\n```jsonc\n{\n  \"workspaceRoot\": \"/path/to/workspace\",\n  \"maxSlots\": 9,\n  \"services\": {\n    \"api\": {\n      \"port\": 6001,                                                // 端口段基址（= 主 dev/槽0），槽 N 用 6001+N\n      \"vars\": { \"project\": \"myapi-{slug}\" },\n      \"copy\": [\".env\", \"vendor\"],                                  // 从主 checkout 递归拷文件/目录\n      \"env\": { \".env\": { \"APP_PORT\": \"{port}\" } },                 // 合并键值进 dotenv（保留其它键）\n      \"setup\": \"docker compose -p {project} up -d\",                // up 时执行（建运行体）\n      \"stop\": \"docker compose -p {project} stop\",                  // stop/restart 时执行（停而不毁）\n      \"teardown\": \"docker compose -p {project} down -v\",           // down 时执行（销毁）\n      \"exec\": [\"docker\", \"exec\", \"-i\", \"{project}-app-1\", \"{cmd...}\"], // 透传模板（argv）\n      \"run\": { \"test\": [\"composer\", \"run\", \"test\"] }               // 命名命令\n    },\n    \"lms\": {\n      \"port\": 6011,                                                // 与 api 段不重叠（间距 \u003e maxSlots）\n      \"upstream\": { \"service\": \"api\", \"fallback\": \"http://localhost:6001\" }, // → {upstreamBase}\n      \"env\": { \".env.dev.local\": { \"VITE_API_BASE_URL\": \"{upstreamBase}\" } },\n      \"setup\": \"pnpm install\",\n      \"start\": \"pnpm dev --port {port}\"                            // 长进程 dev server：up 时自动后台启动\n    }\n  }\n}\n```\n\n### 原语\n\n| 原语 | 说明 |\n|---|---|\n| `port`（必填） | 本服务端口段基址（= 主 dev/槽0）；槽 N 端口 = `port + N`；各服务的段 `[port, port+maxSlots]` 互不重叠 |\n| `repo` | 仓库目录名（相对 workspaceRoot），默认 = 服务名 |\n| `vars` | 自定义模板变量 |\n| `copy` | 从主 checkout 递归拷贝的文件/目录（含依赖目录） |\n| `env` | 按文件合并 dotenv 键值，文件不存在则建 |\n| `upstream` | 声明依赖的上游服务，产出 `{upstreamBase}` |\n| `setup` / `teardown` | 建立 / 销毁运行体的 shell（`up` 时 setup、`down` 时 teardown） |\n| `start` | 长进程 dev server（如 `pnpm dev`），`up` 时自动**后台启动**、日志落 `.worktree-bay/logs/`，由 `start`/`stop`/`restart` 控制 |\n| `stop` | 停止 infra 运行体的 shell（如 `docker compose stop`），供 `stop`/`restart` 用（让 docker 停而不毁） |\n| `exec` | 透传命令模板（argv 数组，`{cmd...}` splice） |\n| `run` | 命名命令（argv 数组），供 `worktree-bay run \u003cfeature\u003e \u003cservice\u003e \u003cname\u003e` |\n\n### 模板变量\n\n`{slot}` `{port}` `{slug}` `{worktree}` `{repo}` `{upstreamBase}` `{cmd...}`，以及 `vars` 里自定义的。\n\n## 工作原理\n\n- **按服务分段**：每个服务有自己的端口段（基址 `port` = 主 dev/槽0），功能占槽 `N`（1..`maxSlots`）→ 该服务用 `port + N`。服务数量无上限，各段不重叠即可。\n- **占用从文件系统派生**：槽是否被占，看各服务 `\u003crepo\u003e/.worktrees/s\u003cN\u003e-*` 目录是否存在；`.worktree-bay-slots.json` 只是「功能名 → 槽号」的标签账本（预约）。删了 worktree，槽自动空出。\n- **并发安全**：`claim/add/rm/gc` 全程持工作区原子锁。\n- **前端自接**：前端有 `upstream` 时，若同槽已起该上游服务的 worktree，就把 api base 指向本槽端口；否则用 `fallback`。\n- **合并感知回收**：`gc` 先 `git fetch`，用 `merge-base --is-ancestor` 判断是否并入主分支；**只在「已合并 + 工作区干净 + 无未推」时才自动删**，判不准一律保守不删、只标记。\n\n## Shell 补全\n\n一条命令装好（自动探测 shell、幂等写入对应 rc；fish 直接写补全目录）：\n\n```bash\nworktree-bay completion install\n```\n\n执行 `source ~/.bashrc`（或重开终端）即可 tab 补全子命令、功能名、服务名。也可手动：`worktree-bay completion bash`（打印脚本，自行接入）。\n\n## MCP（让 AI 直接用）\n\n内置一个 MCP 服务，让 AI（Claude Code 等）通过 MCP 调用 worktree-bay 完成并行开发，并内置工作流指导（三层模型 + 何时用 doctor/up/path/run/start-stop-restart/down/gc）。\n\n启动：`worktree-bay mcp`（stdio）。在 Claude Code 里注册（项目级 `.mcp.json` 或全局，跨平台、无需写死路径）：\n\n```json\n{\n  \"mcpServers\": {\n    \"worktree-bay\": { \"command\": \"worktree-bay\", \"args\": [\"mcp\"] }\n  }\n}\n```\n\n\u003e 服务在哪个工作区目录启动，就用哪个目录的 `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 调用时自动以非交互模式运行（输出不含颜色/进度控制符）。\n\n## 许可证\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhughcube%2Fworktree-bay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhughcube%2Fworktree-bay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhughcube%2Fworktree-bay/lists"}