Use when you need to extract GitHub Project Board issues into structured JSON for downstream analysis and mapping
Extract all issues from a GitHub Project Board into structured JSON format for downstream analysis, mapping, or reporting.
This skill automates extraction of GitHub Project Board issues into a standardized JSON file (board-issues.json) that captures issue metadata, descriptions, and comments. The output integrates seamlessly with the map-tasks-to-issues skill to correlate board issues with requirement tasks.
Core principle: Project Boards contain curated collections of issues organized by workflow. This skill extracts those issues with full context (comments, timestamps, state) for structured analysis.
Use this skill when:
✅ You need to extract issues from a GitHub Project Board (not general repository issues)
✅ You want structured JSON output for downstream tools or analysis
✅ You plan to map board issues to requirements using map-tasks-to-issues
✅ You need issue metadata (timestamps, state, comments) preserved
✅ over time
Is this about a GitHub Project Board?
├─ YES → Use extract-board-issues
└─ NO → Do you need repo issues or requirements?
├─ Repo issues → Use `gh issue list`
├─ Requirements from PDF → Use extract-requirements
└─ Mapping tasks to issues → Use after extract-board-issues
digraph tool_selection {
"Need GitHub data?" [shape=diamond];
"What data type?" [shape=diamond];
"Use gh issue list" [shape=box, style=filled, fillcolor="#FFE5E5"];
"Use extract-requirements" [shape=box, style=filled, fillcolor="#E5F3FF"];
"Use extract-board-issues" [shape=box, style=filled, fillcolor="#E5FFE5"];
"Use map-tasks-to-issues" [shape=box, style=filled, fillcolor="#FFF5E5"];
"Already have board-issues.json?" [shape=diamond];
"Already have requirements.json?" [shape=diamond];
"Need GitHub data?" -> "What data type?" [label="yes"];
"What data type?" -> "Use extract-board-issues" [label="Project Board\nissues"];
"What data type?" -> "Use gh issue list" [label="Repo\nissues"];
"What data type?" -> "Already have board-issues.json?" [label="Plan to map\nto requirements"];
"Already have board-issues.json?" -> "Already have requirements.json?" [label="yes"];
"Already have requirements.json?" -> "Use map-tasks-to-issues" [label="both present"];
}
❌ You want all repository issues → Use gh issue list instead
❌ You're extracting requirements from PDFs → Use extract-requirements skill
❌ You want to directly map tasks to issues → Use extract-board-issues THEN map-tasks-to-issues
❌ You need to create or modify issues → Use gh CLI directly
❌ Your GitHub CLI isn't authenticated → Validate with gh auth status first
❌ You just want a quick issue count → Use gh issue list --search instead
| Task | Tool | Output | Use When |
|---|---|---|---|
| Extract Project Board | extract-board-issues | board-issues.json | Need curated board issues with full context |
| Extract all repo issues | gh issue list | CLI output | Need any/all issues from repository |
| Extract PDF requirements | extract-requirements | requirements.json | Parsing document-based requirements |
| Map issues to tasks | map-tasks-to-issues | task-issue-mapping.xlsx | Correlating board issues with requirements |
Before using this skill, ensure:
brew install ghgh auth login (if not already authenticated)gh repo view to verify--repo flagValidate prerequisites:
gh auth status # Check authentication
gh repo view # Verify repository access
gh project view # List available boards
Script automatically detects repository name and owner from current directory using gh repo view, or you provide via --repo and --owner flags.
Script checks gh auth status to ensure GitHub CLI is authenticated before proceeding.
Script retrieves all Project Board V2 items from the repository using GraphQL query.
--board flag to skip selectionScript executes paginated GraphQL queries to extract:
Script validates JSON schema compliance and saves to:
/Users/admin/dev/Reports/{repo-name}/board-issues.json
{
"repository": "owner/repo-name",
"board_name": "Project Board Name",
"extracted_at": "2024-01-20T15:30:00Z",
"total_issues": 42,
"issues": [
{
"number": 123,
"title": "Issue Title",
"body": "Issue description...",
"state": "OPEN",
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-20T15:30:00Z",
"comments": [
{
"author": "username",
"body": "Comment text...",
"created_at": "2024-01-16T09:00:00Z"
}
]
}
]
}
| Field | Type | Required | Notes |
|---|---|---|---|
| repository | string | Yes | Format: owner/repo-name |
| board_name | string | Yes | Exact board title from GitHub |
| extracted_at | ISO 8601 | Yes | UTC timestamp when extracted |
| total_issues | integer | Yes | Count of issues in array |
| issues | array | Yes | Array of issue objects |
| number | integer | Yes | GitHub issue number |
| title | string | Yes | Issue title (< 500 chars) |
| body | string | No | Issue description (markdown) |
| state | string | Yes | Must be "OPEN" or "CLOSED" |
| created_at | ISO 8601 | Yes | UTC timestamp |
| updated_at | ISO 8601 | Yes | UTC timestamp |
| comments | array | Yes | Array of comment objects (may be empty) |
| author | string | Yes | GitHub username |
| created_at | ISO 8601 | Yes | Comment timestamp (UTC) |
Validation: JSON must validate against this schema before saving. Script will fail with clear error if structure is invalid.
# Auto-detect repo, interactive board selection
python3 extract_board_issues.py
# Specify repo and owner (useful when not in git directory)
python3 extract_board_issues.py --repo goetz-kundenportal-phoenix --owner num42
# You will be presented with a list of all available boards to choose from
📋 Found 5 board(s):
1. Götz Kundenportal Phoenix - Formulardesigner
(17 items)
2. Götz: QMS (Inventur Erweiterung)
(9 items)
3. goetz kundenportal subcontractor feedback
(32 items)
4. goetz fms erweiterung EST-001284
(11 items)
5. Götz: Kundenportal
(218 items)
🎯 Select board number (1-5):
# Skip board selection, extract from board #5 directly
python3 extract_board_issues.py --repo goetz-kundenportal-phoenix --owner num42 --board 5
# Validate authentication & boards without extraction
python3 extract_board_issues.py --repo goetz-kundenportal-phoenix --owner num42 --dry-run
$ python3 extract_board_issues.py --repo goetz-kundenportal-phoenix --owner num42
🔍 Extract Board Issues
✅ Repository: goetz-kundenportal-phoenix
✅ Owner: num42
✅ GitHub authentication valid
📋 Found 5 board(s):
1. Götz Kundenportal Phoenix - Formulardesigner
(17 items)
2. Götz: QMS (Inventur Erweiterung)
(9 items)
3. goetz kundenportal subcontractor feedback
(32 items)
4. goetz fms erweiterung EST-001284
(11 items)
5. Götz: Kundenportal
(218 items)
🎯 Select board number (1-5): 5
📋 Selected board: Götz: Kundenportal
⏳ Extracting issues...
⏳ Page 1: Extracted 21 issues (total: 21)
⏳ Page 2: Extracted 5 issues (total: 26)
⏳ Page 3: Extracted 1 issues (total: 27)
⏳ Page 4: Extracted 7 issues (total: 34)
⏳ Page 5: Extracted 4 issues (total: 38)
✅ Found 38 issue(s)
✅ Extraction complete!
📁 Saved to: /Users/admin/dev/Reports/goetz-kundenportal-phoenix/board-issues.json
📊 Total issues: 38
This skill is PART OF A WORKFLOW CHAIN:
PDF Requirements Document
↓
extract-requirements
↓
requirements.json
↓
+--------+
| |
↓ ↓
GitHub Board (you manually create)
↓
extract-board-issues ← YOU ARE HERE
↓
board-issues.json
↓
+--------+
| |
↓ ↓
requirements.json + board-issues.json
↓
map-tasks-to-issues
↓
task-issue-mapping.xlsx (analysis ready)
requirements.json (what needs doing)board-issues.json (what you're tracking)Critical: These are sequential. You cannot skip or reorder them. Each output feeds the next tool's input.
| Mistake | Why It Fails | Fix |
|---|---|---|
"I'll use gh api directly" | Misses board abstraction; gets all repo issues instead of board subset | Use this skill; it handles board-specific GraphQL query |
| "I'll use extract-requirements here" | Requirements ≠ Board issues; wrong input source | Use this skill; extract-requirements is for PDFs |
| "JSON format doesn't matter" | Breaks downstream mapping (map-tasks-to-issues expects exact schema) | Follow output schema exactly; script validates |
| "I'll skip validation, save time" | Silent failures; corrupted mapping later | Script validates automatically; fast anyway |
| "I'll just extract all repo issues" | Includes issues outside the board scope; polluted data | This skill filters by board; use it |
| "Timestamps don't need ISO 8601" | Parsing breaks in map-tasks-to-issues | Script enforces ISO 8601 UTC format |
| "I can fix the format later" | Downstream tools won't accept malformed JSON | Fix BEFORE extraction, not after |
| "I don't need to check auth first" | Script fails silently on permission denied | Validate with gh auth status upfront |
⚠️ "I'm not sure if I should use this or extract-requirements"
→ Review the Integration with Other Skills section above
⚠️ "The output format doesn't match examples"
→ Script validation catches this; don't ignore errors
⚠️ "GitHub auth is probably already configured"
→ Always run gh auth status first; it's 1 command
⚠️ "I'm extracting everything manually"
→ Use this skill instead; it's automated and reliable
⚠️ "gh api is taking too long"
→ Board might have 1000+ issues; check board size first
⚠️ "I'm not sure which board to select"
→ Script filters by repo name; shows all relevant boards
⚠️ "Comments aren't in the output"
→ Check that board issues actually have comments; empty comments array is OK
⚠️ "The timestamp format is different from examples"
→ Verify timezone; timestamps must be UTC in ISO 8601 format
A: Yes, if gh CLI is configured for Enterprise. The GraphQL API is the same.
A: No, one board per execution. Run the script multiple times for different boards, or automate with a wrapper script.
A: Script will warn if extraction times out. GitHub GraphQL has limits. Consider archiving old issues or splitting into smaller boards.
A: No, only issues currently in the board are extracted. Deleted issues are unavailable via GraphQL API.
gh authentication expires?A: Script will fail with clear error. Re-authenticate: gh auth login
A: Yes, use GH_TOKEN environment variable. Authenticate locally first: gh auth login, then use token in CI.
A: As needed. No duplicate detection—each extraction overwrites previous. Consider timestamped filenames if you need history.
A: GraphQL queries paginate at 100 items; script handles pagination. If fewer items, check that board items are issues (not all board items are issues).
A: Yes, but downstream tools expect exact schema. Validate with test_extract_board_issues.py if you modify.
A: Script respects your GitHub permissions. If you can see the board in GitHub, script can extract it.
| "But I thought..." | Reality | What This Means |
|---|---|---|
| Tools are interchangeable | Each tool has specific input source and format | Use extract-board-issues ONLY for Project Boards |
| I don't need to check auth | Script needs GitHub access; unauthed calls fail | Validate auth before running |
| Output format is flexible | Downstream tools expect exact schema | Follow schema exactly; script validates |
| I can guess which board | Boards have similar names; picking wrong wastes time | Script shows all boards clearly |
| Comments aren't important | Comments are critical context for mapping | Script extracts all comments automatically |
| Timestamps can be any format | Downstream tools parse ISO 8601 only | Script enforces ISO 8601 UTC |
| I'll fix problems manually | Manual fixes are slower and error-prone | Let script handle validation |
| One tool can do all steps | Each skill specializes in one input source | Use all three skills in sequence |
Cause: Not in a git directory or no remote configured
Fix:
# Option 1: Change to git directory
cd /path/to/git/repo
# Option 2: Specify repo with --repo flag
python3 extract_board_issues.py --repo goetz-kundenportal-phoenix
# Option 3: Configure remote
git remote add origin https://github.com/owner/repo.git
Cause: gh CLI not configured
Fix:
gh auth login
# Follow prompts to authenticate
python3 extract_board_issues.py # Try again
Cause: Insufficient permissions for board access
Fix:
# Verify access to the repository
gh repo view goetz-kundenportal-phoenix
# Re-authenticate with proper permissions
gh auth logout
gh auth login
Cause: Organization has no Project Boards, or permission denied
Fix:
# Check boards exist
gh project view
# If empty, create a board in GitHub first
# Then run extraction again
Cause: Board exists but has no issues
Fix: This is normal. Script will create board-issues.json with total_issues: 0 and empty issues array. This is valid output.
Cause: Script extracts all comments, but some may be deleted or private
Fix: This is expected. Comments array contains only accessible comments. Empty array is valid.
/Users/admin/dev/Reports/{repo}/)✅ Script no longer hangs - Added 30-60 second timeouts on all GraphQL queries
✅ User must select board - Script now prompts to choose before extracting (no silent defaults)
✅ Better error messages - Clear feedback on what's happening at each step
✅ Progress visibility - Shows page count and running issue total during extraction
✅ Pagination handling - Properly handles boards with 100+ issues across multiple pages
✅ Flexible repo detection - Works with --owner flag when not in git directory
✅ Comment formatting - Properly cleans up JSON structure for downstream tools
Before (v2.0):
Script hangs indefinitely trying to fetch boards
No board selection shown
Unclear error messages
After (v2.1):
⏳ Fetching project boards for num42/goetz-kundenportal-phoenix...
✅ Found 5 board(s)
📋 Found 5 board(s):
1. Götz Kundenportal Phoenix - Formulardesigner (17 items)
2. Götz: QMS (Inventur Erweiterung) (9 items)
3. goetz kundenportal subcontractor feedback (32 items)
4. goetz fms erweiterung EST-001284 (11 items)
5. Götz: Kundenportal (218 items)
🎯 Select board number (1-5): 5
python3 extract_board_issues.py --help for all optionstest_extract_board_issues.py to validate functionality