Initial commit
This commit is contained in:
514
commands/list.md
Normal file
514
commands/list.md
Normal 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]'
|
||||
)
|
||||
```
|
||||
Reference in New Issue
Block a user