rollercoaster-dev

board-manager

@rollercoaster-dev/board-manager
rollercoaster-dev
0
0 forks
Updated 1/6/2026
View on GitHub

Manage GitHub Project board items - add issues, update status, move between columns. Use when user asks to add issues to board, change status, or organize the project.

Installation

$skills install @rollercoaster-dev/board-manager
Claude Code
Cursor
Copilot
Codex
Antigravity

Details

Path.claude/skills/board-manager/SKILL.md
Branchmain
Scoped Name@rollercoaster-dev/board-manager

Usage

After installing, this skill will be available to your AI coding assistant.

Verify installation:

skills list

Skill Instructions


name: board-manager description: Manage GitHub Project board items - add issues, update status, move between columns. Use when user asks to add issues to board, change status, or organize the project. allowed-tools: Bash, Read

Board Manager Skill

Purpose

Add issues to the project board and update their status. This skill has write permissions for board operations.

When Claude Should Use This

  • User asks "add this issue to the board"
  • User asks "move #X to In Progress"
  • User asks "update status of issue"
  • User asks "put this in the backlog"
  • After creating a new issue (auto-add to board)
  • After completing work (move to Done)

Project Board Configuration

Project: Monorepo Development (#11) URL: https://github.com/orgs/rollercoaster-dev/projects/11

IDs Reference

ResourceID
Project IDPVT_kwDOB1lz3c4BI2yZ
Status Field IDPVTSSF_lADOB1lz3c4BI2yZzg5MUx4

Status Option IDs

StatusOption IDDescription
Backlog8b7bb58fNot ready / needs triage
Next266160c2Ready to pick up
In Progress3e320f16Currently being worked on
Blocked51c2af7bPR created, awaiting review
Done56048761Merged to main

Helper Functions

These reusable functions simplify board operations:

Get Item ID for Issue

get_item_id_for_issue() {
  local issue_number=$1
  gh api graphql -f query='
    query {
      organization(login: "rollercoaster-dev") {
        projectV2(number: 11) {
          items(first: 100) {
            nodes {
              id
              content { ... on Issue { number } }
            }
          }
        }
      }
    }' | jq -r ".data.organization.projectV2.items.nodes[] | select(.content.number == $issue_number) | .id"
}

Update Board Status (with validation)

update_board_status() {
  local item_id=$1
  local option_id=$2
  local status_name=$3

  RESULT=$(gh api graphql \
    -f projectId="PVT_kwDOB1lz3c4BI2yZ" \
    -f itemId="$item_id" \
    -f fieldId="PVTSSF_lADOB1lz3c4BI2yZzg5MUx4" \
    -f optionId="$option_id" \
    -f query='mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $optionId: String!) {
      updateProjectV2ItemFieldValue(input: {
        projectId: $projectId
        itemId: $itemId
        fieldId: $fieldId
        value: { singleSelectOptionId: $optionId }
      }) {
        projectV2Item { id }
      }
    }' 2>&1)

  # Validate response - check for GraphQL errors
  if echo "$RESULT" | jq -e '.errors | length > 0' > /dev/null 2>&1; then
    echo "ERROR: Board update failed (GraphQL error)"
    return 1
  elif echo "$RESULT" | jq -e '.data.updateProjectV2ItemFieldValue.projectV2Item.id' > /dev/null 2>&1; then
    echo "Board Update: Issue moved to '$status_name'"
    return 0
  else
    echo "ERROR: Board update failed (unexpected response)"
    return 1
  fi
}

Commands

Add Issue to Project Board

gh project item-add 11 --owner rollercoaster-dev --url https://github.com/rollercoaster-dev/monorepo/issues/<number>

Get Item ID for an Issue

# Using GraphQL (more reliable - doesn't require read:org scope)
gh api graphql -f query='
  query {
    organization(login: "rollercoaster-dev") {
      projectV2(number: 11) {
        items(first: 100) {
          nodes {
            id
            content { ... on Issue { number } }
          }
        }
      }
    }
  }' | jq -r '.data.organization.projectV2.items.nodes[] | select(.content.number == <issue-number>) | .id'

Update Issue Status

# Use GraphQL mutation (avoids OAuth scope issues with gh project item-edit)
gh api graphql \
  -f projectId="PVT_kwDOB1lz3c4BI2yZ" \
  -f itemId="<item-id>" \
  -f fieldId="PVTSSF_lADOB1lz3c4BI2yZzg5MUx4" \
  -f optionId="<option-id>" \
  -f query='mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $optionId: String!) {
    updateProjectV2ItemFieldValue(input: {
      projectId: $projectId
      itemId: $itemId
      fieldId: $fieldId
      value: { singleSelectOptionId: $optionId }
    }) {
      projectV2Item { id }
    }
  }'

Remove Issue from Project

gh project item-delete 11 --owner rollercoaster-dev --id <item-id>

Workflow Examples

Add New Issue and Set Status

# 1. Add to project using GraphQL mutation
ISSUE_NODE_ID=$(gh issue view 123 --json id -q .id)
gh api graphql -f query='
  mutation($projectId: ID!, $contentId: ID!) {
    addProjectV2ItemById(input: {
      projectId: $projectId
      contentId: $contentId
    }) { item { id } }
  }' -f projectId="PVT_kwDOB1lz3c4BI2yZ" -f contentId="$ISSUE_NODE_ID" 2>/dev/null || true

# 2. Get item ID and set status using helper functions
ITEM_ID=$(get_item_id_for_issue 123)
update_board_status "$ITEM_ID" "266160c2" "Next"

Move Issue to In Progress

# Using helper functions
ITEM_ID=$(get_item_id_for_issue <issue-number>)
update_board_status "$ITEM_ID" "3e320f16" "In Progress"

Move Issue to Blocked (after PR creation)

ITEM_ID=$(get_item_id_for_issue <issue-number>)
update_board_status "$ITEM_ID" "51c2af7b" "Blocked"

Move Issue to Done (after merge)

ITEM_ID=$(get_item_id_for_issue <issue-number>)
update_board_status "$ITEM_ID" "56048761" "Done"

Status Mapping

ActionStatusOption ID
New issue, not readyBacklog8b7bb58f
Ready to workNext266160c2
Started workIn Progress3e320f16
PR createdBlocked51c2af7b
PR mergedDone56048761

Output Format

After operations, confirm:

**Board Update:** Issue #X moved to [Status]
**URL:** https://github.com/orgs/rollercoaster-dev/projects/11

Query Current IDs (if they change)

gh api graphql -f query='
query {
  organization(login: "rollercoaster-dev") {
    projectV2(number: 11) {
      id
      field(name: "Status") {
        ... on ProjectV2SingleSelectField {
          id
          options { id name }
        }
      }
    }
  }
}'