10 KiB
name, description, tools, model
| name | description | tools | model |
|---|---|---|---|
| gh-item-add | Add issues, PRs, or draft items to projects with field assignment | Bash, AskUserQuestion, TodoWrite | inherit |
Add Item to GitHub Project
This command guides you through adding items to GitHub Projects with proper field configuration.
Instructions
Step 1: Identify Target Project
Ask the user which project to add items to:
# List available projects using Python for safe JSON parsing
gh project list --owner "@me" --format json | python3 -c "
import json, sys
projects = json.load(sys.stdin)
for p in projects:
print(f\"#{p.get('number')} - {p.get('title')}\")
"
# For organization
gh project list --owner "org-name" --format json | python3 -c "
import json, sys
projects = json.load(sys.stdin)
for p in projects:
print(f\"#{p.get('number')} - {p.get('title')}\")
"
Get the project ID:
PROJECT_ID=$(gh project list --owner "@me" --format json | python3 -c "
import json, sys
projects = json.load(sys.stdin)
target_number = <number> # Replace with actual number
for p in projects:
if p.get('number') == target_number:
print(p.get('id', ''))
break
")
Step 2: Determine Item Type
Ask the user what type of item to add:
- Existing Issue: Add issue from this or another repository
- Existing PR: Add pull request from this or another repository
- Draft Item: Create new draft item (no issue created)
Step 3A: Add Existing Issue or PR
If adding existing issue/PR:
-
Get the URL or number:
- Ask user for issue/PR number or full URL
- If just number provided, construct URL:
https://github.com/<owner>/<repo>/issues/<number>
-
Add to project:
gh project item-add <project-number> --owner "<owner>" --url <issue-or-pr-url> -
Capture item ID from output or query:
ITEM_ID=$(gh project item-list <project-number> --owner "@me" --format json --limit 100 | python3 -c "
import json, sys data = json.load(sys.stdin) target_url = '' # Replace with actual URL for item in data.get('items', []): if item.get('content', {}).get('url') == target_url: print(item.get('id', '')) break ")
### Step 3B: Create Draft Item
If creating draft item:
1. **Get title and body**:
- Ask user for item title (required)
- Ask user for item description/body (optional)
2. **Create draft**:
```bash
DRAFT_RESPONSE=$(gh project item-create <project-number> --owner "@me" \
--title "<title>" \
--body "<body>" \
--format json)
ITEM_ID=$(echo "$DRAFT_RESPONSE" | python3 -c "import json, sys; print(json.load(sys.stdin).get('id', ''))")
- Note: Draft items can be converted to issues later when ready
Step 4: Get Project Fields
Fetch available fields for the project:
FIELDS=$(gh project field-list <project-number> --owner "@me" --format json)
# Show fields to user using Python
echo "$FIELDS" | python3 -c "
import json, sys
fields = json.load(sys.stdin)
for field in fields:
print(f\"- {field.get('name')} ({field.get('dataType')})\")
"
Step 5: Set Initial Field Values
Ask user which fields to set initially (optional but recommended):
Set Status
# Get Status field ID and options using Python
echo "$FIELDS" > /tmp/gh_fields.json
STATUS_FIELD=$(python3 -c "
import json
with open('/tmp/gh_fields.json') as f:
fields = json.load(f)
for field in fields:
if field.get('name') == 'Status':
print(field.get('id', ''))
break
")
# Show options to user
python3 -c "
import json
with open('/tmp/gh_fields.json') as f:
fields = json.load(f)
for field in fields:
if field.get('name') == 'Status':
for option in field.get('options', []):
print(f\"{option.get('name')}: {option.get('id')}\")
break
"
# Then update (after user selects option):
gh project item-edit --id $ITEM_ID --project-id $PROJECT_ID \
--field-id $STATUS_FIELD --single-select-option-id <option-id>
Set Priority
PRIORITY_FIELD=$(python3 -c "
import json
with open('/tmp/gh_fields.json') as f:
fields = json.load(f)
for field in fields:
if field.get('name') == 'Priority':
print(field.get('id', ''))
break
")
# Show options
python3 -c "
import json
with open('/tmp/gh_fields.json') as f:
fields = json.load(f)
for field in fields:
if field.get('name') == 'Priority':
for option in field.get('options', []):
print(f\"{option.get('name')}: {option.get('id')}\")
break
"
# Update after selection
gh project item-edit --id $ITEM_ID --project-id $PROJECT_ID \
--field-id $PRIORITY_FIELD --single-select-option-id <option-id>
Set Other Fields (as applicable)
Number field (e.g., Story Points):
gh project item-edit --id $ITEM_ID --project-id $PROJECT_ID \
--field-id <field-id> --number <value>
Date field (e.g., Due Date):
gh project item-edit --id $ITEM_ID --project-id $PROJECT_ID \
--field-id <field-id> --date "YYYY-MM-DD"
Text field (e.g., Owner):
gh project item-edit --id $ITEM_ID --project-id $PROJECT_ID \
--field-id <field-id> --text "<value>"
Iteration field (e.g., Sprint):
# Get iteration ID (complex, may need GraphQL)
gh project item-edit --id $ITEM_ID --project-id $PROJECT_ID \
--field-id <field-id> --iteration-id <iteration-id>
Step 6: Verify Addition
Confirm the item was added successfully:
# View the item in the project using Python
gh project item-list <project-number> --owner "@me" --format json --limit 100 | python3 -c "
import json, sys
data = json.load(sys.stdin)
target_id = '$ITEM_ID'
for item in data.get('items', []):
if item.get('id') == target_id:
content = item.get('content', {})
result = {
'title': content.get('title'),
'type': content.get('type'),
'url': content.get('url'),
'fieldValues': item.get('fieldValues', [])
}
print(json.dumps(result, indent=2))
break
"
Step 7: Provide Summary
Generate a clear summary for the user:
## Item Added Successfully!
### Item Details
- **Title**: [Item Title]
- **Type**: [Issue/PR/Draft]
- **URL**: [URL if applicable]
- **Added to**: [Project Name] (#[Project Number])
### Initial Field Values
- Status: [Value]
- Priority: [Value]
- [Other fields set...]
### Next Steps
1. **View in Project**: [Project URL]
2. **Update Additional Fields**: Use project UI or:
- Set iteration/sprint
- Add estimation (story points)
- Assign team member
3. **Start Work**: Move to "In Progress" when ready
4. **Link to PR**: When you create a PR for this issue
### Quick Commands
- View project: `/gh-project-view`
- Update fields: Use project-manager agent
- View item details: `gh issue view <number>` or `gh pr view <number>`
Batch Adding Items
If user wants to add multiple items:
-
Get list of items to add:
- From issue search:
gh issue list --repo owner/repo --label feature --limit 20 - From PR list:
gh pr list --repo owner/repo --limit 20 - From user input: Array of issue numbers
- From issue search:
-
Loop through items:
for ISSUE_NUM in $ISSUES; do ISSUE_URL="https://github.com/<owner>/<repo>/issues/$ISSUE_NUM" gh project item-add <project-number> --owner "@me" --url $ISSUE_URL echo "Added issue #$ISSUE_NUM" done -
Set common fields (if requested):
- Get all newly added item IDs
- Apply same field values to all
- Report batch results
Smart Field Assignment
Suggest field values based on context:
Auto-Priority from Issue Labels
# If issue has 'critical' or 'blocking' label → P0
# If issue has 'bug' or 'urgent' label → P1
# If issue has 'enhancement' label → P2
# Default → P3
LABELS=$(gh issue view <number> --json labels --jq '.labels[].name')
if echo $LABELS | grep -q "critical\|blocking"; then
SUGGESTED_PRIORITY="P0"
elif echo $LABELS | grep -q "bug\|urgent"; then
SUGGESTED_PRIORITY="P1"
else
SUGGESTED_PRIORITY="P2"
fi
Auto-Status from Issue State
# If issue is OPEN → Backlog or Todo
# If PR is OPEN → In Review
# If closed → Done or Archived
ISSUE_STATE=$(gh issue view <number> --json state --jq '.state')
if [ "$ISSUE_STATE" = "OPEN" ]; then
SUGGESTED_STATUS="Backlog"
else
SUGGESTED_STATUS="Done"
fi
Important Notes
- Item IDs vs Issue Numbers: Item IDs are project-specific identifiers, different from issue numbers
- Field IDs: Must fetch field IDs for each project, they're not universal
- Option IDs: Single-select fields require option IDs, not option names
- Permissions: Ensure 'project' scope is enabled:
gh auth status - Rate Limits: When batch adding, respect API rate limits (pause if needed)
Definition of Done
- Target project identified
- Item type determined (issue/PR/draft)
- Item added to project successfully
- Item ID captured
- Initial field values set (at minimum: Status, Priority)
- Addition verified
- Comprehensive summary provided
- Next steps documented
Error Handling
- If project not found: List available projects, let user choose
- If issue/PR not found: Verify URL/number, check repository access
- If item already in project: Report duplicate, ask if should update fields
- If field update fails: Verify field ID and option ID are correct
- If permission denied: Check project access and gh auth scopes
Special Cases
Converting Draft to Issue
When user is ready to convert draft to real issue:
# This requires GraphQL API call (gh CLI doesn't have direct command)
# Provide instructions for manual conversion via GitHub UI
# Or use gh api graphql with mutation
Linking PR to Issue Item
When adding a PR that closes an issue already in the project:
- Note the relationship
- Suggest linking them in descriptions
- Consider setting up automation for status sync
Cross-Repository Items
When adding items from different repositories:
- Verify project is linked to target repository:
gh project link - If not linked, link it first
- Then add items
Remember: Proper field assignment at addition time saves triage work later. Take the extra minute to set Status and Priority correctly from the start.