From eafe6ea895a542387bf2a3584d956191ca346c0b Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Tue, 1 Sep 2026 10:55:02 +0200 Subject: [PATCH 1/4] feat(git-worktree): add worktree management command and skill New community plugin giving parallel ZCode sessions first-class git worktree handling: /git-worktree:worktree dispatches list, create, open, remove, and prune with dirty-state and branch-in-use guardrails. A bundled git-worktrees skill carries the same isolation rules into ad-hoc chat. Addresses zai-org/feedback#132 and #220. --- marketplace.json | 22 ++++++++++ .../git-worktree/.zcode-plugin/plugin.json | 20 +++++++++ plugins/git-worktree/README.md | 40 +++++++++++++++++ plugins/git-worktree/README_CN.md | 40 +++++++++++++++++ plugins/git-worktree/commands/worktree.md | 44 +++++++++++++++++++ .../skills/git-worktrees/SKILL.md | 22 ++++++++++ 6 files changed, 188 insertions(+) create mode 100644 plugins/git-worktree/.zcode-plugin/plugin.json create mode 100644 plugins/git-worktree/README.md create mode 100644 plugins/git-worktree/README_CN.md create mode 100644 plugins/git-worktree/commands/worktree.md create mode 100644 plugins/git-worktree/skills/git-worktrees/SKILL.md diff --git a/marketplace.json b/marketplace.json index 415f7eb..0d94ef1 100644 --- a/marketplace.json +++ b/marketplace.json @@ -106,6 +106,28 @@ "codespaces" ] }, + { + "name": "git-worktree", + "source": "./plugins/git-worktree", + "description": "Git worktree management for parallel ZCode sessions: list, create, open, remove, and prune isolated working copies with dirty-state and branch-in-use safeguards.", + "description_i18n": { + "en": "Git worktree management for parallel ZCode sessions: list, create, open, remove, and prune isolated working copies with dirty-state and branch-in-use safeguards.", + "zh-CN": "面向并行 ZCode 会话的 git worktree 管理:列出、创建、打开、移除和清理隔离工作副本,内置脏状态与分支占用防护。" + }, + "version": "0.1.0", + "author": { + "name": "EtienneLescot", + "url": "https://github.com/EtienneLescot" + }, + "category": "developer-tools", + "keywords": [ + "git", + "worktree", + "parallel", + "isolation", + "branch" + ] + }, { "name": "video-agent-kit", "source": "./plugins/video-agent-kit", diff --git a/plugins/git-worktree/.zcode-plugin/plugin.json b/plugins/git-worktree/.zcode-plugin/plugin.json new file mode 100644 index 0000000..1be24e9 --- /dev/null +++ b/plugins/git-worktree/.zcode-plugin/plugin.json @@ -0,0 +1,20 @@ +{ + "name": "git-worktree", + "description": "Git worktree management for parallel ZCode sessions: list, create, open, remove, and prune isolated working copies with dirty-state and branch-in-use safeguards.", + "description_i18n": { + "en": "Git worktree management for parallel ZCode sessions: list, create, open, remove, and prune isolated working copies with dirty-state and branch-in-use safeguards.", + "zh-CN": "面向并行 ZCode 会话的 git worktree 管理:列出、创建、打开、移除和清理隔离工作副本,内置脏状态与分支占用防护。" + }, + "version": "0.1.0", + "author": { + "name": "EtienneLescot", + "url": "https://github.com/EtienneLescot" + }, + "keywords": [ + "git", + "worktree", + "parallel", + "isolation", + "branch" + ] +} diff --git a/plugins/git-worktree/README.md b/plugins/git-worktree/README.md new file mode 100644 index 0000000..2928cba --- /dev/null +++ b/plugins/git-worktree/README.md @@ -0,0 +1,40 @@ +# git-worktree + +Git worktree management for parallel ZCode sessions — a Claude-Code-style `/worktree` experience: list, create, open, remove, and prune isolated working copies, with guardrails against the two classic accidents (deleting uncommitted work, and fighting over a branch two worktrees cannot share). + +Addresses the UX gaps tracked in [zai-org/feedback#132](https://github.com/zai-org/feedback/issues/132) and [#220](https://github.com/zai-org/feedback/issues/220). + +## Why + +ZCode has no built-in worktree switcher, so users who want two conversations on one repository — one per feature — either collide in the same folder or hand-roll git commands and hit cryptic errors like `branch is already used by worktree`. This plugin makes the workflow first-class: + +- **Isolation**: each conversation gets its own worktree (directory + branch), so parallel sessions never overwrite each other's uncommitted changes. +- **Clarity**: `list` shows every worktree with its branch and dirty state; errors are translated into what to do next. +- **Safety**: dirty worktrees are never removed without explicit confirmation; the main worktree and merged-branch checks protect against the two easiest ways to lose work. + +## Install + +Settings → Plugin Management → Discover → search `git-worktree` → Install. Requires git 2.20 or newer on your `PATH`. + +## Usage + +| Invocation | What it does | +|---|---| +| `/git-worktree:worktree` or `… list` | Table of every worktree: name, branch, uncommitted file count, path; main worktree marked | +| `… create [base]` | Creates worktree + branch `` (default base: `origin/HEAD`, else `main`/`master`, else `HEAD`) as a sibling directory of the repo; warns before occupying a default branch | +| `… open ` | Resolves the worktree and prints the exact File → Open Folder path | +| `… remove ` | Refuses the main worktree; summarizes uncommitted changes and requires confirmation before `--force`; offers merged-only branch cleanup afterwards | +| `… prune` | Shows stale entries first, prunes the registry, reports (never silently deletes) orphan directories | + +The bundled `git-worktrees` skill auto-triggers on worktree questions and carries the same rules for ad-hoc chat ("can I run three sessions on this repo?"). + +## Side effects, permissions, dependencies + +- Runs local `git` commands only: `worktree add/remove/list/prune`, `status`, `diff --stat`, `branch -d/-D`. No other binaries, no scripts, no hooks, no MCP servers. +- Creates directories (default: siblings of your repository root) and deletes worktree directories — every destructive step requires explicit confirmation first. +- No network access, no credentials, no data leaves the machine. +- Cross-platform: plain git invocations, no shell-specific syntax; tested path handling on Windows and POSIX. + +## Versioning and license + +`0.1.0` — manifest and marketplace entry kept in lockstep. Apache-2.0, same license as the [zcode-plugins](https://github.com/zai-org/zcode-plugins) repository. No third-party code or assets. diff --git a/plugins/git-worktree/README_CN.md b/plugins/git-worktree/README_CN.md new file mode 100644 index 0000000..c32bf63 --- /dev/null +++ b/plugins/git-worktree/README_CN.md @@ -0,0 +1,40 @@ +# git-worktree + +面向并行 ZCode 会话的 git worktree 管理——类似 Claude Code 的 `/worktree` 体验:列出、创建、打开、移除和清理隔离工作副本,并针对两类经典事故(误删未提交的改动、两个 worktree 争抢同一分支)内置防护。 + +对应社区反馈 [zai-org/feedback#132](https://github.com/zai-org/feedback/issues/132) 与 [#220](https://github.com/zai-org/feedback/issues/220) 的体验缺口。 + +## 为什么需要 + +ZCode 目前没有内置的 worktree 切换器。想让两个会话同时处理同一个仓库(一人一个特性)的用户,要么在同一目录里互相覆盖,要么手敲 git 命令并撞上 `branch is already used by worktree` 这类难懂的错误。本插件把这套流程变为一等公民: + +- **隔离**:每个会话拥有自己的 worktree(目录 + 分支),并行会话绝不会互相覆盖未提交的改动。 +- **清晰**:`list` 用表格展示每个 worktree 的分支与脏状态;错误信息会翻译成下一步该做什么。 +- **安全**:脏 worktree 未经明确确认绝不移除;主 worktree 与“仅删除已合并分支”的检查防止最容易丢工作的两条路径。 + +## 安装 + +设置 → 插件管理 → 发现 → 搜索 `git-worktree` → 安装。要求 `PATH` 上有 git 2.20 及以上。 + +## 用法 + +| 调用方式 | 作用 | +|---|---| +| `/git-worktree:worktree` 或 `… list` | 表格列出所有 worktree:名称、分支、未提交文件数、路径;标注主 worktree | +| `… create <名称> [基准]` | 创建 worktree 与分支 `<名称>`(默认基准:`origin/HEAD`,否则 `main`/`master`,否则 `HEAD`),目录位于仓库同级;占用默认分支前会先警告 | +| `… open <名称>` | 解析 worktree,并给出确切的 File → Open Folder 打开路径 | +| `… remove <名称>` | 拒绝移除主 worktree;先汇总未提交改动,`--force` 前必须明确确认;随后提供“仅已合并”的分支清理 | +| `… prune` | 先展示过期条目,再清理注册表;孤儿目录只报告路径与大小,绝不静默删除 | + +附带的 `git-worktrees` 技能在用户问到 worktree 话题时自动触发,把同样的规则带进日常对话(“这个仓库能同时开三个会话吗?”)。 + +## 副作用、权限与依赖 + +- 只运行本地 `git` 命令:`worktree add/remove/list/prune`、`status`、`diff --stat`、`branch -d/-D`。无其他二进制、无脚本、无 hooks、无 MCP 服务器。 +- 会创建目录(默认位于仓库根目录同级)并删除 worktree 目录——每个破坏性步骤都先要求明确确认。 +- 无网络访问、无凭据、数据不出本机。 +- 跨平台:纯 git 调用,无特定 shell 语法;已在 Windows 与 POSIX 上验证路径处理。 + +## 版本与许可 + +`0.1.0`——manifest 与市场条目保持同步。Apache-2.0,与 [zcode-plugins](https://github.com/zai-org/zcode-plugins) 仓库许可证一致。无第三方代码或资产。 diff --git a/plugins/git-worktree/commands/worktree.md b/plugins/git-worktree/commands/worktree.md new file mode 100644 index 0000000..e02f738 --- /dev/null +++ b/plugins/git-worktree/commands/worktree.md @@ -0,0 +1,44 @@ +--- +description: Manage git worktrees — list, create, open, remove, and prune isolated working copies for parallel ZCode sessions +argument-hint: [list] | create [base] | open | remove | prune +--- + +Manage git worktrees for the current repository. The subcommand comes from `$ARGUMENTS`; when it is empty or unrecognized, default to `list` and end with a one-line summary of the other subcommands. Reply in the user's language. + +## Ground rules (every subcommand) + +1. Resolve the repository first with `git rev-parse --show-toplevel`. If the workspace is not inside a git repository, say so and stop. +2. The first entry of `git worktree list` is the main worktree. Never remove or prune it. +3. A branch can be checked out in only ONE worktree at a time. If git answers `fatal: '' is already used by worktree at `, that is NOT a stuck git operation — the branch is owned by another worktree. Name the owning worktree and offer the user two options: open that worktree instead, or create this one on a different branch. +4. One ZCode conversation works in one working copy. Never guide two conversations into the same worktree folder — their checkouts and uncommitted changes would collide. When you create or open a worktree, remind the user of this rule in one sentence. +5. Run plain git commands only. Do not assume bash syntax; the user may be on Windows. + +## list + +Run `git worktree list --porcelain`. For each worktree also run `git -C status --porcelain` to count uncommitted files. Present a table: name (directory basename), branch (`refs/heads/` stripped; `(detached)` kept), uncommitted file count, path. Mark the main worktree. Under the table, name any branch mentioned in more than one row as "checked out once per worktree only" if the user seems about to reuse it — otherwise omit. + +## create [base] + +1. Normalize ``: trim it, replace spaces with hyphens, refuse it if it is empty or contains path separators. Use it as the branch name as-is. +2. Warn and ask before proceeding when `` equals the repository's default branch (`main`, `master`, or the `origin/HEAD` target): occupying the default branch in a worktree blocks every other session that wants it. Suggest a task branch based on it instead, but obey an explicit confirmation. +3. Default base: the `origin/HEAD` target if it exists, else `main` or `master` if either exists, else the current `HEAD`. +4. Default location: a sibling of the repository root — `/../-`. If the user asks for an in-repo location such as `.worktrees/`, honor it and append that directory to `.git/info/exclude` (never to a tracked `.gitignore`) so the worktree is not flagged as untracked. +5. Create with `git worktree add -b ` (drop `-b ` and append `` instead when branch `` already exists). Interpret a failure per ground rule 3. +6. After creation, print the path and the next steps: open it in ZCode via File → Open Folder (each worktree is a separate project with its own context), keep one conversation per worktree, and note that files not under version control — dependencies, build output — will not exist in the fresh worktree and must be installed or linked per the project's own setup guide. + +## open + +Resolve `` against `git worktree list --porcelain` by directory basename, branch name, or path prefix; refuse an ambiguous name by listing the candidates. A command cannot switch the ZCode workspace itself, so print the absolute path and the exact click path: File → Open Folder → select that directory. Add the one-sentence one-conversation-per-worktree reminder from ground rule 4. + +## remove + +1. Resolve the worktree as in `open`. Refuse the main worktree. +2. Check `git -C status --porcelain`. If there are uncommitted changes, STOP: summarize them (file list plus `git -C diff --stat`), and ask whether to discard them. Only after an explicit confirmation run `git worktree remove --force `; otherwise suggest committing or stashing first and stop. +3. Clean worktree: `git worktree remove `. On Windows this can fail if another process (editor, terminal, antivirus) holds the directory — say so, and suggest closing it before retrying rather than jumping to `--force`. +4. After removal, offer branch cleanup: `git branch -d ` when the branch is merged; never run `git branch -D` without an explicit confirmation that unmerged work will be lost. + +## prune + +1. Show what is stale first: `git worktree prune --dry-run --verbose` plus `git worktree list --porcelain`. +2. Run `git worktree prune`. +3. Orphan directories (a worktree directory on disk that no longer appears in `git worktree list`) are only ever reported with their paths and sizes — never deleted without an explicit confirmation, because the same look can hide uncommitted work the registry simply forgot. diff --git a/plugins/git-worktree/skills/git-worktrees/SKILL.md b/plugins/git-worktree/skills/git-worktrees/SKILL.md new file mode 100644 index 0000000..053e934 --- /dev/null +++ b/plugins/git-worktree/skills/git-worktrees/SKILL.md @@ -0,0 +1,22 @@ +--- +name: git-worktrees +description: Safe git worktree usage for parallel ZCode sessions. Use when the user mentions worktrees, wants to run several conversations or agents on one repository in parallel, hits "branch is already used by worktree", asks how to create/list/remove worktrees, or wonders which folder a session should work in. +--- + +# Git worktrees for parallel sessions + +A worktree is its own directory holding one checked-out branch. The directory — not the branch — is the unit of isolation: two sessions sharing a directory collide no matter which branches they name, because each `git checkout` rewrites the shared files under the other session's feet. Two sessions in two worktrees cannot collide. + +## The three rules + +1. **One branch, one worktree.** Git refuses to check out a branch that another worktree already holds. `fatal: '' is already used by worktree at ` means exactly that — not a locked or crashed git operation. Free the branch by removing the other worktree, or work on a different branch. +2. **One conversation, one worktree.** To parallelize work, give each conversation its own worktree opened as its own project (File → Open Folder). Two conversations in the same directory overwrite each other's uncommitted changes. +3. **Keep the default branch free.** Base task branches on `main` (or `master`), but do not check out the default branch itself in a session worktree — it blocks the next session that wants it, which surfaces as rule 1's error. + +## Operating safely + +- Create: `git worktree add -b ` — default path as a sibling of the repository root so nothing untracked appears inside the checkout. +- Before removing, check `git -C status --porcelain`; show the user what would be lost and require confirmation for `--force`. +- Delete a branch with `-d` only (merged check); `-D` destroys unmerged work and needs explicit user sign-off. +- A fresh worktree has no untracked dependencies or build output — install or link them per the project's own instructions before building. +- If this plugin's `/git-worktree:worktree` command is available, prefer it: it walks these steps with the guardrails built in. From 8a8916398a35a0c77c74fd803f2616cc78f4f334 Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Tue, 1 Sep 2026 11:30:19 +0200 Subject: [PATCH 2/4] fix(git-worktree): forbid implicit mutations when no subcommand is given Real-world testing showed a bare invocation could be interpreted as a create (the companion skill carries no default-subcommand rule). Make report-only the explicit contract for empty/ambiguous invocations in both the command and the skill, and bump to 0.1.1. --- marketplace.json | 2 +- plugins/git-worktree/.zcode-plugin/plugin.json | 2 +- plugins/git-worktree/commands/worktree.md | 2 +- plugins/git-worktree/skills/git-worktrees/SKILL.md | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/marketplace.json b/marketplace.json index 0d94ef1..a6f112c 100644 --- a/marketplace.json +++ b/marketplace.json @@ -114,7 +114,7 @@ "en": "Git worktree management for parallel ZCode sessions: list, create, open, remove, and prune isolated working copies with dirty-state and branch-in-use safeguards.", "zh-CN": "面向并行 ZCode 会话的 git worktree 管理:列出、创建、打开、移除和清理隔离工作副本,内置脏状态与分支占用防护。" }, - "version": "0.1.0", + "version": "0.1.1", "author": { "name": "EtienneLescot", "url": "https://github.com/EtienneLescot" diff --git a/plugins/git-worktree/.zcode-plugin/plugin.json b/plugins/git-worktree/.zcode-plugin/plugin.json index 1be24e9..5c23a4b 100644 --- a/plugins/git-worktree/.zcode-plugin/plugin.json +++ b/plugins/git-worktree/.zcode-plugin/plugin.json @@ -5,7 +5,7 @@ "en": "Git worktree management for parallel ZCode sessions: list, create, open, remove, and prune isolated working copies with dirty-state and branch-in-use safeguards.", "zh-CN": "面向并行 ZCode 会话的 git worktree 管理:列出、创建、打开、移除和清理隔离工作副本,内置脏状态与分支占用防护。" }, - "version": "0.1.0", + "version": "0.1.1", "author": { "name": "EtienneLescot", "url": "https://github.com/EtienneLescot" diff --git a/plugins/git-worktree/commands/worktree.md b/plugins/git-worktree/commands/worktree.md index e02f738..15a57cf 100644 --- a/plugins/git-worktree/commands/worktree.md +++ b/plugins/git-worktree/commands/worktree.md @@ -3,7 +3,7 @@ description: Manage git worktrees — list, create, open, remove, and prune isol argument-hint: [list] | create [base] | open | remove | prune --- -Manage git worktrees for the current repository. The subcommand comes from `$ARGUMENTS`; when it is empty or unrecognized, default to `list` and end with a one-line summary of the other subcommands. Reply in the user's language. +Manage git worktrees for the current repository. The subcommand comes from `$ARGUMENTS`; when it is empty or unrecognized, default to `list` and end with a one-line summary of the other subcommands. Never create, modify, or remove anything without an explicit subcommand naming that action — an empty or ambiguous invocation must only report state. Reply in the user's language. ## Ground rules (every subcommand) diff --git a/plugins/git-worktree/skills/git-worktrees/SKILL.md b/plugins/git-worktree/skills/git-worktrees/SKILL.md index 053e934..ed36e3c 100644 --- a/plugins/git-worktree/skills/git-worktrees/SKILL.md +++ b/plugins/git-worktree/skills/git-worktrees/SKILL.md @@ -15,6 +15,7 @@ A worktree is its own directory holding one checked-out branch. The directory ## Operating safely +- Report state by default: when the user has not explicitly asked to create or remove anything, list worktrees and stop. Creating or removing requires an explicit request. - Create: `git worktree add -b ` — default path as a sibling of the repository root so nothing untracked appears inside the checkout. - Before removing, check `git -C status --porcelain`; show the user what would be lost and require confirmation for `--force`. - Delete a branch with `-d` only (merged check); `-D` destroys unmerged work and needs explicit user sign-off. From ba358b2adb97ab180e1d63dd4ef33734e225fd76 Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Tue, 1 Sep 2026 11:35:34 +0200 Subject: [PATCH 3/4] feat(git-worktree): make bare invocation create an isolated worktree User testing showed the natural mental model: invoking /worktree at the start of a conversation means 'give me isolation'. A bare invocation now runs the create flow with safe defaults (auto-named branch off the default branch, sibling folder, idempotent when the workspace is already a linked worktree) and states plainly that the current conversation stays in its own workspace until the worktree is opened as its own project. list becomes explicit; remove/prune keep their confirmations. Bump to 0.1.2. --- marketplace.json | 2 +- .../git-worktree/.zcode-plugin/plugin.json | 2 +- plugins/git-worktree/README.md | 5 +-- plugins/git-worktree/README_CN.md | 5 +-- plugins/git-worktree/commands/worktree.md | 32 ++++++++++--------- .../skills/git-worktrees/SKILL.md | 4 +-- 6 files changed, 27 insertions(+), 23 deletions(-) diff --git a/marketplace.json b/marketplace.json index a6f112c..5e74a64 100644 --- a/marketplace.json +++ b/marketplace.json @@ -114,7 +114,7 @@ "en": "Git worktree management for parallel ZCode sessions: list, create, open, remove, and prune isolated working copies with dirty-state and branch-in-use safeguards.", "zh-CN": "面向并行 ZCode 会话的 git worktree 管理:列出、创建、打开、移除和清理隔离工作副本,内置脏状态与分支占用防护。" }, - "version": "0.1.1", + "version": "0.1.2", "author": { "name": "EtienneLescot", "url": "https://github.com/EtienneLescot" diff --git a/plugins/git-worktree/.zcode-plugin/plugin.json b/plugins/git-worktree/.zcode-plugin/plugin.json index 5c23a4b..482f7f7 100644 --- a/plugins/git-worktree/.zcode-plugin/plugin.json +++ b/plugins/git-worktree/.zcode-plugin/plugin.json @@ -5,7 +5,7 @@ "en": "Git worktree management for parallel ZCode sessions: list, create, open, remove, and prune isolated working copies with dirty-state and branch-in-use safeguards.", "zh-CN": "面向并行 ZCode 会话的 git worktree 管理:列出、创建、打开、移除和清理隔离工作副本,内置脏状态与分支占用防护。" }, - "version": "0.1.1", + "version": "0.1.2", "author": { "name": "EtienneLescot", "url": "https://github.com/EtienneLescot" diff --git a/plugins/git-worktree/README.md b/plugins/git-worktree/README.md index 2928cba..32b37c3 100644 --- a/plugins/git-worktree/README.md +++ b/plugins/git-worktree/README.md @@ -20,8 +20,9 @@ Settings → Plugin Management → Discover → search `git-worktree` → Instal | Invocation | What it does | |---|---| -| `/git-worktree:worktree` or `… list` | Table of every worktree: name, branch, uncommitted file count, path; main worktree marked | -| `… create [base]` | Creates worktree + branch `` (default base: `origin/HEAD`, else `main`/`master`, else `HEAD`) as a sibling directory of the repo; warns before occupying a default branch | +| `/git-worktree:worktree` | Default: **create** — ensures an isolated worktree for a new session (auto-named branch off the default branch, sibling folder); prints the File → Open Folder path, since the current conversation stays in its own workspace | +| `… create [base]` | Same, with an explicit worktree/branch `` and base (`origin/HEAD`, else `main`/`master`, else `HEAD`); never occupies a default branch | +| `… list` | Table of every worktree: name, branch, uncommitted file count, path; main worktree marked | | `… open ` | Resolves the worktree and prints the exact File → Open Folder path | | `… remove ` | Refuses the main worktree; summarizes uncommitted changes and requires confirmation before `--force`; offers merged-only branch cleanup afterwards | | `… prune` | Shows stale entries first, prunes the registry, reports (never silently deletes) orphan directories | diff --git a/plugins/git-worktree/README_CN.md b/plugins/git-worktree/README_CN.md index c32bf63..d03d7d2 100644 --- a/plugins/git-worktree/README_CN.md +++ b/plugins/git-worktree/README_CN.md @@ -20,8 +20,9 @@ ZCode 目前没有内置的 worktree 切换器。想让两个会话同时处理 | 调用方式 | 作用 | |---|---| -| `/git-worktree:worktree` 或 `… list` | 表格列出所有 worktree:名称、分支、未提交文件数、路径;标注主 worktree | -| `… create <名称> [基准]` | 创建 worktree 与分支 `<名称>`(默认基准:`origin/HEAD`,否则 `main`/`master`,否则 `HEAD`),目录位于仓库同级;占用默认分支前会先警告 | +| `/git-worktree:worktree` | 默认行为:**创建**——为新会话准备一个隔离 worktree(基于默认分支自动命名、位于仓库同级目录);输出 File → Open Folder 路径(当前会话仍留在原工作区) | +| `… create <名称> [基准]` | 同上,但显式指定 worktree/分支 `<名称>` 与基准(`origin/HEAD`,否则 `main`/`master`,否则 `HEAD`);绝不占用默认分支 | +| `… list` | 表格列出所有 worktree:名称、分支、未提交文件数、路径;标注主 worktree | | `… open <名称>` | 解析 worktree,并给出确切的 File → Open Folder 打开路径 | | `… remove <名称>` | 拒绝移除主 worktree;先汇总未提交改动,`--force` 前必须明确确认;随后提供“仅已合并”的分支清理 | | `… prune` | 先展示过期条目,再清理注册表;孤儿目录只报告路径与大小,绝不静默删除 | diff --git a/plugins/git-worktree/commands/worktree.md b/plugins/git-worktree/commands/worktree.md index 15a57cf..06ec2be 100644 --- a/plugins/git-worktree/commands/worktree.md +++ b/plugins/git-worktree/commands/worktree.md @@ -1,34 +1,36 @@ --- -description: Manage git worktrees — list, create, open, remove, and prune isolated working copies for parallel ZCode sessions -argument-hint: [list] | create [base] | open | remove | prune +description: Manage git worktrees — create an isolated working copy for a new session, or list, open, remove, and prune them +argument-hint: [create [name]] | list | open | remove | prune --- -Manage git worktrees for the current repository. The subcommand comes from `$ARGUMENTS`; when it is empty or unrecognized, default to `list` and end with a one-line summary of the other subcommands. Never create, modify, or remove anything without an explicit subcommand naming that action — an empty or ambiguous invocation must only report state. Reply in the user's language. +Manage git worktrees for the current repository. The subcommand comes from `$ARGUMENTS`. With no subcommand at all, behave as `create` — the common case is a user starting a conversation who wants isolation from other sessions. Reply in the user's language. ## Ground rules (every subcommand) 1. Resolve the repository first with `git rev-parse --show-toplevel`. If the workspace is not inside a git repository, say so and stop. 2. The first entry of `git worktree list` is the main worktree. Never remove or prune it. -3. A branch can be checked out in only ONE worktree at a time. If git answers `fatal: '' is already used by worktree at `, that is NOT a stuck git operation — the branch is owned by another worktree. Name the owning worktree and offer the user two options: open that worktree instead, or create this one on a different branch. -4. One ZCode conversation works in one working copy. Never guide two conversations into the same worktree folder — their checkouts and uncommitted changes would collide. When you create or open a worktree, remind the user of this rule in one sentence. +3. A branch can be checked out in only ONE worktree at a time. If git answers `fatal: '' is already used by worktree at `, that is NOT a stuck git operation — the branch is owned by another worktree. Name the owning worktree and offer two options: open that worktree instead, or use a different branch here. +4. One ZCode conversation works in one working copy. Creating a worktree from this conversation does NOT move this conversation into it — say this plainly every time you create. To work in the worktree, the user opens it via File → Open Folder and converses there. 5. Run plain git commands only. Do not assume bash syntax; the user may be on Windows. -## list +## create [name] [base] + +This is the default when no subcommand is given. -Run `git worktree list --porcelain`. For each worktree also run `git -C status --porcelain` to count uncommitted files. Present a table: name (directory basename), branch (`refs/heads/` stripped; `(detached)` kept), uncommitted file count, path. Mark the main worktree. Under the table, name any branch mentioned in more than one row as "checked out once per worktree only" if the user seems about to reuse it — otherwise omit. +1. If the CURRENT workspace already sits in a linked worktree (its `.git` is a `gitdir:` pointer into `/.git/worktrees/`), it is already isolated: report its branch and path, and stop. +2. Pick ``: use the one given; else derive it from the task or topic at hand (kebab-case, no slashes, no path separators); else fall back to `session-`. If branch `` already exists, append `-2`, `-3`, … until free. +3. Base: the `origin/HEAD` target if it exists, else `main` or `master` if either exists, else current `HEAD`. NEVER check the default branch itself out into the worktree — occupying it blocks every other session that wants it. +4. Path: a sibling of the repository root, `-`. If the user asks for an in-repo location such as `.worktrees/`, honor it and append that directory to `.git/info/exclude` (never a tracked `.gitignore`). +5. Create with `git worktree add -b ` (drop `-b` and append the existing branch name instead if it already exists). Interpret failures per ground rule 3. +6. Finish with: the worktree path and branch; ground rule 4's reminder verbatim; and the note that untracked files (dependencies, build output) do not exist in the fresh worktree — install or link them per the project's own setup instructions. -## create [base] +## list -1. Normalize ``: trim it, replace spaces with hyphens, refuse it if it is empty or contains path separators. Use it as the branch name as-is. -2. Warn and ask before proceeding when `` equals the repository's default branch (`main`, `master`, or the `origin/HEAD` target): occupying the default branch in a worktree blocks every other session that wants it. Suggest a task branch based on it instead, but obey an explicit confirmation. -3. Default base: the `origin/HEAD` target if it exists, else `main` or `master` if either exists, else the current `HEAD`. -4. Default location: a sibling of the repository root — `/../-`. If the user asks for an in-repo location such as `.worktrees/`, honor it and append that directory to `.git/info/exclude` (never to a tracked `.gitignore`) so the worktree is not flagged as untracked. -5. Create with `git worktree add -b ` (drop `-b ` and append `` instead when branch `` already exists). Interpret a failure per ground rule 3. -6. After creation, print the path and the next steps: open it in ZCode via File → Open Folder (each worktree is a separate project with its own context), keep one conversation per worktree, and note that files not under version control — dependencies, build output — will not exist in the fresh worktree and must be installed or linked per the project's own setup guide. +Run `git worktree list --porcelain`. For each worktree also run `git -C status --porcelain` to count uncommitted files. Present a table: name (directory basename), branch (`refs/heads/` stripped; `(detached)` kept), uncommitted file count, path. Mark the main worktree. ## open -Resolve `` against `git worktree list --porcelain` by directory basename, branch name, or path prefix; refuse an ambiguous name by listing the candidates. A command cannot switch the ZCode workspace itself, so print the absolute path and the exact click path: File → Open Folder → select that directory. Add the one-sentence one-conversation-per-worktree reminder from ground rule 4. +Resolve `` against `git worktree list --porcelain` by directory basename, branch name, or path prefix; refuse an ambiguous name by listing the candidates. A command cannot switch the ZCode workspace itself, so print the absolute path and the exact click path: File → Open Folder → select that directory. Repeat ground rule 4's reminder in one sentence. ## remove diff --git a/plugins/git-worktree/skills/git-worktrees/SKILL.md b/plugins/git-worktree/skills/git-worktrees/SKILL.md index ed36e3c..5c05458 100644 --- a/plugins/git-worktree/skills/git-worktrees/SKILL.md +++ b/plugins/git-worktree/skills/git-worktrees/SKILL.md @@ -15,8 +15,8 @@ A worktree is its own directory holding one checked-out branch. The directory ## Operating safely -- Report state by default: when the user has not explicitly asked to create or remove anything, list worktrees and stop. Creating or removing requires an explicit request. -- Create: `git worktree add -b ` — default path as a sibling of the repository root so nothing untracked appears inside the checkout. +- Match the intent: when the user signals wanting isolation for new work ("create a worktree", "work in parallel without collisions"), ensure a worktree exists with the safe defaults below. When asked about state, list. Creating is additive and safe; removing is not — never remove without an explicit request, and never put a session worktree on the default branch. +- Create: `git worktree add -b ` — default path as a sibling of the repository root so nothing untracked appears inside the checkout. Say plainly that the current conversation stays in its own workspace: to work in the worktree, open it as its own project. - Before removing, check `git -C status --porcelain`; show the user what would be lost and require confirmation for `--force`. - Delete a branch with `-d` only (merged check); `-D` destroys unmerged work and needs explicit user sign-off. - A fresh worktree has no untracked dependencies or build output — install or link them per the project's own instructions before building. From 8e627051af213627c228c1189df36f87716db521 Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Tue, 1 Sep 2026 11:41:31 +0200 Subject: [PATCH 4/4] docs(git-worktree): document the three invocation paths Command for the deterministic procedure, @-mention to apply the worktree discipline to a free-form request, and skill auto-trigger as the safety net. Bump to 0.1.3. --- marketplace.json | 2 +- plugins/git-worktree/.zcode-plugin/plugin.json | 2 +- plugins/git-worktree/README.md | 6 ++++++ plugins/git-worktree/README_CN.md | 6 ++++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/marketplace.json b/marketplace.json index 5e74a64..77dde9e 100644 --- a/marketplace.json +++ b/marketplace.json @@ -114,7 +114,7 @@ "en": "Git worktree management for parallel ZCode sessions: list, create, open, remove, and prune isolated working copies with dirty-state and branch-in-use safeguards.", "zh-CN": "面向并行 ZCode 会话的 git worktree 管理:列出、创建、打开、移除和清理隔离工作副本,内置脏状态与分支占用防护。" }, - "version": "0.1.2", + "version": "0.1.3", "author": { "name": "EtienneLescot", "url": "https://github.com/EtienneLescot" diff --git a/plugins/git-worktree/.zcode-plugin/plugin.json b/plugins/git-worktree/.zcode-plugin/plugin.json index 482f7f7..9e207f0 100644 --- a/plugins/git-worktree/.zcode-plugin/plugin.json +++ b/plugins/git-worktree/.zcode-plugin/plugin.json @@ -5,7 +5,7 @@ "en": "Git worktree management for parallel ZCode sessions: list, create, open, remove, and prune isolated working copies with dirty-state and branch-in-use safeguards.", "zh-CN": "面向并行 ZCode 会话的 git worktree 管理:列出、创建、打开、移除和清理隔离工作副本,内置脏状态与分支占用防护。" }, - "version": "0.1.2", + "version": "0.1.3", "author": { "name": "EtienneLescot", "url": "https://github.com/EtienneLescot" diff --git a/plugins/git-worktree/README.md b/plugins/git-worktree/README.md index 32b37c3..7cd6c4f 100644 --- a/plugins/git-worktree/README.md +++ b/plugins/git-worktree/README.md @@ -29,6 +29,12 @@ Settings → Plugin Management → Discover → search `git-worktree` → Instal The bundled `git-worktrees` skill auto-triggers on worktree questions and carries the same rules for ad-hoc chat ("can I run three sessions on this repo?"). +## Three ways to invoke + +1. **Command** — `/git-worktree:worktree` (bare = create with safe defaults; or `list`, `create`, `open`, `remove`, `prune`). The deterministic path: a fixed procedure with the guardrails built in. +2. **Mention** — type `@Git-Worktree` in the composer to attach the bundled skill to your message. Ask in natural language ("work on the export fix in isolation") and the worktree discipline — default-branch protection, dirty-state checks, one conversation per worktree — applies to whatever you asked. +3. **Auto-trigger** — the skill also loads by itself when a conversation turns to worktrees or parallel-session isolation, as a safety net when you didn't think to ask. + ## Side effects, permissions, dependencies - Runs local `git` commands only: `worktree add/remove/list/prune`, `status`, `diff --stat`, `branch -d/-D`. No other binaries, no scripts, no hooks, no MCP servers. diff --git a/plugins/git-worktree/README_CN.md b/plugins/git-worktree/README_CN.md index d03d7d2..045d1da 100644 --- a/plugins/git-worktree/README_CN.md +++ b/plugins/git-worktree/README_CN.md @@ -29,6 +29,12 @@ ZCode 目前没有内置的 worktree 切换器。想让两个会话同时处理 附带的 `git-worktrees` 技能在用户问到 worktree 话题时自动触发,把同样的规则带进日常对话(“这个仓库能同时开三个会话吗?”)。 +## 三种调用方式 + +1. **命令**——`/git-worktree:worktree`(无参数即以安全默认值创建;也可用 `list`、`create`、`open`、`remove`、`prune`)。确定性路径:固定流程,内置防护。 +2. **提及**——在输入框中输入 `@Git-Worktree`,把附带技能挂载到你的消息上。用自然语言提问(“在隔离环境里修 export 的问题”),worktree 纪律——默认分支保护、脏状态检查、一会话一 worktree——就会作用于你所请求的内容。 +3. **自动触发**——当对话涉及 worktree 或并行会话隔离时,技能也会自行加载,在你没想到要求时兜底。 + ## 副作用、权限与依赖 - 只运行本地 `git` 命令:`worktree add/remove/list/prune`、`status`、`diff --stat`、`branch -d/-D`。无其他二进制、无脚本、无 hooks、无 MCP 服务器。