Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:47:41 +08:00
commit f9c8c37217
13 changed files with 6174 additions and 0 deletions

758
commands/adopt.md Normal file
View File

@@ -0,0 +1,758 @@
---
description: Add .ai-context.json metadata to an existing worktree
argument-hint: [--mode <mode>] [--description "<text>"]
allowed-tools: Bash, Write, Read
model: sonnet
---
# /adopt:working-tree
Generate `.ai-context.json` and `README.working-tree.md` for existing worktree lacking metadata.
## ARGUMENT SPECIFICATION
```
SYNTAX: /adopt:working-tree [--mode <mode>] [--description "<text>"]
OPTIONAL:
--mode <mode>
Type: enum[main, feature, bugfix, experiment, review]
Default: inferred from branch-name (see MODE_INFERENCE_ALGORITHM)
Validation: must match exactly one of the enum values
--description "<text>"
Type: string (quoted if contains spaces)
Default: "" (empty string)
Validation: any string, no restrictions
```
## MODE_INFERENCE_ALGORITHM
APPLY rules sequentially, first match wins:
```python
def infer_mode(branch_name: str) -> str:
if branch_name.startswith("feature/"):
return "feature"
elif branch_name.startswith(("bugfix/", "fix/")):
return "bugfix"
elif branch_name.startswith(("exp/", "experiment/")):
return "experiment"
elif branch_name.startswith("review/"):
return "review"
elif branch_name in ("main", "master"):
return "main"
else:
return "feature" # DEFAULT
```
DETERMINISTIC: Given same branch_name, always produces same mode.
## EXECUTION PROTOCOL
Execute steps sequentially. Each step must complete successfully before proceeding.
### STEP 1: DETECT REPOSITORY INFO
EXECUTE:
```bash
REPO_ROOT=$(git rev-parse --show-toplevel 2>&1)
EXIT_CODE_ROOT=$?
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>&1)
EXIT_CODE_BRANCH=$?
```
VALIDATION:
- IF EXIT_CODE_ROOT != 0 → ERROR PATTERN "not-in-git-repo"
- IF EXIT_CODE_BRANCH != 0 → ERROR PATTERN "git-command-failed"
- REPO_ROOT must be absolute path starting with /
DATA EXTRACTION:
```bash
WORKTREE_NAME=$(basename "$REPO_ROOT")
```
NEXT:
- On success → STEP 2
- On failure → ABORT
### STEP 2: CHECK EXISTING METADATA
EXECUTE:
```bash
METADATA_PATH="$REPO_ROOT/.ai-context.json"
test -f "$METADATA_PATH"
EXISTS=$?
```
VALIDATION:
- EXISTS is 0 (exists) or 1 (does not exist)
ACTION:
- IF EXISTS == 0 → STEP 3 (check for overwrite)
- IF EXISTS == 1 → STEP 4 (proceed with creation)
NEXT:
- Conditional based on EXISTS value
### STEP 3: HANDLE EXISTING METADATA
EXECUTE:
```bash
EXISTING_JSON=$(cat "$METADATA_PATH" 2>&1)
EXISTING_MODE=$(echo "$EXISTING_JSON" | jq -r '.mode // "unknown"' 2>&1)
EXISTING_DESC=$(echo "$EXISTING_JSON" | jq -r '.description // ""' 2>&1)
EXISTING_CREATED=$(echo "$EXISTING_JSON" | jq -r '.created // ""' 2>&1)
```
DISPLAY TO USER:
```
Current worktree already has metadata:
Directory: {WORKTREE_NAME}
Branch: {CURRENT_BRANCH}
Mode: {EXISTING_MODE}
Created: {EXISTING_CREATED}
Description: {EXISTING_DESC or "None"}
Do you want to overwrite this metadata?
```
USER DECISION (use AskUserQuestion):
- Option 1: "Keep existing metadata" → TERMINATE (no changes)
- Option 2: "Overwrite with new metadata" → STEP 4 (proceed)
- Option 3: "Cancel" → TERMINATE (no changes)
NEXT:
- IF user selects overwrite → STEP 4
- IF user selects keep/cancel → TERMINATE
### STEP 4: PARSE AND VALIDATE ARGUMENTS
PARSE:
```bash
# Parse --mode flag (if present)
if [[ "$@" =~ --mode[[:space:]]+([a-z]+) ]]; then
MODE_ARG="${BASH_REMATCH[1]}"
else
MODE_ARG=""
fi
# Parse --description flag (if present)
if [[ "$@" =~ --description[[:space:]]+\"([^\"]+)\" ]]; then
DESCRIPTION="${BASH_REMATCH[1]}"
elif [[ "$@" =~ --description[[:space:]]+([^[:space:]]+) ]]; then
DESCRIPTION="${BASH_REMATCH[1]}"
else
DESCRIPTION=""
fi
```
VALIDATION:
- IF MODE_ARG not empty AND MODE_ARG not in [main, feature, bugfix, experiment, review] → ERROR PATTERN "invalid-mode"
NEXT:
- On success → STEP 5
- On failure → ABORT
### STEP 5: DETERMINE MODE
EXECUTE:
```bash
if [ -n "$MODE_ARG" ]; then
# Explicit mode provided
MODE="$MODE_ARG"
else
# Infer from branch name using MODE_INFERENCE_ALGORITHM
case "$CURRENT_BRANCH" in
feature/*)
MODE="feature"
;;
bugfix/*|fix/*)
MODE="bugfix"
;;
exp/*|experiment/*)
MODE="experiment"
;;
review/*)
MODE="review"
;;
main|master)
MODE="main"
;;
*)
MODE="feature"
;;
esac
fi
```
VALIDATION:
- MODE must be exactly one of: main, feature, bugfix, experiment, review
- MODE must not be empty
DATA:
- MODE = final determined mode (explicit or inferred)
NEXT:
- On success → STEP 6
- On failure → ABORT (should not occur if STEP 4 validation passed)
### STEP 6: GENERATE TIMESTAMP
EXECUTE:
```bash
CREATED_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
```
FORMAT: ISO 8601 UTC (example: 2025-11-23T12:34:56Z)
VALIDATION:
- CREATED_TIMESTAMP must match pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$
NEXT:
- On success → STEP 7
- No failure case
### STEP 7: GENERATE .ai-context.json
CONTENT TEMPLATE:
```json
{
"worktree": "{WORKTREE_NAME}",
"branch": "{CURRENT_BRANCH}",
"mode": "{MODE}",
"created": "{CREATED_TIMESTAMP}",
"description": "{DESCRIPTION}"
}
```
SUBSTITUTIONS:
- {WORKTREE_NAME} = from STEP 1
- {CURRENT_BRANCH} = from STEP 1
- {MODE} = from STEP 5
- {CREATED_TIMESTAMP} = from STEP 6
- {DESCRIPTION} = from STEP 4 (empty string if not provided)
EXECUTE:
```bash
cat > "$REPO_ROOT/.ai-context.json" <<EOF
{
"worktree": "$WORKTREE_NAME",
"branch": "$CURRENT_BRANCH",
"mode": "$MODE",
"created": "$CREATED_TIMESTAMP",
"description": "$DESCRIPTION"
}
EOF
```
VALIDATION:
- File must be created at exact path: $REPO_ROOT/.ai-context.json
- File must contain valid JSON
- Verify with: `jq empty "$REPO_ROOT/.ai-context.json"`
- IF jq fails → ERROR PATTERN "metadata-write-failed"
NEXT:
- On success → STEP 8
- On failure → ABORT
### STEP 8: GENERATE README.working-tree.md (IF MISSING)
CHECK:
```bash
README_PATH="$REPO_ROOT/README.working-tree.md"
test -f "$README_PATH"
README_EXISTS=$?
```
ACTION:
- IF README_EXISTS == 0 (exists) → SKIP to STEP 9 (don't overwrite)
- IF README_EXISTS == 1 (missing) → Create README
CONTENT TEMPLATE:
```markdown
# Worktree: {WORKTREE_NAME}
**Branch:** `{CURRENT_BRANCH}`
**Mode:** `{MODE}`
**Created:** {CREATED_TIMESTAMP}
## Purpose
{DESCRIPTION_OR_DEFAULT}
## Mode Semantics
- **main**: Minimal changes, stable work only
- **feature**: Active development, larger changes allowed
- **bugfix**: Isolated, surgical fixes only
- **experiment**: Prototypes, large swings, unsafe changes allowed
- **review**: Documentation, analysis, audits
## About This Worktree
This directory is an independent Git worktree attached to the main repository.
- Main repo: {REPO_ROOT}
- Worktree path: {REPO_ROOT}
- Branch: {CURRENT_BRANCH}
See `.ai-context.json` for machine-readable metadata.
```
SUBSTITUTIONS:
- {WORKTREE_NAME} = from STEP 1
- {CURRENT_BRANCH} = from STEP 1
- {MODE} = from STEP 5
- {CREATED_TIMESTAMP} = from STEP 6
- {DESCRIPTION_OR_DEFAULT} = DESCRIPTION if not empty, else "No description provided"
- {REPO_ROOT} = from STEP 1
EXECUTE (only if README_EXISTS == 1):
```bash
DESCRIPTION_TEXT="${DESCRIPTION:-No description provided}"
cat > "$REPO_ROOT/README.working-tree.md" <<EOF
# Worktree: $WORKTREE_NAME
**Branch:** \`$CURRENT_BRANCH\`
**Mode:** \`$MODE\`
**Created:** $CREATED_TIMESTAMP
## Purpose
$DESCRIPTION_TEXT
## Mode Semantics
- **main**: Minimal changes, stable work only
- **feature**: Active development, larger changes allowed
- **bugfix**: Isolated, surgical fixes only
- **experiment**: Prototypes, large swings, unsafe changes allowed
- **review**: Documentation, analysis, audits
## About This Worktree
This directory is an independent Git worktree attached to the main repository.
- Main repo: $REPO_ROOT
- Worktree path: $REPO_ROOT
- Branch: $CURRENT_BRANCH
See \`.ai-context.json\` for machine-readable metadata.
EOF
```
VALIDATION:
- IF created, file must exist at: $REPO_ROOT/README.working-tree.md
- IF file creation failed → Warning (not fatal)
NEXT:
- On success or skip → STEP 9
- On failure → Warning (continue)
### STEP 9: OUTPUT SUCCESS SUMMARY
OUTPUT FORMAT (exact):
```
Adopted worktree successfully!
Directory: {WORKTREE_NAME}
Branch: {CURRENT_BRANCH}
Mode: {MODE}
Description: {DESCRIPTION_OR_NONE}
Metadata files created:
✓ .ai-context.json
{README_STATUS}
Use /status:working-tree to view metadata anytime.
```
SUBSTITUTIONS:
- {WORKTREE_NAME} = from STEP 1
- {CURRENT_BRANCH} = from STEP 1
- {MODE} = from STEP 5
- {DESCRIPTION_OR_NONE} = DESCRIPTION if not empty, else "None"
- {README_STATUS} = "✓ README.working-tree.md (created)" if created, "- README.working-tree.md (already exists)" if skipped
NEXT:
- TERMINATE (success)
## ERROR PATTERNS
### PATTERN: not-in-git-repo
DETECTION:
- TRIGGER: git rev-parse --show-toplevel exit code != 0
- INDICATORS: stderr contains "not a git repository"
RESPONSE (exact):
```
Error: Not in a git repository
Run this command from within a git repository.
To create a new worktree with metadata:
/create:working-tree <branch-name>
```
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: git-command-failed
DETECTION:
- TRIGGER: Any git command (except rev-parse --show-toplevel) returns non-zero exit code
- CAPTURE: stderr from git command
RESPONSE (exact):
```
Error: Failed to read git information
Git error: {GIT_STDERR}
Check that:
- You're in a git repository
- Git is installed and working
```
TEMPLATE SUBSTITUTIONS:
- {GIT_STDERR} = captured stderr
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: invalid-mode
DETECTION:
- TRIGGER: MODE_ARG provided but not in [main, feature, bugfix, experiment, review]
RESPONSE (exact):
```
Error: Invalid mode '{MODE_ARG}'
Valid modes: main, feature, bugfix, experiment, review
Example:
/adopt:working-tree --mode feature --description "new feature work"
```
TEMPLATE SUBSTITUTIONS:
- {MODE_ARG} = the invalid mode provided
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: metadata-write-failed
DETECTION:
- TRIGGER: .ai-context.json write fails or invalid JSON (STEP 7)
- CHECK: jq validation fails
RESPONSE (exact):
```
Error: Failed to write .ai-context.json
Write error: {ERROR_MESSAGE}
Check that:
- You have write permission in this directory
- Disk space is available
- No file conflicts exist
```
TEMPLATE SUBSTITUTIONS:
- {ERROR_MESSAGE} = error message from write operation
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: readme-write-failed
DETECTION:
- TRIGGER: README.working-tree.md write fails (STEP 8)
RESPONSE (exact):
```
Warning: Failed to write README.working-tree.md
The .ai-context.json was created successfully.
You can manually create the README if needed.
```
CONTROL FLOW:
- ABORT: false (warning, not critical)
- CLEANUP: none
- FALLBACK: Continue without README
## TOOL PERMISSION MATRIX
| Tool | Pattern | Permission | Pre-Check | Post-Check | On-Deny-Action |
|------|---------|------------|-----------|------------|----------------|
| Bash | git:* | ALLOW | command_safe | validate_output | N/A |
| Bash | date:* | ALLOW | N/A | N/A | N/A |
| Bash | test:* | ALLOW | N/A | N/A | N/A |
| Bash | basename:* | ALLOW | N/A | N/A | N/A |
| Bash | cat > *.json | ALLOW | dir_writable | valid_json | N/A |
| Bash | cat > *.md | ALLOW | dir_writable | N/A | N/A |
| Bash | jq:* | ALLOW | N/A | N/A | N/A |
| Bash | rm:* | DENY | N/A | N/A | ABORT "Destructive operation" |
| Bash | sudo:* | DENY | N/A | N/A | ABORT "Elevated privileges" |
| Write | $REPO_ROOT/.ai-context.json | ALLOW | dir_exists | valid_json | N/A |
| Write | $REPO_ROOT/README.working-tree.md | ALLOW | dir_exists | N/A | N/A |
| Write | **/.env* | DENY | N/A | N/A | ABORT "Secrets file" |
| Read | $REPO_ROOT/.ai-context.json | ALLOW | file_exists | N/A | N/A |
SECURITY CONSTRAINTS:
- Can only write to current worktree directory (REPO_ROOT)
- Cannot modify files outside current worktree
- Cannot execute destructive operations
- All file writes must be to metadata files only
## TEST CASES
### TC001: Adopt worktree without metadata
PRECONDITIONS:
- In git repository at /Users/dev/myapp
- Current branch: feature/login
- File does NOT exist: /Users/dev/myapp/.ai-context.json
INPUT:
```
/adopt:working-tree
```
EXPECTED EXECUTION FLOW:
1. STEP 1 → REPO_ROOT="/Users/dev/myapp", WORKTREE_NAME="myapp", CURRENT_BRANCH="feature/login"
2. STEP 2 → EXISTS=1 (no metadata)
3. STEP 4 → MODE_ARG="", DESCRIPTION=""
4. STEP 5 → MODE="feature" (inferred from "feature/" prefix)
5. STEP 6 → Generate timestamp
6. STEP 7 → Write .ai-context.json
7. STEP 8 → README_EXISTS=1, create README
8. STEP 9 → Output summary
EXPECTED OUTPUT:
```
Adopted worktree successfully!
Directory: myapp
Branch: feature/login
Mode: feature
Description: None
Metadata files created:
✓ .ai-context.json
✓ README.working-tree.md (created)
Use /status:working-tree to view metadata anytime.
```
VALIDATION COMMANDS:
```bash
# Verify .ai-context.json created
test -f /Users/dev/myapp/.ai-context.json && echo "PASS" || echo "FAIL"
jq -r '.mode' /Users/dev/myapp/.ai-context.json | grep "feature" && echo "PASS" || echo "FAIL"
# Verify README created
test -f /Users/dev/myapp/README.working-tree.md && echo "PASS" || echo "FAIL"
```
### TC002: Adopt with explicit mode and description
PRECONDITIONS:
- In git repository at /Users/dev/myapp
- Current branch: main
- No existing metadata
INPUT:
```
/adopt:working-tree --mode main --description "Primary development branch"
```
EXPECTED EXECUTION FLOW:
1-2. Standard detection
3. STEP 4 → MODE_ARG="main", DESCRIPTION="Primary development branch"
4. STEP 5 → MODE="main" (explicit, not inferred)
5-8. Standard flow
EXPECTED .ai-context.json:
```json
{
"worktree": "myapp",
"branch": "main",
"mode": "main",
"created": "2025-11-23T12:34:56Z",
"description": "Primary development branch"
}
```
VALIDATION:
```bash
jq -r '.mode' .ai-context.json | grep "main" && echo "PASS" || echo "FAIL"
jq -r '.description' .ai-context.json | grep "Primary development branch" && echo "PASS" || echo "FAIL"
```
### TC003: Metadata already exists - user keeps existing
PRECONDITIONS:
- In git repository at /Users/dev/myapp
- File exists: /Users/dev/myapp/.ai-context.json with valid data
INPUT:
```
/adopt:working-tree --mode experiment
```
EXPECTED EXECUTION FLOW:
1. STEP 1 → Detect repo
2. STEP 2 → EXISTS=0 (metadata exists)
3. STEP 3 → Display existing metadata, ask user
4. USER SELECTS "Keep existing metadata"
5. TERMINATE (no changes)
EXPECTED OUTPUT:
```
Current worktree already has metadata:
Directory: myapp
Branch: feature/login
Mode: feature
Created: 2025-11-20T10:00:00Z
Description: Original description
Do you want to overwrite this metadata?
```
POSTCONDITIONS:
- .ai-context.json unchanged
- No files modified
### TC004: Metadata already exists - user overwrites
PRECONDITIONS:
- In git repository with existing .ai-context.json
INPUT:
```
/adopt:working-tree --mode experiment --description "New description"
```
EXPECTED EXECUTION FLOW:
1-2. Detect repo, metadata exists
3. STEP 3 → Display existing, ask user
4. USER SELECTS "Overwrite with new metadata"
5-9. Continue with creation (new timestamp, new mode, new description)
EXPECTED OUTPUT:
```
Current worktree already has metadata:
[existing data shown]
Do you want to overwrite this metadata?
[User confirms overwrite]
Adopted worktree successfully!
Directory: myapp
Branch: feature/login
Mode: experiment
Description: New description
Metadata files created:
✓ .ai-context.json
- README.working-tree.md (already exists)
Use /status:working-tree to view metadata anytime.
```
### TC005: README already exists
PRECONDITIONS:
- No .ai-context.json
- README.working-tree.md already exists
INPUT:
```
/adopt:working-tree
```
EXPECTED EXECUTION FLOW:
1-7. Standard flow, create .ai-context.json
8. STEP 8 → README_EXISTS=0 (exists), skip creation
9. STEP 9 → Output shows README skipped
EXPECTED OUTPUT:
```
Adopted worktree successfully!
Directory: myapp
Branch: feature/login
Mode: feature
Description: None
Metadata files created:
✓ .ai-context.json
- README.working-tree.md (already exists)
Use /status:working-tree to view metadata anytime.
```
## USE CASES
### UC001: Adopting main repository
When working in main repo without worktrees:
```bash
cd ~/myapp
/adopt:working-tree --mode main --description "Primary development branch"
```
### UC002: Adopting manually created worktree
If worktree created without /create:working-tree:
```bash
cd ../myapp-feature-something
/adopt:working-tree
```
### UC003: Adding description later
If worktree created without description:
```bash
/adopt:working-tree --description "Working on user authentication refactor"
```
(Will prompt to overwrite existing metadata)
### UC004: Correcting mode
If mode was inferred incorrectly:
```bash
/adopt:working-tree --mode experiment
```
(Will prompt to overwrite existing metadata)
## RELATED COMMANDS
- /status:working-tree - View current metadata after adoption
- /create:working-tree - Create new worktree with metadata from start
- /list:working-tree - See all worktrees and their metadata status
## DELEGATION
For organizing worktree adoption strategy:
```
Task(
subagent_type='working-tree-consultant',
description='Worktree adoption strategy',
prompt='[question about when/how to adopt worktrees]'
)
```

673
commands/destroy.md Normal file
View File

@@ -0,0 +1,673 @@
---
description: Safely remove a git worktree and its metadata (preserves branch)
argument-hint: <worktree-path>
allowed-tools: Bash, Read
model: sonnet
---
# /destroy:working-tree
Safely remove git worktree directory and metadata files. Branch is preserved.
## ARGUMENT SPECIFICATION
```
SYNTAX: /destroy:working-tree <worktree-path>
REQUIRED:
<worktree-path>
Type: path (absolute or relative)
Validation: Must be registered git worktree
Examples: "../myapp-feature-login", "/Users/dev/myapp-feature-login"
```
## EXECUTION PROTOCOL
Execute steps sequentially. Each step must complete successfully before proceeding.
### STEP 1: VALIDATE AND RESOLVE WORKTREE PATH
EXECUTE:
```bash
# Resolve to absolute path
if [[ "$WORKTREE_PATH_ARG" = /* ]]; then
WORKTREE_PATH="$WORKTREE_PATH_ARG"
else
WORKTREE_PATH=$(cd "$(dirname "$WORKTREE_PATH_ARG")" && pwd)/$(basename "$WORKTREE_PATH_ARG")
fi
```
VALIDATION:
- IF WORKTREE_PATH_ARG is empty → ERROR PATTERN "missing-path"
- WORKTREE_PATH must be absolute after resolution
NEXT:
- On success → STEP 2
- On failure → ABORT
### STEP 2: CHECK PATH EXISTS
EXECUTE:
```bash
test -e "$WORKTREE_PATH"
EXISTS=$?
```
VALIDATION:
- IF EXISTS != 0 → ERROR PATTERN "path-not-exist"
NEXT:
- On EXISTS == 0 → STEP 3
- On EXISTS != 0 → ABORT
### STEP 3: GET ALL WORKTREES AND VALIDATE
EXECUTE:
```bash
WORKTREE_LIST=$(git worktree list --porcelain 2>&1)
EXIT_CODE=$?
```
VALIDATION:
- IF EXIT_CODE != 0 → ERROR PATTERN "git-command-failed"
PARSE WORKTREE_LIST:
```bash
# Extract all worktree paths and branches
# Format: worktree /path\nHEAD hash\nbranch refs/heads/name\n\n
CURRENT_MAIN=$(echo "$WORKTREE_LIST" | head -1 | cut -d' ' -f2)
IS_MAIN_REPO=false
if [ "$WORKTREE_PATH" = "$CURRENT_MAIN" ]; then
IS_MAIN_REPO=true
fi
# Find worktree entry for target path
WORKTREE_ENTRY=$(echo "$WORKTREE_LIST" | grep -A 3 "^worktree $WORKTREE_PATH$")
IS_REGISTERED=$(echo "$WORKTREE_ENTRY" | wc -l)
```
VALIDATION:
- IF IS_MAIN_REPO == true → ERROR PATTERN "cannot-destroy-main"
- IF IS_REGISTERED == 0 → ERROR PATTERN "not-a-worktree"
DATA EXTRACTION:
```bash
BRANCH_REF=$(echo "$WORKTREE_ENTRY" | grep "^branch " | cut -d' ' -f2)
BRANCH_NAME=$(echo "$BRANCH_REF" | sed 's|refs/heads/||')
```
NEXT:
- On success → STEP 4
- On failure → ABORT
### STEP 4: CHECK FOR UNCOMMITTED CHANGES
EXECUTE:
```bash
cd "$WORKTREE_PATH"
GIT_STATUS=$(git status --porcelain 2>&1)
STATUS_EXIT=$?
```
VALIDATION:
- IF STATUS_EXIT != 0 → Warning (worktree may be corrupted, allow removal)
DETECTION:
```bash
if [ -n "$GIT_STATUS" ]; then
HAS_CHANGES=true
else
HAS_CHANGES=false
fi
```
ACTION:
- IF HAS_CHANGES == false → STEP 5 (proceed directly)
- IF HAS_CHANGES == true → Display warning, ask user confirmation
USER DECISION (if HAS_CHANGES == true):
```
⚠ Warning: Uncommitted changes detected
Modified files:
{GIT_STATUS output}
These changes will be lost if you proceed.
Recommendations:
1. Commit changes: cd {WORKTREE_PATH} && git commit -am "message"
2. Stash changes: cd {WORKTREE_PATH} && git stash
3. Proceed anyway (changes will be lost)
Proceed with removal? (This will permanently delete uncommitted work)
```
Use AskUserQuestion:
- Option 1: "Cancel removal" → TERMINATE (no changes)
- Option 2: "Proceed with removal (discard changes)" → STEP 5
NEXT:
- IF user cancels → TERMINATE
- IF user proceeds OR no changes → STEP 5
### STEP 5: REMOVE WORKTREE
EXECUTE:
```bash
git worktree remove --force "$WORKTREE_PATH" 2>&1
EXIT_CODE=$?
```
VALIDATION:
- IF EXIT_CODE != 0 → ERROR PATTERN "worktree-removal-failed"
NEXT:
- On success → STEP 6
- On failure → ABORT
### STEP 6: PRUNE STALE REFERENCES
EXECUTE:
```bash
git worktree prune 2>&1
EXIT_CODE=$?
```
VALIDATION:
- IF EXIT_CODE != 0 → Warning (not fatal, removal succeeded)
NEXT:
- On success → STEP 7
- On warning → STEP 7 (continue)
### STEP 7: OUTPUT SUCCESS SUMMARY
OUTPUT FORMAT (exact):
```
✓ Worktree removed successfully
Path: {WORKTREE_PATH}
Branch: {BRANCH_NAME}
Branch '{BRANCH_NAME}' has been preserved.
To delete the branch as well:
git branch -d {BRANCH_NAME} # Safe delete (only if merged)
git branch -D {BRANCH_NAME} # Force delete (even if unmerged)
To delete remote branch:
git push origin --delete {BRANCH_NAME}
```
SUBSTITUTIONS:
- {WORKTREE_PATH} = from STEP 1
- {BRANCH_NAME} = from STEP 3
NEXT:
- TERMINATE (success)
## ERROR PATTERNS
### PATTERN: missing-path
DETECTION:
- TRIGGER: WORKTREE_PATH_ARG is empty (no argument provided)
RESPONSE (exact):
```
Error: Missing worktree path
Usage:
/destroy:working-tree <worktree-path>
Example:
/destroy:working-tree ../myapp-feature-login
To see all worktrees:
/list:working-tree
```
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: path-not-exist
DETECTION:
- TRIGGER: Provided path does not exist (STEP 2)
RESPONSE (exact):
```
Error: Path does not exist
Path: {WORKTREE_PATH}
The specified path doesn't exist. Check for typos.
To list existing worktrees:
/list:working-tree
```
TEMPLATE SUBSTITUTIONS:
- {WORKTREE_PATH} = provided path
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: git-command-failed
DETECTION:
- TRIGGER: git worktree list command fails (STEP 3)
- CAPTURE: stderr from git command
RESPONSE (exact):
```
Error: Failed to list worktrees
Git error: {GIT_STDERR}
Check that:
- You're in a git repository
- Git is installed and working
```
TEMPLATE SUBSTITUTIONS:
- {GIT_STDERR} = captured stderr
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: cannot-destroy-main
DETECTION:
- TRIGGER: Target path matches main repository path (STEP 3)
RESPONSE (exact):
```
Error: Cannot destroy main repository
The path '{WORKTREE_PATH}' is the main repository, not a worktree.
To remove worktrees, use paths like:
/destroy:working-tree ../myapp-feature-branch
/destroy:working-tree ../myapp-bugfix-something
To see all worktrees:
/list:working-tree
```
TEMPLATE SUBSTITUTIONS:
- {WORKTREE_PATH} = main repository path
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: not-a-worktree
DETECTION:
- TRIGGER: Path exists but is not registered as git worktree (STEP 3)
RESPONSE (exact):
```
Error: Not a registered git worktree
Path: {WORKTREE_PATH}
This path is not a git worktree. To see all worktrees:
/list:working-tree
Valid worktree paths look like:
/Users/dev/myapp-feature-login
../myapp-bugfix-auth
```
TEMPLATE SUBSTITUTIONS:
- {WORKTREE_PATH} = provided path
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: worktree-removal-failed
DETECTION:
- TRIGGER: git worktree remove fails (STEP 5)
- CAPTURE: stderr from git worktree remove
RESPONSE (exact):
```
Error: Failed to remove worktree
Git error: {GIT_STDERR}
This can happen if:
- Worktree is locked
- Permission issues
- Worktree is corrupted
Try:
- Check file permissions
- Run: git worktree prune
- Manually remove directory and run: git worktree prune
```
TEMPLATE SUBSTITUTIONS:
- {GIT_STDERR} = captured stderr
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
## TOOL PERMISSION MATRIX
| Tool | Pattern | Permission | Pre-Check | Post-Check | On-Deny-Action |
|------|---------|------------|-----------|------------|----------------|
| Bash | git worktree:* | ALLOW | command_safe | validate_output | N/A |
| Bash | git status:* | ALLOW | command_safe | N/A | N/A |
| Bash | git branch:* | DENY | N/A | N/A | ABORT "Cannot delete branches automatically" |
| Bash | cd:* | ALLOW | N/A | N/A | N/A |
| Bash | test:* | ALLOW | N/A | N/A | N/A |
| Bash | pwd:* | ALLOW | N/A | N/A | N/A |
| Bash | dirname:* | ALLOW | N/A | N/A | N/A |
| Bash | basename:* | ALLOW | N/A | N/A | N/A |
| Bash | grep:* | ALLOW | N/A | N/A | N/A |
| Bash | sed:* | ALLOW | N/A | N/A | N/A |
| Bash | cut:* | ALLOW | N/A | N/A | N/A |
| Bash | wc:* | ALLOW | N/A | N/A | N/A |
| Bash | head:* | ALLOW | N/A | N/A | N/A |
| Bash | rm:* | DENY | N/A | N/A | ABORT "Use git worktree remove" |
| Bash | sudo:* | DENY | N/A | N/A | ABORT "Elevated privileges" |
| Read | * | DENY | N/A | N/A | ABORT "Destroy is read-only except git" |
| Write | * | DENY | N/A | N/A | ABORT "Destroy does not write files" |
SECURITY CONSTRAINTS:
- Can ONLY remove worktrees via git worktree remove
- CANNOT delete branches (user must do manually)
- CANNOT use rm/rmdir (git manages removal)
- MUST check for uncommitted changes
- MUST prevent main repository deletion
## TEST CASES
### TC001: Remove worktree with no uncommitted changes
PRECONDITIONS:
- Worktree exists at /Users/dev/myapp-feature-login
- Branch: feature/login
- No uncommitted changes
- Not the main repository
INPUT:
```
/destroy:working-tree /Users/dev/myapp-feature-login
```
EXPECTED EXECUTION FLOW:
1. STEP 1 → WORKTREE_PATH="/Users/dev/myapp-feature-login"
2. STEP 2 → EXISTS=0 (path exists)
3. STEP 3 → IS_MAIN_REPO=false, IS_REGISTERED>0, BRANCH_NAME="feature/login"
4. STEP 4 → HAS_CHANGES=false (no uncommitted changes)
5. STEP 5 → git worktree remove succeeds
6. STEP 6 → git worktree prune succeeds
7. STEP 7 → Output summary
EXPECTED OUTPUT:
```
✓ Worktree removed successfully
Path: /Users/dev/myapp-feature-login
Branch: feature/login
Branch 'feature/login' has been preserved.
To delete the branch as well:
git branch -d feature/login # Safe delete (only if merged)
git branch -D feature/login # Force delete (even if unmerged)
To delete remote branch:
git push origin --delete feature/login
```
VALIDATION COMMANDS:
```bash
# Verify worktree no longer exists
test ! -e /Users/dev/myapp-feature-login && echo "PASS" || echo "FAIL"
# Verify branch still exists
git show-ref --verify refs/heads/feature/login && echo "PASS" || echo "FAIL"
# Verify not in worktree list
git worktree list | grep -v "feature-login" && echo "PASS" || echo "FAIL"
```
### TC002: Remove worktree with uncommitted changes - user proceeds
PRECONDITIONS:
- Worktree exists at /Users/dev/myapp-bugfix-auth
- Has uncommitted changes: Modified src/auth.ts
INPUT:
```
/destroy:working-tree /Users/dev/myapp-bugfix-auth
```
EXPECTED EXECUTION FLOW:
1-3. Standard detection
4. STEP 4 → HAS_CHANGES=true
5. Display warning with git status output
6. USER SELECTS "Proceed with removal (discard changes)"
7. STEP 5 → git worktree remove --force succeeds
8. STEP 6-7 → Standard cleanup and output
EXPECTED OUTPUT (includes warning):
```
⚠ Warning: Uncommitted changes detected
Modified files:
M src/auth.ts
These changes will be lost if you proceed.
Recommendations:
1. Commit changes: cd /Users/dev/myapp-bugfix-auth && git commit -am "message"
2. Stash changes: cd /Users/dev/myapp-bugfix-auth && git stash
3. Proceed anyway (changes will be lost)
Proceed with removal? (This will permanently delete uncommitted work)
[User confirms]
✓ Worktree removed successfully
Path: /Users/dev/myapp-bugfix-auth
Branch: bugfix/auth
Branch 'bugfix/auth' has been preserved.
To delete the branch as well:
git branch -d bugfix/auth # Safe delete (only if merged)
git branch -D bugfix/auth # Force delete (even if unmerged)
To delete remote branch:
git push origin --delete bugfix/auth
```
### TC003: Remove worktree with uncommitted changes - user cancels
PRECONDITIONS:
- Worktree with uncommitted changes
INPUT:
```
/destroy:working-tree /Users/dev/myapp-feature-test
```
EXPECTED EXECUTION FLOW:
1-4. Detect changes
5. Display warning
6. USER SELECTS "Cancel removal"
7. TERMINATE (no changes)
EXPECTED OUTPUT:
```
⚠ Warning: Uncommitted changes detected
[warning displayed]
Proceed with removal?
[User cancels]
Removal cancelled. No changes made.
```
POSTCONDITIONS:
- Worktree still exists
- No files modified
### TC004: Attempt to destroy main repository
PRECONDITIONS:
- Main repository at /Users/dev/myapp
INPUT:
```
/destroy:working-tree /Users/dev/myapp
```
EXPECTED EXECUTION FLOW:
1. STEP 1 → Resolve path
2. STEP 2 → Path exists
3. STEP 3 → IS_MAIN_REPO=true
4. ERROR PATTERN "cannot-destroy-main"
5. ABORT
EXPECTED OUTPUT:
```
Error: Cannot destroy main repository
The path '/Users/dev/myapp' is the main repository, not a worktree.
To remove worktrees, use paths like:
/destroy:working-tree ../myapp-feature-branch
/destroy:working-tree ../myapp-bugfix-something
To see all worktrees:
/list:working-tree
```
POSTCONDITIONS:
- Main repository untouched
- No changes made
### TC005: Path does not exist
PRECONDITIONS:
- Path /Users/dev/nonexistent does not exist
INPUT:
```
/destroy:working-tree /Users/dev/nonexistent
```
EXPECTED EXECUTION FLOW:
1. STEP 1 → Resolve path
2. STEP 2 → EXISTS=1 (does not exist)
3. ERROR PATTERN "path-not-exist"
4. ABORT
EXPECTED OUTPUT:
```
Error: Path does not exist
Path: /Users/dev/nonexistent
The specified path doesn't exist. Check for typos.
To list existing worktrees:
/list:working-tree
```
### TC006: Not a git worktree
PRECONDITIONS:
- Directory /Users/dev/random-dir exists but is not a git worktree
INPUT:
```
/destroy:working-tree /Users/dev/random-dir
```
EXPECTED EXECUTION FLOW:
1-2. Resolve and verify path exists
3. STEP 3 → IS_REGISTERED=0 (not in worktree list)
4. ERROR PATTERN "not-a-worktree"
5. ABORT
EXPECTED OUTPUT:
```
Error: Not a registered git worktree
Path: /Users/dev/random-dir
This path is not a git worktree. To see all worktrees:
/list:working-tree
Valid worktree paths look like:
/Users/dev/myapp-feature-login
../myapp-bugfix-auth
```
## SAFETY FEATURES
### PROTECTED OPERATIONS
- CANNOT remove main repository
- WARNS about uncommitted changes
- REQUIRES confirmation for destructive operations
- PRESERVES branch by default
### BRANCH DELETION GUIDANCE
Command provides guidance but NEVER auto-deletes branches:
**Safe delete** (only if merged):
```bash
git branch -d <branch-name>
```
**Force delete** (even if unmerged):
```bash
git branch -D <branch-name>
```
**Remote branch delete**:
```bash
git push origin --delete <branch-name>
```
## RELATED COMMANDS
- /list:working-tree - See all worktrees before deciding what to remove
- /status:working-tree - Check current worktree before removing
- /create:working-tree - Create new worktree after removal
## DELEGATION
For guidance on when to remove worktrees:
```
Task(
subagent_type='working-tree-consultant',
description='Worktree removal strategy',
prompt='[question about when/how to safely remove worktrees]'
)
```

514
commands/list.md Normal file
View File

@@ -0,0 +1,514 @@
---
description: List all git worktrees with their associated .ai-context metadata
allowed-tools: Bash, Read, Glob
model: sonnet
---
# /list:working-tree
Enumerate all git worktrees and display metadata from `.ai-context.json`.
## ARGUMENT SPECIFICATION
```
SYNTAX: /list:working-tree
NO ARGUMENTS
```
## EXECUTION PROTOCOL
Execute steps sequentially. Each step must complete successfully before proceeding.
### STEP 1: GET CURRENT WORKTREE
EXECUTE:
```bash
CURRENT_ROOT=$(git rev-parse --show-toplevel 2>&1)
EXIT_CODE=$?
```
VALIDATION:
- IF EXIT_CODE != 0 → ERROR PATTERN "not-in-git-repo"
NEXT:
- On success → STEP 2
- On failure → ABORT
### STEP 2: LIST ALL WORKTREES
EXECUTE:
```bash
WORKTREE_LIST=$(git worktree list --porcelain 2>&1)
EXIT_CODE=$?
```
VALIDATION:
- IF EXIT_CODE != 0 → ERROR PATTERN "git-command-failed"
NEXT:
- On success → STEP 3
- On failure → ABORT
### STEP 3: PARSE WORKTREES
PARSE FORMAT:
```
worktree /path/to/worktree
HEAD commit-hash
branch refs/heads/branch-name
worktree /another/path
HEAD commit-hash
branch refs/heads/another-branch
```
PARSING ALGORITHM:
```python
worktrees = []
current_entry = {}
for line in WORKTREE_LIST.split("\n"):
if line.startswith("worktree "):
if current_entry:
worktrees.append(current_entry)
current_entry = {"path": line.split(" ", 1)[1]}
elif line.startswith("branch refs/heads/"):
current_entry["branch"] = line.split("/")[-1]
elif line == "":
if current_entry:
worktrees.append(current_entry)
current_entry = {}
if current_entry:
worktrees.append(current_entry)
```
DATA EXTRACTED:
- List of worktree entries, each with:
- path: absolute path to worktree
- branch: branch name (without refs/heads/)
NEXT:
- On success → STEP 4
- No failure case (empty list is valid)
### STEP 4: READ METADATA FOR EACH WORKTREE
FOR EACH worktree in worktrees:
```bash
METADATA_PATH="$worktree_path/.ai-context.json"
test -f "$METADATA_PATH"
HAS_METADATA=$?
if [ $HAS_METADATA -eq 0 ]; then
METADATA=$(cat "$METADATA_PATH" 2>&1)
MODE=$(echo "$METADATA" | jq -r '.mode // "(invalid)"' 2>&1)
DESCRIPTION=$(echo "$METADATA" | jq -r '.description // ""' 2>&1)
# Validate JSON
if [ $? -ne 0 ]; then
MODE="(invalid json)"
DESCRIPTION=""
fi
else
MODE="(no metadata)"
DESCRIPTION="-"
fi
```
DATA STRUCTURE:
```
worktree_data = [
{
"path": "/path/to/worktree",
"branch": "feature/login",
"mode": "feature",
"description": "OAuth refactor",
"is_current": true/false,
"has_metadata": true/false
},
...
]
```
CURRENT DETECTION:
- IF worktree_path == CURRENT_ROOT → is_current = true
NEXT:
- On success → STEP 5
- Continue even if individual metadata reads fail
### STEP 5: FORMAT AND DISPLAY TABLE
TABLE FORMAT:
```
Git Worktrees
═══════════════════════════════════════════════════════════════════════════════
Path Branch Mode Description
───────────────────────────────────────────────────────────────────────────────
{INDICATOR} {PATH} {BRANCH} {MODE} {DESCRIPTION}
...
═══════════════════════════════════════════════════════════════════════════════
Total: {COUNT} worktrees ({WITH_META} with metadata, {WITHOUT_META} without)
{TIP_IF_MISSING_METADATA}
```
FORMATTING RULES:
- INDICATOR: "→" if is_current, else " " (2 spaces)
- PATH: Truncate to 30 chars if longer, add "..." suffix
- BRANCH: Truncate to 20 chars if longer
- MODE: Truncate to 12 chars
- DESCRIPTION: Truncate to 40 chars if longer, add "..."
- Align columns with padding
PADDING ALGORITHM:
```python
def pad_column(text, width):
if len(text) > width:
return text[:width-3] + "..."
return text + " " * (width - len(text))
```
TIP LOGIC:
- IF any worktree has has_metadata == false:
- Display: "Tip: Use /adopt:working-tree to add metadata to worktrees that lack it"
NEXT:
- On success → STEP 6
- No failure case
### STEP 6: COUNT AND SUMMARIZE
COUNTS:
```bash
TOTAL=$(echo "$worktrees" | wc -l)
WITH_META=$(count worktrees where has_metadata == true)
WITHOUT_META=$(count worktrees where has_metadata == false)
```
SUMMARY LINE:
```
Total: {TOTAL} worktrees ({WITH_META} with metadata, {WITHOUT_META} without)
```
SPECIAL CASES:
- IF TOTAL == 1 AND WITHOUT_META == 1:
- Summary: "Total: 1 worktree (main repository only)"
- Tip: "To create a new worktree: /create:working-tree <branch-name>"
NEXT:
- TERMINATE (success)
## ERROR PATTERNS
### PATTERN: not-in-git-repo
DETECTION:
- TRIGGER: git rev-parse --show-toplevel exit code != 0
- INDICATORS: stderr contains "not a git repository"
RESPONSE (exact):
```
Error: Not in a git repository
Run this command from within a git repository.
```
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: git-command-failed
DETECTION:
- TRIGGER: git worktree list command fails (STEP 2)
- CAPTURE: stderr from git command
RESPONSE (exact):
```
Error: Failed to list worktrees
Git error: {GIT_STDERR}
Check that:
- You're in a git repository
- Git is installed and working
```
TEMPLATE SUBSTITUTIONS:
- {GIT_STDERR} = captured stderr
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: invalid-metadata-json
DETECTION:
- TRIGGER: jq fails to parse .ai-context.json (STEP 4)
- OCCURS: per-worktree, not fatal
RESPONSE:
```
Warning: Invalid .ai-context.json in {WORKTREE_PATH}
Displaying worktree without metadata. Consider:
- Fixing the JSON manually
- Running /adopt:working-tree in that worktree to regenerate
```
CONTROL FLOW:
- ABORT: false (warning only)
- DISPLAY: Show worktree with MODE="(invalid json)"
- CONTINUE: Process remaining worktrees
## TOOL PERMISSION MATRIX
| Tool | Pattern | Permission | Pre-Check | Post-Check | On-Deny-Action |
|------|---------|------------|-----------|------------|----------------|
| Bash | git worktree:* | ALLOW | command_safe | N/A | N/A |
| Bash | git rev-parse:* | ALLOW | command_safe | N/A | N/A |
| Bash | test:* | ALLOW | N/A | N/A | N/A |
| Bash | cat:* | ALLOW | N/A | N/A | N/A |
| Bash | jq:* | ALLOW | N/A | N/A | N/A |
| Bash | wc:* | ALLOW | N/A | N/A | N/A |
| Bash | grep:* | ALLOW | N/A | N/A | N/A |
| Bash | cut:* | ALLOW | N/A | N/A | N/A |
| Bash | sed:* | ALLOW | N/A | N/A | N/A |
| Bash | head:* | ALLOW | N/A | N/A | N/A |
| Bash | sudo:* | DENY | N/A | N/A | ABORT "Elevated privileges" |
| Read | */.ai-context.json | ALLOW | N/A | N/A | N/A |
| Write | * | DENY | N/A | N/A | ABORT "List is read-only" |
| Edit | * | DENY | N/A | N/A | ABORT "List is read-only" |
SECURITY CONSTRAINTS:
- Command is READ-ONLY
- Cannot modify any files
- Cannot execute destructive operations
- Safe to run multiple times
## TEST CASES
### TC001: Multiple worktrees with metadata
PRECONDITIONS:
- Main repository at /Users/dev/myapp
- Worktree at /Users/dev/myapp-feature-api with metadata (mode: feature, description: "New API")
- Worktree at /Users/dev/myapp-bugfix-auth with metadata (mode: bugfix, description: "Fix auth")
- Currently in /Users/dev/myapp
INPUT:
```
/list:working-tree
```
EXPECTED EXECUTION FLOW:
1. STEP 1 → CURRENT_ROOT="/Users/dev/myapp"
2. STEP 2 → Get worktree list
3. STEP 3 → Parse 3 worktrees
4. STEP 4 → Read metadata for each
5. STEP 5-6 → Format and display
EXPECTED OUTPUT:
```
Git Worktrees
═══════════════════════════════════════════════════════════════════════════════
Path Branch Mode Description
───────────────────────────────────────────────────────────────────────────────
→ /Users/dev/myapp main main Main development
/Users/dev/myapp-feature... feature/api feature New API
/Users/dev/myapp-bugfix-... bugfix/auth bugfix Fix auth
═══════════════════════════════════════════════════════════════════════════════
Total: 3 worktrees (3 with metadata)
```
VALIDATION:
- Current worktree marked with →
- All columns aligned
- Counts correct
### TC002: Mixed metadata status
PRECONDITIONS:
- Main repository without metadata
- One worktree with metadata
- One worktree without metadata
INPUT:
```
/list:working-tree
```
EXPECTED OUTPUT:
```
Git Worktrees
═══════════════════════════════════════════════════════════════════════════════
Path Branch Mode Description
───────────────────────────────────────────────────────────────────────────────
/Users/dev/myapp main (no metadata) -
→ /Users/dev/myapp-feature... feature/new feature New feature work
/Users/dev/old-checkout feature/abandoned (no metadata) -
═══════════════════════════════════════════════════════════════════════════════
Total: 3 worktrees (1 with metadata, 2 without)
Tip: Use /adopt:working-tree to add metadata to worktrees that lack it
```
VALIDATION:
- Tip displayed because some worktrees lack metadata
- (no metadata) shown for worktrees without .ai-context.json
### TC003: Only main repository
PRECONDITIONS:
- Main repository only, no additional worktrees
- No metadata file
INPUT:
```
/list:working-tree
```
EXPECTED OUTPUT:
```
Git Worktrees
═══════════════════════════════════════════════════════════════════════════════
Path Branch Mode Description
───────────────────────────────────────────────────────────────────────────────
→ /Users/dev/myapp main (no metadata) -
═══════════════════════════════════════════════════════════════════════════════
Total: 1 worktree (main repository only)
To create a new worktree: /create:working-tree <branch-name>
```
VALIDATION:
- Special message for single worktree
- Tip suggests creating worktree
### TC004: Invalid JSON in metadata file
PRECONDITIONS:
- Worktree at /Users/dev/myapp-test
- File exists: /Users/dev/myapp-test/.ai-context.json
- File contains invalid JSON: `{invalid`
INPUT:
```
/list:working-tree
```
EXPECTED EXECUTION FLOW:
1-3. Standard flow
4. STEP 4 → jq fails on invalid JSON
5. Display warning
6. Show worktree with MODE="(invalid json)"
7. Continue with other worktrees
EXPECTED OUTPUT:
```
Warning: Invalid .ai-context.json in /Users/dev/myapp-test
Displaying worktree without metadata. Consider:
- Fixing the JSON manually
- Running /adopt:working-tree in that worktree to regenerate
Git Worktrees
═══════════════════════════════════════════════════════════════════════════════
Path Branch Mode Description
───────────────────────────────────────────────────────────────────────────────
→ /Users/dev/myapp-test feature/test (invalid json) -
═══════════════════════════════════════════════════════════════════════════════
Total: 1 worktree (0 with metadata, 1 without)
Tip: Use /adopt:working-tree to add metadata to worktrees that lack it
```
### TC005: Long paths and descriptions
PRECONDITIONS:
- Worktree with very long path: /Users/dev/myapp-feature-really-long-branch-name-that-exceeds-column-width
- Description: "This is a very long description that exceeds the maximum column width and should be truncated"
INPUT:
```
/list:working-tree
```
EXPECTED OUTPUT:
```
Git Worktrees
═══════════════════════════════════════════════════════════════════════════════
Path Branch Mode Description
───────────────────────────────────────────────────────────────────────────────
→ /Users/dev/myapp-feature... feature/really-lo... feature This is a very long description that...
═══════════════════════════════════════════════════════════════════════════════
Total: 1 worktree (1 with metadata)
```
VALIDATION:
- Long path truncated with "..."
- Long branch truncated with "..."
- Long description truncated with "..."
- Columns remain aligned
## DISPLAY NOTES
### COLUMN WIDTHS
Fixed widths for consistent alignment:
- Indicator: 2 chars ("→ " or " ")
- Path: 30 chars
- Branch: 20 chars
- Mode: 13 chars
- Description: remaining width (or 40 chars minimum)
### TRUNCATION STRATEGY
```python
def truncate(text, max_width):
if len(text) <= max_width:
return text
return text[:max_width-3] + "..."
```
### BOX DRAWING
Use consistent box-drawing characters:
- Top/bottom: `═` (double horizontal)
- Separator: `─` (single horizontal)
- No vertical bars (cleaner appearance)
## RELATED COMMANDS
- /status:working-tree - Show current worktree details
- /create:working-tree - Create new worktree with metadata
- /adopt:working-tree - Add metadata to existing worktree
- /destroy:working-tree - Remove worktree
## DELEGATION
For organizing multiple worktrees strategically:
```
Task(
subagent_type='working-tree-consultant',
description='Worktree organization strategy',
prompt='[question about managing multiple worktrees]'
)
```

947
commands/new.md Normal file
View File

@@ -0,0 +1,947 @@
---
description: Create a new git worktree with branch and .ai-context.json metadata
argument-hint: <branch-name> [--mode <mode>] [--description "<text>"]
allowed-tools: Bash, Write, Read
model: sonnet
---
# /working-tree:new
Create new branch (if needed), attach git worktree, generate AI metadata files for isolated development.
## ARGUMENT SPECIFICATION
```
SYNTAX: /working-tree:new <branch-name> [--mode <mode>] [--description "<text>"]
REQUIRED:
<branch-name>
Type: string
Position: 1
Validation: ^[a-zA-Z0-9/_-]+$
Examples: "feature/login", "bugfix/timeout", "main"
OPTIONAL:
--mode <mode>
Type: enum[main, feature, bugfix, experiment, review]
Default: inferred from branch-name (see MODE_INFERENCE_ALGORITHM)
Validation: must match exactly one of the enum values
--description "<text>"
Type: string (quoted if contains spaces)
Default: "" (empty string)
Validation: any string, no restrictions
```
## MODE_INFERENCE_ALGORITHM
APPLY rules sequentially, first match wins:
```python
def infer_mode(branch_name: str) -> str:
if branch_name.startswith("feature/"):
return "feature"
elif branch_name.startswith(("bugfix/", "fix/")):
return "bugfix"
elif branch_name.startswith(("exp/", "experiment/")):
return "experiment"
elif branch_name.startswith("review/"):
return "review"
elif branch_name in ("main", "master"):
return "main"
else:
return "feature" # DEFAULT
```
DETERMINISTIC: Given same branch_name, always produces same mode.
## EXECUTION PROTOCOL
Execute steps sequentially. Each step must complete successfully before proceeding.
### STEP 1: DETECT REPOSITORY INFO
EXECUTE:
```bash
REPO_ROOT=$(git rev-parse --show-toplevel 2>&1)
EXIT_CODE_ROOT=$?
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>&1)
EXIT_CODE_BRANCH=$?
```
VALIDATION:
- IF EXIT_CODE_ROOT != 0 → ERROR PATTERN "not-in-git-repo"
- IF EXIT_CODE_BRANCH != 0 → ERROR PATTERN "git-command-failed"
- REPO_ROOT must be absolute path starting with /
DATA EXTRACTION:
```bash
REPO_NAME=$(basename "$REPO_ROOT")
PARENT_DIR=$(dirname "$REPO_ROOT")
```
NEXT:
- On success → STEP 2
- On failure → ABORT
### STEP 2: PARSE AND VALIDATE ARGUMENTS
PARSE:
```bash
# Extract branch name (first positional argument)
BRANCH_NAME="$1"
# Parse --mode flag (if present)
if [[ "$@" =~ --mode[[:space:]]+([a-z]+) ]]; then
MODE_ARG="${BASH_REMATCH[1]}"
else
MODE_ARG=""
fi
# Parse --description flag (if present)
if [[ "$@" =~ --description[[:space:]]+\"([^\"]+)\" ]]; then
DESCRIPTION="${BASH_REMATCH[1]}"
elif [[ "$@" =~ --description[[:space:]]+([^[:space:]]+) ]]; then
DESCRIPTION="${BASH_REMATCH[1]}"
else
DESCRIPTION=""
fi
```
VALIDATION:
- IF BRANCH_NAME is empty → ERROR PATTERN "missing-branch-name"
- IF BRANCH_NAME !~ ^[a-zA-Z0-9/_-]+$ → ERROR PATTERN "invalid-branch-name"
- IF MODE_ARG not empty AND MODE_ARG not in [main, feature, bugfix, experiment, review] → ERROR PATTERN "invalid-mode"
NEXT:
- On success → STEP 3
- On failure → ABORT
### STEP 3: DETERMINE MODE
EXECUTE:
```bash
if [ -n "$MODE_ARG" ]; then
# Explicit mode provided
MODE="$MODE_ARG"
else
# Infer from branch name using MODE_INFERENCE_ALGORITHM
case "$BRANCH_NAME" in
feature/*)
MODE="feature"
;;
bugfix/*|fix/*)
MODE="bugfix"
;;
exp/*|experiment/*)
MODE="experiment"
;;
review/*)
MODE="review"
;;
main|master)
MODE="main"
;;
*)
MODE="feature"
;;
esac
fi
```
VALIDATION:
- MODE must be exactly one of: main, feature, bugfix, experiment, review
- MODE must not be empty
DATA:
- MODE = final determined mode (explicit or inferred)
NEXT:
- On success → STEP 4
- On failure → ABORT (should not occur if STEP 2 validation passed)
### STEP 4: CHECK BRANCH EXISTENCE
EXECUTE:
```bash
git show-ref --verify --quiet refs/heads/$BRANCH_NAME
BRANCH_EXISTS=$?
```
BRANCH_EXISTS values:
- 0 = branch exists
- 1 = branch does not exist
- Other = error
VALIDATION:
- IF BRANCH_EXISTS not in [0, 1] → ERROR PATTERN "git-command-failed"
ACTION:
- IF BRANCH_EXISTS == 1 (does not exist) → Create branch in STEP 5
- IF BRANCH_EXISTS == 0 (exists) → Use existing branch, skip to STEP 6
NEXT:
- On BRANCH_EXISTS == 0 → STEP 6
- On BRANCH_EXISTS == 1 → STEP 5
- On error → ABORT
### STEP 5: CREATE NEW BRANCH
EXECUTE (only if BRANCH_EXISTS == 1):
```bash
git branch "$BRANCH_NAME" 2>&1
EXIT_CODE=$?
```
VALIDATION:
- IF EXIT_CODE != 0 → ERROR PATTERN "branch-creation-failed"
NEXT:
- On success → STEP 6
- On failure → ABORT
### STEP 6: DERIVE WORKTREE DIRECTORY NAME
EXECUTE:
```bash
# Normalize branch name: replace / and _ with -, convert to lowercase
NORMALIZED_BRANCH=$(echo "$BRANCH_NAME" | tr '/_' '-' | tr '[:upper:]' '[:lower:]')
WORKTREE_NAME="${REPO_NAME}-${NORMALIZED_BRANCH}"
WORKTREE_PATH="${PARENT_DIR}/${WORKTREE_NAME}"
```
NORMALIZATION RULES:
- Replace `/` with `-`
- Replace `_` with `-`
- Convert to lowercase
EXAMPLES:
- myapp + feature/login → myapp-feature-login
- api-server + bugfix/SESSION_timeout → api-server-bugfix-session-timeout
DATA:
- WORKTREE_NAME = derived directory name
- WORKTREE_PATH = absolute path to worktree location
NEXT:
- On success → STEP 7
- No validation needed (pure transformation)
### STEP 7: CHECK FOR EXISTING WORKTREE ON BRANCH
EXECUTE:
```bash
EXISTING_WORKTREE=$(git worktree list --porcelain | grep -A 3 "^branch refs/heads/$BRANCH_NAME$" | grep "^worktree " | cut -d' ' -f2)
```
VALIDATION:
- IF EXISTING_WORKTREE not empty → ERROR PATTERN "branch-has-worktree" with path=$EXISTING_WORKTREE
NEXT:
- On EXISTING_WORKTREE empty → STEP 8
- On EXISTING_WORKTREE not empty → ABORT
### STEP 8: CHECK TARGET DIRECTORY DOESN'T EXIST
EXECUTE:
```bash
test -e "$WORKTREE_PATH"
DIR_EXISTS=$?
```
VALIDATION:
- IF DIR_EXISTS == 0 (directory exists) → ERROR PATTERN "directory-exists"
NEXT:
- On DIR_EXISTS != 0 (does not exist) → STEP 9
- On DIR_EXISTS == 0 (exists) → ABORT
### STEP 9: CREATE WORKTREE
EXECUTE:
```bash
git worktree add "$WORKTREE_PATH" "$BRANCH_NAME" 2>&1
EXIT_CODE=$?
```
VALIDATION:
- IF EXIT_CODE != 0 → ERROR PATTERN "worktree-creation-failed"
NEXT:
- On success → STEP 10
- On failure → ABORT
### STEP 10: GENERATE TIMESTAMP
EXECUTE:
```bash
CREATED_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
```
FORMAT: ISO 8601 UTC (example: 2025-11-23T12:34:56Z)
VALIDATION:
- CREATED_TIMESTAMP must match pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$
NEXT:
- On success → STEP 11
- No failure case
### STEP 11: GENERATE .ai-context.json
CONTENT TEMPLATE:
```json
{
"worktree": "{WORKTREE_NAME}",
"branch": "{BRANCH_NAME}",
"mode": "{MODE}",
"created": "{CREATED_TIMESTAMP}",
"description": "{DESCRIPTION}"
}
```
SUBSTITUTIONS:
- {WORKTREE_NAME} = from STEP 6
- {BRANCH_NAME} = from STEP 2
- {MODE} = from STEP 3
- {CREATED_TIMESTAMP} = from STEP 10
- {DESCRIPTION} = from STEP 2 (empty string if not provided)
EXECUTE:
```bash
cat > "$WORKTREE_PATH/.ai-context.json" <<EOF
{
"worktree": "$WORKTREE_NAME",
"branch": "$BRANCH_NAME",
"mode": "$MODE",
"created": "$CREATED_TIMESTAMP",
"description": "$DESCRIPTION"
}
EOF
```
VALIDATION:
- File must be created at exact path: $WORKTREE_PATH/.ai-context.json
- File must contain valid JSON
- Verify with: `jq empty "$WORKTREE_PATH/.ai-context.json"`
- IF jq fails → ERROR PATTERN "metadata-write-failed"
NEXT:
- On success → STEP 12
- On failure → ABORT (and cleanup worktree)
### STEP 12: GENERATE README.working-tree.md
CONTENT TEMPLATE:
```markdown
# Worktree: {WORKTREE_NAME}
**Branch:** `{BRANCH_NAME}`
**Mode:** `{MODE}`
**Created:** {CREATED_TIMESTAMP}
## Purpose
{DESCRIPTION_OR_DEFAULT}
## Mode Semantics
- **main**: Minimal changes, stable work only
- **feature**: Active development, larger changes allowed
- **bugfix**: Isolated, surgical fixes only
- **experiment**: Prototypes, large swings, unsafe changes allowed
- **review**: Documentation, analysis, audits
## About This Worktree
This directory is an independent Git worktree attached to the main repository.
- Main repo: {REPO_ROOT}
- Worktree path: {WORKTREE_PATH}
- Branch: {BRANCH_NAME}
See `.ai-context.json` for machine-readable metadata.
```
SUBSTITUTIONS:
- {WORKTREE_NAME} = from STEP 6
- {BRANCH_NAME} = from STEP 2
- {MODE} = from STEP 3
- {CREATED_TIMESTAMP} = from STEP 10
- {DESCRIPTION_OR_DEFAULT} = DESCRIPTION if not empty, else "No description provided"
- {REPO_ROOT} = from STEP 1
- {WORKTREE_PATH} = from STEP 6
EXECUTE:
```bash
DESCRIPTION_TEXT="${DESCRIPTION:-No description provided}"
cat > "$WORKTREE_PATH/README.working-tree.md" <<EOF
# Worktree: $WORKTREE_NAME
**Branch:** \`$BRANCH_NAME\`
**Mode:** \`$MODE\`
**Created:** $CREATED_TIMESTAMP
## Purpose
$DESCRIPTION_TEXT
## Mode Semantics
- **main**: Minimal changes, stable work only
- **feature**: Active development, larger changes allowed
- **bugfix**: Isolated, surgical fixes only
- **experiment**: Prototypes, large swings, unsafe changes allowed
- **review**: Documentation, analysis, audits
## About This Worktree
This directory is an independent Git worktree attached to the main repository.
- Main repo: $REPO_ROOT
- Worktree path: $WORKTREE_PATH
- Branch: $BRANCH_NAME
See \`.ai-context.json\` for machine-readable metadata.
EOF
```
VALIDATION:
- File must exist at: $WORKTREE_PATH/README.working-tree.md
- IF file creation failed → ERROR PATTERN "readme-write-failed"
NEXT:
- On success → STEP 13
- On failure → ABORT (and cleanup)
### STEP 13: OUTPUT SUCCESS SUMMARY
OUTPUT FORMAT (exact):
```
Created worktree successfully!
Path: {WORKTREE_PATH}
Branch: {BRANCH_NAME}
Mode: {MODE}
Description: {DESCRIPTION_OR_NONE}
Metadata files created:
✓ .ai-context.json
✓ README.working-tree.md
To switch to this worktree:
cd {WORKTREE_PATH}
```
SUBSTITUTIONS:
- {WORKTREE_PATH} = from STEP 6
- {BRANCH_NAME} = from STEP 2
- {MODE} = from STEP 3
- {DESCRIPTION_OR_NONE} = DESCRIPTION if not empty, else "None"
NEXT:
- TERMINATE (success)
## ERROR PATTERNS
### PATTERN: not-in-git-repo
DETECTION:
- TRIGGER: git rev-parse --show-toplevel exit code != 0
- INDICATORS: stderr contains "not a git repository"
RESPONSE (exact):
```
Error: Not in a git repository
Run this command from within a git repository.
```
CONTROL FLOW:
- ABORT: true
- CLEANUP: none needed
- RETRY: false
### PATTERN: missing-branch-name
DETECTION:
- TRIGGER: BRANCH_NAME is empty string after parsing
RESPONSE (exact):
```
Error: Missing required argument <branch-name>
Usage:
/working-tree:new <branch-name> [--mode <mode>] [--description "<text>"]
Example:
/working-tree:new feature/my-feature
```
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: invalid-branch-name
DETECTION:
- TRIGGER: BRANCH_NAME does not match ^[a-zA-Z0-9/_-]+$
- INDICATORS: Contains invalid characters
RESPONSE (exact):
```
Error: Invalid branch name '{BRANCH_NAME}'
Branch names must contain only:
- Letters (a-z, A-Z)
- Numbers (0-9)
- Forward slashes (/)
- Hyphens (-)
- Underscores (_)
Example valid names:
feature/login
bugfix/timeout-issue
exp/ai_integration
```
TEMPLATE SUBSTITUTIONS:
- {BRANCH_NAME} = the invalid branch name provided
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: invalid-mode
DETECTION:
- TRIGGER: MODE_ARG provided but not in [main, feature, bugfix, experiment, review]
RESPONSE (exact):
```
Error: Invalid mode '{MODE_ARG}'
Valid modes: main, feature, bugfix, experiment, review
Example:
/working-tree:new my-branch --mode feature
```
TEMPLATE SUBSTITUTIONS:
- {MODE_ARG} = the invalid mode provided
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: git-command-failed
DETECTION:
- TRIGGER: Any git command (except specific patterns) returns non-zero exit code
- CAPTURE: stderr from git command
RESPONSE (exact):
```
Error: Git command failed
Git error: {GIT_STDERR}
Check that:
- You're in a git repository
- Git is installed and working
- You have necessary permissions
```
TEMPLATE SUBSTITUTIONS:
- {GIT_STDERR} = captured stderr
CONTROL FLOW:
- ABORT: true
- CLEANUP: Remove worktree if created
- RETRY: false
### PATTERN: branch-creation-failed
DETECTION:
- TRIGGER: git branch command fails (STEP 5)
- CAPTURE: stderr from git branch
RESPONSE (exact):
```
Error: Failed to create branch '{BRANCH_NAME}'
Git error: {GIT_STDERR}
Check that:
- Branch name is valid
- You're not in detached HEAD state
- You have permission to create branches
```
TEMPLATE SUBSTITUTIONS:
- {BRANCH_NAME} = attempted branch name
- {GIT_STDERR} = captured stderr
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: branch-has-worktree
DETECTION:
- TRIGGER: git worktree list shows branch already has attached worktree (STEP 7)
- CAPTURE: EXISTING_WORKTREE path
RESPONSE (exact):
```
Error: Branch '{BRANCH_NAME}' already has a worktree at {EXISTING_WORKTREE}
Use one of:
- /working-tree:list to see all worktrees
- cd {EXISTING_WORKTREE} to use the existing worktree
- /working-tree:destroy {EXISTING_WORKTREE} to remove it first
```
TEMPLATE SUBSTITUTIONS:
- {BRANCH_NAME} = branch with existing worktree
- {EXISTING_WORKTREE} = path to existing worktree
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: directory-exists
DETECTION:
- TRIGGER: Target directory already exists (STEP 8)
- CHECK: test -e "$WORKTREE_PATH" returns 0
RESPONSE (exact):
```
Error: Directory '{WORKTREE_PATH}' already exists
Choose a different branch name or remove the existing directory.
To remove:
rm -rf {WORKTREE_PATH}
(Be careful - this will delete all contents)
```
TEMPLATE SUBSTITUTIONS:
- {WORKTREE_PATH} = path that already exists
CONTROL FLOW:
- ABORT: true
- CLEANUP: none
- RETRY: false
### PATTERN: worktree-creation-failed
DETECTION:
- TRIGGER: git worktree add fails (STEP 9)
- CAPTURE: stderr from git worktree add
RESPONSE (exact):
```
Error: Failed to create worktree
Git error: {GIT_STDERR}
Check that:
- Parent directory is writable
- Branch name is valid
- No permission issues
```
TEMPLATE SUBSTITUTIONS:
- {GIT_STDERR} = captured stderr
CONTROL FLOW:
- ABORT: true
- CLEANUP: Attempt to remove partially created worktree
- RETRY: false
### PATTERN: metadata-write-failed
DETECTION:
- TRIGGER: .ai-context.json write fails or invalid JSON (STEP 11)
- CHECK: jq validation fails
RESPONSE (exact):
```
Error: Failed to write .ai-context.json
The worktree was created but metadata file generation failed.
Worktree location: {WORKTREE_PATH}
You can:
1. Manually create .ai-context.json
2. Use /working-tree:adopt to regenerate metadata
3. Remove worktree with /working-tree:destroy {WORKTREE_PATH}
```
TEMPLATE SUBSTITUTIONS:
- {WORKTREE_PATH} = worktree path
CONTROL FLOW:
- ABORT: false (worktree exists, metadata failed)
- CLEANUP: none (leave worktree intact)
- FALLBACK: User can manually fix or adopt
### PATTERN: readme-write-failed
DETECTION:
- TRIGGER: README.working-tree.md write fails (STEP 12)
RESPONSE (exact):
```
Warning: Failed to write README.working-tree.md
The worktree and .ai-context.json were created successfully.
Worktree location: {WORKTREE_PATH}
You can manually create the README if needed.
```
TEMPLATE SUBSTITUTIONS:
- {WORKTREE_PATH} = worktree path
CONTROL FLOW:
- ABORT: false (warning, not critical)
- CLEANUP: none
- FALLBACK: Continue without README
## TOOL PERMISSION MATRIX
| Tool | Pattern | Permission | Pre-Check | Post-Check | On-Deny-Action |
|------|---------|------------|-----------|------------|----------------|
| Bash | git:* | ALLOW | command_safe | validate_output | N/A |
| Bash | date:* | ALLOW | N/A | N/A | N/A |
| Bash | test:* | ALLOW | N/A | N/A | N/A |
| Bash | basename:* | ALLOW | N/A | N/A | N/A |
| Bash | dirname:* | ALLOW | N/A | N/A | N/A |
| Bash | tr:* | ALLOW | N/A | N/A | N/A |
| Bash | grep:* | ALLOW | N/A | N/A | N/A |
| Bash | cat > *.json | ALLOW | parent_dir_writable | valid_json | N/A |
| Bash | cat > *.md | ALLOW | parent_dir_writable | N/A | N/A |
| Bash | jq:* | ALLOW | N/A | N/A | N/A |
| Bash | rm -rf:* | DENY | N/A | N/A | ABORT "Destructive operation not allowed" |
| Bash | sudo:* | DENY | N/A | N/A | ABORT "Elevated privileges" |
| Write | $WORKTREE_PATH/.ai-context.json | ALLOW | dir_exists | valid_json | N/A |
| Write | $WORKTREE_PATH/README.working-tree.md | ALLOW | dir_exists | N/A | N/A |
| Write | **/.env* | DENY | N/A | N/A | ABORT "Secrets file" |
| Read | * | DENY | N/A | N/A | ABORT "Command is write-only" |
SECURITY CONSTRAINTS:
- Can only write to newly created worktree directory
- Cannot modify existing files
- Cannot remove directories (even on cleanup)
- Git worktree add is safe (git manages cleanup)
## TEST CASES
### TC001: Create new feature branch worktree
PRECONDITIONS:
- In git repository at /Users/dev/myapp
- Current branch: main
- Branch "feature/login-refactor" does not exist
- Directory /Users/dev/myapp-feature-login-refactor does not exist
INPUT:
```
/working-tree:new feature/login-refactor
```
EXPECTED EXECUTION FLOW:
1. STEP 1 → REPO_ROOT="/Users/dev/myapp", REPO_NAME="myapp", PARENT_DIR="/Users/dev"
2. STEP 2 → BRANCH_NAME="feature/login-refactor", MODE_ARG="", DESCRIPTION=""
3. STEP 3 → MODE="feature" (inferred from "feature/" prefix)
4. STEP 4 → BRANCH_EXISTS=1 (does not exist)
5. STEP 5 → Create branch "feature/login-refactor"
6. STEP 6 → WORKTREE_NAME="myapp-feature-login-refactor", WORKTREE_PATH="/Users/dev/myapp-feature-login-refactor"
7. STEP 7 → No existing worktree
8. STEP 8 → Directory does not exist
9. STEP 9 → Create worktree
10. STEP 10 → Generate timestamp
11. STEP 11 → Write .ai-context.json
12. STEP 12 → Write README.working-tree.md
13. STEP 13 → Output summary
EXPECTED OUTPUT:
```
Created worktree successfully!
Path: /Users/dev/myapp-feature-login-refactor
Branch: feature/login-refactor
Mode: feature
Description: None
Metadata files created:
✓ .ai-context.json
✓ README.working-tree.md
To switch to this worktree:
cd /Users/dev/myapp-feature-login-refactor
```
VALIDATION COMMANDS:
```bash
# Verify worktree created
test -d /Users/dev/myapp-feature-login-refactor && echo "PASS" || echo "FAIL"
# Verify branch created
git show-ref --verify refs/heads/feature/login-refactor && echo "PASS" || echo "FAIL"
# Verify .ai-context.json
test -f /Users/dev/myapp-feature-login-refactor/.ai-context.json && echo "PASS" || echo "FAIL"
jq -r '.mode' /Users/dev/myapp-feature-login-refactor/.ai-context.json | grep "feature" && echo "PASS" || echo "FAIL"
# Verify README
test -f /Users/dev/myapp-feature-login-refactor/README.working-tree.md && echo "PASS" || echo "FAIL"
```
### TC002: Create with explicit mode and description
PRECONDITIONS:
- In git repository at /Users/dev/myapp
- Branch "my-experiment" does not exist
INPUT:
```
/working-tree:new my-experiment --mode experiment --description "Testing new architecture"
```
EXPECTED EXECUTION FLOW:
1-2. Parse arguments → BRANCH_NAME="my-experiment", MODE_ARG="experiment", DESCRIPTION="Testing new architecture"
3. STEP 3 → MODE="experiment" (explicit, not inferred)
4-13. Standard flow
EXPECTED .ai-context.json:
```json
{
"worktree": "myapp-my-experiment",
"branch": "my-experiment",
"mode": "experiment",
"created": "2025-11-23T12:34:56Z",
"description": "Testing new architecture"
}
```
VALIDATION:
```bash
jq -r '.mode' .ai-context.json | grep "experiment" && echo "PASS" || echo "FAIL"
jq -r '.description' .ai-context.json | grep "Testing new architecture" && echo "PASS" || echo "FAIL"
```
### TC003: Branch already has worktree
PRECONDITIONS:
- Branch "feature/existing" already has worktree at /Users/dev/myapp-feature-existing
INPUT:
```
/working-tree:new feature/existing
```
EXPECTED EXECUTION FLOW:
1-6. Standard detection and parsing
7. STEP 7 → EXISTING_WORKTREE="/Users/dev/myapp-feature-existing"
8. ERROR PATTERN "branch-has-worktree"
9. ABORT
EXPECTED OUTPUT:
```
Error: Branch 'feature/existing' already has a worktree at /Users/dev/myapp-feature-existing
Use one of:
- /working-tree:list to see all worktrees
- cd /Users/dev/myapp-feature-existing to use the existing worktree
- /working-tree:destroy /Users/dev/myapp-feature-existing to remove it first
```
POSTCONDITIONS:
- No new worktree created
- No new branch created
- Existing worktree unchanged
### TC004: Invalid mode specified
PRECONDITIONS:
- In git repository
INPUT:
```
/working-tree:new test-branch --mode production
```
EXPECTED EXECUTION FLOW:
1. STEP 1 → Detect repo
2. STEP 2 → MODE_ARG="production"
3. Validation fails: "production" not in [main, feature, bugfix, experiment, review]
4. ERROR PATTERN "invalid-mode"
5. ABORT
EXPECTED OUTPUT:
```
Error: Invalid mode 'production'
Valid modes: main, feature, bugfix, experiment, review
Example:
/working-tree:new my-branch --mode feature
```
### TC005: Directory already exists
PRECONDITIONS:
- Directory /Users/dev/myapp-feature-test already exists (not a worktree)
INPUT:
```
/working-tree:new feature/test
```
EXPECTED EXECUTION FLOW:
1-7. Standard flow
8. STEP 8 → DIR_EXISTS=0 (directory exists)
9. ERROR PATTERN "directory-exists"
10. ABORT
EXPECTED OUTPUT:
```
Error: Directory '/Users/dev/myapp-feature-test' already exists
Choose a different branch name or remove the existing directory.
To remove:
rm -rf /Users/dev/myapp-feature-test
(Be careful - this will delete all contents)
```
## RELATED COMMANDS
- /working-tree:status - Show current worktree metadata
- /working-tree:list - List all worktrees with metadata
- /working-tree:adopt - Add metadata to existing worktree
- /working-tree:destroy - Remove worktree safely
## DELEGATION
For complex worktree strategy or organization questions:
```
Task(
subagent_type='working-tree-consultant',
description='Worktree strategy consultation',
prompt='[question about worktree organization, naming, or workflow]'
)
```

466
commands/status.md Normal file
View File

@@ -0,0 +1,466 @@
---
description: Show metadata for the current git worktree from .ai-context.json
allowed-tools: Bash, Read
model: sonnet
---
# /working-tree:status
Display current worktree AI context metadata and git information.
## EXECUTION PROTOCOL
Execute steps sequentially. Each step must complete successfully before proceeding.
### STEP 1: DETECT REPOSITORY ROOT
EXECUTE:
```bash
REPO_ROOT=$(git rev-parse --show-toplevel 2>&1)
EXIT_CODE=$?
```
VALIDATION:
- IF EXIT_CODE != 0 → ERROR PATTERN "not-in-git-repo"
- REPO_ROOT must be absolute path starting with /
- REPO_ROOT directory must exist
DATA EXTRACTION:
- REPO_NAME = basename of REPO_ROOT
NEXT:
- On success → STEP 2
- On failure → ABORT
### STEP 2: DETECT CURRENT BRANCH
EXECUTE:
```bash
BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD 2>&1)
EXIT_CODE=$?
```
VALIDATION:
- IF EXIT_CODE != 0 → ERROR PATTERN "git-command-failed"
- BRANCH_NAME must not be empty string
NEXT:
- On success → STEP 3
- On failure → ABORT
### STEP 3: CHECK METADATA FILE
EXECUTE:
```bash
METADATA_PATH="$REPO_ROOT/.ai-context.json"
test -f "$METADATA_PATH"
EXISTS=$?
```
VALIDATION:
- EXISTS is 0 (true) or 1 (false), no other values
NEXT:
- IF EXISTS == 0 → STEP 4 (metadata exists)
- IF EXISTS == 1 → STEP 5 (no metadata)
### STEP 4: READ AND PARSE METADATA
EXECUTE:
```bash
METADATA_JSON=$(cat "$METADATA_PATH" 2>&1)
CAT_EXIT=$?
```
VALIDATION:
- IF CAT_EXIT != 0 → ERROR PATTERN "file-read-failed"
DATA EXTRACTION:
```bash
MODE=$(echo "$METADATA_JSON" | jq -r '.mode // "unknown"' 2>&1)
JQ_EXIT_MODE=$?
DESCRIPTION=$(echo "$METADATA_JSON" | jq -r '.description // ""' 2>&1)
JQ_EXIT_DESC=$?
CREATED=$(echo "$METADATA_JSON" | jq -r '.created // ""' 2>&1)
JQ_EXIT_CREATED=$?
```
VALIDATION:
- IF JQ_EXIT_MODE != 0 → ERROR PATTERN "invalid-json"
- MODE must be one of: main, feature, bugfix, experiment, review, unknown
- DESCRIPTION can be empty string
- CREATED should be ISO8601 format or empty
NEXT:
- On success → STEP 6 (display with metadata)
- On jq failure → ERROR PATTERN "invalid-json"
### STEP 5: DISPLAY NO METADATA
OUTPUT FORMAT (exact):
```
Worktree Status
═══════════════════════════════════════════════════════════
Directory: {REPO_NAME}
Branch: {BRANCH_NAME}
Mode: (no metadata)
⚠ No .ai-context.json found
This worktree doesn't have AI context metadata.
To add metadata to this worktree:
/working-tree:adopt [--mode <mode>] [--description "<text>"]
To create a new worktree with metadata:
/working-tree:new <branch-name>
```
NEXT:
- TERMINATE (success)
### STEP 6: DISPLAY WITH METADATA
OUTPUT FORMAT (exact):
```
Worktree Status
═══════════════════════════════════════════════════════════
Directory: {REPO_NAME}
Branch: {BRANCH_NAME}
Mode: {MODE}
Created: {CREATED}
Purpose:
{DESCRIPTION or "No description provided"}
───────────────────────────────────────────────────────────
Mode Semantics:
main → Minimal changes, stable work only
feature → Active development, larger changes allowed
bugfix → Isolated, surgical fixes only
experiment → Prototypes, large swings, unsafe changes allowed
review → Documentation, analysis, audits
Metadata file: .ai-context.json
```
TEMPLATE SUBSTITUTIONS:
- {REPO_NAME} = extracted from STEP 1
- {BRANCH_NAME} = extracted from STEP 2
- {MODE} = extracted from STEP 4
- {CREATED} = extracted from STEP 4
- {DESCRIPTION} = extracted from STEP 4, if empty use "No description provided"
NEXT:
- TERMINATE (success)
## ERROR PATTERNS
### PATTERN: not-in-git-repo
DETECTION:
- TRIGGER: git rev-parse --show-toplevel exit code != 0
- INDICATORS: stderr contains "not a git repository" OR "not inside a work tree"
RESPONSE (exact):
```
Error: Not in a git repository
Run this command from within a git repository.
```
CONTROL FLOW:
- ABORT: true
- RETRY: false
- FALLBACK: None
### PATTERN: git-command-failed
DETECTION:
- TRIGGER: git command exit code != 0 (excluding rev-parse --show-toplevel which uses "not-in-git-repo")
- CAPTURE: stderr from failed git command
RESPONSE (exact):
```
Error: Failed to read git information
Git error: {GIT_STDERR}
Check that:
- You're in a git repository
- Git is installed and working
```
TEMPLATE SUBSTITUTIONS:
- {GIT_STDERR} = captured stderr from failed command
CONTROL FLOW:
- ABORT: true
- RETRY: false
- FALLBACK: None
### PATTERN: invalid-json
DETECTION:
- TRIGGER: jq command exit code != 0 when parsing .ai-context.json
- CAPTURE: jq error message from stderr
RESPONSE (exact):
```
Warning: .ai-context.json exists but is invalid
JSON error: {JQ_ERROR}
The metadata file may be corrupted. Consider:
- Fixing the JSON manually
- Running /working-tree:adopt to regenerate
```
TEMPLATE SUBSTITUTIONS:
- {JQ_ERROR} = captured stderr from jq
CONTROL FLOW:
- ABORT: false (warning, not error)
- RETRY: false
- FALLBACK: STEP 5 (display as if no metadata)
### PATTERN: file-read-failed
DETECTION:
- TRIGGER: cat command on .ai-context.json fails despite file existence check passing
- CAPTURE: stderr from cat command
RESPONSE (exact):
```
Error: Failed to read .ai-context.json
Read error: {CAT_ERROR}
Check file permissions on .ai-context.json
```
TEMPLATE SUBSTITUTIONS:
- {CAT_ERROR} = captured stderr from cat
CONTROL FLOW:
- ABORT: true
- RETRY: false
- FALLBACK: None
## TOOL PERMISSION MATRIX
| Tool | Pattern | Permission | Pre-Check | Post-Check | On-Deny-Action |
|------|---------|------------|-----------|------------|----------------|
| Bash | git:* | ALLOW | command_safe | validate_output | N/A |
| Bash | jq:* | ALLOW | command_safe | validate_json | N/A |
| Bash | cat .ai-context.json | ALLOW | file_exists | validate_output | N/A |
| Bash | test:* | ALLOW | N/A | N/A | N/A |
| Bash | rm:* | DENY | N/A | N/A | ABORT "Destructive operation" |
| Bash | sudo:* | DENY | N/A | N/A | ABORT "Elevated privileges" |
| Read | .ai-context.json | ALLOW | file_exists | valid_json | N/A |
| Write | ** | DENY | N/A | N/A | ABORT "Status is read-only" |
| Edit | ** | DENY | N/A | N/A | ABORT "Status is read-only" |
SECURITY CONSTRAINTS:
- This command is READ-ONLY
- NO file modifications allowed
- NO destructive operations allowed
- Git commands limited to read operations (rev-parse, status, etc.)
## TEST CASES
### TC001: Worktree with valid metadata
PRECONDITIONS:
- In git repository at /path/to/myapp
- Current branch: feature/login-refactor
- File exists: /path/to/myapp/.ai-context.json
- File contains valid JSON:
```json
{
"mode": "feature",
"description": "Refactor authentication flow to support OAuth2",
"created": "2025-11-23T10:30:00Z",
"branch": "feature/login-refactor"
}
```
EXPECTED EXECUTION FLOW:
1. STEP 1 → REPO_ROOT="/path/to/myapp", REPO_NAME="myapp"
2. STEP 2 → BRANCH_NAME="feature/login-refactor"
3. STEP 3 → EXISTS=0 (metadata exists)
4. STEP 4 → MODE="feature", DESCRIPTION="Refactor authentication flow to support OAuth2", CREATED="2025-11-23T10:30:00Z"
5. STEP 6 → Display formatted output
EXPECTED OUTPUT:
```
Worktree Status
═══════════════════════════════════════════════════════════
Directory: myapp
Branch: feature/login-refactor
Mode: feature
Created: 2025-11-23T10:30:00Z
Purpose:
Refactor authentication flow to support OAuth2
───────────────────────────────────────────────────────────
Mode Semantics:
main → Minimal changes, stable work only
feature → Active development, larger changes allowed
bugfix → Isolated, surgical fixes only
experiment → Prototypes, large swings, unsafe changes allowed
review → Documentation, analysis, audits
Metadata file: .ai-context.json
```
VALIDATION COMMANDS:
```bash
# Verify file exists
test -f /path/to/myapp/.ai-context.json && echo "PASS" || echo "FAIL"
# Verify valid JSON
jq empty /path/to/myapp/.ai-context.json && echo "PASS" || echo "FAIL"
# Verify mode field
test "$(jq -r '.mode' /path/to/myapp/.ai-context.json)" = "feature" && echo "PASS" || echo "FAIL"
```
### TC002: Worktree without metadata
PRECONDITIONS:
- In git repository at /path/to/myapp
- Current branch: main
- File does NOT exist: /path/to/myapp/.ai-context.json
EXPECTED EXECUTION FLOW:
1. STEP 1 → REPO_ROOT="/path/to/myapp", REPO_NAME="myapp"
2. STEP 2 → BRANCH_NAME="main"
3. STEP 3 → EXISTS=1 (no metadata)
4. STEP 5 → Display no-metadata output
5. TERMINATE
EXPECTED OUTPUT:
```
Worktree Status
═══════════════════════════════════════════════════════════
Directory: myapp
Branch: main
Mode: (no metadata)
⚠ No .ai-context.json found
This worktree doesn't have AI context metadata.
To add metadata to this worktree:
/working-tree:adopt [--mode <mode>] [--description "<text>"]
To create a new worktree with metadata:
/working-tree:new <branch-name>
```
VALIDATION COMMANDS:
```bash
# Verify file does not exist
test ! -f /path/to/myapp/.ai-context.json && echo "PASS" || echo "FAIL"
```
### TC003: Invalid JSON in metadata file
PRECONDITIONS:
- In git repository at /path/to/myapp
- Current branch: feature/test
- File exists: /path/to/myapp/.ai-context.json
- File contains invalid JSON: `{invalid json}`
EXPECTED EXECUTION FLOW:
1. STEP 1 → REPO_ROOT="/path/to/myapp"
2. STEP 2 → BRANCH_NAME="feature/test"
3. STEP 3 → EXISTS=0
4. STEP 4 → jq fails with parse error
5. ERROR PATTERN "invalid-json" → Warning displayed
6. FALLBACK → STEP 5 (display as no metadata)
EXPECTED OUTPUT:
```
Warning: .ai-context.json exists but is invalid
JSON error: parse error: Invalid numeric literal at line 1, column 10
The metadata file may be corrupted. Consider:
- Fixing the JSON manually
- Running /working-tree:adopt to regenerate
Worktree Status
═══════════════════════════════════════════════════════════
Directory: myapp
Branch: feature/test
Mode: (no metadata)
⚠ No .ai-context.json found
This worktree doesn't have AI context metadata.
To add metadata to this worktree:
/working-tree:adopt [--mode <mode>] [--description "<text>"]
To create a new worktree with metadata:
/working-tree:new <branch-name>
```
VALIDATION COMMANDS:
```bash
# Verify file exists but is invalid
test -f /path/to/myapp/.ai-context.json && echo "EXISTS"
jq empty /path/to/myapp/.ai-context.json 2>&1 | grep -q "parse error" && echo "INVALID"
```
### TC004: Not in git repository
PRECONDITIONS:
- Current directory: /tmp (not a git repository)
EXPECTED EXECUTION FLOW:
1. STEP 1 → git rev-parse fails with exit code 128
2. ERROR PATTERN "not-in-git-repo" triggered
3. ABORT
EXPECTED OUTPUT:
```
Error: Not in a git repository
Run this command from within a git repository.
```
VALIDATION COMMANDS:
```bash
# Verify not in git repo
cd /tmp
git rev-parse --show-toplevel 2>&1 | grep -q "not a git repository" && echo "PASS" || echo "FAIL"
```
## RELATED COMMANDS
- /working-tree:adopt - Add metadata to current worktree
- /working-tree:new - Create new worktree with metadata
- /working-tree:list - List all worktrees with metadata
- /working-tree:destroy - Remove worktree safely
## DELEGATION
For complex worktree strategy questions or multi-worktree workflows:
```
Task(
subagent_type='working-tree-consultant',
description='Worktree strategy consultation',
prompt='[detailed question about worktree organization]'
)
```