Skip to main content

Scripting

arc is designed for use in scripts, CI, and AI agents. All commands are non-interactive by default.


Output modes

Every command that produces data supports three output modes:

FlagOutputUse for
(default)Human-readable, coloredTerminal use
--plainBranch names only, one per lineShell scripts
--jsonStructured JSON to stdoutScripts, CI, agents

Status messages always go to stderr. --json output always goes to stdout. This separation makes it safe to pipe --json output without filtering out status messages.


arc status --json

arc status --json
{
"base": "main",
"prefix": "feat",
"current_branch": "feat/api",
"branches": [
{
"name": "feat/auth",
"index": 1,
"pr_number": 42,
"pr_url": "https://github.com/owner/repo/pull/42",
"pr_state": "OPEN",
"commits": 2,
"revision": 3,
"needs_rebase": false,
"is_current": false,
"is_merged": false
},
{
"name": "feat/api",
"index": 2,
"pr_number": 43,
"pr_url": "https://github.com/owner/repo/pull/43",
"pr_state": "OPEN",
"commits": 1,
"revision": 3,
"needs_rebase": false,
"is_current": true,
"is_merged": false
}
]
}

Common queries

# All branch names
arc status --plain

# Branches that need rebasing
arc status --json | jq '.branches[] | select(.needs_rebase) | .name'

# PR numbers for all branches
arc status --json | jq '.branches[] | {name, pr_number}'

# Is the current branch merged?
arc status --json | jq '.branches[] | select(.is_current) | .is_merged'

JSON schemas

Print the JSON Schema for any --json output:

arc schema status # schema for arc status --json
arc schema submit # schema for arc submit --json
arc schema analyze # schema for arc stack analyze --json

Use these schemas to validate arc output in typed pipelines.


Exit codes

Scripts should check exit codes, not parse stderr:

CodeMeaning
0Success
1General error
2Not in a stack (arc init needed)
3Rebase conflict (resolve + arc rebase --continue)
4GitHub API failure
5Invalid arguments
6Setup check failed (arc setup needed)
7Pre-hook returned non-zero
arc sync
case $? in
0) echo "Stack is current" ;;
3) echo "Conflict — resolve and run arc rebase --continue" ;;
*) echo "Error" ;;
esac

See Exit codes for the full table.


Dry run

arc sync -n # show the rebase plan without executing
arc push -n # show what would be pushed
arc submit -n # show what PRs would be created/updated
arc land -n # show what would be removed and restacked

Chain dry runs before committing:

arc sync -n && arc push -n && arc submit -n

Scripting patterns

Wait for CI before landing

#!/bin/bash
set -e
branch=$(git rev-parse --abbrev-ref HEAD)
pr=$(arc status --json | jq ".branches[] | select(.name == \"$branch\") | .pr_number")

# Wait for CI using gh
gh pr checks "$pr" --watch --fail-fast
arc land "$branch" -f

Check stack health in CI

# Fail if any branch needs a rebase
needs_rebase=$(arc status --json | jq '[.branches[] | select(.needs_rebase)] | length')
if [ "$needs_rebase" -gt 0 ]; then
echo "Stack out of date — run arc sync"
exit 1
fi

Bulk submit

arc push && arc submit --open