gh-arc
🚧 Fork in progress, expect some dust 🚧

gh-arc is a github cli extension that implements an opinionated trunk-based development workflow with Github, built upon the great traditions of tools like phacility/arcanist and phorge/arcanist.
[!TIP]
Check out this DORA Trunk-based development page if, by any chance, this is the first time you're hearing about it and interested to learn more about about this methodology.
Installation
Install the latest release using the GitHub CLI:
gh extension install serpro69/gh-arc
Installation from Source
git clone https://github.com/serpro69/gh-arc.git
cd gh-arc && go build . && gh extension install .
[!TIP]
Clone the repo to a permanent location, gh cli will alias the binary when you run gh extension install . command.
Usage
Authentication
gh-arc requires GitHub CLI authentication with specific OAuth scopes to access user information and repository data. The required additional scopes are:
user:email - Access to user email addresses
read:user - Read user profile data
Setting up authentication
If you're already logged in to GitHub CLI, refresh your token with the additional required scopes:
gh auth refresh --scopes "user:email,read:user"
If you're not logged in, authenticate with the additional required scopes:
gh auth login --scopes "user:email,read:user"
Alternatively, you can provide your own personal access token:
echo "your-token-here" | gh auth login --with-token
[!NOTE]
Personal access tokens must include the user:email and read:user scopes, in addition to the scopes needed by gh cli itself, to work with gh-arc.
To verify your authentication and scopes:
gh arc auth
Commands Overview
gh-arc is a "wrapper" that sits on top of other tools: Github (naturally, being a github-cli extension) and Linear (if you use it for issue management instead of Github), but also linters, formatters, unit test frameworks and others. It provides a simple command-line API to manage code review and some related revision control operations.
For a detailed list of all available commands, run:
gh arc help
For detailed information about a specific command, run:
gh arc help <command>
In a gist, gh arc allows you to do things like:
- get detailed help about available commands with
gh arc help
- create a new, short-lived, feature branch from an up-to-date
origin/HEAD with gh arc work
- send your code to Github for review with
gh arc diff
- show pending revision information with
gh arc list
- find likely reviewers for a change with
gh arc cover
- apply changes in a revision to the working copy with
gh arc patch
- download a patch from Github with
gh arc export
- update Git commit messages after review with
gh arc amend
- push changes with
gh arc land
- view enhanced information about Git branches with
gh arc branch
Once you've configured lint and unit test integration, you can also:
- check your code for syntax and style errors with
gh arc lint
- run unit tests that cover your changes with
gh arc unit
This extension also integrates with other tools:
- create and view github gists with
gh arc gist
It has some advanced features as well, you can:
- enable tab completion with
gh arc completion
- ...or extend the extension and add new commands
Shell Completion
Github CLI does not currently support shell completion for extensions (See cli/cli#5309), but even if it did, who wants to type gh arc <TAB> <TAB> <TAB> ...that's just too much work if you ask me 🤷
So we've come up with a "simple as a rock" (is that a thing? 🤔) solution to both of the above problems 💡
-
Find out where github cli installs extensions on your machine. On Linux (and maybe on Mac), it's usually under ~/.local/share/gh/extensions.
-
Create a simple arc shell script file with the following contents:
#!/usr/bin/env bash
# Simple wrapper to enable completions for 'gh-arc' extension
gh arc "$@"
-
Make it executable and place it on your PATH.
-
Get the completion script for your shell from the releases page. Don't forget to source it or whatever, you know what to do.
-
Then try typing arc <TAB> ...you should see the command completion for the extension; and as an added bonus, you've shortened the overall gh ... command as well... 🤯 Who said ingenious can't be simple?
-
Profit... ⏱️
Configuration
gh-arc can be configured using either JSON or YAML configuration files. The extension looks for configuration files in the following locations (in order of precedence):
- Current directory:
./.arc.json, ./.arc.yaml, or ./.arc.yml
- User config:
~/.config/gh-arc/.arc.json, ~/.config/gh-arc/.arc.yaml, or ~/.config/gh-arc/.arc.yml
- System-wide:
/etc/gh-arc/.arc.json, /etc/gh-arc/.arc.yaml, or /etc/gh-arc/.arc.yml
Within each directory, JSON files take precedence over YAML files (.arc.json > .arc.yaml > .arc.yml).
Create a .arc.json or .arc.yaml file in your project root or user config directory:
JSON format (.arc.json):
{
"github": {
"defaultBranch": "main",
"defaultReviewers": [],
"autoAssignReviewer": false
},
"diff": {
"createAsDraft": true,
"autoUpdatePR": true,
"includeCommitMessages": true,
"enableStacking": true,
"defaultBase": "",
"showStackingWarnings": true,
"templatePath": "",
"requireTestPlan": true,
"linearEnabled": false,
"linearDefaultProject": ""
},
"land": {
"defaultMergeMethod": "squash",
"deleteLocalBranch": true,
"deleteRemoteBranch": true,
"requireApproval": true,
"requireCI": true
},
"output": {
"verbose": false,
"quiet": false,
"json": false,
"color": true
}
}
YAML format (.arc.yaml or .arc.yml):
github:
defaultBranch: main
defaultReviewers: []
autoAssignReviewer: false
diff:
createAsDraft: true
autoUpdatePR: true
includeCommitMessages: true
enableStacking: true
defaultBase: ""
showStackingWarnings: true
templatePath: ""
requireTestPlan: true
linearEnabled: false
linearDefaultProject: ""
land:
defaultMergeMethod: squash
deleteLocalBranch: true
deleteRemoteBranch: true
requireApproval: true
requireCI: true
output:
verbose: false
quiet: false
json: false
color: true
Configuration Options
GitHub Settings
github.defaultBranch (string, default: "main"): The default base branch for new PRs
github.defaultReviewer (string, default: ""): Default reviewer to assign to PRs
github.autoAssignReviewer (bool, default: false): Automatically assign the default reviewer to new PRs
Diff (PR Creation) Settings
diff.createAsDraft (bool, default: true): Create PRs as drafts by default
diff.autoUpdatePR (bool, default: true): Automatically update existing PRs when running gh arc diff
diff.includeCommitMessages (bool, default: true): Include commit messages in PR description
diff.enableStacking (bool, default: true): Enable automatic stacked PR detection
diff.defaultBase (string, default: ""): Force a specific base branch (empty = auto-detect)
diff.showStackingWarnings (bool, default: true): Show warnings when dependent PRs exist
diff.templatePath (string, default: ""): Path to custom PR template (empty = use built-in)
diff.requireTestPlan (bool, default: true): Require test plan in PR template
diff.linearEnabled (bool, default: false): Enable Linear issue integration
diff.linearDefaultProject (string, default: ""): Default Linear project for issue references
Land (Merge) Settings
land.defaultMergeMethod (string, default: "squash"): Default merge method (squash, merge, or rebase)
land.deleteLocalBranch (bool, default: true): Delete local branch after landing
land.deleteRemoteBranch (bool, default: true): Delete remote branch after landing
land.requireApproval (bool, default: true): Require PR approval before landing
land.requireCI (bool, default: true): Require CI checks to pass before landing
Output Settings
output.verbose (bool, default: false): Enable verbose output
output.quiet (bool, default: false): Suppress non-essential output
output.json (bool, default: false): Output results in JSON format
output.color (bool, default: true): Enable colored output
Environment Variables
All configuration options can be overridden using environment variables with the GHARC_ prefix. Use underscores to separate nested keys:
# Override diff.createAsDraft
export GHARC_DIFF_CREATEASDRAFT=false
# Override github.defaultBranch
export GHARC_GITHUB_DEFAULTBRANCH=master
# Override land.defaultMergeMethod
export GHARC_LAND_DEFAULTMERGEMETHOD=merge
Advanced Configuration
Test Runners
Configure custom test runners in your .arc.json:
{
"test": {
"runners": [
{
"name": "go-test",
"command": "go",
"args": ["test", "./..."],
"workingDir": "",
"timeout": "5m"
}
]
}
}
Lint Runners
Configure custom linters:
{
"lint": {
"runners": [
{
"name": "golangci-lint",
"command": "golangci-lint",
"args": ["run"],
"workingDir": "",
"autoFix": true
}
],
"megaLinter": {
"enabled": "auto",
"config": ".mega-linter.yml",
"fixIssues": false
}
}
}
Example: Minimal Configuration
For most projects, you only need to override a few settings:
JSON (.arc.json):
{
"diff": {
"createAsDraft": false,
"requireTestPlan": false
}
}
YAML (.arc.yaml):
diff:
createAsDraft: false
requireTestPlan: false
This configuration:
- Creates PRs as ready-for-review by default
- Makes the test plan field optional
All other settings will use their default values.