Skip to content

Commit c4ec438

Browse files
Kiyohito Itohclaude
andauthored
feat: Add persistent worktree support with auto-numbering and protection (#58)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 42643a4 commit c4ec438

6 files changed

Lines changed: 224 additions & 129 deletions

File tree

‎.claude/commands/bb.md‎

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,47 @@
11
---
22
name: bb
3-
description: Approve and merge PR, detach HEAD, delete branch
3+
description: Approve and merge PR, delete feature branch, return to worktree base branch
44
argument-hint: [PR number]
55
allowed-tools: Bash, Skill, AskUserQuestion
66
---
77

8-
Approve PR, merge it using /pr skill, detach HEAD, and delete branch using /git skill.
8+
Approve PR, merge it using /pr skill, delete feature branch, and return to worktree base branch.
99

1010
# Instructions
1111

1212
1. Get PR number from $ARGUMENTS or auto-detect from current branch
13-
2. Approve PR if not already approved: `gh pr review $PR_NUMBER --approve`
14-
3. Merge PR: Use Skill tool - `Skill(skill: "pr", args: "merge $PR_NUMBER")`
15-
4. Detach HEAD to main: `git checkout main && git pull`
16-
5. Delete branch: Use Skill tool - `Skill(skill: "git", args: "branch-delete $BRANCH_NAME")`
13+
2. Get current branch name: `git branch --show-current`
14+
3. Approve PR if not already approved: `gh pr review $PR_NUMBER --approve`
15+
4. Merge PR: Use Skill tool - `Skill(skill: "pr", args: "merge $PR_NUMBER")`
16+
5. Determine base branch:
17+
- If in worktree (work1, work2, etc.), detect worktree base branch
18+
- If in main repo, use main branch
19+
6. Switch to base branch: `git checkout $BASE_BRANCH`
20+
7. Update base branch: `git pull origin main` (to sync with latest main)
21+
8. Delete feature branch: Use Skill tool - `Skill(skill: "git", args: "branch-delete $FEATURE_BRANCH")`
22+
23+
# Worktree Detection
24+
25+
To determine if current directory is a worktree and find base branch:
26+
27+
```bash
28+
# Get worktree info
29+
worktree_path=$(pwd)
30+
worktree_list=$(git worktree list --porcelain)
31+
32+
# Find base branch for this worktree
33+
# Look for pattern: work1, work2, work3, etc.
34+
if [[ "$worktree_path" =~ /work([0-9]+)$ ]]; then
35+
base_branch="work${BASH_REMATCH[1]}"
36+
else
37+
base_branch="main"
38+
fi
39+
```
1740

1841
# Important
1942

2043
- Always use Skill tool for pr merge and git branch-delete operations
2144
- Never run `gh pr merge` or `git branch -d` manually
45+
- In worktrees: return to workX branch (not main)
46+
- In main repo: return to main branch
2247
- Ask user if anything is unclear

‎.claude/commands/hi.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,5 @@ Execute full development workflow from issue/PR to review request.
2727
- Use Skill tool for git commit and PR creation
2828
- Never manually run git commit or gh pr create commands
2929
- Ask questions when requirements are unclear
30+
- Works in both main repo and worktrees (work1, work2, etc.)
31+
- In worktrees: Creates feature branch from current workX branch

‎.claude/commands/qf.md‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
name: qf
3+
description: Quick fix workflow for small changes without issue tracking
4+
argument-hint: [description]
5+
allowed-tools: Bash, Task, AskUserQuestion, Glob, Grep, Read, Edit, Write, Skill
6+
---
7+
8+
Quick fix workflow for small changes that don't need issue tracking (typos, docs, minor fixes).
9+
10+
# Instructions
11+
12+
1. Get description from $ARGUMENTS or ask user interactively
13+
2. Ensure on main branch and sync with remote:
14+
```bash
15+
current_branch=$(git branch --show-current)
16+
if [[ "$current_branch" != "main" ]]; then
17+
echo "Switching to main branch..."
18+
git checkout main
19+
fi
20+
git pull origin main
21+
```
22+
3. Generate branch name from description:
23+
- Convert to lowercase
24+
- Replace spaces with hyphens
25+
- Pattern: `qf/<slug>`
26+
- Example: "Fix README typo" → `qf/fix-readme-typo`
27+
4. Create branch: `git checkout -b qf/<slug>`
28+
5. Analyze requirements from description
29+
6. Implement changes: Use Task tool with general-purpose agent
30+
- Pass description, relevant files to agent
31+
- Agent will read files, implement changes, ask questions if unclear
32+
7. Commit: Use Skill tool - `Skill(skill: "git", args: "commit")`
33+
8. Create PR: Use Skill tool - `Skill(skill: "pr", args: "create")`
34+
- PR workflow will auto-detect qf/ branch and skip issue requirement
35+
36+
# Branch Naming
37+
38+
- Pattern: `qf/<descriptive-slug>`
39+
- Examples:
40+
- qf/fix-typo-readme
41+
- qf/update-changelog
42+
- qf/remove-unused-import
43+
- qf/fix-broken-link
44+
45+
# Important
46+
47+
- Use Skill tool for git commit and PR creation
48+
- Never manually run git commit or gh pr create commands
49+
- Always sync with remote main before branching
50+
- For significant features, use /hi instead (issue-driven development)
51+
- Works in both main repo and worktrees
52+
- In worktrees: Creates qf branch from current workX branch

‎.claude/skills/git/workflows/worktree-create.md‎

Lines changed: 63 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Worktree Creation Workflow
22

3-
This workflow creates a new worktree for parallel work from the repository's default branch.
3+
This workflow creates a persistent worktree (work1, work2, work3, etc.) for parallel development. Each worktree has its own tracking branch that stays in sync with main via fetch/pull.
44

55
## Required Tools
66

@@ -46,82 +46,59 @@ base_branch="${default_branch}"
4646
echo "Worktree will be created from: ${base_branch}"
4747
```
4848

49-
### 2. Get Issue Number and Create Branch Name
49+
### 2. Auto-Generate Worktree Name
5050

51-
**2.1 Ask for Issue Number**
51+
**2.1 Find Available Worktree Number**
5252

53-
Use the AskUserQuestion tool to prompt the user:
54-
- Question: "What is the issue number for this work?"
55-
- Provide two options: "I have an issue number" and "No issue yet"
56-
- If user selects "I have an issue number", they will provide the number via text input
57-
- If user selects "No issue yet", exit with guidance
58-
59-
If user selects "No issue yet", exit with guidance:
60-
61-
Please create an issue first using GitHub issues.
62-
This ensures work is tracked and follows issue-driven development.
63-
64-
I can help create the issue. Please provide:
65-
- Role: Who is affected?
66-
- Goal: What do you want?
67-
- Benefit: Why is this important?
68-
69-
Or you can create it manually on GitHub following .claude/rules/issues.md format.
70-
Once created, return here with the issue number.
71-
72-
If user provides an issue number, validate it is numeric:
73-
74-
```bash
75-
if ! [[ "$issue_number" =~ ^[0-9]+$ ]]; then
76-
echo "Error: Issue number must be a positive integer"
77-
exit 1
78-
fi
79-
echo "Issue number validated: ${issue_number}"
80-
```
81-
82-
**2.2 Validate Issue Exists**
83-
84-
Verify the issue exists using gh CLI:
53+
Scan existing worktrees to find the next available number:
8554

8655
```bash
87-
echo "Validating issue #${issue_number}..."
88-
if ! gh issue view "$issue_number" &>/dev/null; then
89-
echo "Error: Issue #${issue_number} not found."
90-
echo ""
91-
echo "Please verify the issue number or create the issue first:"
92-
echo "gh issue create"
93-
exit 1
94-
fi
95-
echo "Issue #${issue_number} confirmed"
96-
```
56+
# Get list of existing worktree paths
57+
existing_worktrees=$(git worktree list --porcelain | grep "^worktree" | awk '{print $2}')
9758

98-
**2.3 Generate Branch Name**
59+
# Find highest work number in use
60+
max_num=0
61+
while IFS= read -r wt_path; do
62+
wt_basename=$(basename "$wt_path")
63+
if [[ "$wt_basename" =~ ^work([0-9]+)$ ]]; then
64+
num="${BASH_REMATCH[1]}"
65+
if (( num > max_num )); then
66+
max_num=$num
67+
fi
68+
fi
69+
done <<< "$existing_worktrees"
9970

100-
Branch name is always: `issue-${issue_number}`
101-
102-
Example:
103-
- Issue #42 → Branch: `issue-42`
104-
- Issue #123 → Branch: `issue-123`
71+
# Next available number
72+
worktree_num=$((max_num + 1))
73+
worktree_name="work${worktree_num}"
74+
branch_name="work${worktree_num}"
10575

106-
```bash
107-
branch_name="issue-${issue_number}"
108-
echo "Branch name will be: ${branch_name}"
76+
echo "Next available worktree: ${worktree_name}"
77+
echo "Branch name: ${branch_name}"
10978
```
11079

111-
**2.4 Check for Branch Duplicates**
80+
**2.2 Check for Branch/Worktree Conflicts**
11281

11382
```bash
83+
# Check if branch already exists
11484
if git branch --list "${branch_name}" | grep -q .; then
11585
echo "Error: Branch '${branch_name}' already exists."
11686
echo ""
117-
echo "To work on existing branch in a new worktree:"
87+
echo "To use existing branch:"
11888
echo "git worktree add <path> ${branch_name}"
89+
exit 1
90+
fi
91+
92+
# Check if worktree already exists
93+
existing_wt=$(git worktree list --porcelain | grep -A 2 "branch refs/heads/${branch_name}" | grep "worktree" | awk '{print $2}')
94+
if [[ -n "$existing_wt" ]]; then
95+
echo "Error: Worktree already exists for ${branch_name} at: ${existing_wt}"
11996
echo ""
120-
echo "To delete and recreate:"
121-
echo "git branch -D ${branch_name}"
97+
echo "Use existing worktree: cd '${existing_wt}'"
12298
exit 1
12399
fi
124-
echo "Branch name is available"
100+
101+
echo "Branch and worktree names are available"
125102
```
126103

127104
### 3. Determine Worktree Path
@@ -131,14 +108,14 @@ echo "Branch name is available"
131108
Generate path using consistent naming:
132109

133110
```bash
134-
worktree_path="${parent_dir}/issue-${issue_number}"
111+
worktree_path="${parent_dir}/${worktree_name}"
135112
echo "Generated worktree path: ${worktree_path}"
136113
```
137114

138115
Example:
139116
- Current: `/home/user/work/nabledge-dev`
140-
- Issue #42 → Worktree: `/home/user/work/issue-42`
141-
- Issue #123 → Worktree: `/home/user/work/issue-123`
117+
- First worktree → Path: `/home/user/work/work1`
118+
- Second worktree → Path: `/home/user/work/work2`
142119

143120
Validate parent directory is writable:
144121

@@ -175,36 +152,17 @@ fi
175152
echo "Path is available"
176153
```
177154

178-
**3.3 Check for Existing Worktree**
179-
180-
Check if a worktree already exists for this branch:
181-
182-
```bash
183-
existing_worktree=$(git worktree list --porcelain | grep -A 2 "branch refs/heads/${branch_name}" | grep "worktree" | awk '{print $2}')
184-
if [[ -n "$existing_worktree" ]]; then
185-
echo "Error: Worktree already exists for ${branch_name} at: ${existing_worktree}"
186-
echo ""
187-
echo "Options:"
188-
echo "1. Use existing worktree: cd '${existing_worktree}'"
189-
echo "2. Remove existing: git worktree remove '${existing_worktree}'"
190-
echo "3. Cancel operation"
191-
exit 1
192-
fi
193-
echo "No existing worktree for this branch"
194-
```
195-
196-
**3.4 Confirm Path**
155+
**3.3 Confirm Path**
197156

198157
Use the AskUserQuestion tool to confirm:
199-
- Question: "Create worktree at the following path. OK?"
158+
- Question: "Create persistent worktree at the following path. OK?"
200159
- Display the full path in the question
201160
- Provide options: "Yes, create it" and "No, cancel"
202161

203162
Display information:
204163
```
205164
Path: ${worktree_path}
206-
Branch: ${branch_name}
207-
Issue: #${issue_number}
165+
Branch: ${branch_name} (will track ${base_branch})
208166
Base: ${base_branch}
209167
```
210168

@@ -244,15 +202,23 @@ Please verify:
244202
## Worktree Creation Complete
245203
246204
**Path**: ${worktree_path}
247-
**Branch**: ${branch_name}
248-
**Issue**: #${issue_number}
205+
**Branch**: ${branch_name} (tracks ${base_branch})
249206
**Base Branch**: ${base_branch}
250207
251208
### Move to Worktree
252209
cd ${worktree_path}
253210
254-
You can now start working on this issue.
255-
Use `/git commit` to commit changes.
211+
### Working with This Worktree
212+
213+
This is a persistent worktree for parallel development. To work on issues:
214+
215+
1. Create feature branch: `/hi <issue-number>`
216+
2. Work on your changes
217+
3. Commit: `/git commit`
218+
4. Create PR: `/pr create`
219+
5. Merge: `/bb <pr-number>` (returns to ${branch_name} after cleanup)
220+
221+
The ${branch_name} branch stays in sync with ${base_branch}. Use `git pull origin ${base_branch}` to update.
256222
257223
### Open in Editor (optional)
258224
code ${worktree_path}
@@ -262,23 +228,22 @@ code ${worktree_path}
262228

263229
| Error | Response |
264230
|-------|----------|
265-
| Branch name exists | Guide to use different issue or delete existing |
266-
| Path exists | Guide to remove existing or use different issue |
231+
| Branch name exists | Guide to use existing or delete |
232+
| Path exists | Guide to remove existing path |
267233
| Failed to update default branch | Guide to resolve conflicts |
268234
| Insufficient permissions | Guide to check write permissions |
269235
| Insufficient disk space | Guide to check disk space |
270-
| Issue not found | Guide to create issue first |
271-
| Invalid issue number | Reject non-numeric input |
272-
| Existing worktree | Guide to use existing or remove |
236+
| Existing worktree | Guide to use existing worktree |
273237

274238
## Important Notes
275239

276240
1. **No emojis**: Never use emojis unless explicitly requested by user
277-
2. **Path naming convention**: `${parent_dir}/issue-${issue_number}`
278-
3. **Branch naming convention**: `issue-${issue_number}`
279-
4. **Issue-driven development**: All worktrees must be linked to a GitHub issue
280-
5. **Issue validation**: Always verify issue exists before creating worktree
241+
2. **Path naming convention**: `${parent_dir}/work${N}` where N is auto-incremented
242+
3. **Branch naming convention**: `work${N}` matching worktree name
243+
4. **Persistent worktrees**: work1/work2/work3 are permanent development spaces, not deleted after PR merge
244+
5. **Auto-numbering**: Automatically detects existing worktrees and assigns next available number
281245
6. **Base branch**: Always branch from repository's default branch (main, develop, etc.)
282246
7. **Variable syntax**: Always use `${variable}` or `"$variable"` in bash commands for safety
283247
8. **Path safety**: Validate parent directory permissions and path availability
284-
9. **Worktree cleanup**: Use `git worktree remove` instead of `rm -rf` for proper cleanup
248+
9. **Branch tracking**: workX branches track main and can be updated via `git pull origin main`
249+
10. **Feature branches**: Use `/hi` within worktree to create feature branches for actual work

0 commit comments

Comments
 (0)