@chronsyn/hangar-cli
v0.1.2
Published
Hangar CLI — authenticate and submit builds to a Hangar server.
Readme
@chronsyn/hangar-cli
The hangar CLI — authenticate to a self-hosted Hangar build server, submit
your Expo/React Native app for an EAS-style build, and download the artifacts.
Runs on macOS, Linux, and Windows. Requires Node.js 22+. Submitting builds also requires git on your PATH.
Install
npm i -g @chronsyn/hangar-cliThis installs the hangar command globally. Verify with:
hangar helpSetup
Point the CLI at your server (saved as the default so you don't repeat it):
hangar config set defaultServer https://your-hangar-server:4000Log in. This runs an RFC 8628 device flow — it prints a verification URL and a user code. Open the URL, sign in, and confirm the code:
hangar loginConfirm you're connected:
hangar whoami
Your credentials are stored locally (see Storage); you stay logged
in until you run hangar logout.
Submitting a build
Run from inside your Expo/React Native project (where app.json /
app.config.* and eas.json live):
# Dry run first — bundles and resolves config without uploading
hangar build --dry-run
# Submit a build and wait for it to finish
hangar build --platform ios --profile production --wait
# Android, with build-time env vars
hangar build --platform android --profile preview --env API_URL=https://api.example.com --waitCommon build flags:
| Flag | Purpose |
|---|---|
| --platform <ios\|android> | Target platform (required). |
| --profile <name> | Build profile from your eas.json (required). |
| --wait | Stream status until the build finishes instead of returning immediately. |
| --env KEY=VAL | Set a build-time env var (repeatable). |
| --env-file <path> | Load build-time env vars from a file. |
| --project-dir <path> | Project root, if not the current directory. |
| --app-dir <rel-path> | App subdirectory within the project (monorepos). |
| --nodejs-version <X.Y.Z> | Override the Node version used on the build server. |
| --xcode <X.Y> | Override the Xcode version (iOS). |
| --jdk <N> | Override the JDK major version (Android). |
| --dry-run | Bundle + resolve config locally; don't upload. |
| --upload-only | Upload the bundle but don't enqueue a build. |
| --debug | Verbose output (e.g. full expo config errors). |
| --json | Machine-readable output. |
Commands
Auth
| Command | Behavior |
|---|---|
| hangar login [--server <url>] [--name <token-name>] | Device-flow login; stores a bearer token. |
| hangar whoami [--server <url>] | Show the identity behind your stored token. |
| hangar logout [--server <url>] | Revoke the token at the server and remove it locally. |
Builds
| Command | Behavior |
|---|---|
| hangar build … | Bundle the current project and submit a build (see flags above). |
| hangar builds list [--server <url>] | List builds on the server. |
| hangar builds view <id> [--server <url>] | Show details for one build. |
| hangar builds cancel <id> [--server <url>] | Cancel a queued/running build. |
| hangar builds delete <id> [--yes] [--server <url>] | Delete a build (--yes skips the prompt). |
Artifacts
| Command | Behavior |
|---|---|
| hangar artifacts download <build-id> [--output <path>] [--kind <ipa\|apk\|aab\|ios-simulator>] | Download a build's artifact. |
Config
| Command | Behavior |
|---|---|
| hangar config set defaultServer <url> | Persist the default server URL. |
| hangar config get <key> | Read one config value. |
| hangar config list | Print the full config. |
hangar help prints the full usage. Most commands accept --server <url> to
target a specific server and --json for machine-readable output.
Server resolution
When a command needs a server and you don't pass --server, it resolves in
this order:
--server <url>flagHANGAR_SERVERenvironment variabledefaultServerfrom your config file- otherwise, an error asking you to set one
Environment variables
HANGAR_SERVER— default server URL (overrides the config file).HANGAR_TOKEN— bearer token to use (skips the on-disk credential).HANGAR_CONFIG_DIR— override the config + credential directory.
Storage
Config and credentials live in a per-user directory:
- Windows:
%APPDATA%\hangar\ - macOS / Linux:
$XDG_CONFIG_HOME/hangar/or~/.config/hangar/
hangar/
├── config.json { "defaultServer": "..." }
└── auth.json { "version": 1, "servers": { "<url>": { tokenId, bearer, ... } } }On macOS/Linux, auth.json is created with mode 0600 and the directory with
0700. A malformed file is recovered by rewriting it on the next change.
Developing this CLI
From the monorepo root:
npm install
npm run build # bundles apps/cli into dist/ via esbuild
# run without installing globally
node apps/cli/bin/hangar.js help
# tests
npm test --workspace @chronsyn/hangar-cliThe published package is a single bundled ESM file — @hangar/protocol is
inlined at build time, so it has no @hangar/* runtime dependency.
