Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Added
- `/speckit.worktrees.specify` command for a worktree-first specify workflow: create or reuse the feature worktree before writing spec artifacts, then continue the normal Spec Kit flow from the worktree root
- VS Code handoff guidance for `/speckit.worktrees.specify`: optional `--open-vscode` behavior, configurable `code -n <worktree-path>` new-window default, and explicit reuse/print modes

### Changed
- README now documents the recommended response to "pre-hook for specify": use an explicit worktree-first command unless Spec Kit itself can also switch the active project root for the rest of `/speckit.specify`
Expand Down
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ layout: "nested" # nested | sibling
auto_create: true # Cursor + /worktree users: set false to avoid in-repo worktrees after every specify
sibling_pattern: "{{repo}}--{{branch}}"
dotworktrees_dir: ".worktrees"

# Optional VS Code handoff for /speckit.worktrees.specify
vscode_open_after_create: false
vscode_open_mode: "new-window" # new-window | reuse-window | print-command
vscode_command: "code"
```

## How worktrees stay isolated
Expand Down Expand Up @@ -151,6 +156,30 @@ For VS Code, the most reliable variant remains one window per active worktree:
4. Commit, push, and open the PR from the worktree.
5. Close the worktree window and run `/speckit.worktrees.clean` from the primary checkout when done.

### VS Code handoff

`/speckit.worktrees.specify` can hand the created worktree to VS Code via the `code` CLI:

```text
/speckit.worktrees.specify 005-user-auth Build sign-in --open-vscode
```

By default this uses a new window:

```bash
code -n <worktree-path>
```

You can make that the project default in `.specify/extensions/worktrees/worktree-config.yml`:

```yaml
vscode_open_after_create: true
vscode_open_mode: "new-window"
vscode_command: "code"
```

Use `vscode_open_mode: "reuse-window"` only when you explicitly want VS Code to replace the current window with the worktree. If the `code` CLI is unavailable, or if `vscode_open_mode: "print-command"` is set, the command reports the exact `code -n <worktree-path>` command to run manually.

## Hook

**`after_specify`** — automatically creates a worktree after a new feature is specified. Controlled by the `auto_create` config value.
Expand Down
50 changes: 48 additions & 2 deletions commands/speckit.worktrees.specify.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ You **MUST** consider the user input before proceeding. The user input should in
- A feature branch name or slug (for example `005-user-auth`)
- The feature description to specify
- Optional worktree flags accepted by `/speckit.worktrees.create`, such as `--layout sibling`, `--path <dir>`, or `--base-ref HEAD`
- Optional IDE handoff flags: `--open-vscode`, `--no-open-vscode`, `--vscode-new-window`, `--vscode-reuse-window`, or `--vscode-print-command`

If the branch name is missing, ask for it before creating anything. If the feature description is missing, create the worktree only after the user confirms they want to continue specifying in that worktree.

Expand All @@ -25,11 +26,32 @@ If the branch name is missing, ask for it before creating anything. If the featu
2. Verify the working tree has the intended base state for the new feature
3. Verify `git worktree` is available (`git worktree list` succeeds)

## Configuration

Read configuration from `.specify/extensions/worktrees/worktree-config.yml` if it exists. Defaults apply when the file is absent.

| Key | Default | Description |
|-----|---------|-------------|
| `vscode_open_after_create` | `false` | Open the returned worktree with the VS Code CLI after creation |
| `vscode_open_mode` | `new-window` | `new-window`, `reuse-window`, or `print-command` |
| `vscode_command` | `code` | VS Code CLI command to run |

User flags override configuration for the current command:

| Flag | Behavior |
|------|----------|
| `--open-vscode` | Enable VS Code handoff |
| `--no-open-vscode` | Disable VS Code handoff |
| `--vscode-new-window` | Run `code -n <worktree-path>` |
| `--vscode-reuse-window` | Run `code -r <worktree-path>` |
| `--vscode-print-command` | Print the command instead of running it |

## Outline

1. **Parse the request**:
- Extract the target branch name
- Extract any worktree flags
- Extract any VS Code handoff flags
- Preserve the remaining text as the feature description

2. **Create the worktree first**:
Expand All @@ -51,7 +73,29 @@ If the branch name is missing, ask for it before creating anything. If the featu
- Run all file reads, writes, scripts, git commands, and follow-up Spec Kit steps from that path
- If using an IDE, open the returned path as its own window before continuing

4. **Write the spec inside the worktree**:
4. **Open VS Code when requested**:
If VS Code handoff is enabled, open or print the worktree command after creation:

```bash
if [[ "$VSCODE_OPEN_MODE" == "print-command" ]]; then
echo "$VSCODE_COMMAND -n \"$WORKTREE_PATH\""
elif command -v "$VSCODE_COMMAND" >/dev/null 2>&1; then
if [[ "$VSCODE_OPEN_MODE" == "reuse-window" ]]; then
"$VSCODE_COMMAND" -r "$WORKTREE_PATH"
else
"$VSCODE_COMMAND" -n "$WORKTREE_PATH"
fi
else
echo "VS Code CLI not found. Run: code -n \"$WORKTREE_PATH\""
fi
```

Rules:
- Use `new-window` unless the user or config explicitly chooses `reuse-window`
- Never replace the current VS Code window unless `reuse-window` was explicit
- If the CLI is unavailable or mode is `print-command`, print the exact command to run

5. **Write the spec inside the worktree**:
Continue the normal `/speckit.specify` workflow from the worktree root using the feature description. Spec artifacts should be created under:

```text
Expand All @@ -60,7 +104,7 @@ If the branch name is missing, ask for it before creating anything. If the featu

Do not write spec artifacts to the primary checkout.

5. **Report**:
6. **Report**:
Output a concise summary:

```markdown
Expand All @@ -73,6 +117,7 @@ If the branch name is missing, ask for it before creating anything. If the featu
| **Spec root** | /Users/me/code/my-project/.worktrees/005-user-auth/specs/005-user-auth |

**Next steps:**
- Open VS Code: code -n /Users/me/code/my-project/.worktrees/005-user-auth
- Continue `/speckit.plan` from the worktree root
- Keep commits and PR work inside that worktree
- Return to the primary checkout only for `/speckit.worktrees.clean`
Expand All @@ -83,5 +128,6 @@ If the branch name is missing, ask for it before creating anything. If the featu
- Create or reuse the worktree before writing any spec files
- Never run `git checkout` in the primary checkout as part of this workflow
- Prefer `--base-ref HEAD` when the primary checkout has committed spec seed work that the new worktree must include
- Open VS Code in a new window by default when VS Code handoff is enabled; reuse the current window only with an explicit user/config opt-in
- Keep all generated artifacts, plans, tasks, implementation changes, commits, and PR operations in the worktree
- Use `/speckit.worktrees.clean` from the primary checkout after the PR is merged or the worktree is no longer needed
12 changes: 12 additions & 0 deletions worktree-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,15 @@ sibling_pattern: "{{repo}}--{{branch}}"

# Directory name for nested layout (relative to repo root, auto-gitignored).
dotworktrees_dir: ".worktrees"

# VS Code handoff for /speckit.worktrees.specify.
# false — print the worktree path and let the user open it manually
# true — open the worktree after creation when the VS Code CLI is available
vscode_open_after_create: false

# VS Code open mode:
# new-window — code -n <worktree-path> (recommended)
# reuse-window — code -r <worktree-path> (explicit opt-in)
# print-command — only print the command to run
vscode_open_mode: "new-window"
vscode_command: "code"
Loading