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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ node_modules/
# Python
__pycache__/
*.pyc

# Git worktrees
.worktrees/
2 changes: 1 addition & 1 deletion agents/implementer.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Check for existing project conventions first. If none:
- Never source venv activate scripts - use `uv run` or `poetry run`

### Git
- Don't use `git -C /path` when already in that directory
- When assigned a worktree, work from within it directly (cd into it). Fall back to `git -C` only when necessary
- Create feature branches for changes (never commit to main)
- Conventional commits: `feat: description` or `fix: description`

Expand Down
27 changes: 21 additions & 6 deletions hooks/git-guard.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,24 @@
import subprocess


def get_current_branch():
"""Get current git branch name."""
def parse_git_c_path(command):
"""Extract the -C <path> argument from a git command, if present."""
# Handle both quoted and unquoted paths: git -C "path with spaces" or git -C path
match = re.search(r'git\s+-C\s+(?:"([^"]+)"|(\S+))', command)
if match:
return match.group(1) if match.group(1) else match.group(2)
return None


def get_current_branch(cwd=None):
"""Get current git branch name, optionally for a specific directory."""
try:
cmd = ["git"]
if cwd:
cmd += ["-C", cwd]
cmd += ["rev-parse", "--abbrev-ref", "HEAD"]
result = subprocess.run(
["git", "rev-parse", "--abbrev-ref", "HEAD"],
capture_output=True, text=True, timeout=5
cmd, capture_output=True, text=True, timeout=5
)
return result.stdout.strip() if result.returncode == 0 else None
except Exception:
Expand Down Expand Up @@ -53,8 +65,11 @@ def main():
sys.exit(2)

# Block commits on main/master branch
if re.search(r'git\s+commit', command):
branch = get_current_branch()
# Match git commit at the start of the command or after shell operators (&&, ;, |)
# but NOT inside heredocs or string arguments (no re.MULTILINE — ^ only matches string start)
if re.search(r'(?:^|&&|;|\|)\s*git\s+(-C\s+(?:"[^"]+"|(\S+))\s+)?commit', command):
worktree_path = parse_git_c_path(command)
branch = get_current_branch(cwd=worktree_path)
if branch in ["main", "master"]:
print("❌ BLOCKED: Cannot commit directly to main/master branch", file=sys.stderr)
print("", file=sys.stderr)
Expand Down
64 changes: 37 additions & 27 deletions skills/agent-team-development/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,20 @@ SETUP
WORKTREE SETUP
======================================================================
5. Create git worktrees for each implementer:
Pattern: ../REPO-team-BRANCH-impl-N
Pattern: .worktrees/team-BRANCH-impl-N

Example for repo "my-app" on branch "feature/auth":
../my-app-team-feature-auth-impl-1
../my-app-team-feature-auth-impl-2
../my-app-team-feature-auth-impl-3
Example for branch "feature/auth":
.worktrees/team-feature-auth-impl-1
.worktrees/team-feature-auth-impl-2
.worktrees/team-feature-auth-impl-3

Commands:
git worktree add ../REPO-team-BRANCH-impl-1 HEAD
git worktree add ../REPO-team-BRANCH-impl-2 HEAD
git worktree add .worktrees/team-feature-auth-impl-1 HEAD
git worktree add .worktrees/team-feature-auth-impl-2 HEAD
...

Ensure `.worktrees/` is in `.gitignore`.

DELEGATE MODE
======================================================================
6. Enter delegate mode (Shift+Tab)
Expand Down Expand Up @@ -151,9 +153,10 @@ FINAL
======================================================================
17. Lead performs final staff-code-reviewer (opus) on entire implementation
18. Clean up worktrees:
git worktree remove ../REPO-team-BRANCH-impl-1
git worktree remove ../REPO-team-BRANCH-impl-2
git worktree remove .worktrees/team-BRANCH-impl-1
git worktree remove .worktrees/team-BRANCH-impl-2
...
git worktree prune
19. Create PR (follow repo template if exists)
20. Invoke /pr-merge workflow (or user invokes manually)
```
Expand All @@ -170,20 +173,26 @@ from the shared task list, implement them, and commit your work.
Working directory: [WORKTREE_PATH]
Feature branch: [BRANCH_NAME]

IMPORTANT: cd into your worktree directory and work from there.
All git and file operations should happen from within the worktree.
Only fall back to `git -C` if you cannot cd into the worktree.

## Workflow
1. Check the shared task list for unclaimed tasks
2. Claim a task by marking it in_progress
3. Before starting: git pull to get latest changes
4. Implement the task following its acceptance criteria
5. Run tests and verify your changes
6. Commit with conventional message: feat|fix|refactor: description
7. Push to remote: git push
8. Mark the task as ready for review (add "READY FOR REVIEW" to task)
9. Wait for reviewer feedback via mailbox
10. If reviewer requests fixes: fix, commit, push, notify reviewer
11. Once approved: move to next task
1. cd into your worktree: cd [WORKTREE_PATH]
2. Check the shared task list for unclaimed tasks
3. Claim a task by marking it in_progress
4. Before starting: git pull to get latest changes
5. Implement the task following its acceptance criteria
6. Run tests and verify your changes
7. Commit with conventional message: feat|fix|refactor: description
8. Push to remote: git push
9. Mark the task as ready for review (add "READY FOR REVIEW" to task)
10. Wait for reviewer feedback via mailbox
11. If reviewer requests fixes: fix, commit, push, notify reviewer
12. Once approved: move to next task

## Guidelines
- Work from within your worktree directory (cd into it first)
- Follow project conventions from CLAUDE.md
- Write tests as specified in the task's testing approach
- Keep commits focused on the task
Expand Down Expand Up @@ -285,21 +294,22 @@ Options:
### Creation (during setup)

```bash
# Get repo name and branch for naming
REPO_NAME=$(basename "$(git rev-parse --show-toplevel)")
# Get branch name for worktree naming
BRANCH_NAME=$(git branch --show-current | tr '/' '-')

# Create worktrees
git worktree add "../${REPO_NAME}-team-${BRANCH_NAME}-impl-1" HEAD
git worktree add "../${REPO_NAME}-team-${BRANCH_NAME}-impl-2" HEAD
# Create worktrees inside .worktrees/
git worktree add ".worktrees/team-${BRANCH_NAME}-impl-1" HEAD
git worktree add ".worktrees/team-${BRANCH_NAME}-impl-2" HEAD
# Add impl-3 if 5+ tasks

# Ensure .worktrees/ is in .gitignore
```

### Cleanup (during final)

```bash
git worktree remove "../${REPO_NAME}-team-${BRANCH_NAME}-impl-1"
git worktree remove "../${REPO_NAME}-team-${BRANCH_NAME}-impl-2"
git worktree remove ".worktrees/team-${BRANCH_NAME}-impl-1"
git worktree remove ".worktrees/team-${BRANCH_NAME}-impl-2"
# Remove impl-3 if it exists
git worktree prune
```
Expand Down
Loading