Use to keep GitHub Project fields synchronized with actual work state - updates status, verification, criteria counts, and other project-specific fields
Synchronizes GitHub Project fields with actual work state. Automatically updates status, verification, criteria counts, and other project fields when work state changes or verification runs.
/plugin marketplace add troykelly/claude-skills/plugin install issue-driven-development@troykelly-skillsThis skill is limited to using the following tools:
Keep GitHub Project fields in sync with actual work state.
Core principle: Project fields are the dashboard. Keep them accurate.
This skill is used throughout work, called by other skills.
# Must have GITHUB_PROJECT set
echo $GITHUB_PROJECT
# Example: https://github.com/users/troykelly/projects/4
| Field | Type | Values | Updated When |
|---|---|---|---|
| Status | Single select | Backlog, Ready, In Progress, In Review, Done, Blocked | Work state changes |
| Verification | Single select | Not Verified, Failing, Partial, Passing | Verification runs |
| Criteria Met | Number | 0-N | Criteria checked off |
| Criteria Total | Number | N | Issue created/updated |
| Priority | Single select | Critical, High, Medium, Low | Priority changes |
| Type | Single select | Feature, Bug, Chore, Research, Spike | Issue created |
| Last Verified | Date | ISO date | Verification runs |
| Verified By | Text | agent/human/ci | Verification runs |
To update project fields, you need various IDs:
# Get project number from URL
# https://github.com/users/troykelly/projects/4 → PROJECT_NUMBER=4
# Get project ID
gh project list --owner @me --format json | jq -r '.projects[] | select(.number == 4) | .id'
# Get field IDs
gh project field-list [PROJECT_NUMBER] --owner @me --format json
# Get item ID for a specific issue
gh project item-list [PROJECT_NUMBER] --owner @me --format json | \
jq -r '.items[] | select(.content.number == [ISSUE_NUMBER]) | .id'
Backlog ──► Ready ──► In Progress ──► In Review ──► Done
│ │ │ │
│ │ │ │
└─────────┴────────────┴──────────────┴──► Blocked
│
▼
(any previous state)
| From | To | Trigger |
|---|---|---|
| Backlog | Ready | Dependencies cleared, ready to work |
| Ready | In Progress | Work begins on issue |
| In Progress | In Review | PR created |
| In Review | Done | PR merged, verification passes |
| Any | Blocked | Blocker encountered |
| Blocked | Previous | Blocker resolved |
# First, get the field ID for Status
STATUS_FIELD_ID=$(gh project field-list [PROJECT_NUMBER] --owner @me --format json | \
jq -r '.fields[] | select(.name == "Status") | .id')
# Get the option ID for the desired status
OPTION_ID=$(gh project field-list [PROJECT_NUMBER] --owner @me --format json | \
jq -r '.fields[] | select(.name == "Status") | .options[] | select(.name == "In Progress") | .id')
# Get the item ID for the issue
ITEM_ID=$(gh project item-list [PROJECT_NUMBER] --owner @me --format json | \
jq -r '.items[] | select(.content.number == [ISSUE_NUMBER]) | .id')
# Update the field
gh project item-edit --project-id [PROJECT_ID] --id $ITEM_ID \
--field-id $STATUS_FIELD_ID --single-select-option-id $OPTION_ID
# Similar pattern for Verification field
VERIFICATION_FIELD_ID=$(gh project field-list [PROJECT_NUMBER] --owner @me --format json | \
jq -r '.fields[] | select(.name == "Verification") | .id')
PASSING_OPTION_ID=$(gh project field-list [PROJECT_NUMBER] --owner @me --format json | \
jq -r '.fields[] | select(.name == "Verification") | .options[] | select(.name == "Passing") | .id')
gh project item-edit --project-id [PROJECT_ID] --id $ITEM_ID \
--field-id $VERIFICATION_FIELD_ID --single-select-option-id $PASSING_OPTION_ID
# Update Criteria Met
CRITERIA_MET_FIELD_ID=$(gh project field-list [PROJECT_NUMBER] --owner @me --format json | \
jq -r '.fields[] | select(.name == "Criteria Met") | .id')
gh project item-edit --project-id [PROJECT_ID] --id $ITEM_ID \
--field-id $CRITERIA_MET_FIELD_ID --number 3
# Update Last Verified
LAST_VERIFIED_FIELD_ID=$(gh project field-list [PROJECT_NUMBER] --owner @me --format json | \
jq -r '.fields[] | select(.name == "Last Verified") | .id')
gh project item-edit --project-id [PROJECT_ID] --id $ITEM_ID \
--field-id $LAST_VERIFIED_FIELD_ID --date "$(date -u +%Y-%m-%d)"
# Update Verified By
VERIFIED_BY_FIELD_ID=$(gh project field-list [PROJECT_NUMBER] --owner @me --format json | \
jq -r '.fields[] | select(.name == "Verified By") | .id')
gh project item-edit --project-id [PROJECT_ID] --id $ITEM_ID \
--field-id $VERIFIED_BY_FIELD_ID --text "agent"
After verification, update multiple fields at once:
# After verification completes, update:
# - Verification status
# - Criteria Met count
# - Last Verified date
# - Verified By
PROJECT_ID="[PROJECT_ID]"
ITEM_ID="[ITEM_ID]"
# Update verification status
gh project item-edit --project-id $PROJECT_ID --id $ITEM_ID \
--field-id $VERIFICATION_FIELD_ID --single-select-option-id $PASSING_OPTION_ID
# Update criteria met
gh project item-edit --project-id $PROJECT_ID --id $ITEM_ID \
--field-id $CRITERIA_MET_FIELD_ID --number 4
# Update last verified
gh project item-edit --project-id $PROJECT_ID --id $ITEM_ID \
--field-id $LAST_VERIFIED_FIELD_ID --date "$(date -u +%Y-%m-%d)"
# Update verified by
gh project item-edit --project-id $PROJECT_ID --id $ITEM_ID \
--field-id $VERIFIED_BY_FIELD_ID --text "agent"
| Verification | Recommended Status |
|---|---|
| Not Verified | In Progress (still working) |
| Failing | In Progress (needs fixes) |
| Partial | In Progress (needs work) |
| Passing | In Review (ready for PR review) |
When a new issue is created, add it to the project:
# Add issue to project
gh project item-add [PROJECT_NUMBER] --owner @me --url [ISSUE_URL]
# Then set initial field values
# Status: Backlog or Ready
# Priority: as specified
# Type: as specified
# Criteria Total: count from issue
# Verification: Not Verified
| Issue | Solution |
|---|---|
| Can't find project | Check GITHUB_PROJECT env var is set correctly |
| Field not found | Verify field exists in project (may need to create) |
| Permission denied | Check gh auth has correct scopes |
| Item not in project | Add issue to project first with item-add |
This skill is called by:
issue-lifecycle - Status transitionsacceptance-criteria-verification - Verification field updatesissue-prerequisite - Initial field setupissue-decomposition - Adding sub-issues to projectThis skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.