skills/openspec-beads-worktree/SKILL.md
Coordinate OpenSpec proposals with coordinator issue tracking and isolated git worktree execution. Implements systematic spec-driven development with parallel agent coordination.
npx skillsauth add jankneumann/agentic-coding-tools openspec-coordinator-worktreeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill coordinates the complete workflow from OpenSpec proposal through coordinator issue creation to isolated git worktree execution. It enables systematic spec-driven development with support for parallel agent coordination.
Activate this skill when:
OpenSpec Proposal → Coordinator Issues → Git Worktrees → Execution → Merge → Archive
↓ ↓ ↓ ↓ ↓ ↓
Planning Tracking Isolation Implementation Review Knowledge
# Check if OpenSpec is initialized
if [ -d "openspec" ]; then
echo "✓ OpenSpec initialized"
else
echo "✗ OpenSpec not found - run: openspec init"
exit 1
fi
# List available proposals
openspec list
# View specific proposal
openspec show <proposal-name>
What to Check:
openspec/changes/<proposal-name>/proposal.md with clear objectivestasks.md with implementation tasksspecs/ directory with spec deltasRead and validate:
openspec/changes/<proposal-name>/proposal.md - Feature descriptionopenspec/changes/<proposal-name>/tasks.md - Task breakdownopenspec/changes/<proposal-name>/specs/*/spec.md - Specification changesQuality Checks:
Issue operations can be called two ways, depending on where the caller runs:
| Caller | Use | Example |
|---|---|---|
| Claude Code agent (or other MCP client) | MCP tool names | issue_create(title=...) via the agent's tool interface |
| Python script / orchestrator outside an MCP client | Bridge helpers | from coordination_bridge import try_issue_create; try_issue_create(...) |
The examples in this skill use MCP-tool-style pseudocode (issue_create(...))
because the agent running the skill has these tools in its toolbelt. For
generated scripts that run outside the agent (e.g. worktree bootstrap hooks,
CI jobs), reach for the bridge helpers in
skills/coordination-bridge/scripts/coordination_bridge.py — same underlying
HTTP API, stdlib-only transport, SSRF-validated, works anywhere Python runs.
The mapping is one-to-one: issue_create ↔ try_issue_create,
issue_list ↔ try_issue_list, and so on for show, update, close,
comment, ready, blocked, search.
Check that the coordinator is running and issue tools are available:
python3 skills/coordination-bridge/scripts/check_coordinator.py --json
If coordinator is unavailable, fall back to tracking tasks only in tasks.md without issue creation.
Use the coordinator's issue_create MCP tool:
# Create epic for the OpenSpec proposal
issue_create(
title="OpenSpec: <proposal title>",
issue_type="epic",
priority=1,
description="Implementing OpenSpec proposal: <proposal-name>\nLocation: openspec/changes/<proposal-name>/",
labels=["openspec", "<proposal-name>"]
)
Record the returned issue_id as EPIC_ID for linking children.
For each task in tasks.md, create a coordinator issue:
issue_create(
title="<task title>",
issue_type="task",
priority=<priority>,
description="<task description and file scope>",
labels=["openspec", "<proposal-name>", "task-<number>"],
parent_id="<EPIC_ID>"
--type task \
--priority $priority \
--parent $epic_id \
--label "openspec,$proposal,task-$task_num" \
--description "$description" \
--json | jq -r '.id')
echo "Created: $issue_id - Task $task_num: $task_title"
# Store mapping for dependency linking
echo "$task_num:$issue_id" >> /tmp/coordinator_task_map_$proposal.txt
fi
done < "$tasks_file"
}
# Execute conversion
create_coordinator_from_tasks "$PROPOSAL_NAME" "$EPIC_ID"
# Parse dependencies from tasks.md and create Coordinator deps
link_dependencies() {
local proposal=$1
local map_file="/tmp/coordinator_task_map_$proposal.txt"
local tasks_file="openspec/changes/$proposal/tasks.md"
# Look for "Dependencies: Task X.Y" patterns
grep -n "Dependencies:" "$tasks_file" | while IFS=: read -r line_num dep_line; do
# Get task number from nearby ## Task X.Y
task_num=$(sed -n "$((line_num-5)),$((line_num))p" "$tasks_file" | \
grep -o "Task [0-9.]*" | tail -1 | cut -d' ' -f2)
# Extract dependency task numbers
dep_tasks=$(echo "$dep_line" | grep -o "Task [0-9.]*" | cut -d' ' -f2)
# Get Coordinator IDs from map
task_id=$(grep "^$task_num:" "$map_file" | cut -d: -f2)
for dep_task in $dep_tasks; do
dep_id=$(grep "^$dep_task:" "$map_file" | cut -d: -f2)
if [[ -n "$dep_id" ]] && [[ -n "$task_id" ]]; then
issue_update (with depends_on) "$task_id" "$dep_id" --type blocks
echo "Linked: $task_id blocks on $dep_id"
fi
done
done
}
link_dependencies "$PROPOSAL_NAME"
# Show the created structure
echo -e "\n=== Epic and Tasks ==="
issue_show $EPIC_ID
issue_list --parent $EPIC_ID --json | jq -r '.[] | "\(.id): \(.title)"'
# Show ready work
echo -e "\n=== Ready Tasks (no blockers) ==="
issue_ready --parent $EPIC_ID --json | jq -r '.[] | "\(.id): \(.title)"'
# Visualize dependencies
echo -e "\n=== Dependency Graph ==="
issue_blocked $EPIC_ID --graph
# Determine worktree strategy based on task count
TASK_COUNT=$(issue_list --parent $EPIC_ID --status open --json | jq '. | length')
if [ $TASK_COUNT -le 3 ]; then
STRATEGY="single"
echo "Strategy: Single worktree (sequential execution)"
elif [ $TASK_COUNT -le 10 ]; then
STRATEGY="parallel"
echo "Strategy: Parallel worktrees (2-3 concurrent)"
else
STRATEGY="swarm"
echo "Strategy: Swarm worktrees (5+ concurrent)"
fi
# Get base branch
BASE_BRANCH=$(git branch --show-current)
FEATURE_BRANCH="openspec/${PROPOSAL_NAME}"
# Create feature branch
git checkout -b "$FEATURE_BRANCH"
git push -u origin "$FEATURE_BRANCH"
git checkout "$BASE_BRANCH"
# Function to create worktree for a task
create_task_worktree() {
local task_id=$1
local task_title=$2
local task_num=$3
# Sanitize title for branch name
local branch_name=$(echo "$task_title" | \
tr '[:upper:]' '[:lower:]' | \
sed 's/[^a-z0-9]/-/g' | \
sed 's/--*/-/g' | \
sed 's/^-//;s/-$//')
# Use agent-id for worktree disambiguation
local agent_id="task-${task_num}-${branch_name}"
local branch="${FEATURE_BRANCH}-task-${task_num}-${branch_name}"
# Create worktree via worktree skill (creates .git-worktrees/<proposal>/<agent-id>/)
eval "$(python3 "<skill-base-dir>/../worktree/scripts/worktree.py" setup "${PROPOSAL_NAME}" --branch "${branch}" --agent-id "${agent_id}")"
# Store worktree info in Coordinator
issue_update "$task_id" --description "$(issue_show $task_id --json | jq -r '.description')
Worktree: $WORKTREE_PATH
Branch: $branch
Agent-ID: $agent_id
Base: $FEATURE_BRANCH"
echo "Created worktree: $WORKTREE_PATH"
echo "$task_id|$WORKTREE_PATH|$branch|$agent_id" >> /tmp/worktree_map_$PROPOSAL_NAME.txt
}
# Create worktrees for ready tasks
issue_ready --parent $EPIC_ID --json | jq -r '.[] | "\(.id)|\(.title)"' | \
while IFS='|' read -r task_id task_title; do
# Extract task number from labels
task_num=$(issue_show $task_id --json | jq -r '.labels[]' | grep -o 'task-[0-9.]*' | cut -d- -f2)
create_task_worktree "$task_id" "$task_title" "$task_num"
done
# For each worktree, setup CLAUDE.md or AGENTS.md
setup_worktree_context() {
local worktree_path=$1
local task_id=$2
# Get task details
local task_info=$(issue_show $task_id --json)
local task_title=$(echo "$task_info" | jq -r '.title')
local task_desc=$(echo "$task_info" | jq -r '.description')
# Create CLAUDE.md in worktree
cat > "$worktree_path/CLAUDE.md" <<EOF
# Task Context: $task_title
## Coordinator Task ID: $task_id
## Objective
$task_desc
## OpenSpec Reference
See: openspec/changes/$PROPOSAL_NAME/
## Working Instructions
1. **Check Dependencies**
\`\`\`bash
issue_show $task_id
# Verify all blockers are resolved
\`\`\`
2. **Update Status**
\`\`\`bash
issue_update $task_id --status in_progress
\`\`\`
3. **Reference Specs**
- Read openspec/changes/$PROPOSAL_NAME/specs/
- Follow acceptance criteria in tasks.md
4. **When Complete**
\`\`\`bash
# Run tests
npm test # or appropriate test command
# Commit changes
git add .
git commit -m "$task_title"
# Update Coordinator
issue_close $task_id --reason "Implementation complete"
# Push branch
git push origin HEAD
\`\`\`
5. **Coordination**
- Use \`issue_list --parent $EPIC_ID\` to see other tasks
- Check \`issue_ready --parent $EPIC_ID\` for next work
- Communicate via Coordinator comments if blocked
## Implementation Checklist
$(echo "$task_desc" | grep -E '^- \[ \]' || echo "- [ ] Implement feature\n- [ ] Write tests\n- [ ] Update documentation")
---
Generated: $(date)
Worktree: $worktree_path
EOF
# Initialize Coordinator in worktree (links to main .coordinator)
cd "$worktree_path"
# coordinator issues are accessible via MCP - no onboard needed
cd - > /dev/null
echo "✓ Setup context in $worktree_path"
}
# Setup all worktrees
while IFS='|' read -r task_id worktree_path branch agent_id; do
setup_worktree_context "$worktree_path" "$task_id"
done < /tmp/worktree_map_$PROPOSAL_NAME.txt
# Create orchestrator script
cat > "execute_${PROPOSAL_NAME}.sh" <<'EOF'
#!/bin/bash
set -e
PROPOSAL_NAME="${1:-$PROPOSAL_NAME}"
MAP_FILE="/tmp/worktree_map_$PROPOSAL_NAME.txt"
echo "=== OpenSpec Execution Orchestrator ==="
echo "Proposal: $PROPOSAL_NAME"
echo "Strategy: $STRATEGY"
echo ""
# Function to execute task in worktree
execute_task() {
local task_id=$1
local worktree_path=$2
local branch=$3
echo "→ Starting task: $task_id in $worktree_path"
cd "$worktree_path"
# Update status
issue_update $task_id --status in_progress --assignee "@claude-$(hostname)"
# Launch Claude Code
claude -p "Review CLAUDE.md and implement this task. Follow all instructions in the file. When done, update Coordinator status."
# Return to main directory
cd - > /dev/null
}
# Execute based on strategy
case "$STRATEGY" in
single)
echo "Sequential execution..."
while IFS='|' read -r task_id worktree_path branch agent_id; do
execute_task "$task_id" "$worktree_path" "$branch"
done < "$MAP_FILE"
;;
parallel)
echo "Parallel execution (max 3)..."
cat "$MAP_FILE" | parallel -j 3 --colsep '|' execute_task {1} {2} {3}
;;
swarm)
echo "Swarm execution (max 5)..."
cat "$MAP_FILE" | parallel -j 5 --colsep '|' execute_task {1} {2} {3}
;;
esac
echo ""
echo "=== Execution Complete ==="
issue_list --parent $EPIC_ID --json | jq -r '.[] | "\(.id): \(.status)"'
EOF
chmod +x "execute_${PROPOSAL_NAME}.sh"
echo "Orchestrator created: execute_${PROPOSAL_NAME}.sh"
echo ""
echo "To execute:"
echo " ./execute_${PROPOSAL_NAME}.sh"
# Create monitoring dashboard
cat > "monitor_${PROPOSAL_NAME}.sh" <<'EOF'
#!/bin/bash
PROPOSAL_NAME="${1:-$PROPOSAL_NAME}"
EPIC_ID=$(issue_list --label "openspec,$PROPOSAL_NAME" --type epic --json | jq -r '.[0].id')
while true; do
clear
echo "=== OpenSpec Progress Dashboard ==="
echo "Proposal: $PROPOSAL_NAME"
echo "Epic: $EPIC_ID"
echo "Time: $(date)"
echo ""
# Status summary
echo "Status Summary:"
issue_list --parent $EPIC_ID --json | \
jq -r 'group_by(.status) | map({status: .[0].status, count: length}) | .[] | " \(.status): \(.count)"'
echo ""
echo "Active Tasks:"
issue_list --parent $EPIC_ID --status in_progress --json | \
jq -r '.[] | " [\(.id)] \(.title) - \(.assignee // "unassigned")"'
echo ""
echo "Ready Work:"
issue_ready --parent $EPIC_ID --limit 5 --json | \
jq -r '.[] | " [\(.id)] \(.title)"'
echo ""
echo "Blocked:"
issue_list --parent $EPIC_ID --status blocked --json | \
jq -r '.[] | " [\(.id)] \(.title)"'
echo ""
echo "[Refreshing in 30s... Ctrl+C to exit]"
sleep 30
done
EOF
chmod +x "monitor_${PROPOSAL_NAME}.sh"
echo "Monitor created: monitor_${PROPOSAL_NAME}.sh"
echo "Run in separate terminal: ./monitor_${PROPOSAL_NAME}.sh"
# Create merge orchestrator
merge_worktrees() {
local proposal=$1
local epic_id=$2
local feature_branch="openspec/$proposal"
echo "=== Merging Completed Tasks ==="
# Get completed tasks
issue_list --parent $epic_id --status closed --json | jq -r '.[] | .id' | \
while read -r task_id; do
# Get worktree info
worktree_info=$(issue_show $task_id --json | jq -r '.description' | grep -A2 "Worktree:")
branch=$(echo "$worktree_info" | grep "Branch:" | cut -d: -f2- | xargs)
if [[ -n "$branch" ]]; then
echo "→ Merging $branch into $feature_branch"
git checkout "$feature_branch"
git merge --no-ff "$branch" -m "Merge task $task_id: $(issue_show $task_id --json | jq -r '.title')"
if [ $? -eq 0 ]; then
echo " ✓ Merged successfully"
issue_update $task_id --label "+merged"
else
echo " ✗ Merge conflict - manual resolution needed"
issue_update $task_id --status blocked --label "+merge-conflict"
fi
fi
done
git checkout $(git branch --show-current)
}
# Execute merge
merge_worktrees "$PROPOSAL_NAME" "$EPIC_ID"
# Remove completed worktrees
cleanup_worktrees() {
local proposal=$1
while IFS='|' read -r task_id worktree_path branch agent_id; do
# Check if task is merged
if issue_show $task_id --json | jq -e '.labels[] | select(. == "merged")' > /dev/null; then
echo "Removing worktree: $worktree_path (agent-id: $agent_id)"
python3 "<skill-base-dir>/../worktree/scripts/worktree.py" teardown "${proposal}" --agent-id "${agent_id}"
git branch -d "$branch"
issue_update $task_id --description "$(issue_show $task_id --json | jq -r '.description')
[Worktree cleaned up: $(date)]"
fi
done < "/tmp/worktree_map_$proposal.txt"
}
# Prompt before cleanup
read -p "Remove merged worktrees? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
cleanup_worktrees "$PROPOSAL_NAME"
fi
# Verify all tasks complete
validate_completion() {
local epic_id=$1
echo "=== Completion Validation ==="
# Check for open tasks
open_count=$(issue_list --parent $epic_id --status open --json | jq '. | length')
in_progress=$(issue_list --parent $epic_id --status in_progress --json | jq '. | length')
blocked=$(issue_list --parent $epic_id --status blocked --json | jq '. | length')
if [[ $open_count -gt 0 ]] || [[ $in_progress -gt 0 ]] || [[ $blocked -gt 0 ]]; then
echo "✗ Not ready for archive:"
echo " - Open: $open_count"
echo " - In Progress: $in_progress"
echo " - Blocked: $blocked"
return 1
fi
echo "✓ All tasks complete"
# Verify tests pass
echo "Running tests..."
git checkout "openspec/$PROPOSAL_NAME"
npm test # or appropriate test command
if [ $? -eq 0 ]; then
echo "✓ Tests pass"
return 0
else
echo "✗ Tests failing"
return 1
fi
}
validate_completion "$EPIC_ID"
# Archive the proposal
archive_openspec() {
local proposal=$1
echo "Archiving OpenSpec proposal: $proposal"
# If using OpenSpec CLI
if command -v openspec &> /dev/null; then
openspec archive "$proposal" --yes
else
# Manual archive
mv "openspec/changes/$proposal" "openspec/changes/.archived/$proposal"
# Consolidate specs
for spec in openspec/changes/.archived/$proposal/specs/*/spec.md; do
capability=$(basename $(dirname "$spec"))
target="openspec/specs/$capability/spec.md"
echo "Consolidating $capability spec..."
cat "$spec" >> "$target"
done
fi
git add openspec/
git commit -m "Archive OpenSpec proposal: $proposal"
}
# Execute archive
read -p "Archive OpenSpec proposal? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
archive_openspec "$PROPOSAL_NAME"
fi
# Close the epic
issue_close $EPIC_ID --reason "OpenSpec proposal implemented and archived"
# Add summary
issue_comment $EPIC_ID "Implementation Summary:
- Total tasks: $(issue_list --parent $EPIC_ID --json | jq '. | length')
- Duration: [manual entry]
- Worktrees used: $(wc -l < /tmp/worktree_map_$PROPOSAL_NAME.txt)
- Final branch: openspec/$PROPOSAL_NAME
- Archived: $(date)
"
echo "✓ Epic closed: $EPIC_ID"
Always update status
issue_update <id> --status in_progress # When starting
issue_close <id> # When done
Track blockers immediately
issue_update <id> --status blocked
issue_comment <id> "Blocked by: [reason]"
Use labels for filtering
--label "openspec,urgent"
--label "frontend,review-needed"
One feature branch, multiple task branches
feature/openspec-xxx
├─ feature/openspec-xxx-task-1.1
├─ feature/openspec-xxx-task-1.2
└─ feature/openspec-xxx-task-2.1
Always merge to feature branch first
Clean up regularly
git worktree list
git worktree remove <path>
Keep specs as source of truth
openspec/changes/<name>/specs/ in all Coordinator issuesArchive only when complete
Document decisions
issue_comment <id> "Decision: [architectural choice]
Rationale: [reasoning]
Reference: [spec section]"
Problem: Can't find issue
issue_list --json | grep -i "search-term"
Problem: Dependency cycle
issue_blocked <id> --graph # Visualize
# Break cycle by clearing depends_on on one side of the cycle:
issue_update <id1> --depends-on "[]"
Problem: Worktree won't remove
git worktree remove --force <path>
Problem: Branch merge conflicts
# In feature branch
git merge --no-commit --no-ff <task-branch>
# Resolve conflicts
git merge --continue
Problem: Tasks out of sync with Coordinator
# Re-run Phase 2 with --force flag
# Or manually update Coordinator to match
# Check status
issue_ready --parent <epic-id>
issue_list --parent <epic-id> --status in_progress
# Update task
issue_update <id> --status <status>
issue_comment <id> "Progress update"
# Worktree management
git worktree list
git worktree add -b <branch> <path> <base>
# OpenSpec
openspec list
openspec show <proposal>
openspec archive <proposal>
issue_ready filtering: Only show relevant tasks# In CI pipeline
issue_list --label "openspec,$PROPOSAL" --status closed --json
# Verify all tasks complete before deploy
# On task completion
issue_close <id> && \
slack-cli chat send --channel dev \
--text "Task completed: $(issue_show <id> --json | jq -r '.title')"
# Export metrics
issue_list --parent <epic-id> --json | \
jq '{total: length, by_status: group_by(.status) | map({status: .[0].status, count: length})}'
# 1. Start with OpenSpec proposal
openspec show add-user-authentication
# 2. Invoke this skill
# "Implement the add-user-authentication OpenSpec proposal using Coordinator and worktrees"
# 3. Claude will:
# - Convert OpenSpec tasks to Coordinator issues
# - Create git worktrees for parallel work
# - Set up execution environment
# - Coordinate implementation
# - Handle merging and archival
# 4. Monitor progress
./monitor_add-user-authentication.sh
# 5. Execute (manual or automated)
./execute_add-user-authentication.sh
Last Updated: January 2026
Skill Version: 1.0.0
Compatibility: OpenSpec 1.x, Coordinator 0.21+, Git 2.x
development
Open the artifacts relevant to a review (OpenSpec proposal, branch changes, or explicit paths) in VS Code, in a curated read-order, in the right worktree.
tools
Render and seed coordinator-owned task status block in OpenSpec tasks.md
testing
User-invocable skill that omits the tail block
tools
Missing several required keys