monorepo-setup-worktrees
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMonorepo Worktree System
单体仓库(Monorepo)工作区系统
Scope-based worktree isolation for parallel development streams. Each worktree gets isolated Docker services, databases, and domains.
基于作用域的工作区隔离,支持并行开发流。每个工作区都拥有独立的Docker服务、数据库和域名。
Scopes
作用域(Scopes)
| Scope | Services | Containers | Create time |
|---|---|---|---|
| Elements runner + dev-projects only | 2 | ~28s |
| Elements + telecine core (web, hasura, valkey, maintenance) | 8 | ~1:30 |
| Elements + telecine core + render pipeline (workers, scheduler) | ~22 | ~2:30 |
Upgrade path: → → . Downgrade not supported.
elementswebrender| 作用域 | 服务内容 | 容器数量 | 创建时间 |
|---|---|---|---|
| 仅包含Elements运行器和dev-projects | 2 | ~28秒 |
| Elements + Telecine核心服务(web、hasura、valkey、维护服务) | 8 | ~1分30秒 |
| Elements + Telecine核心服务 + 渲染流水线(工作节点、调度器) | ~22 | ~2分30秒 |
升级路径: → → 。不支持降级操作。
elementswebrenderWorktree Management
工作区管理
All worktree operations use the unified CLI: .
scripts/worktree <command>bash
worktree create <branch> [scope] # Create new worktree (default: web)
worktree list # List all worktrees
worktree status [branch] # Health check
worktree pause <branch> # Stop containers
worktree resume <branch> # Start containers
worktree remove <branch> [--force] # Full cleanup
worktree upgrade <branch> <scope> # Escalate scope (elements→web→render)
worktree merge <branch> # Merge branch into main (feature → main)
worktree pull # Fetch upstream, update local main, sync main → all worktrees
worktree prune [--dry-run] # Remove worktrees whose branches are fully merged into main
worktree smoke <branch> # One-shot render verification
worktree logs [branch] [options] # View logs
worktree doctor [branch] [--skills] # Diagnose issues
worktree editor-deps [branch] # Install host-side node_modules for editor tooling
worktree deps [--workspace=...] # Show dependency graph所有工作区操作均使用统一CLI:。
scripts/worktree <command>bash
worktree create <branch> [scope] # 创建新工作区(默认作用域:web)
worktree list # 列出所有工作区
worktree status [branch] # 健康检查
worktree pause <branch> # 停止容器
worktree resume <branch> # 启动容器
worktree remove <branch> [--force] # 完全清理
worktree upgrade <branch> <scope> # 升级作用域(elements→web→render)
worktree merge <branch> # 将分支合并到main(特性分支→主分支)
worktree pull # 获取上游代码、更新本地main分支、同步main到所有工作区
worktree prune [--dry-run] # 删除已完全合并到main的工作区分支
worktree smoke <branch> # 一次性渲染验证
worktree logs [branch] [options] # 查看日志
worktree doctor [branch] [--skills] # 诊断问题
worktree editor-deps [branch] # 为编辑器工具安装主机端node_modules
worktree deps [--workspace=...] # 显示依赖关系图Architecture
架构
Repo layout
代码库布局
~/Editframe/
monorepo -> worktrees/main/monorepo (symlink for convenience)
worktrees/
main/
.worktree-scope # scope for main (e.g. "render")
monorepo/ # primary monorepo checkout [main]
telecine -> ../telecine # symlink
elements -> ../elements # symlink
telecine/ # primary telecine clone [main]
elements/ # primary elements clone [main]
<branch>/
.worktree-scope # scope for this branch
monorepo/ # monorepo worktree [branch]
telecine/ # telecine git worktree [branch]
elements/ # elements git worktree [branch]The main worktree () must always be on the branch. Never run , , or any branch-switching command in the main worktree directories. All feature work lives in a dedicated branch worktree created with . An LLM agent is most likely to violate this by running directly, treating the main worktree like a normal single-checkout repo, or using merge patterns that require a prior checkout.
worktrees/main/maingit checkoutgit switchworktree creategit checkout <branch>scripts/worktree.ts- asserts the main worktree is on
cmdCreatebefore creating any new worktree, and always bases new branches offmain.main - asserts each repo is already on
cmdMergeand merges without a checkout — never callsmainin the main worktree.git checkout
~/Editframe/monorepo~/Editframe/
monorepo -> worktrees/main/monorepo (方便使用的符号链接)
worktrees/
main/
.worktree-scope # main分支的作用域(例如:"render")
monorepo/ # 主单体仓库检出目录 [main]
telecine -> ../telecine # 符号链接
elements -> ../elements # 符号链接
telecine/ # Telecine主分支的主克隆目录 [main]
elements/ # Elements主分支的主克隆目录 [main]
<branch>/
.worktree-scope # 当前分支的作用域
monorepo/ # 单体仓库工作区 [分支]
telecine/ # Telecine Git工作区 [分支]
elements/ # Elements Git工作区 [分支]主工作区()必须始终处于分支。绝不要在主工作区目录中运行、或任何分支切换命令。所有特性开发工作都应在通过创建的专用分支工作区中进行。LLM Agent很可能会违反此规则,直接运行,将主工作区当作普通单检出代码库处理,或使用需要提前切换分支的合并模式。
worktrees/main/maingit checkoutgit switchworktree creategit checkout <branch>scripts/worktree.ts- 在创建任何新工作区之前,会验证主工作区是否处于
cmdCreate分支,并且始终基于main分支创建新分支。main - 会验证每个代码库已处于
cmdMerge分支,并在不切换分支的情况下完成合并——绝不会在主工作区中调用main。git checkout
~/Editframe/monorepoWorking in a branch worktree as an agent
Agent在分支工作区中的操作方式
An agent's working directory is fixed at launch — typically . There is no persistent . After creating or identifying a branch worktree, every file edit, git command, and script invocation must use the full absolute path rooted at the branch worktree, not a relative path from the agent's cwd.
worktrees/main/monorepocdGiven branch the worktree root is . Concrete rules:
my-feature~/Editframe/worktrees/my-feature/monorepo/- File reads/edits: absolute paths under
~/Editframe/worktrees/my-feature/monorepo/ - Git operations: or use the
git -C ~/Editframe/worktrees/my-feature/monorepo <command>parameter in tool callsworkdir - Elements scripts:
~/Editframe/worktrees/my-feature/elements/scripts/<script> - Telecine scripts:
~/Editframe/worktrees/my-feature/telecine/scripts/<script> - Never use relative paths or paths under for branch work
worktrees/main/
To find the root for an existing branch:
git worktree list | grep my-featureEDITFRAME_DIR$(dirname $(dirname $(dirname $(git rev-parse --show-toplevel))))Agent的工作目录在启动时是固定的——通常为。不存在持久化的操作。创建或定位到分支工作区后,所有文件编辑、Git命令和脚本调用都必须使用分支工作区根目录的完整绝对路径,而非相对于Agent当前工作目录的相对路径。
worktrees/main/monorepocd假设分支名为,其工作区根目录为。具体规则如下:
my-feature~/Editframe/worktrees/my-feature/monorepo/- 文件读取/编辑:使用下的绝对路径
~/Editframe/worktrees/my-feature/monorepo/ - Git操作:使用,或在工具调用中使用
git -C ~/Editframe/worktrees/my-feature/monorepo <command>参数workdir - Elements脚本:
~/Editframe/worktrees/my-feature/elements/scripts/<script> - Telecine脚本:
~/Editframe/worktrees/my-feature/telecine/scripts/<script> - 绝不要使用相对路径或下的路径进行分支工作
worktrees/main/
查找现有分支的根目录:
git worktree list | grep my-feature脚本中的始终为——即单体仓库检出路径向上三级目录。
EDITFRAME_DIR$(dirname $(dirname $(dirname $(git rev-parse --show-toplevel))))Shared infrastructure
共享基础设施
- — single shared PostgreSQL, each worktree gets its own database (
editframe-postgres)telecine-<branch> - — shared reverse proxy, routes by
editframe-traefikheader (Host)<branch>.localhost - /
telecine-runner— shared Docker images (not rebuilt per worktree)elements-runner
- —— 单个共享PostgreSQL实例,每个工作区拥有自己的数据库(
editframe-postgres)telecine-<branch> - —— 共享反向代理,通过
editframe-traefik头路由(Host)<branch>.localhost - /
telecine-runner—— 共享Docker镜像(不会为每个工作区重新构建)elements-runner
Database template
数据库模板
telecine-templatetelecine-maintelecine/scripts/starttelecine-templatetelecine-maintelecine/scripts/startPort offsets
端口偏移
Worktree services use -based port offsets (200 slots, spacing of 100) so host tools like Postico can connect. Main worktree uses standard ports.
cksum工作区服务使用基于的端口偏移(200个可用槽位,间隔为100),以便Postico等主机工具可以连接。主工作区使用标准端口。
cksumConfig scripts
配置脚本
- — exports
telecine/scripts/worktree-config,WORKTREE_ID,WORKTREE_DATABASE,WORKTREE_DOMAIN, port variablesWORKTREE_DOCKER_PROJECT_NAME - — same pattern for elements
elements/scripts/worktree-config - file in monorepo worktree root tracks current scope
.worktree-scope
- —— 导出
telecine/scripts/worktree-config、WORKTREE_ID、WORKTREE_DATABASE、WORKTREE_DOMAIN及端口变量WORKTREE_DOCKER_PROJECT_NAME - —— Elements采用相同的配置模式
elements/scripts/worktree-config - 单体仓库工作区根目录下的文件跟踪当前作用域
.worktree-scope
Docker Compose profiles
Docker Compose配置文件
- No profile = core services (always start): runner, web, valkey, graphql-engine, data-connector-agent, maintenance
- profile: all worker services, scheduler-go, jit-transcoding
render - profile: tracing, otel-viewer, mailhog, playwright
dev - reads
telecine/scripts/startto set.worktree-scopeCOMPOSE_PROFILES
- 无配置文件 = 核心服务(始终启动):运行器、web、valkey、graphql-engine、data-connector-agent、维护服务
- 配置文件:所有工作节点服务、scheduler-go、即时转码服务
render - 配置文件:链路追踪、otel-viewer、mailhog、playwright
dev - 读取
telecine/scripts/start来设置.worktree-scopeCOMPOSE_PROFILES
Service startup ordering
服务启动顺序
Runner must start and must complete before other services that execute application code (web, dev-projects, workers). The create and upgrade scripts handle this: → → (remaining services).
npm installup -d runnernpm installup -d运行器必须先启动,且必须完成后,才能启动其他执行应用代码的服务(web、dev-projects、工作节点)。创建和升级脚本会处理此顺序: → → (剩余服务)。
npm installup -d runnernpm installup -dSyncing main into worktrees
将main分支同步到工作区
After PRs merge to main (which happens frequently), run from the main worktree:
worktree pullbash
worktree pullThis does three things in sequence:
- Fetches upstream remotes for monorepo, telecine, and elements
- Merges into local main for telecine and elements (fast-forward when clean)
origin/main - Merges local main into every active worktree branch
Conflicts in , , and are auto-resolved by accepting main's version. All other conflicts are reported and skipped — the affected worktree is left untouched for manual resolution.
package.jsonpackage-lock.jsonVERSION.tsTo clean up worktrees whose branches have been fully merged into main across all three repos:
bash
worktree prune # remove all fully-merged worktrees
worktree prune --dry-run # preview what would be removedprune当PR频繁合并到main分支后,在主工作区中运行:
worktree pullbash
worktree pull该命令会依次执行以下三个操作:
- 获取单体仓库、Telecine和Elements的上游远程代码
- 将合并到Telecine和Elements的本地main分支(无冲突时执行快进合并)
origin/main - 将本地main分支合并到每个活跃的工作区分支
package.jsonpackage-lock.jsonVERSION.ts要清理已在所有三个代码库中完全合并到main分支的工作区:
bash
worktree prune # 删除所有已完全合并的工作区
worktree prune --dry-run # 预览将要删除的内容pruneWorktree lifecycle
工作区生命周期
create (elements, 28s) → upgrade (web, 63s) → upgrade (render)
↓ ↓
pause/resume pause/resume
↓
removecreate(elements,28秒)→ upgrade(web,63秒)→ upgrade(render)
↓ ↓
pause/resume pause/resume
↓
removeDev Server URLs
开发服务器URL
The elements dev-projects Vite server uses . Files are served at the root path — not under .
root: elements/dev-projects//dev-projects/- →
video.htmlhttp://<branch>.localhost:4321/video.html - →
canvas-demo.htmlhttp://<branch>.localhost:4321/canvas-demo.html
Never include in the URL path.
dev-projects/Elements dev-projects Vite服务器使用。文件在根路径下提供服务——不要放在路径下。
root: elements/dev-projects//dev-projects/- →
video.htmlhttp://<branch>.localhost:4321/video.html - →
canvas-demo.htmlhttp://<branch>.localhost:4321/canvas-demo.html
绝不要在URL路径中包含。
dev-projects/dev-projects in worktrees
工作区中的dev-projects
elements/dev-projects/worktree createDEV_PROJECTS_HOSTelements/.envdocker-compose.yaml/packages/dev-projectselements/dev-projects/worktree createelements/.envDEV_PROJECTS_HOSTdocker-compose.yaml/packages/dev-projectsSmoke testing
冒烟测试
worktree smoke <branch>- Requires or
webscope (errors onrender)elements - If scope is : temporarily starts render-profile services, registers a cleanup trap to stop them on exit
web - If scope is : runs against already-running services, no lifecycle management
render - Runs inside the runner container with
telecine/scripts/smoke-test.tsand the worktree'sEF_HOST=http://web:3000EF_TOKEN - Prints the dashboard URL () for visual inspection of render outputs
http://<branch>.localhost:3000 - Prompts to press enter before stopping render services (if they were started)
Render development workflow: stay at scope, run unit tests directly, use as the merge gate rather than keeping a full render stack running all day.
webworktree smokescheduler-goworktree smokescripts/build-runner-imagesworktree smoke <branch>- 需要或
web作用域(使用render作用域会报错)elements - 如果是作用域:临时启动render配置文件中的服务,并注册清理陷阱以在退出时停止这些服务
web - 如果是作用域:针对已运行的服务执行测试,不进行生命周期管理
render - 在运行器容器中执行,使用
telecine/scripts/smoke-test.ts和工作区的EF_HOST=http://web:3000EF_TOKEN - 打印仪表盘URL(),用于可视化检查渲染输出
http://<branch>.localhost:3000 - 在停止渲染服务(如果已启动)前,提示按回车键确认
渲染开发工作流:保持在作用域,直接运行单元测试,使用作为合并检查环节,而非全天运行完整的渲染栈。
webworktree smokescheduler-goworktree smokescripts/build-runner-imagesEditor tooling
编辑器工具
Docker containers use named volumes for , which are invisible to the host filesystem. The host-side editor (VS Code, Cursor, etc.) needs its own to resolve TypeScript types and JSX intrinsics.
node_modulesnode_modulesworktree createnpm install --ignore-scriptsworktree editor-deps <branch>worktree doctorDocker容器使用命名卷存储,这些卷对主机文件系统不可见。主机端编辑器(VS Code、Cursor等)需要自己的来解析TypeScript类型和JSX内置组件。
node_modulesnode_modulesworktree createnpm install --ignore-scriptsworktree editor-deps <branch>worktree doctorTroubleshooting
故障排除
- Port conflict: two branches hashed to same offset. Extremely unlikely with cksum/200 slots but possible. Remove one worktree and recreate.
- Orphaned containers: detects orphaned projects (containers with no matching git worktree) and prints the exact
worktree doctorcommand to clean them up.docker rm -f - Partial create failure: if fails partway through, the worktree directory exists but is incomplete. Run
worktree createbefore retrying.worktree remove --force <branch> - Stale template: run to refresh from current main DB state.
scripts/update-template-db
- 端口冲突:两个分支哈希到相同的偏移量。虽然使用cksum/200槽位时概率极低,但仍有可能发生。删除其中一个工作区并重新创建。
- 孤立容器:会检测孤立项目(无匹配Git工作区的容器),并打印用于清理的精确
worktree doctor命令。docker rm -f - 创建失败:如果中途失败,工作区目录已存在但不完整。重新尝试前运行
worktree create。worktree remove --force <branch> - 模板过期:运行从当前main分支数据库状态刷新模板。
scripts/update-template-db