JSON Output for Automation
JSON Output for Automation
gh-please supports JSON output for all list commands, enabling automation, scripting, and LLM integration.
Overview
All list commands support the --json flag following GitHub CLI patterns:
--json [fields] Output in JSON format with optional field selection
Features:
- ✅ GitHub CLI compatible syntax
- ✅ Field selection for minimal output
- ✅ Machine-readable for automation
- ✅ LLM-friendly structured data
- ✅ Pipe-friendly (clean output, no progress messages)
Basic Usage
Output All Fields
# Get all sub-issues as JSON
gh please issue sub-issue list 123 --json
Output:
[
{
"number": 124,
"title": "Implement authentication module",
"state": "OPEN",
"nodeId": "I_kwDOABC123",
"url": "https://github.com/owner/repo/issues/124"
},
{
"number": 125,
"title": "Add unit tests",
"state": "CLOSED",
"nodeId": "I_kwDODEF456",
"url": "https://github.com/owner/repo/issues/125"
}
]
Field Selection
Select specific fields to reduce output size:
# Get only number and title
gh please issue sub-issue list 123 --json number,title
Output:
[
{
"number": 124,
"title": "Implement authentication module"
},
{
"number": 125,
"title": "Add unit tests"
}
]
Available Fields by Command
Issue Sub-issues
gh please issue sub-issue list <issue> --json [fields]
Fields: number, title, state, nodeId, url
# Example: Get open sub-issues
gh please issue sub-issue list 123 --json number,title,state
Issue Dependencies
gh please issue dependency list <issue> --json [fields]
Fields: number, title, state, nodeId, url
# Example: Check blocking issues
gh please issue dependency list 200 --json
PR Review Threads
gh please pr review thread list <pr> --json [fields]
Fields: nodeId, isResolved, path, line, resolvedBy, firstCommentBody, url
# Example: Get unresolved threads
gh please pr review thread list 456 --unresolved-only --json nodeId,path,line
Issue Comments
gh please issue comment list <issue> --json [fields]
Fields: id, body, author, createdAt, updatedAt, url
# Example: Get comment IDs and authors
gh please issue comment list 789 --json id,author
PR Review Comments
gh please pr review comment list <pr> --json [fields]
Fields: id, body, author, path, line, createdAt, updatedAt, url
# Example: Get comments with file locations
gh please pr review comment list 456 --json id,path,line,body
Integration with jq
Process JSON output with jq for powerful filtering and transformation:
Filter by State
# Get only open sub-issues
gh please issue sub-issue list 123 --json | jq '.[] | select(.state == "OPEN")'
# Count open issues
gh please issue sub-issue list 123 --json | jq '[.[] | select(.state == "OPEN")] | length'
Extract Specific Data
# Get issue numbers only
gh please issue sub-issue list 123 --json number
# Get unresolved thread paths
gh please pr review thread list 456 --unresolved-only --json path | jq -r '.[].path' | sort -u
Complex Queries
# Get open issues with titles
gh please issue sub-issue list 123 --json | jq '.[] | select(.state == "OPEN") | {number, title}'
# Group comments by author
gh please issue comment list 789 --json | jq 'group_by(.author) | map({author: .[0].author, count: length})'
Use Cases
Shell Scripting
#!/bin/bash
# Check if all sub-issues are closed
sub_issues=$(gh please issue sub-issue list 123 --json state)
open_count=$(echo "$sub_issues" | jq '[.[] | select(.state == "OPEN")] | length')
if [ "$open_count" -eq 0 ]; then
echo "✅ All sub-issues closed!"
else
echo "⚠️ $open_count sub-issue(s) still open"
fi
CI/CD Integration
# GitHub Actions example
- name: Check blocking dependencies
run: |
blockers=$(gh please issue dependency list ${{ github.event.issue.number }} --json)
if [ "$(echo "$blockers" | jq 'length')" -gt 0 ]; then
echo "::error::Issue has blocking dependencies"
exit 1
fi
Python Integration
import json
import subprocess
# Get sub-issues as Python objects
result = subprocess.run(
["gh", "please", "issue", "sub-issue", "list", "123", "--json"],
capture_output=True,
text=True
)
sub_issues = json.loads(result.stdout)
for issue in sub_issues:
if issue["state"] == "OPEN":
print(f"TODO: #{issue['number']} - {issue['title']}")
LLM/AI Agent Integration
# Feed structured data to Claude/ChatGPT
gh please pr review thread list 456 --unresolved-only --json | \
jq '{threads: [.[] | {location: .path, line: .line, comment: .firstCommentBody}]}' | \
ai-agent --prompt "Summarize review feedback"
JSON Mode Behavior
When --json is used:
✅ Clean Output:
- Progress messages suppressed
- Only valid JSON printed to stdout
- Suitable for piping to other commands
✅ Error Handling:
- Errors still output to stderr
- Human-readable error messages
- Non-zero exit code on failure
✅ Field Selection:
- Filtering happens after data fetch
- Invalid field names silently ignored
- Empty selection returns all fields
Comparison with GitHub CLI
The --json flag follows GitHub CLI conventions:
| Feature | gh CLI | gh-please |
|---|---|---|
| Flag syntax | --json [fields] | --json [fields] ✅ |
| Field selection | Comma-separated | Comma-separated ✅ |
| Output format | JSON array/object | JSON array/object ✅ |
| Clean output | Yes | Yes ✅ |
| Pipe-friendly | Yes | Yes ✅ |
Example compatibility:
# Both commands use same pattern
gh issue list --json number,title,state
gh please issue sub-issue list 123 --json number,title,state
Migration from Markdown/XML (ADR 0002)
Previous plans included Markdown and XML output formats, but these were not implemented based on analysis showing:
- JSON is more accurately parsed by LLMs than Markdown/XML
- Industry standard for machine-readable output
- Better tooling ecosystem (jq, python json, etc.)
- Simpler implementation and maintenance
For details, see:
Examples
Daily Workflow
# Morning standup: Check my open tasks
gh please issue sub-issue list 100 --json | \
jq '.[] | select(.state == "OPEN") | "\(.number): \(.title)"'
# Before merge: Verify no unresolved threads
gh please pr review thread list 456 --unresolved-only --json | \
jq 'if length == 0 then "Ready to merge ✅" else "Unresolved threads ⚠️" end'
Reporting
# Generate completion report
echo "## Sub-Issue Progress"
total=$(gh please issue sub-issue list 123 --json | jq 'length')
closed=$(gh please issue sub-issue list 123 --json | jq '[.[] | select(.state == "CLOSED")] | length')
echo "Progress: $closed/$total ($(( closed * 100 / total ))%)"
Related
- Issue Management - Issue commands
- PR Management - PR commands
- GitHub Workflow - Complete workflow guide
- API Limitations - Known constraints