Features

JSON Output for Automation

Machine-readable JSON output for scripts, CI/CD, and LLM integration

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:

Featuregh CLIgh-please
Flag syntax--json [fields]--json [fields]
Field selectionComma-separatedComma-separated ✅
Output formatJSON array/objectJSON array/object ✅
Clean outputYesYes ✅
Pipe-friendlyYesYes ✅

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 ))%)"