JSON Output & Scripting

Every major SDF command supports a --json flag that outputs structured JSON instead of human-readable terminal output. This enables integration with CI pipelines, shell scripts, and AI agents.


Commands with JSON support

CommandFlagNotes
sdf new--json
sdf branch--json
sdf status--json
sdf sync--jsonImplies --yes; aborts on conflict
sdf merge--jsonRequires --yes
sdf pr--json
sdf move--json
sdf fetch--jsonAuto-selects if one stack found
sdf switch--json
sdf config show--json
sdf config set--json
sdf doctor--json

Output shapes

sdf new --json

{
  "stack": "my-feature",
  "base": "main",
  "branch": "my-feature/my-feature",
  "pushed": true
}

sdf branch --json

{
  "branch": "my-feature/api-layer",
  "stack": "my-feature",
  "parent": "my-feature/db-schema"
}

sdf status --json

{
  "stack": "my-feature",
  "base": "main",
  "current_branch": "my-feature/api-layer",
  "nodes": [
    {
      "branch": "my-feature/db-schema",
      "pr": 142,
      "status": "merged",
      "sync_state": "in_sync"
    },
    {
      "branch": "my-feature/api-layer",
      "pr": 143,
      "status": "open",
      "sync_state": "needs_sync",
      "commits_ahead": 3,
      "is_current": true,
      "ci_status": "success",
      "review_status": "approved",
      "mergeable": "mergeable"
    }
  ],
  "needs_sync": ["my-feature/api-layer"]
}

sdf sync --json

{
  "stack": "my-feature",
  "base": "main",
  "branches": [
    {
      "branch": "my-feature/db-schema",
      "pr": 142,
      "action": "merged"
    },
    {
      "branch": "my-feature/api-layer",
      "pr": 143,
      "action": "rebased",
      "pushed": true,
      "base_updated": true
    }
  ],
  "pr_updates": [
    { "pr": 143, "field": "title", "status": "updated" }
  ]
}

Possible action values: "merged", "rebased", "in_sync", "failed", "blocked".

sdf merge --json

{
  "stack": "my-feature",
  "merged_pr": 142,
  "merged_branch": "my-feature/db-schema",
  "method": "squash",
  "base": "main",
  "retargeted_pr": 143,
  "remaining": 2
}

sdf pr --json

{
  "number": 145,
  "url": "https://github.com/org/repo/pull/145",
  "title": "feat(my-feature): add API endpoints"
}

sdf move --json

{
  "source": "my-feature/api-layer",
  "target": "my-feature/db-schema",
  "commits": ["abc1234", "def5678"]
}

sdf fetch --json

{
  "stack": "my-feature",
  "base": "main",
  "nodes": [
    { "branch": "my-feature/db-schema", "pr": 142 },
    { "branch": "my-feature/api-layer", "pr": 143 }
  ],
  "action": "registered"
}

Possible action values: "registered", "reconciled", "up_to_date".

sdf switch --json

{
  "branch": "my-feature/api-layer",
  "stack": "my-feature",
  "layer": 2,
  "total": 3
}

sdf doctor --json

{
  "dependencies": [
    { "name": "git", "found": true, "version": "2.43.0", "path": "/usr/bin/git", "required": true },
    { "name": "gh", "found": true, "version": "2.40.1", "path": "/usr/bin/gh", "required": false },
    { "name": "claude", "found": false, "required": false }
  ],
  "ok": true
}

Scripting examples

Check if sync is needed

needs_sync=$(sdf status --json | jq -r '.needs_sync | length')
if [ "$needs_sync" -gt 0 ]; then
  echo "Stack needs sync"
  sdf sync -y
fi

Get the current branch's PR number

pr=$(sdf status --json | jq -r '.nodes[] | select(.is_current) | .pr')
echo "Current PR: #$pr"

Check all CI statuses

sdf status --json | jq -r '.nodes[] | select(.status == "open") | "\(.branch): CI=\(.ci_status) Review=\(.review_status)"'

Merge the head PR and report

result=$(sdf merge --json --yes)
merged=$(echo "$result" | jq -r '.merged_pr')
remaining=$(echo "$result" | jq -r '.remaining')
echo "Merged PR #$merged, $remaining remaining"

Gotchas

sdf sync --json aborts on conflict. Since JSON mode cannot display the interactive conflict resolution menu, any rebase conflict causes an immediate abort. The error is included in the JSON output as the error field. Run sdf sync without --json to resolve conflicts interactively.

sdf merge --json requires --yes. The merge command requires explicit confirmation in JSON mode since it performs a destructive operation.

sdf fetch --json with multiple stacks. If sdf fetch discovers multiple stacks and --json is specified, it returns an error. Use --base to narrow the results to one stack.

Errors in JSON output. When a command fails in JSON mode, the error is included in the JSON output as an error field rather than being printed to stderr. The command still exits with code 0 so the JSON can be parsed.