| name | openspec-coordinator-worktree |
| version | 2.0.0 |
| description | Coordinate OpenSpec proposals with coordinator issue tracking and isolated git worktree execution. Implements systematic spec-driven development with parallel agent coordination. |
| author | Enterprise AI Strategy |
| tags | ["openspec","coordinator","git-worktree","multi-agent","coordination","issues"] |
| requires | ["openspec (CLI or manual)","coordinator (MCP or HTTP)","git (2.x with worktree support)"] |
| triggers | ["implement openspec proposal","convert openspec to issues","setup worktree for","coordinate openspec work","parallel implementation"] |
OpenSpec + Coordinator Issues + Git Worktree Coordination
Purpose
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.
When to Use This Skill
Activate this skill when:
- Starting work on an OpenSpec proposal
- Converting OpenSpec tasks to coordinator issues
- Setting up isolated execution environments
- Coordinating multiple agents on one feature
- Implementing complex changes that span multiple sessions
Workflow Overview
OpenSpec Proposal → Coordinator Issues → Git Worktrees → Execution → Merge → Archive
↓ ↓ ↓ ↓ ↓ ↓
Planning Tracking Isolation Implementation Review Knowledge
Phase 1: OpenSpec Proposal Review
Step 1.1: Locate and Review Proposal
if [ -d "openspec" ]; then
echo "✓ OpenSpec initialized"
else
echo "✗ OpenSpec not found - run: openspec init"
exit 1
fi
openspec list
openspec show <proposal-name>
What to Check:
- Proposal exists in
openspec/changes/<proposal-name>/
- Has
proposal.md with clear objectives
- Has
tasks.md with implementation tasks
- Has
specs/ directory with spec deltas
Step 1.2: Validate Proposal Structure
Read and validate:
openspec/changes/<proposal-name>/proposal.md - Feature description
openspec/changes/<proposal-name>/tasks.md - Task breakdown
openspec/changes/<proposal-name>/specs/*/spec.md - Specification changes
Quality Checks:
Phase 2: Convert OpenSpec to Coordinator Issues
Transport Options
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.
Step 2.1: Verify Coordinator Available
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.
Step 2.2: Create Epic from Proposal
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.
Step 2.3: Parse Tasks and Create Issues
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"
Step 2.4: Link Dependencies
link_dependencies() {
local proposal=$1
local map_file="/tmp/coordinator_task_map_$proposal.txt"
local tasks_file="openspec/changes/$proposal/tasks.md"
grep -n "Dependencies:" "$tasks_file" | while IFS=: read -r line_num dep_line; do
task_num=$(sed -n "$((line_num-5)),$((line_num))p" "$tasks_file" | \
grep -o "Task [0-9.]*" | tail -1 | cut -d' ' -f2)
dep_tasks=$(echo "$dep_line" | grep -o "Task [0-9.]*" | cut -d' ' -f2)
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"
Step 2.5: Validate Coordinator Structure
echo -e "\n=== Epic and Tasks ==="
issue_show $EPIC_ID
issue_list --parent $EPIC_ID --json | jq -r '.[] | "\(.id): \(.title)"'
echo -e "\n=== Ready Tasks (no blockers) ==="
issue_ready --parent $EPIC_ID --json | jq -r '.[] | "\(.id): \(.title)"'
echo -e "\n=== Dependency Graph ==="
issue_blocked $EPIC_ID --graph
Phase 3: Git Worktree Setup
Step 3.1: Create Worktree Strategy
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
Step 3.2: Create Worktree(s)
BASE_BRANCH=$(git branch --show-current)
FEATURE_BRANCH="openspec/${PROPOSAL_NAME}"
git checkout -b "$FEATURE_BRANCH"
git push -u origin "$FEATURE_BRANCH"
git checkout "$BASE_BRANCH"
create_task_worktree() {
local task_id=$1
local task_title=$2
local task_num=$3
local branch_name=$(echo "$task_title" | \
tr '[:upper:]' '[:lower:]' | \
sed 's/[^a-z0-9]/-/g' | \
sed 's/--*/-/g' | \
sed 's/^-//;s/-$//')
local agent_id="task-${task_num}-${branch_name}"
local branch="${FEATURE_BRANCH}-task-${task_num}-${branch_name}"
eval "$(python3 "<skill-base-dir>/../worktree/scripts/worktree.py" setup "${PROPOSAL_NAME}" --branch "${branch}" --agent-id "${agent_id}")"
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
}
issue_ready --parent $EPIC_ID --json | jq -r '.[] | "\(.id)|\(.title)"' | \
while IFS='|' read -r task_id task_title; do
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
Step 3.3: Setup Worktree Environment
setup_worktree_context() {
local worktree_path=$1
local task_id=$2
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')
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
cd "$worktree_path"
cd - > /dev/null
echo "✓ Setup context in $worktree_path"
}
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
Phase 4: Execution Coordination
Step 4.1: Launch Execution Sessions
cat > "execute_${PROPOSAL_NAME}.sh" <<'EOF'
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 ""
execute_task() {
local task_id=$1
local worktree_path=$2
local branch=$3
echo "→ Starting task: $task_id in $worktree_path"
cd "$worktree_path"
issue_update $task_id --status in_progress --assignee "@claude-$(hostname)"
claude -p "Review CLAUDE.md and implement this task. Follow all instructions in the file. When done, update Coordinator status."
cd - > /dev/null
}
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"
Step 4.2: Monitor Progress
cat > "monitor_${PROPOSAL_NAME}.sh" <<'EOF'
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 ""
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"
Phase 5: Integration and Review
Step 5.1: Merge Worktree Branches
merge_worktrees() {
local proposal=$1
local epic_id=$2
local feature_branch="openspec/$proposal"
echo "=== Merging Completed Tasks ==="
issue_list --parent $epic_id --status closed --json | jq -r '.[] | .id' | \
while read -r task_id; do
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)
}
merge_worktrees "$PROPOSAL_NAME" "$EPIC_ID"
Step 5.2: Cleanup Worktrees
cleanup_worktrees() {
local proposal=$1
while IFS='|' read -r task_id worktree_path branch agent_id; do
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"
}
read -p "Remove merged worktrees? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
cleanup_worktrees "$PROPOSAL_NAME"
fi
Phase 6: Archive OpenSpec Proposal
Step 6.1: Final Validation
validate_completion() {
local epic_id=$1
echo "=== Completion Validation ==="
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"
echo "Running tests..."
git checkout "openspec/$PROPOSAL_NAME"
npm test
if [ $? -eq 0 ]; then
echo "✓ Tests pass"
return 0
else
echo "✗ Tests failing"
return 1
fi
}
validate_completion "$EPIC_ID"
Step 6.2: Archive OpenSpec
archive_openspec() {
local proposal=$1
echo "Archiving OpenSpec proposal: $proposal"
if command -v openspec &> /dev/null; then
openspec archive "$proposal" --yes
else
mv "openspec/changes/$proposal" "openspec/changes/.archived/$proposal"
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"
}
read -p "Archive OpenSpec proposal? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
archive_openspec "$PROPOSAL_NAME"
fi
Step 6.3: Close Epic
issue_close $EPIC_ID --reason "OpenSpec proposal implemented and archived"
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"
Best Practices
Coordinator Discipline
-
Always update status
issue_update <id> --status in_progress
issue_close <id>
-
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"
Git Worktree Hygiene
-
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
- Test integration before main branch merge
- Resolve conflicts incrementally
-
Clean up regularly
git worktree list
git worktree remove <path>
OpenSpec Integration
-
Keep specs as source of truth
- Reference
openspec/changes/<name>/specs/ in all Coordinator issues
- Don't duplicate spec content in Coordinator descriptions
-
Archive only when complete
- All Coordinator closed
- All tests passing
- Feature branch merged
-
Document decisions
issue_comment <id> "Decision: [architectural choice]
Rationale: [reasoning]
Reference: [spec section]"
Troubleshooting
Coordinator Issues
Problem: Can't find issue
issue_list --json | grep -i "search-term"
Problem: Dependency cycle
issue_blocked <id> --graph
issue_update <id1> --depends-on "[]"
Worktree Issues
Problem: Worktree won't remove
git worktree remove --force <path>
Problem: Branch merge conflicts
git merge --no-commit --no-ff <task-branch>
git merge --continue
OpenSpec Issues
Problem: Tasks out of sync with Coordinator
Quick Reference
Common Commands
issue_ready --parent <epic-id>
issue_list --parent <epic-id> --status in_progress
issue_update <id> --status <status>
issue_comment <id> "Progress update"
git worktree list
git worktree add -b <branch> <path> <base>
openspec list
openspec show <proposal>
openspec archive <proposal>
Workflow Checklist
Performance Tips
- Limit parallel execution: 3-5 concurrent agents max
- Use
issue_ready filtering: Only show relevant tasks
- Batch Coordinator operations: Update multiple issues at once
- Reuse worktrees: Keep active for related tasks
Integration with Other Tools
CI/CD
issue_list --label "openspec,$PROPOSAL" --status closed --json
Slack/Notifications
issue_close <id> && \
slack-cli chat send --channel dev \
--text "Task completed: $(issue_show <id> --json | jq -r '.title')"
Monitoring
issue_list --parent <epic-id> --json | \
jq '{total: length, by_status: group_by(.status) | map({status: .[0].status, count: length})}'
Example Usage
openspec show add-user-authentication
./monitor_add-user-authentication.sh
./execute_add-user-authentication.sh
Last Updated: January 2026
Skill Version: 1.0.0
Compatibility: OpenSpec 1.x, Coordinator 0.21+, Git 2.x