Worktrunk 扩展机制完全指南:Hooks 生命周期钩子、Aliases 别名与自定义子命令实战
2026/9/16 17:42:42 网站建设 项目流程

Worktrunk 扩展机制完全指南:Hooks 生命周期钩子、Aliases 别名与自定义子命令实战

【免费下载链接】worktrunkWorktrunk is a CLI for Git worktree management, designed for parallel AI agent workflows项目地址: https://gitcode.com/GitHub_Trending/wo/worktrunk

本文系统讲解 Worktrunk(Git worktree 管理 CLI,专为并行 AI Agent 工作流设计)提供的三种扩展机制:Hooks(生命周期钩子)Aliases(别名命令)Custom subcommands(自定义子命令)。通过本文,你将掌握如何在.config/wt.toml中配置自动化钩子与可复用别名、如何编写多步骤流水线、如何利用模板引擎做智能参数路由与延迟展开,以及如何通过PATH上的wt-<name>可执行文件扩展任意语言的子命令——让 Worktrunk 完全贴合你的团队与工作流。

三种扩展机制总览

Worktrunk 的扩展能力由三套机制构成,它们触发方式、定义位置与能力边界各不相同:

HooksAliasesCustom subcommands
触发方式自动(生命周期事件)手动(wt <name>手动(wt <name>
定义位置TOML 配置TOML 配置PATH上的任意可执行文件
模板变量支持支持不支持
通过仓库共享.config/wt.toml.config/wt.toml分发二进制
语言Shell 命令Shell 命令任意语言

Hooks 与 Aliases 存放在同一份 TOML 配置中,共享同一套模板引擎。用户配置(~/.config/worktrunk/config.toml)被信任,项目配置(.config/wt.toml)首次运行需要审批;当用户与项目配置定义了同名条目时,两者都会执行,用户优先

命令解析优先级

从源码看,顶层命令解析遵循严格的优先级链(见 src/commands/custom.rs):内置命令 → 别名(Alias)→PATH上的wt-<name>可执行文件

  • 内置命令永远优先:clap 只有在没有匹配到内置子命令时才会进入Commands::Custom分发分支,因此不存在用别名或PATH上的wt-switch覆盖wt switch的可能;
  • 别名优先于 PATH 二进制:解析到别名后即走try_alias路径执行(用户配置优先于项目配置),同一名字的 PATH 二进制不会被调用;且别名执行需要处于 git 仓库内,在仓库外会直接报"别名只能在 git 仓库内运行"并终止,不会回退到 PATH 二进制;
  • 两者皆无:合成 clap 原生的InvalidSubcommand错误(错误提示的 "did you mean" 候选会混入已配置的别名名),并附带嵌套子命令提示(如wt squashperhaps wt step squash?)。

这一解析逻辑在 tests/integration_tests/custom.rs 中有完整测试覆盖,包括wt wt-test-extcmd-ok能找到PATH上的wt-wt-test-extcmd-ok并透传参数。

Hooks:五个生命周期事件 × 十个钩子

Hooks 覆盖五个生命周期事件——switch(切换)、start(创建)、commit(提交)、merge(合并)、remove(移除)——每个事件各有一个阻塞式pre-变体(失败即中止操作)与一个后台post-变体:

事件pre-(阻塞)post-(后台)
switchpre-switchpost-switch
createpre-startpost-start
commitpre-commitpost-commit
mergepre-mergepost-merge
removepre-removepost-remove

各钩子的定位与典型用途(详细参考见 hook.md):

钩子用途
pre-switch切换前在源 worktree 中运行——无论创建、切换到已有分支还是停留在当前分支
post-switch所有切换结果后触发:创建、切换到已有、停留在当前
pre-start新 worktree 创建时运行一次,阻塞post-start/--execute直至完成:依赖安装、env 文件生成
post-start新 worktree 创建时后台运行一次:dev server、长构建、文件监听、缓存复制
pre-commit格式化、lint、类型检查——在任何 Worktrunk 提交(wt step commitwt step squashwt merge产生的提交)之前运行
post-commitCI 触发、通知、后台 lint
pre-merge测试、安全扫描、构建验证——在 rebase 之后、合并到目标之前运行
post-merge部署、通知、安装更新后的二进制。在目标分支的 worktree 中运行(不存在则在主 worktree)
pre-removeworktree 删除前的清理:保存测试产物、备份状态。在待删除的 worktree 中运行
post-remove停止 dev server、移除容器、通知外部系统。模板变量指向已移除的 worktree

最常用的创建钩子是post-start——它以后台方式运行任务(dev server、文件复制、构建),不阻塞 worktree 创建。除非后续步骤必须等该任务完成,否则优先post-start而非pre-start

最简单的 TOML 配置示例:

[pre-start] deps = "npm ci" [post-start] server = "npm run dev -- --port {{ branch | hash_port }}" [pre-merge] test = "npm test"

合并流水线中的钩子顺序

wt merge期间,阻塞式钩子按pre-commit → pre-merge → pre-remove顺序运行;合并完成后所有post-*钩子一起启动,各自锚定在对应 worktree 上——post-merge、post-switch 与 post-remove 在目标 worktree,post-commit 在提交产生的那个 worktree。若合并移除了该 worktree,post-commit会报告为跳过(worktree 已不存在),此时应使用pre-remove完成必须在移除前做的工作,或用--no-remove保留 worktree。完整流水线见 merge.md。

钩子的三种 TOML 形态

钩子由 TOML 形状决定三种形态(详见 hook.md):

字符串——单条命令:

pre-start = "npm install"

——多条命令并发运行:

[post-start] server = "npm run dev" watch = "npm run watch"

流水线——[[hook]]块按顺序执行,块内多 key 并发;任一步骤失败即中止后续:

[[post-start]] install = "npm ci" [[post-start]] build = "npm run build" server = "npm run dev"

这里install先运行,随后buildserver并发。模板会在流水线启动前做语法检查、随步骤执行时渲染——因此一个步骤可以写入按分支存储的变量,后续步骤通过{{ vars.<key> }}读取。大多数钩子并不需要[[hook]]块,只有存在依赖链(典型如先装依赖、再并发跑构建与 dev server)时才需要。

项目钩子与用户钩子

维度项目钩子用户钩子
位置.config/wt.toml~/.config/worktrunk/config.toml
作用域单一仓库所有仓库(或按项目覆盖)
审批必需不需要
执行顺序pre-*:在用户钩子之后;post-*:与用户钩子并行pre-*:最先;post-*:与项目钩子并行

当用户与项目配置定义了同名钩子时,可用user:nameproject:name语法指定来源。pre-*钩子阻塞命令,两个来源合为一条流水线:用户命令先跑,其失败会跳过项目的命令;post-*钩子后台运行,每个来源是独立的分离流水线——它们同时启动、互不等待,一方的失败不影响另一方。两个post-*钩子若写同一文件或在同一 worktree 中跑 git 会竞争,相互依赖的命令应放在同一来源中。

安全与审批

项目命令首次运行需要审批(hook.md):

▲ repo needs approval to execute 3 commands: ○ pre-start install: npm ci ○ pre-start build: cargo build --release ○ pre-start env: echo 'PORT={{ branch | hash_port }}' > .env.local ❯ Allow and remember? [y/N]
  • 审批保存在~/.config/worktrunk/approvals.toml
  • 命令一旦变更,需重新审批;
  • 拒绝会跳过该操作的全部项目命令(含已审批的)并继续,已保存的审批不受影响;
  • --yes绕过提示——适合 CI 与自动化;
  • --no-hooks跳过钩子——由执行钩子的命令接受(wt switchwt mergewt removewt step commitwt step squash),wt hook不接受。

审批管理用wt config approvals addwt config approvals clear。底层实现上(src/commands/hooks.rs),凡是审批门禁与执行之间夹着状态变更(merge、rebase、remove、git worktree add)的钩子,都采用plan-backed 模型:门禁时一次性加载项目配置、选定命令并冻结成ApprovedHookPlan,执行器只渲染运行这份冻结值,杜绝 TOCTOU(检查与使用之间的竞态)导致执行了未经审批的命令。

模板变量与过滤器

钩子可使用运行时展开的模板变量(完整清单见 hook.md),按类别分为:

  • active(随 worktree 变化){{ branch }}(分离头下未定义)、{{ worktree_path }}{{ worktree_name }}{{ commit }}{{ short_commit }}{{ upstream }}
  • operation(操作上下文){{ base }}{{ base_worktree_path }}{{ target }}{{ target_worktree_path }}{{ pr_number }}{{ pr_url }}
  • repo(全仓库恒定){{ repo }}{{ repo_path }}{{ owner }}{{ remote_repo }}{{ primary_worktree_path }}{{ default_branch }}{{ remote }}{{ remote_url }}
  • exec{{ cwd }}{{ hook_type }}{{ hook_name }}{{ args }}
  • user{{ vars.<key> }}wt config state vars的按分支变量)。

裸变量(branchworktree_pathcommit)指操作作用的分支:switch/create 指目的地,merge/remove 指来源;basetarget给出另一侧(方向对照表见 hook.md)。变量自动做 shell 转义——{{ ... }}外无需引号,加引号反而可能因特殊字符出问题。

未定义变量会报错,可用条件或默认值处理可选行为:

[pre-start] # 若跟踪远程分支则 rebase 到上游(如 wt switch --create feature --base origin/feature) sync = "{% if upstream %}git fetch && git rebase {{ upstream }}{% endif %}"

模板还支持 Jinja2 过滤器(完整清单见 hook.md):sanitize/\替换为-)、sanitize_db(数据库安全标识符,[a-z0-9_],最多 48 字符带哈希后缀)、sanitize_hash(文件系统安全名,变更时追加 3 字符哈希后缀保证唯一)、hash(3 字符 base36 摘要)、hash_port(哈希到 10000–19999 端口)、dirname/basenamecodename(n)(确定性友好词汇)等。经典的每 worktree 独立 dev server 端口就是hash_port

[post-start] dev = "npm run dev -- --host {{ branch }}.localhost --port {{ branch | hash_port }}"

任何字符串都可哈希,包括拼接:

# 每个 repo+branch 组合唯一端口 dev = "npm run dev --port {{ (repo ~ '-' ~ branch) | hash_port }}"

worktree_path_of_branch(branch)函数可按分支名查另一 worktree 的路径,用于跨 worktree 引用文件:

[pre-start] # 从主 worktree 复制配置 setup = "cp {{ worktree_path_of_branch('main') }}/config.local {{ worktree_path }}"

此外,钩子执行时所有模板变量会以JSON 形式通过 stdin传给命令(未设置的变量在 JSON 中同样缺席,需用默认值读取),适合模板难以表达的复杂逻辑:

[pre-start] setup = "python3 scripts/pre-start-setup.py"
import json, sys, subprocess ctx = json.load(sys.stdin) if ctx.get('branch', '').startswith('feature/') and 'backend' in ctx['repo']: subprocess.run(['make', 'seed-db'])

值得一提的专用命令是wt step copy-ignored(见 step.md):git worktree 共享仓库但不共享未跟踪文件,它负责在 worktree 间复制 gitignore 文件,典型用法是放进post-start

[post-start] copy = "wt step copy-ignored"

Aliases:可复用的wt <name>命令

别名在[aliases]下配置:

[aliases] deploy = "fly deploy --config=fly.{{ env }}.toml --app=myproject-{{ branch }}" open = "open http://localhost:{{ branch | hash_port }}" since-main = "git log --oneline {{ default_branch }}..HEAD"
wt deploy --env=staging wt open

wt <name>的解析顺序是:内置命令 → 别名 → 自定义子命令(见前文"命令解析优先级")。

模板与智能参数路由

别名与钩子共用同一套模板引擎:变量、过滤器、函数,以及--KEY=VALUE智能路由(模板引用了KEY则绑定,否则转发给{{ args }})。例如wt deploy --env=staging会设置{{ env }}

从 src/commands/alias.rs 的AliasOptions::parse可见完整路由文法:

  • --KEY=VALUE:若KEY被模板引用则绑定KEY=VALUE,否则两个部分都作为位置参数转发;
  • --KEY VALUE(空格形式):无条件消费下一个 token 作为值——即使它以--开头。要避免歧义请用=形式,或把其他 flag 放在被绑定的 key 之前;
  • --KEY在末尾:作为位置参数转发;
  • --:字面转发转义——之后的所有 token 直接进入{{ args }},不做任何绑定;
  • 连字符规范化:key 中的-会转为_(minijinja 将{{ my-var }}解析为减法),所以--my-var=value在模板引用{{ my_var }}时绑定它。

别名的模板上下文还额外提供{{ args }}(位置参数)。操作上下文变量(targetbasepr_number不会自动填充,但依然可以通过--KEY=VALUE绑定。变量渲染时机值得注意:别名主体在分发时只渲染一次(在调用所在的 worktree 中),因此一个在wt step for-each中打印相同分支的别名,{{ branch }}早已被烘焙成调用 worktree 的分支——这引出了下面的"延迟展开"技巧。

位置参数

{{ args }}渲染为空格连接、经 shell 转义的字符串,可直接拼进命令:

[aliases] s = "wt switch {{ args }}"
wt s some-branch wt s feature/api wt s 'has a space'

需要索引({{ args[0] }})、循环({% for a in args %}…{% endfor %})与计数({{ args | length }})时,参见 hook.md 的 Passing values 一节。

--之后的 token无条件转发,绕过任何绑定。写wt deploy -- --branch=foo会把字面量--branch=foo转给{{ args }}——即使模板引用了{{ branch }}也一样。

{{ args }}转发给wt命令的别名——如co = "wt switch {{ args }}"cm = "wt step commit {{ args }}"——会继承该命令的参数与补全wt co <Tab>补全分支的方式与wt switch <Tab>完全一致。

检视与预览

  • wt config alias show <name>:打印模板本体;
  • wt config alias dry-run <name> [-- args...]:打印渲染后的命令。
wt config alias show deploy wt config alias dry-run deploy wt config alias dry-run deploy -- --env=staging

别名没有 clap 风格的帮助页——模板本身就是文档wt <alias> --help会重定向到wt config alias show/dry-runwt --helpwt step --help会把已配置的别名列在内置命令旁边(被内置命令遮蔽的别名会标注(shadowed by built-in))。别名相关输出通过 src/commands/alias.rs 的augment_help拼入 clap 渲染的帮助文本。

多步骤流水线

[[aliases.NAME]]定义流水线,采用与钩子相同的[[block]]语义:块按顺序执行、块内 key 并发、步骤失败中止剩余部分:

[[aliases.release]] test = "cargo test" [[aliases.release]] build = "cargo build --release" package = "cargo package --no-verify" [[aliases.release]] publish = "cargo publish {{ args }}"

每个步骤看到相同的{{ args }}与已绑定变量。wt release -- --dry-run只把--dry-run转发给publish,不影响前面的步骤。

从实现看(src/commands/alias.rs 的run_alias),别名的用户/项目主体分开保存(AliasEntry { user, project }),执行时用户优先、项目在后,各按自身信任体制运行:用户步骤跳过审批,项目步骤需审批;所有步骤通过共享的execute_pipeline_foreground以前台方式执行。

改变目录

wt switchwt merge(离开被移除的源 worktree 时)与wt remove(移除当前 worktree 时)会改变父 shell 的工作目录——即使从别名内调用也一样,Worktrunk 的 shell 集成会把目录变更传播出去。但其他 shell 状态不会持久:别名在子 shell 中运行,cdexport等只影响该子 shell。

延迟展开到嵌套wt命令

上文提到,别名主体在分发时渲染一次。{% raw %}…{% endraw %}可延迟变量:它作为字面量{{ branch }}存活过分发渲染,随后由 for-each 在每个 worktree 中展开。对for-each有一个坑:延迟的{{ branch }}含空格,别名主体的sh -c会把它拆成{{branch}}三个 token,导致Failed to expand for-each argument: syntax error。解决方法是给 for-each 自己的sh -c '…'保持值为单一 token:

[aliases] show-branches = "wt step for-each -- sh -c 'echo {% raw %}{{ branch }}{% endraw %}'"

wt show-branches会打印每个 worktree 自己的分支。

wt switch --execute以同样方式延迟。-x指定程序,--后的参数保持独立,因此需把延迟模板作为别名主体的单个 token 引号包裹。这里{{ worktree_path }}针对正在创建的worktree 展开,而不是别名运行所在的 worktree:

[aliases] echo-target = "wt switch {{ args }} --no-cd --execute echo -- '{% raw %}{{ worktree_path }}{% endraw %}'"

而仓库级变量如{{ default_branch }}无需延迟:它在每个 worktree 中相同,裸{{ default_branch }}在任何地方都已正确。

配方一:把每个 worktree rebase 到其上游

[aliases] up = ''' git fetch --all --prune; wt step for-each -- sh -c ' git rev-parse --verify -q @{u} >/dev/null || exit 0 g=$(git rev-parse --git-dir) rebasing() { test -d "$g/rebase-merge" || test -d "$g/rebase-apply"; } rebasing && exit 0 git diff --quiet HEAD || { git merge --ff-only --no-autostash @{u}; exit 0; } git rebase @{u} --no-autostash || { rebasing || exit 0; git rebase --abort; } ''' '''

wt up先 fetch 所有远程,再把每个 worktree 对齐到其上游:无上游或已有 rebase 在进行则跳过;有已修改/已暂存的跟踪文件则 fast-forward;否则 rebase,遇冲突则中止。它 rebase 到 git 原生的@{u}而非{{ … }}模板,因此由 git 解析每个 worktree 自己的上游,无需延迟。

扫描会命中你以任意状态留下的每个 worktree,所以脚本主体是各种守卫:

  • git fetch --all在任一远程失败时退出非零。用&&时,一个凭据过期的远程就足以跳过整个扫描,连 refs 正常 fetch 的 worktree 也不会 rebase;用;则基于已 fetch 的部分继续扫描,fetch 错误照常打印;
  • git rebase拒绝在含已修改/已暂存跟踪文件的 worktree 中运行(无论是否有东西可 rebase)——你在编辑的 worktree 会拖垮整个扫描。git merge --ff-only是 git 在此仍会执行的 rebase 部分:它推进单纯落后的分支,否则不改变任何东西——分叉的分支或与你编辑冲突的传入文件会让 worktree 保持原样并打印原因。未跟踪文件既不触发拒绝也不触发git diff守卫,因此只含新文件的 worktree 仍会 rebase——除非新文件与传入提交新增的文件同名,git 拒绝覆盖;
  • rebasing区分git rebase失败的两种情形:中途冲突会留下进行中的 rebase,由 abort 回退;拒绝启动(跟踪文件被改、未跟踪文件挡路、pre-rebase钩子拒绝)则没有可 abort 的东西、无需清理,扫描继续——无条件git rebase --abort此时会回答fatal: no rebase in progress并以 128 退出,顶掉 git 自己的消息;
  • 两个分支都传--no-autostash,因为全局rebase.autostashmerge.autostash会破坏两个分支各自依赖的机制:带冲突的 autostash pop 会留下冲突标记却仍以 0 退出,扫描会对刚陷入冲突的 worktree 报告成功;且 autostash 让树短暂干净,本应拒绝的 fast-forward 会通过,碰撞落到 pop 上。

因此该扫描只在留下需要人工处理的 worktree(abort 自身失败)时退出非零。git 拒绝的事都是原子拒绝,扫描带着 git 的原因继续处理下一个 worktree。这一点在别名作为钩子步骤时很关键——失败的步骤会停掉流水线其余部分。

配方二:把进行中的改动移动或复制到新 worktree

wt switch --create会让你落到一个干净的 worktree。要把已暂存、未暂存与未跟踪的改动一并带过去,配合git stash

# .config/wt.toml [aliases] move-changes = ''' if git diff --quiet HEAD && test -z "$(git ls-files --others --exclude-standard)"; then wt switch --create {{ to }} --execute sh -- -c \ 'if [ "$#" -gt 0 ]; then exec "$@"; fi' worktrunk-move {{ args }} else git stash push --include-untracked --quiet wt switch --create {{ to }} --execute sh -- -c \ 'git stash pop --index; if [ "$#" -gt 0 ]; then exec "$@"; fi' worktrunk-move {{ args }} fi '''

wt move-changes --to=feature-xyz运行。守卫在无进行中改动时跳过 stash;否则git stash push捕获一切,显式sh -c步骤在新 worktree 中 pop,保持暂存/未暂存的分割。--之后的一切作为 argv 转发,在 pop 之后于新 worktree 中运行。例如wt move-changes --to=feature-xyz -- claude会在那里打开 Claude。

复制而非移动,在 push 后加git stash apply --index --quiet即可。

配方三:tail 某个具体的钩子日志

wt config state logs --format=json输出结构化条目(branchsourcehook_typenamepath)。用jq解析出某条记录,再包成别名快速访问:

[aliases] hook-log = ''' tail -f "$(wt config state logs --format=json | jq -r --arg name "{{ name | sanitize_hash }}" --arg kind "{{ kind }}" ' .hook_output[] | select(.branch == "{{ branch | sanitize_hash }}" and .hook_type == $kind and .name == $name) | .path ' | head -1)" '''

wt hook-log --kind=post-start --name=server运行,tail 当前分支上server钩子的日志。--kind选钩子类型;分支经{{ branch }}从当前 worktree 取得。sanitize_hashbranchname改写为带哈希后缀的文件系统安全形式(与 Worktrunk 落盘时相同的变换),保证任一含/等字符时也能解析到正确的日志。

Custom subcommands:wt-<name>即插即用

标注为 experimental。

PATH上任意名为wt-<name>的可执行文件都可用作wt <name>——这与 git 用git-foo的模式相同。内置命令与别名优先。

wt sync origin # runs: wt-sync origin wt -C /tmp/repo sync # -C is forwarded as the child's working directory

参数原样透传、stdio 继承、子进程退出码原样传播。从 src/commands/custom.rs 的run_custom实现细节看:

  • 参数、环境与工作目录透传后以Command::status()等待;
  • 信号杀死的子进程以WorktrunkError::Interrupted呈现(按 shell 惯例退出码为128 + signal);
  • 非零退出AlreadyDisplayed呈现(退出码原样转发,不额外打印错误行)——子命令已经报告了自己的失败,wt只转发状态码;
  • 子进程的环境会剥离 Worktrunk 内部的指令文件环境变量,避免旧版父包装器在进程退出后把指令文件当 shell 代码 source。

实际案例(名称引用自官方文档,可自行cargo install):

  • worktrunk-sync:按 git 历史推断的依赖顺序 rebase 堆叠的 worktree 分支。cargo install worktrunk-sync后以wt sync运行;
  • workz:为当前 worktree 提供无冲突的端口区间、独立数据库与 Docker Compose 项目,合并进.env.local,让并行 worktree 互不冲突。cargo install workz后,把其wt-workz适配器放到PATH,以wt workz运行。

参考:Hooks 与 Aliases 的接口差异

除下表差异外,Hooks 与 Aliases 行为一致。

维度HooksAliases
调用方式wt hook <type> [args...](嵌套在hook内置命令下)wt <name> [args...](顶层)
裸位置参数过滤器名(wt hook pre-merge test build只跑testbuild转发给{{ args }}
从位置参数到达{{ args }}必须用--wt hook pre-merge -- extra任意裸位置参数直接到达
跳过审批的 flag支持子命令后--yes/-ywt hook pre-merge --yes仅全局形式(wt -y <alias>);别名后--yes落入{{ args }}
来源区分user:/project:/user:name/project:name过滤语法用户先、项目后,无过滤语法
强制绑定转义--var KEY=VALUE(已废弃,推荐--KEY=VALUE,但仍强制绑定)无;智能路由是唯一路径
--helpwt hook --help列出钩子类型;wt hook <type> --help显示该类型的 flag 与参数模板本体即文档:wt <alias> --help重定向到wt config alias show/dry-runwt --helpwt step --help把已配置别名列在内置命令旁
检视wt hook show [type] [--expanded]wt config alias show <name>/wt config alias dry-run <name>
stdin全部模板变量以 JSON 形式提供(用json.load(sys.stdin)解析)继承父进程 stdin(管道透传;wt switch等交互式 TUI 保留 tty)
模板上下文额外项hook_typehook_name、按类型的操作变量(basetargetpr_number等)共享基础变量之上另有args

小结与选型建议

三条扩展路径覆盖了从"自动"到"手动"、从"Shell"到"任意语言"的完整谱系:

  • Hooks适合把依赖安装、测试、构建、部署等固定动作自动挂接到 worktree 生命周期上——在 .config/wt.toml 中配置,随仓库共享,项目钩子经首次审批后对团队生效;
  • Aliases适合把高频手动操作压缩为短命令,模板引擎 + 智能路由 +[[aliases.NAME]]流水线足以支撑复杂的多步发布流程;
  • Custom subcommands适合语言无关的重型扩展——任何可执行文件放到PATH即成为wt的一等子命令,参数透传、stdio 继承与退出码传播让集成无摩擦。

无论选择哪种机制,都建议先用wt config alias dry-run/wt hook <type> --dry-run预览渲染结果,用-v检视模板变量——配置即代码,预览即调试。更丰富的内置配方(dev server per worktree、database per worktree、progressive validation 等)可继续参阅 tips-patterns.md。

【免费下载链接】worktrunkWorktrunk is a CLI for Git worktree management, designed for parallel AI agent workflows项目地址: https://gitcode.com/GitHub_Trending/wo/worktrunk

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询