Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -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.3",
"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",
Expand Down
20 changes: 20 additions & 0 deletions plugins/git-worktree/.zcode-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -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.3",
"author": {
"name": "EtienneLescot",
"url": "https://github.com/EtienneLescot"
},
"keywords": [
"git",
"worktree",
"parallel",
"isolation",
"branch"
]
}
47 changes: 47 additions & 0 deletions plugins/git-worktree/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# 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` | 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 <name> [base]` | Same, with an explicit worktree/branch `<name>` 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 <name>` | Resolves the worktree and prints the exact File → Open Folder path |
| `… remove <name>` | 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?").

## 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.
- 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.
47 changes: 47 additions & 0 deletions plugins/git-worktree/README_CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# 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` | 默认行为:**创建**——为新会话准备一个隔离 worktree(基于默认分支自动命名、位于仓库同级目录);输出 File → Open Folder 路径(当前会话仍留在原工作区) |
| `… create <名称> [基准]` | 同上,但显式指定 worktree/分支 `<名称>` 与基准(`origin/HEAD`,否则 `main`/`master`,否则 `HEAD`);绝不占用默认分支 |
| `… list` | 表格列出所有 worktree:名称、分支、未提交文件数、路径;标注主 worktree |
| `… open <名称>` | 解析 worktree,并给出确切的 File → Open Folder 打开路径 |
| `… remove <名称>` | 拒绝移除主 worktree;先汇总未提交改动,`--force` 前必须明确确认;随后提供“仅已合并”的分支清理 |
| `… prune` | 先展示过期条目,再清理注册表;孤儿目录只报告路径与大小,绝不静默删除 |

附带的 `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 服务器。
- 会创建目录(默认位于仓库根目录同级)并删除 worktree 目录——每个破坏性步骤都先要求明确确认。
- 无网络访问、无凭据、数据不出本机。
- 跨平台:纯 git 调用,无特定 shell 语法;已在 Windows 与 POSIX 上验证路径处理。

## 版本与许可

`0.1.0`——manifest 与市场条目保持同步。Apache-2.0,与 [zcode-plugins](https://github.com/zai-org/zcode-plugins) 仓库许可证一致。无第三方代码或资产。
46 changes: 46 additions & 0 deletions plugins/git-worktree/commands/worktree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
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 <name> | remove <name> | prune
---

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: '<branch>' is already used by worktree at <path>`, 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.

## create [name] [base]

This is the default when no subcommand is given.

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 `<name>`: 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-<YYYYMMDD>`. If branch `<name>` 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, `<repo-dirname>-<name>`. If the user asks for an in-repo location such as `.worktrees/<name>`, honor it and append that directory to `.git/info/exclude` (never a tracked `.gitignore`).
5. Create with `git worktree add -b <name> <path> <base>` (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.

## list

Run `git worktree list --porcelain`. For each worktree also run `git -C <path> 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 <name>

Resolve `<name>` 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 <name>

1. Resolve the worktree as in `open`. Refuse the main worktree.
2. Check `git -C <path> status --porcelain`. If there are uncommitted changes, STOP: summarize them (file list plus `git -C <path> diff --stat`), and ask whether to discard them. Only after an explicit confirmation run `git worktree remove --force <path>`; otherwise suggest committing or stashing first and stop.
3. Clean worktree: `git worktree remove <path>`. 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 <branch>` 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.
23 changes: 23 additions & 0 deletions plugins/git-worktree/skills/git-worktrees/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
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: '<branch>' is already used by worktree at <path>` 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

- 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 <branch> <path> <base>` — 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 <path> 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.