All docs
The hangar command line
The hangar command line is a program that runs your software on GPUs and CPUs in Australia from your terminal. Each job ends with a certificate that you can verify on your own machine. A container is your software packaged with everything that it needs. You pay from prepaid credit for each job that you start.
With hangar you can do these tasks:
- Sign in through your browser.
- Run a container on a GPU or CPU in Sydney or Melbourne, now or in a booking.
- Watch a job from its image to its certificate, and read its log.
- Download the outputs of a job.
- Book hours on an H100 night.
- Show and add credit.
- Verify the certificate of a job.
A vendor also uses hangar to create release packages, make release keys, submit and follow releases, move channels, start release jobs for tenants, register pools and manage tenants.
An organisation can make request keys for its CI jobs and agents. A request key lets a CI job or an agent use the same commands inside the spend limit that you set. Every command works the same way with a request key. Every command has --json.
The examples below use the booking HG-7K3M2Q on Saturday 24 October, 23:00 to 02:00 AEDT, and the CPU job HG-C9P4WD.
The commands#
| Command | What it does |
|---|---|
hangar | Shows who you are, your credit, the capacity that is free now, your jobs and the next command. |
hangar login | Sign in through your browser. |
hangar run | Runs a container on a GPU or CPU now, in a booking, or runs a release, and shows the job until its certificate. |
hangar status [JOB] | Shows your jobs and the capacity that is free now, or the position of one job. |
hangar logs [JOB] | Shows the log of a job. On a terminal, the log keeps updating while the job runs. |
hangar verify JOB or hangar verify FILE | Fetches, keeps and verifies the certificate of a job. With a file, verifies the file with no account and no network. |
hangar pull JOB [DIR] | Downloads the outputs and the certificate of a job. The command checks each file against its digest. |
hangar stop [JOB] | Stops a job or a session. |
hangar book | Holds and pays for hours on a night of H100 capacity. |
hangar cancel ID | Cancels a booking or a hold. |
hangar credit | Shows credit. credit add adds credit and credit usage shows usage. |
More: upload, secret, keys, tenant, release, pool, sandbox, logout, mcp and completion.
The older names work until hangar 1.1. Each older name does what it did before. Each older name also prints one grey line on standard error with the new name. For example: hangar start is now hangar run --gpu. This name works until hangar 1.1. Under --json, standard output stays one JSON document.
| Older name | New name |
|---|---|
hangar start | hangar run --gpu |
hangar certificate JOB | hangar verify JOB |
hangar outputs JOB --download DIR | hangar pull JOB DIR |
hangar usage | hangar credit usage |
hangar nights | hangar book --list |
hangar package create and list | hangar release create and hangar release packages |
Install#
Homebrew, on a Mac or on Linux#
brew install talos-defence/hangar/hangar hangar --version
Homebrew also installs the completion scripts for zsh, bash and fish. To update, run brew upgrade hangar.
Direct download, with the digest checked#
Each release has one archive for each platform, a SHA384SUMS file and a signed release manifest:
| Platform | Archive |
|---|---|
| Mac with Apple silicon | hangar-<version>-aarch64-apple-darwin.tar.gz |
| Linux on x86_64 | hangar-<version>-x86_64-unknown-linux-musl.tar.gz |
| Linux on arm64 | hangar-<version>-aarch64-unknown-linux-musl.tar.gz |
Download the archive and SHA384SUMS from the release page at https://github.com/talos-defence/hangar-cli/releases. Check the digest before you open the archive:
# macOS shasum -a 384 -c SHA384SUMS --ignore-missing # Linux sha384sum -c SHA384SUMS --ignore-missing
The check prints OK beside the archive. Any other result means that the archive is not the archive that TALOS Defence released. Delete the archive and download the archive again. Then install:
tar -xzf hangar-<version>-<platform>.tar.gz install -m 0755 hangar ~/.local/bin/hangar hangar --version
hangar -V prints the release, the build digest, the key set in the program, the verifier and the end of support:
hangar 0.9.0 build sha384:4b1f0e9a72c3 (aarch64-apple-darwin) key set 4c1a90d2e09b verifier hangar_cert 0.9.0 supported until 5 November 2031
hangar -V also asks the control plane for the Hangar platform version and prints the answer as the second line, for example Hangar platform 4.0.1. The CLI waits three seconds at most. When the control plane does not answer, the line reads Hangar platform: not reached. When the control plane has no published platform version, the line reads Hangar platform: none published. With --json, the field platform_version holds the version, or null. The platform version is the version of the whole set of Hangar components. The release in the first line is the version of the CLI.
The signed release manifest also lists the build digest and the archive digests. You can compare them.
How the command line prints#
| Rule | Why |
|---|---|
| No line is wider than 80 columns. | The text is easy to read in any terminal and in a support email. |
| The answer goes to standard output. Progress, prompts and notices go to standard error. | hangar status > file saves the answer and not the spinner. |
--json prints one JSON document on standard output and nothing else. | Scripts and agents read one format. |
| An error is three lines on standard error: what failed, the next step, and what to do if the next step fails. | You always know the next action. The words come from the API error catalogue, which the website also uses. |
hangar asks a question only when four things are true: standard input and standard error are terminals, --json is absent, no request key is in use, and CI and HANGAR_NO_INPUT are not set. Otherwise a missing value is an error that shows the flag to add, with exit status 64. | A script never waits for an answer that no one will give. Every question has a flag. |
The tick ✓ prints only for a state that Hangar has just confirmed. | A saved or unproven state never looks done. |
Times are Melbourne time with the zone, such as Sat 24 Oct 23:00 AEDT. UTC follows in brackets where the minute matters. | The schedule uses Melbourne time. UTC is for people who compare logs. |
Money is A$104.85. A charge shows its GST once: including GST of A$9.53. Every price includes GST. | The website and the tax invoice use the same format. |
A digest prints as its first 12 hex digits, sha384:9f2c41e0b37d. Every command accepts that prefix or a longer prefix. | You can paste the printed form. --json prints the whole digest. |
A length of time prints as 3 h, 2 h 30 or 48 min. A point in time prints as a clock, 1:31:08. | One format shows how long. Another format shows how far. |
Colour#
The CLI uses one accent colour. Gold marks what is confirmed or live: the ✓ of a step, the live ●, the spinner, the filled part of a progress bar, and the countdown digits. Bold marks the one line that you came to read. Grey marks UTC times, as at lines, hints, links and log timestamps.
Every state has a shape and a word. Only the shape and the word use the colour of the state: ✓ Returned, ✓ Valid and passed in green (#BED3A4); ✗ Refused, ✗ Failed and FAILED in red (#EDAC99); ‖ Held in blue (#B3C9E8); ○ Scheduled and ○ Warming in grey (#99978B). A sentence never uses a colour, so you can read every state with colour off.
Colour is off in these cases: NO_COLOR is set, CLICOLOR=0 or TERM=dumb is set, the output is not a terminal, or you use --json. CLICOLOR_FORCE=1 turns colour on in a pipe. NO_COLOR overrides CLICOLOR_FORCE=1. Standard output and standard error each follow these rules on their own. When the terminal sets COLORTERM=truecolor, gold is #F6AE35. When COLORFGBG shows a light background, gold is #D9A34B. In other terminals, gold is the nearest of the 256 colours.
Progress#
On a terminal, a progress line redraws in the same place, at most ten times a second:
Sending ████████████████░░░░░░░░ 68% 1.4 of 2.1 GB 41 MB/s 0:17 left
When the output is not a terminal, one plain line prints at each tenth of the progress: Sending 70%, 1.5 of 2.1 GB. On a terminal, a wait with no measurable progress shows a braille spinner before the words.
References#
A booking has a reference such as HG-7K3M2Q. A job has the reference of its booking and its position, such as HG-7K3M2Q-1. Every command that takes a job also takes the reference of a booking. Then the command uses the current job of the booking. Every command also takes the id that --json prints. References use Crockford's base 32, which has no I, L, O or U. If you read a reference aloud or copy a reference by hand, it cannot become a different reference.
Exit status#
| Status | Meaning |
|---|---|
| 0 | Done as asked. Also when you leave a follow or a watch. The job continues. |
| 1 | An error. The CLI prints what failed, the next step, and what to do if the next step fails. |
| 2 | hangar verify ran and the certificate is not valid. |
| 64 | The command line has the wrong form. |
| 130 | You pressed Ctrl C during an upload, a payment wait or a booking. Hangar keeps finished work. |
A script can tell "not valid" (2), "could not check" (1) and "typed wrong" (64) apart.
Sign in#
$ hangar login Open https://gethangar.au/device and enter the code WDJB-MJHT. Your browser is open at that address. Approve the sign-in there. Waiting for approval. Signed in as taylor@talosdefence.com.au for TALOS Defence Pty Ltd. Credit A$150.00. Write a first job to ./hello_gpu? [Y/n] y Wrote hello_gpu/hangar.toml: an NVIDIA L4 in Sydney prints its name and memory. Run it with cd hello_gpu && hangar run
The terminal and the browser both show the code. Check that the codes match before you approve with your passkey. If the browser is not signed in to Hangar, the browser first goes to gethangar.au/login. Enter the code that Hangar emails to you, then use your passkey. The browser then returns to the approval. Your passkey stays on your device. If you are already signed in, hangar login shows your name. To sign in as someone else, run hangar logout first. A sign-in code lasts 10 minutes.
After a new sign-in, the CLI prints your credit. On a terminal, the CLI also offers to write a first job. The file hello_gpu/hangar.toml sets an L4, the public CUDA image that TALOS Defence publishes for first jobs (by its digest), and the command nvidia-smi. Hangar fetches the image into Sydney by its digest, so the first job does not need Docker on your machine. Hangar never writes over a folder that already exists.
When the sign-up checks hold your account, the sign-in shows the held state and the next step:
‖ Held A person at TALOS Defence is checking your sign-up before your
account opens.
Register your passkey now, and Hangar emails you when the check ends.
If no email arrives, write to support@gethangar.au and quote the reference.hangar alone#
$ hangar Hangar alex@harbourwater.com.au Harbour Water Pty Ltd Credit A$84.23 Capacity now l4 NVIDIA L4, Sydney free now A$4.55 an hour h100 NVIDIA H100, Sydney free until 22:45 A$34.95 an hour trn2 AWS Trainium2, Melbourne free now A$9.99 an hour cpu CPU, Sydney free now A$0.12 a vCPU-hour Your jobs HG-C9P4WD L4 ✓ Returned 15:13 ✓ certificate HG-7K3M2Q H100 ○ Scheduled Sat 23:00 in 2 d 6 h Next hangar logs HG-C9P4WD Read the last job's log hangar verify HG-C9P4WD Verify its certificate hangar pull HG-C9P4WD Download its outputs and certificate hangar help for every command. Docs https://gethangar.au/docs
The screen first shows the last answer that Hangar gave this machine. On a terminal, the screen then redraws in the same place when Hangar answers. In a pipe, hangar prints the answer from Hangar one time. If Hangar is not reachable, hangar shows the last answer from Hangar. The last line then says as at 15:14. Hangar could not be reached; this is what this machine last saw. With a request key, the first line shows the key in place of a person. When you are signed out, hangar says what Hangar does and shows hangar login and hangar verify FILE. When you are signed out, hangar sends no request.
hangar logouthangar logout ends the session at Hangar and removes the session from this machine.
The session file#
The CLI saves the session in ~/.config/hangar/session.json:
- the CLI creates the file with mode 0600 (only you can read or write the file), in a folder with mode 0700;
- the CLI writes the whole file and then renames the file, so the file is never half written;
- the file also has a P-256 signing key that the CLI makes on this machine at sign-in. The session is tied to this key. The CLI signs every request with the key, so the token does not work on another machine. A request signed with another key ends the session;
- the clock of your machine must be within 60 seconds of the correct time, because each signature includes the time;
- if anyone else can read the file, or the file is a link, the CLI does not use the file. The CLI ends the session at Hangar, removes the file and asks you to sign in again;
- the session lasts 12 hours. Hangar renews the session while you use it.
Book hours on an H100 night#
Booking gives you hours on an H100 night. You pay from your credit when you confirm the booking.
A booking is whole hours that start on the hour: 1 to 21 hours, or 24 for an exclusive night. One NVIDIA H100 in AWS Sydney costs A$34.95 an hour. An exclusive night costs A$595. Prices include GST.
hangar book --list hangar book
hangar book --list lists the open nights. For each night it shows the hours in Melbourne time with UTC beneath, the price of an hour, and the free hours.
hangar book shows the same list and asks three questions. The questions come in this order, because the start decides how many hours fit:
Book a job Credit A$150.00
1. Sat 24 Oct 22:30 to 22:30 AEDT 1 x H100 A$34.95 an hour
11:30 to 11:30 UTC free 18 h: 23:00 to 03:00, 06:00 to 20:00
2. Wed 28 Oct 22:30 to 22:30 AEDT 1 x H100 A$34.95 an hour
11:30 to 11:30 UTC free 21 h: 23:00 to 20:00
An exclusive night is A$595: give 24 as the hours on a night with 21 h free.
For a CPU job, no booking is needed: hangar run --cpu 4 -- <command>
Night [1]: 1
Start, Melbourne time [23:00]:
Hours, 1 to 4 from 23:00 [1]: 3
Holding Sat 24 Oct 23:00 to Sun 25 Oct 02:00 AEDT (12:00 to 15:00 UTC) for 3 h.
The hold lasts 10 minutes.
Credit after: A$45.15.
Charge A$104.85, including GST of A$9.53, from credit? [y/N]: y
Charging A$104.85.
Confirmed ✓ Sat 24 Oct 23:00 to Sun 25 Oct 02:00 AEDT
Booking HG-7K3M2Q. Charged A$104.85. Credit A$45.15.
Next: hangar upload ./trainPress Enter to use the value in brackets. The answer to the charge is N unless you type y. An accidental Enter never spends credit: Hangar releases the hold and charges nothing. Type q at any question to leave and release the hold. If someone else books the hours while you choose, the CLI shows which hours are gone. Run hangar book again to see the hours that are free now.
The CLI asks the questions on a terminal only. In a script, give the night, the start and the hours:
$ hangar book --night 2026-10-24 --at 23:00 --hours 3 Holding Sat 24 Oct 23:00 to Sun 25 Oct 02:00 AEDT (12:00 to 15:00 UTC) for 3 h. Charging A$104.85. Confirmed ✓ booking HG-7K3M2Q charged A$104.85, including GST of A$9.53. Credit A$45.15.
| Option | What it takes |
|---|---|
--night DATE | The night: a date such as 2026-10-24, or next |
--at HH:MM | The start, in Melbourne time, on the hour. A time after midnight is the next morning of the same night. Default: the first start from which the hours fit |
--hours N | 1 to 21, or 24 for an exclusive night |
--hold-only | Hold the hours for 10 minutes and charge nothing |
--confirm ID | Charge a booking that you held earlier with --hold-only |
$ hangar book --night 2026-10-24 --at 23:00 --hours 3 --hold-only Holding Sat 24 Oct 23:00 to Sun 25 Oct 02:00 AEDT (12:00 to 15:00 UTC) for 3 h. The hold lasts until 14:16. Run hangar book --confirm HG-7K3M2Q to book it. $ hangar book --confirm HG-7K3M2Q Charging A$104.85. Confirmed ✓ booking HG-7K3M2Q charged A$104.85, including GST of A$9.53.
The CLI checks what you typed before the CLI asks Hangar anything:
| You typed | The CLI prints | Exit |
|---|---|---|
--hours 6 where 4 fit | 6 hours do not fit from 23:00 on Sat 24 Oct; 4 hours fit. | 1 |
--at 23:30 | Jobs start on the hour, and 23:30 is not on the hour. | 1 |
--hours 30 | The hours must be a whole number from 1 to 21, or 24 for an exclusive night. | 64 |
When your credit is less than the booking price, the CLI shows the booking price, your credit, and the one top-up that covers the price:
This booking is A$104.85 and your credit is A$34.23. Run hangar credit add 75, then run hangar book again.
Upload#
Upload sends your files or your container image to Hangar in Sydney. Hangar stores the upload, and you can use it in a job.
$ hangar upload ./train Archiving the folder. sha384:9f2c41e0b37d 2.1 GB in 1,204 files Sending ████████████████████████ 100% 2.1 of 2.1 GB 44 MB/s Received ✓ sha384:9f2c41e0b37d, 2.1 GB, stored in Sydney. Use it in a job with --data sha384:9f2c41e0b37d
The digest prints before the send. The CLI sends a file as it is. The CLI first archives a folder in the same way every time (sorted names, times and owners set to zero). The same folder therefore always has the same digest. The upload has these properties:
- the CLI sends the upload in chunks, four at a time by default (
--parallel 1to16). Each chunk has its own SHA-384; - the upload resumes where it stopped. Ctrl C ends the upload and keeps every confirmed chunk. When you run the same
hangar uploadcommand again, the CLI sends only the chunks that Hangar has not confirmed (Resuming: 179 of 263 chunks are already in Sydney.); - the CLI sends nothing if Hangar already stores the same bytes for your organisation (
Already stored in Sydney ✓. Nothing was sent.); - the CLI reports success only after Hangar has checked the whole digest and stored the object.
After the last chunk, the CLI asks Hangar once to complete the upload. Hangar checks the digest of every chunk, then joins the chunks into one object in Sydney. The CLI shows the check on one line:
Hangar checks the whole upload before it stores the upload. Ctrl C stops the wait, and the check continues. Run the same command again to follow the check. Checking 1,204 of 2,100 chunks.
The CLI reads the state of the check 2 seconds after the request. The wait between two reads grows to 15 seconds. The line shows Waiting for the check to start., then Checking 1,204 of 2,100 chunks., then Joining 2,100 chunks into one object in Sydney. The CLI prints Received only when Hangar has stored the object. When the check fails, the CLI prints what failed and the next step:
upload_digest_mismatch: the file changed during the upload. Hangar keeps nothing, and the CLI removes its progress file. Upload the file again when nothing writes to the file;upload_completion_failed: Hangar could not finish storing the upload. Hangar keeps the chunks, and the CLI keeps its progress file. Run the samehangar uploadcommand again. The CLI sends no chunk twice.
Ctrl C stops the wait. The check continues, and the CLI keeps its progress file. Run the same command again to follow the same check.
After 6 hours, the CLI stops the wait and prints Later, run hangar upload --status UPLOAD, with the upload id. hangar upload --status UPLOAD reads the state of the check once:
| State | The command prints | Exit status |
|---|---|---|
| Stored | Received, the digest and the size | 0 |
| Checking | The state line, such as Checking 1,204 of 2,100 chunks., and the next step | 1 |
| Failed | What failed and the next step | 1 |
When the upload is stored or the check failed, --status also settles the progress file of the upload on this machine, as the upload command does.
A folder upload needs free disk space equal to the size of the folder, for the archive. The CLI removes the archive afterwards.
Images#
$ hangar upload --image ./finetune.oci.tar --name finetune:2026-10-24 Pushing finetune:2026-10-24 (sha256:5c0e9a17d2b4), 14 layers, 9.8 GB. Sending ████████████████████████ 100% 9.8 of 9.8 GB 52 MB/s Pushed ✓ finetune:2026-10-24 (sha256:5c0e9a17d2b4). Preflight passed: linux/amd64 (GPU pools), CUDA 13.4, entrypoint python.
This command pushes a local OCI image to the registry of your organisation in Sydney. Make the archive with docker buildx build --platform linux/amd64 --output type=oci,dest=finetune.oci.tar .. The CLI does not send layers that the registry already has. Hangar checks every image when you push the image, and the result prints at once. The result shows each platform that passed, with the pool that runs the image (linux/amd64 (GPU pools), linux/arm64 (CPU sandbox)), the CUDA version and the entrypoint. If the image fails, the result shows the reason and the rebuild to make. Hangar checks a multi-platform image for each of the two platforms. When the image fails for a platform, a note shows the platform and the reason. An image built for linux/arm64 passes for the CPU pool. The line under the result says that a GPU job needs linux/amd64. From a multi-platform layout, the CLI sends the linux/amd64 image. If the layout has no linux/amd64 image, the CLI sends the linux/arm64 image.
hangar upload --image docker.io/library/python@sha256:<digest> registers a one-time pull of a public image by its digest. You do not need Docker on your machine. Hangar fetches the image into Sydney from Docker Hub, GitHub Container Registry, NVIDIA NGC, Amazon ECR Public or Quay. The CLI shows a live fetch line (Fetching ... into Sydney: 3 of 7 layers, 0.4 of 1.1 GB.), then the result of the check. Ctrl C ends the wait, and the fetch continues. Run the same command again to follow the fetch. Hangar refuses a tag alone with image_pull_digest_required, because a tag can point at different bytes tomorrow (Images from your registry).
A CI job uploads with a request key that has the uploads capability. Set HANGAR_KEY_ID and HANGAR_KEY_FILE. Then hangar upload sends files, pushes an image and registers a pull, as it does for you. The key signs every request. The image shows the key as the sender, and the Keys page counts the images that each key sent. Only a person can approve a job of an image that your policy does not list.
A TALOS Defence release builder pushes a platform serving image with a grant from hangar-ops image serve: hangar upload --image ARCHIVE --name NAME:VERSION --grant -. The grant is for the platform repository platform/quarantine/NAME, and the bytes go to the platform's own store, never to the registry of an organisation. The grant arrives on standard input over ssh, or from a file that only its owner can read (--grant FILE). --grant is an operator flag, so hangar upload --help does not list it. The grant is a 60-minute credential for the platform repository of that one version. The command needs no session and no key, and sends requests only to the registry. The CLI never prints the grant and never renews it. When the registry refuses the grant, the CLI says that the grant expired and to run hangar-ops image serve again with the next version. A second push sends only the layers that the registry does not hold. The image stays in quarantine until an operator promotes it with hangar-ops image promote-serve NAME@VERSION --digest sha256:... and one touch of a hardware key. The digest is the one the registry recorded from the pushed bytes, and hangar-ops image serve prints the promotion command with it.
Before hangar-ops image serve, prepare the release builder from the same commit:
- On the builder,
cd ~/t2s && git fetch && git checkout COMMIT. - Rebuild the builder's CLI:
cargo build --release -p hangar_cliin~/t2s. The builder command runs~/t2s/target/release/hangar. - Build the image:
~/t2s/images/NAME/build.sh VERSION. The archive is~/t2s/images/NAME/out/NAME-VERSION.oci.tar.
The builder command that hangar-ops image serve prints stops with a sentence when a builder step fails (gstep, bpush, or a builder address that is not an instance id), so the grant is not used up in silence. Push no serving image while a deploy of the API runs: a node of the previous release refuses the grant.
Run#
hangar run starts every kind of run. One view shows the job from its image to its certificate:
$ hangar run --gpu l4 smoke:v1 -- nvidia-smi --query-gpu=name,memory.total --format=csv
smoke:v1 NVIDIA L4, Sydney alex@harbourwater.com.au
✓ Image sha256:5c0e9a17d2b4 smoke:v1
✓ Session HG-C9P4WD, A$4.55 an hour by the second, ends by 16:12:31 AEDT
✓ Instance fresh L4 in apse2-az1
attested at 15:12:32, reset passed at 15:12:33
● Running 0:00:41 A$0.06 so far
──────────────────────────────────────────────────────────────────────────────
15:12:33 name, memory.total [MiB]
15:12:33 NVIDIA L4, 23034 MiB
✓ Returned succeeded in 0:01:12 A$0.09, including GST of A$0.01
Certificate HG-C9P4WD signed 15:13:44 verified on this machine ✓
hangar verify HG-C9P4WD https://gethangar.au/c/C9P4WDOn a terminal, the step in progress and the running clock with the cost so far stay on the last line. The last line redraws in the same place, at most ten times a second. Every other line prints one time. The output of the job goes to standard output. The view goes to standard error. hangar run ... > out.txt therefore saves only the output of the job. Ctrl C leaves the view, and the job continues in Sydney. Hangar signs the certificate within a minute of the end of the job. The CLI then fetches the certificate, verifies the certificate on this machine and keeps the certificate. You can check the certificate again at any time with hangar verify.
| Where the job happens | Flags |
|---|---|
| A GPU now, with no booking | --gpu l4, --gpu l4-fraction, --gpu h100 or --gpu trn2; --limit MINUTES stops the job that many minutes after the start |
| A CPU now | --cpu 2, 4, 8 or 16; --stop-after 2h stops the job after that length of time, 1 hour to 7 days |
| A booking | --booking HG-7K3M2Q |
| A release | --release or --package with --channel, below |
Put the image first after the flags, or use --image. The image can be a name and tag, a digest such as sha256:5c0e9a17d2b4, or a public image by its digest, such as docker.io/nvidia/cuda@sha256:<digest>. Hangar fetches a public image into Sydney and checks the image before the job, so you do not need Docker on this machine. The digest prints when Hangar accepts the job. The digest runs, not the tag, and the certificate shows the digest. Everything after -- is the command of the job. The CLI never reads the flags of that command (--config, --help) as its own flags. --env takes names only. Your secret store has the values. --data takes digests of data that you uploaded.
On a terminal, the CLI asks for each value that you leave out. It asks for your images, newest first, when there is no image. It asks for the command. It asks for the capacity that is free now, with the price, when no flag says where to run. In a script, each missing value is an error that shows the flag to add, with exit status 64:
$ hangar run smoke:v1 -- python job.py < /dev/null Name the capacity: --gpu l4, --gpu h100, --gpu trn2 or --cpu 4. Run hangar status to see what is free now and its price. If it is refused again, run hangar help run to see its form.
A GPU job now gets its own instance. Hangar attests and resets the instance before the job starts. Hangar takes nothing from your prepaid credit until the job starts. Then Hangar takes the cost from when the instance runs to when the instance ends. The price is by the second for l4 (one NVIDIA L4, 24 GB, A$4.55 an hour) and l4-fraction (one eighth of an L4, 3 GB, A$1.35 an hour). The price is by the started minute for h100 and trn2 on Hangar's blocks while the instance of the block is free. A start needs credit for its first ten minutes. The session ends in these cases: the job ends, the --limit time passes, your credit falls to a reserve ten minutes after a warning, the next booking on a block starts, or you run hangar stop. When no capacity is free, Hangar starts nothing and charges nothing. The view shows when the capacity is free again, or the next night with a block. When the machine of a session does not report, Hangar ends the session and the machine. hangar status, hangar logs and the live view show Failed and the reason, for example The machine did not report within 10 minutes after it started. The slot is free again at once. Hangar charges nothing when no job started.
Hangar accepts a job in a booking into the booking. The job happens in the hours of the booking:
$ hangar run --booking HG-7K3M2Q finetune:2026-10-24 \
--data sha384:9f2c41e0b37d --data sha384:d81b6f0c29ae \
--env WANDB_API_KEY -- python train.py --config configs/h100.yaml
finetune:2026-10-24 booking HG-7K3M2Q, NVIDIA H100, Sydney taylor@talosdefence.com.au
✓ Image sha256:5c0e9a17d2b4 finetune:2026-10-24
✓ Job HG-7K3M2Q-1 in booking HG-7K3M2Q
○ Scheduled starts Sat 24 Oct 23:00 AEDT, in 0:42:17
Watch it with hangar status HG-7K3M2QOn a terminal, the view shows the job until its certificate. This starts in the 15 minutes of warming, or when the booking has started. A script gets the acceptance at once.
When a job fails, the view says so. Hangar still signs the certificate:
✗ Failed exit code 137 after 0:00:52 A$0.07, including GST of A$0.01 The whole log is kept: hangar logs HG-D3K9QW Certificate HG-D3K9QW signed 15:31:02 verified on this machine ✓
When TALOS Warrant or Hangar refuses a job before the job starts, the view prints the refusal in three parts under the refusal mark. Hangar charges nothing:
✗ Refused This key has reached its A$200.00 spend limit, so Hangar started
nothing and charged nothing.
Raise the limit with hangar keys limit, or create a new key.
If you cannot change keys, ask an owner of your organisation to raise the limit.If your account policy needs a named approval for an image, Hangar accepts the job in the booking and the job waits. The booking keeps its hours:
‖ Held Your account policy needs a named approval for this image. An owner approves the image on the website or in the iPhone app. The booking keeps its hours while it waits.
--detach returns when Hangar accepts the job. To follow the job later, use hangar logs. In a script, a GPU or CPU job now waits until the job ends. The command exits 0 when your command ended with exit code 0. Otherwise the command exits 1. --json prints one document after the job ends. The document has the job, the image, the outcome, the log and the certificate:
$ hangar run --gpu l4 smoke:v1 --json -- nvidia-smi -L | jq -r .certificate.id HG-C9P4WD
In a script, a job in a booking and a job of a release return when Hangar accepts the job.
A CI job or an agent runs the same commands with a request key that has the jobs capability. Set HANGAR_KEY_ID and HANGAR_KEY_FILE. Then hangar run, status, logs, pull, verify and stop work as they do for you, with no questions. The first line of the view shows the key in place of a person. The session shows the key as the starter:
smoke:v1 NVIDIA L4, Sydney key hgk_syd_7c41e0b3
✓ Image sha256:5c0e9a17d2b4 smoke:v1
✓ Session HG-C9P4WD, A$4.55 an hour by the second, ends by 16:12:31 AEDT
started by key hgk_syd_7c41e0b3A key spends credit only on the jobs that the key starts, inside the limits of your organisation. The spend limit of a key works in this way. Each time the key starts a job, Hangar adds two amounts: what the jobs of the key have spent, and what the running sessions of the key can still spend. A session ends when the rest of the limit runs out, at the price of the GPU. When a key reaches its limit, Hangar starts no job for the key. A key never books, tops up or approves.
A job of a release#
A job of a release starts a release that a vendor made, for one tenant, on the CPU pool hosted-cpu-syd. The page Releases and jobs describes the contract.
$ hangar run --release 5d1c09e2a7b4 --tenant tnt_0192f3a1 \
--input repository=sha384:9f2c41e0b37d --input rules='["path_traversal"]'
Job 0192f3b7 of hangar_patch_agent 1.0.0 for Harbour Water, hosted-cpu-syd.
Release sha384:5d1c09e2a7b4. This release is what runs.
Envelope sha384:c41e0b37d9f2: 1 destination, 2 vCPU, 15 min. It ends 15:42:09.
Starting.
Running ✓ on a fresh instance since 15:12:09 AEDT.
Follow it with hangar logs 0192f3b7 --followOn a terminal, the view continues under a rule. Under the rule, the view shows the events of the job, the end of the job, and the certificate. The CLI verifies the certificate on this machine. In a script, the view ends before the rule.
--release takes a release id, in full or as 12 or more hexadecimal digits. --package P --channel C starts the release that the channel points at. The second line then reads "Channel stable resolved to sha384:5d1c09e2a7b4. Retries keep this release." Sometimes a channel points at a release that needs more permissions than an owner has approved for the tenant. Then the job uses the release before that release, and the view says so:
Channel stable points at sha384:a8e3f1b2c9d0, which asks for more than an owner approved for this tenant, so this job uses sha384:5d1c09e2a7b4.
| Option | What it does |
|---|---|
--tenant TNT | The tenant that the job serves. |
--input NAME=VALUE | An input. VALUE is a sha384: digest or prefix for an artefact. If VALUE is not a digest, it is JSON. If VALUE is not JSON, it is a string. |
--keep DESTINATION | Keeps only these destinations of the envelope. The job gives up the other destinations. |
--pool POOL | The pool. The default is hosted-cpu-syd. |
--client-ref TEXT | Your reference for the job. Hangar uses it to find the job again if you send the request a second time. The default is 32 random hexadecimal digits. |
When TALOS Warrant refuses to start a job of a release, the CLI prints the reason in one line, then the next step. The CLI exits 1:
$ hangar run --release a8e3f1b2c9d0 --tenant tnt_0192f3a1 \
--input repository=sha384:9f2c41e0b37d
TALOS Warrant refused to start the job: an owner has not approved this release.
Ask an owner to approve the difference, then start the job again.The short reasons are: "an owner has not approved this release", "your policy denies" an item, "a narrowing can only remove", a channel "is held", "the release was revoked", "the release is awaiting acceptance", a key "is not set for this pool", and an input "is not its declared type".
hangar.toml#
Write the job in a file named hangar.toml in the folder that you run from. Then hangar run alone reads the file. A flag overrides the file.
booking = "HG-7K3M2Q" # or: gpu = "l4"; or: cpu = 4 and stop_after = "2h" image = "finetune:2026-10-24" command = ["python", "train.py", "--config", "configs/h100.yaml"] environment = ["WANDB_API_KEY"] data = ["sha384:9f2c41e0b37d", "sha384:d81b6f0c29ae"] failure_policy = "retry_once"
The CLI refuses a key that it does not know. A misspelt key is an error. The CLI never ignores a setting without telling you.
Stop#
hangar stop HG-C9P4WDhangar stop stops a GPU session, a CPU job, a job in a booking before the job starts, or a job of a release. A GPU job receives SIGTERM and 60 seconds to save its work. When no job of a GPU session has started, Hangar ends the instance at once. Metering ends when the instance ends, and the certificate records that time. A person, or a request key with jobs, can stop any session of the organisation, whoever started it. If you give no job, on a terminal, hangar stop asks before it stops your live job. The answer is No unless you type y:
$ hangar stop Stop HG-C9P4WD, running for 0:12:40? [y/N] y
In a script, a missing job is an error: Name the job: hangar stop HG-C9P4WD. To end a booking, use hangar cancel. hangar stop does not end a booking.
Status#
$ hangar status HG-7K3M2Q H100 Sat 24 Oct 23:00 to 02:00 AEDT ○ Scheduled starts in 0:42:17 HG-3TQ8KM 16 vCPU Fri 23 Oct 09:30 to 12:35 ✓ Returned certificate ✓ HG-C9P4WD 4 vCPU Thu 22 Oct 15:12 to 16:00 ✓ Returned certificate ✓ as at Sat 24 Oct 22:17 AEDT Up to date with Hangar ✓
The first lines come from this machine at once. The as at line shows the time that Hangar last answered. Then Hangar answers with Up to date with Hangar ✓, or with Changed since then: and the lines that changed. If Hangar is not reachable, the CLI shows the saved answer and says so. The exit status is 0. --offline answers from this machine only.
For one job, the view shows the position of the job first. Before the start, the view shows a countdown:
$ hangar status HG-7K3M2Q
HG-7K3M2Q scheduled one NVIDIA H100, AWS Sydney
starts in 0:42:17 on the minute at 23:00:00 AEDT (12:00:00 UTC)
warming from 22:45
image sha256:5c0e9a17d2b4 finetune:2026-10-24
data sha384:9f2c41e0b37d 2.1 GB, staged
sha384:d81b6f0c29ae 184 MB, staged
Ctrl C leaves. Nothing waits on you.While the job is running, the view shows the elapsed time against the booked window, the step that the job reports, the last checkpoint, the GPU and the envelope. The envelope is the set of limits that Hangar sets for the job. When the job finishes, the view shows the certificate:
$ hangar status HG-7K3M2Q HG-7K3M2Q finished exit code 0 ran 23:00:00 to 01:58:12 AEDT Certificate HG-7K3M2Q signed at 01:58:47 ✓ Get it with hangar verify HG-7K3M2Q
On a terminal, the countdown and the position redraw each second until you press Ctrl C. The job continues in Sydney if you watch or not. With --once, or when the output is not a terminal, the CLI prints the view one time.
For a job of a release, the view shows the time window, the release, the tenant, the pool and the envelope:
$ hangar status 0192f3b7 0192f3b7 running hangar_patch_agent 1.0.0, AWS Sydney 0:00:41 of 0:15:00 █░░░░░░░░░░░░░░░░░░░░░░░ 5% envelope ends 15:42:09 AEDT release sha384:5d1c09e2a7b4 stable tenant tnt_0192f3a1 Harbour Water pool hosted-cpu-syd attempt 1 of 2 envelope 1 connection, 1 refusal Ctrl C leaves. The job continues in Sydney.
When the job ends, the view shows "0192f3b7 returned succeeded ran 15:12:09 to 15:13:20 AEDT". Then the view shows "Return 0192f3b7 signed at 15:13:44 ✓" and "Get it with hangar verify 0192f3b7".
Logs and pull#
$ hangar logs HG-7K3M2Q --follow 00:30:09 [hangar] checkpoint step-3000 copied to Sydney storage, 4.7 GB 00:30:40 step 3040/6000 loss 1.284 lr 1.8e-04 212 samples/s 00:30:52 step 3080/6000 loss 1.279 lr 1.8e-04 214 samples/s
The log is the text that the job wrote. The CLI prints the standard output of the job to standard output. The CLI prints the standard error of the job to standard error. The CLI does not change either one. Hangar adds only the Melbourne time, and marks lines from Hangar with [hangar]. If you give no job, the log is the log of your latest job. On a terminal, the log keeps updating until the job ends, as with --follow. In a script, the CLI prints the lines so far, unless you give --follow. --once prints the lines so far on a terminal too. When you follow a log, each line appears when the job writes the line. If the connection drops, the CLI says that it is reconnecting. Then the CLI prints the missed lines in order. Before the job starts, --follow waits for the first line. Without --follow, the CLI says when the job starts.
$ hangar pull HG-7K3M2Q ./out ... Certificate HG-7K3M2Q verified on this machine ✓ saved at ./out/HG-7K3M2Q.cert
hangar pull downloads every output into the folder, or into a folder named after the job. The CLI checks each output against its digest. Then the CLI fetches the certificate of the job, verifies the certificate on this machine and saves the certificate beside the outputs. You can give the certificate to someone else.
For a job of a release, hangar logs prints the events of the job. The events are the compile, each attempt, each connection and refusal by destination, and each artefact with its descriptor result.
$ hangar logs 0192f3b7 --follow 15:12:04 compiled envelope sha384:c41e0b37d9f2, 1 destination 15:12:09 attempt 1 fresh instance c8g.large, apse2-az1 15:12:31 running 15:12:47 connected pypi.org 15:12:52 refused example.com, not in the envelope 15:13:20 artefact patch.diff sha384:3be08d5f6a12 2.1 KB passed 15:13:20 artefact test_report.json sha384:b70c2e94f1d8 611 B passed 15:13:21 sealing 15:13:44 returned succeeded Job 0192f3b7 returned ✓. Get the return with hangar verify 0192f3b7
hangar pull 0192f3b7 saves the artefacts of the job and the signed return of the job. The CLI checks each artefact against its digest.
Each download counts against the monthly download allowance of your organisation. The CLI opens each download on this machine with the key of the download. The older command hangar outputs JOB --url DIGEST prints a short-lived download address for one output. The command also prints the time that the address stops working. The command downloads nothing. The address gives only encrypted bytes. The command does not print the key that opens the bytes. Hangar records each address that Hangar issues, and counts the address against the allowance.
Cancel#
hangar cancel HG-7K3M2Qhangar cancel cancels a booking or a hold. To end a job, use hangar stop. hangar stop also cancels a job that has not started.
| What | Outcome |
|---|---|
| A hold | Hangar releases the hold and charges nothing |
| A booking 48 hours or more ahead | Hangar cancels the booking and returns the full credit |
| A booking within 48 hours | Hangar offers the hours for booking again. Credit returns for the hours that someone books. Needs --yes |
| A job that has not started | Hangar cancels the job |
| A CPU job | Hangar stops the job. The certificate issues within a minute of the stop |
| A job of a release | Hangar cancels the job. The attempt stops and the envelope closes. Hangar issues the signed return within a minute. The return says that the job was cancelled |
Releases#
Releases take a vendor's package to a release that runs for the tenants of the vendor. The page Releases and jobs describes each step.
$ hangar release keygen talos-release Release key talos-release made on this machine: key 3f9a1c07d2e4. Private key at ~/.config/hangar/release-keys/talos-release.key, mode 0600. Register it with hangar release register talos-release $ hangar release register talos-release Release key 3f9a1c07d2e4 registered for TALOS Defence Pty Ltd ✓ Releases signed with it can be submitted from now on. $ hangar release create Package hangar_patch_agent 1.0.0 created from hangar_package.json ✓ image sha256:5c0e9a17d2b4 linux/arm64 manifest sha384:2d7f9e41a0c3 envelope 1 destination, 2 vCPU, 4 GiB, 15 min, 1 retry Next: hangar release submit hangar_patch_agent@1.0.0 --key talos-release $ hangar release submit hangar_patch_agent@1.0.0 --key talos-release Release sha384:5d1c09e2a7b4 of hangar_patch_agent 1.0.0, sequence 1. The manifest matches hangar_package.json on this machine. Signed with key 3f9a1c07d2e4 on this machine. Submitted ✓. TALOS Defence checks it before it runs for a tenant. Follow it with hangar release status 5d1c09e2a7b4 $ hangar release status 5d1c09e2a7b4 Release sha384:5d1c09e2a7b4 hangar_patch_agent 1.0.0 accepted ✓ accepted Thu 22 Oct 10:42 AEDT by TALOS Defence channels stable envelope 1 destination, 2 vCPU, 4 GiB, 15 min, 1 retry key 3f9a1c07d2e4 $ hangar release channel hangar_patch_agent stable 5d1c09e2a7b4 Channel stable of hangar_patch_agent now points at sha384:5d1c09e2a7b4 ✓ Jobs on stable start this release from now on.
| Command | What it does |
|---|---|
hangar release keygen NAME | Makes a release key on this machine. The private half stays on this machine, in a file of mode 0600. |
hangar release register NAME | Registers the public half of the key for your organisation. Only an owner, signed in with a passkey, can run this command. |
hangar release create [FILE] | Creates a package version from hangar_package.json, or from FILE. The CLI sends the file byte for byte. hangar release packages lists your packages. |
hangar release submit PACKAGE@VERSION --key NAME | Fetches the release draft, checks the draft against the manifest on this machine, signs the draft and submits the draft. |
hangar release status [RELEASE] | Shows the state, acceptance, channels and envelope of one release. With no release, shows your releases. While the checks run, the CLI prints "TALOS Defence is running its checks and a self-test of the release." |
hangar release channel PACKAGE CHANNEL RELEASE | Moves a channel to an accepted release. If the move widens the envelope, the CLI prints the difference. Tenants keep the earlier release until an owner approves the move. |
hangar release revoke RELEASE --reason TEXT | Revokes a release. Hangar holds every channel that points at the revoked release until you move the channel. |
hangar release sbom DIR [--out FILE] | Builds the bill of materials (the list of software inside) of an unpacked image on this machine, with no network. |
hangar release advisories [RELEASE] | Shows the security advisory matches of one release, or of all your releases, oldest first. With --snapshot FILE --sbom FILE, the command matches a bill of materials against the mirror snapshot of a runtime release, with no network. --expect, --max-age-days and --refuse-stale check the snapshot against the signed manifest and against your policy. |
A RELEASE is a sha384: id, or the first 12 or more hexadecimal digits of the id.
Pools#
$ hangar pool list hosted-cpu-syd hosted linux/arm64 AWS Sydney available hosted-h100-syd hosted H100 booked AWS Sydney available harbour-aws customer-controlled linux/arm64 your account registered
A pool is a group of machines that runs your work. hangar pool show POOL prints one pool and its identity. hangar pool register --name NAME --aws-account 12DIGITS registers a customer-controlled pool in ap-southeast-2. hangar pool licence POOL [--save FILE] fetches the licence of the pool, checks the licence offline and saves the licence. The page Pools describes the customer-controlled form.
Certificates#
$ hangar certificate HG-7K3M2Q hangar certificate is now hangar verify. This name works until hangar 1.1. Job certificate HG-7K3M2Q signed by TALOS Defence verified ✓ Organisation: TALOS Defence Pty Ltd, ABN 24 696 691 906 Ran: Sat 24 Oct 23:00:00 to Sun 25 Oct 01:58:12 AEDT Hardware: one NVIDIA H100 80GB, AWS Sydney, apse2-az1 Image: sha256:5c0e9a17d2b4 Outcome: exit code 0 Link: https://gethangar.au/c/7K3M2Q Saved at ~/.config/hangar/certificates/HG-7K3M2Q.cert (fetched from Hangar).
hangar verify JOB fetches the job certificate for a booking or a job. With sha384:<digest>, the command fetches the data certificate for an uploaded object. The CLI saves the certificate as ~/.config/hangar/certificates/HG-7K3M2Q.cert and verifies the certificate on this machine. Each check prints on its own line, as for a file below. If you run the command again, the CLI uses the saved copy. The older hangar certificate JOB prints the summary above. hangar pull saves the certificate beside the outputs. Hangar signs a certificate within a minute of the end of the job. If you ask before then, the CLI says so and says when to ask again.
$ hangar verify HG-7K3M2Q.cert
Valid. Every required check passed. The published tree heads were not checked.
passed decode The certificate is well-formed and in its one
canonical encoding.
passed key_set The published key set is well-formed and
signed by its root.
...
not run published_heads Run hangar verify with --fetch to check the
published tree heads.
Facts
Certificate: HG-7K3M2Q
Issuer: TALOS Defence Pty Ltd, ABN 24 696 691 906
...hangar verify checks a certificate against the published root key set in the CLI. It needs no account and no network. Every check prints on its own line, so an assessor sees each check and not only the result. When a certificate is not valid, the output shows the first check that failed (FAILED). The output then shows the facts in the certificate, marked as not verified. The CLI reads HG-7K3M2Q.cert from the folder that you are in, or from the saved certificates.
| Option | What it does |
|---|---|
--fetch | Also checks the tree head of the certificate against the published tree heads. The CLI also fetches the published key set. The CLI uses the fetched key set only if it is the key set in the CLI or a rotation that the key set in the CLI signed |
--keys FILE | Trusts another key set file instead of the key set in the CLI |
--json | Prints the report of the verifier. The report is byte for byte the report that the verifier page in the browser shows |
The exit status is 0 when the certificate is valid. The exit status is 2 when the certificate is not valid. The exit status is 1 when the CLI could not check the certificate (for example, no such file or an unreadable key set).
The signed return of a job of a release is also a job certificate:
$ hangar certificate 0192f3b7 hangar certificate is now hangar verify. This name works until hangar 1.1. Job certificate 0192f3b7 signed by TALOS Defence verified offline ✓ Organisation: TALOS Defence Pty Ltd, ABN 24 696 691 906 Release: hangar_patch_agent 1.0.0, sha384:5d1c09e2a7b4 Tenant: tnt_0192f3a1 Pool: hosted-cpu-syd, AWS Sydney Ran: Thu 22 Oct 15:12:09 to 15:13:20 AEDT, 1 attempt Outcome: succeeded Outputs: sha384:3be08d5f6a12, sha384:b70c2e94f1d8 Link: https://gethangar.au/c/9QK2MT Saved at ~/.config/hangar/certificates/0192f3b7.cert (fetched from Hangar).
A certificate from Hangar 4.17.0 states where the data of the job was and the Region policy that the job ran under. The facts then show three more lines:
Where: Staged, processed and stored in ap-southeast-4 (Melbourne) only. Records in ap-southeast-4 (Melbourne). Region policy: melbourne only, set by the organisation. Keys held in Australia. Region policy: melbourne only, set by the organisation Placement: The job runs in its preferred Region.
The facts check confirms that each place is in a Region that the policy allows, that the cell that signed is in the Region where the job ran, and that a job outside its preferred Region states why. The check also confirms that the Where line is the one that the places and the policy give.
For the return of a job of a release, hangar verify adds the release check after the facts. The check confirms three things. The vendor signed the release and TALOS Defence accepted the release. The compiled envelope is inside what the release asked for. Every connection and output stayed inside the envelope. The facts also show the release, the tenant, the envelope and the pool.
| Option | What it does |
|---|---|
--release-keys FILE | Checks the acceptance of the release against this release key set. Without this flag, the CLI uses the key set that TALOS Defence publishes |
--issuer-keys FILE | Trusts this key set as the issuer of the return. Use this flag for a return that a customer-controlled pool signed |
Credit#
$ hangar credit Credit A$34.23 Added in October A$150.00 2 payments Spent in October A$115.77 3 jobs Booked, not yet run A$104.85 HG-7K3M2Q New accounts add up to A$200 in their first seven days. You can add A$50.00 until Wed 28 Oct. Add credit with hangar credit add <amount>
$ hangar credit add 50 Stripe Checkout for A$50.00, including GST of A$4.55. Your browser is open at the payment page. Pay there. This command waits. Waiting for Stripe. Received ✓ A$50.00. Credit A$84.23. Tax invoice INV-2RJ8VD is on its way to taylor@talosdefence.com.au.
hangar credit usage [--month YYYY-MM] [--tenant TNT] shows the jobs, sessions, compute and charges of each tenant for a month. The older command hangar usage did the same.
The amount is whole Australian dollars, including GST. The terminal never takes a card number. You pay on the Stripe page in your browser, and the command waits for Stripe to confirm. The smallest top-up is A$50. A new account can add up to A$200 in its first seven days. The CLI shows how much more you can add and from when. Paid credit never expires.
Tenants, request keys and usage#
A tenant is one customer of a vendor. Tenants are for a vendor that runs work for its own customers. A request key lets a program use Hangar without a person. Every organisation whose sign-up checks have passed can make request keys. An organisation key can have the capabilities jobs, sessions, uploads and usage. Only a vendor can have a tenant key and the tenants and releases capabilities. The page for the Python package (gethangar) describes each in full.
$ hangar tenant create --ref harbour-17 --name "Harbour Water"
Tenant tnt_0192f3a1c7d84e6b9a0c5d2e1f4b7a93 created: Harbour Water ✓
Reference harbour-17. The jobs and data of this tenant stay apart from other tenants.
$ hangar tenant list
tnt_0192f3a1 Harbour Water harbour-17 active
tnt_0192f3c4 Northern Ports northern-03 suspended
$ hangar keys create --name build-server --capability jobs --capability uploads --spend-limit 200
Key hgk_syd_7c41e0b3d9f2a81c5e604b2d made for TALOS Defence Pty Ltd ✓
capabilities jobs, uploads
scope the organisation
ends Thu 21 Jan 2027
spend limit A$200.00
Secret 4c1f0a9e7b2d5c83e6f190a4d7b2c58e19f3a6d0b4e72c158a9d3f6e0b1c47a2
Hangar shows the secret this once. Keep it in your secret store.
$ hangar keys list
hgk_syd_7c41e0b3 build-server jobs, uploads organisation ends 21 Jan 2027
A$143.20 of A$200.00 spent
hgk_syd_19ad0f6e harbour-ci jobs tnt_0192f3a1 ends 2 Dec 2026
$ hangar keys limit hgk_syd_7c41e0b3 300
Key hgk_syd_7c41e0b3 may spend A$300.00 ✓. A$143.20 of A$300.00 spent.
$ hangar keys revoke hgk_syd_7c41e0b3
Key hgk_syd_7c41e0b3 revoked ✓. Requests signed with it are refused from now.
$ hangar credit usage --month 2026-10
October 2026, TALOS Defence Pty Ltd
tnt_0192f3a1 Harbour Water 12 jobs 3 sessions 4.2 vCPU-hours A$75.00
tnt_0192f3c4 Northern Ports 4 jobs 0 sessions 1.1 vCPU-hours A$20.00
Total 16 jobs 3 sessions 5.3 vCPU-hours A$95.00| Command | What it does |
|---|---|
hangar tenant create --ref REF --name NAME [--abn ABN] | Creates a tenant. list, show, suspend and resume manage the tenant. close TNT --yes closes the tenant. |
hangar keys create --name NAME --capability CAP... | Makes a request key. Use --tenant TNT for a tenant key. Use --expires DAYS (1 to 365, 90 by default). Use --source CIDR for each allowed address range. Use --save FILE to write the secret to a file of mode 0600 instead of printing the secret. |
hangar keys create ... --spend-limit DOLLARS | Gives the key a spend limit in Australian dollars, A$0.01 to A$1,000,000, including GST. A key with no limit spends inside the limits of your organisation only. |
hangar keys limit KEY DOLLARS or hangar keys limit KEY none | Sets, changes or removes the spend limit of a key. Only owners, signed in with a passkey, can run this command. The new limit applies to the next job that the key starts. A session that is already running keeps its end time. |
hangar keys list and hangar keys revoke KEY | Lists and revokes request keys. For each key that has a limit or has spent anything, the list prints what the jobs of the key have spent. |
hangar credit usage [--month YYYY-MM] [--tenant TNT] | Shows the jobs, sessions, compute and charges of each tenant for a month. |
When you set HANGAR_KEY_ID, the CLI signs each request with that request key instead of your session. The CLI reads the secret from the file that HANGAR_KEY_FILE names. The file must have mode 0600. The CLI sends HANGAR_TENANT as the tenant. A command that needs a person, such as hangar keys create, hangar book or hangar credit add, answers that you are not signed in.
An organisation key with jobs can start GPU jobs now with hangar run --gpu. The key can follow jobs with hangar status and hangar logs. The key can get outputs and certificates with hangar pull and hangar verify. The key can stop jobs with hangar stop. The key can also read the bookings and jobs of your organisation. An organisation key with uploads can send files and push or register images with hangar upload. Hangar refuses a revoked key from the next request. An image push that the key began stops. A session that the key started continues until the session ends, or until a person or another key runs hangar stop.
Where your jobs run#
Your organisation's Region policy decides where each job runs (D-20 Section 15.3). An owner sets it; every change is a record on your organisation's chain.
| Command | What it does |
|---|---|
hangar org region-policy show | Prints the setting in plain words, your organisation's home and whether the setting is locked. |
hangar org region-policy set SETTING | Sets the setting (owners only): melbourne-only, melbourne-preferred, no-preference, sydney-only or sydney-preferred. Add --lock so no job chooses another, or --unlock. An only setting is always locked. |
hangar org region-policy history | Lists every change, newest first, with who and when. |
--region sydney or --region melbourne | On any command that starts a job: this job runs in that Region only. |
--region-policy SETTING | On any command that starts a job: this job's own setting. |
A job may choose its own setting unless your organisation's setting is an only setting or is locked. Today H100 and L4 run in Sydney, Trainium2 runs in Melbourne, and CPU sessions run in Sydney. A job that cannot run under the setting is refused with region_policy_refused before anything is held or charged; the detail says why. Every job answer carries placement: the Region, the cell, the setting, its source and the reason. Run hangar help region for the five settings in plain words.
Visiting jobs#
A job that your setting places in the other Region runs in that Region's cell as a visiting job. Your home cell keeps the job's record, holds your credit for it (at most A$500 by default) and charges what the job's cell metered when the job ends. Nothing about your people or your account goes to the other cell: only your organisation's id, the job request, your account policy and the credit held.
hangar run prints where the job runs and why. It then reads the job straight from the job's cell with a visit token, so the job's logs and outputs stay in the Region the job ran in. hangar stop stops a visiting job through your home cell. A visit token reads one job only and changes nothing.
| Route | What it does |
|---|---|
GET /v1/visits | Lists your visiting jobs, newest first. |
GET /v1/visits/{id} | One visit's record: its cell, status, placement, the credit held, and at its end the charge, the metered seconds and the certificate digest. |
POST /v1/visits/{id}/stop | Stops the job in its cell. |
POST /v1/visits/{id}/token | A new read-only visit token (hgj_<cell>_...), shown once. Send it as Authorization: Hangar-Token ... to the job's read routes in its cell. It lasts one hour, and it ends when the key or person that asked for it loses access. |
A request key reaches a visiting job with the capability of its kind: jobs for a GPU job, sessions for a sandbox session. A key's spend limit covers its visiting jobs too: the credit held for a visiting job is at most what the key has left.
The residency report#
hangar org residency-report prints, signed by your cell, where each class of your organisation's data is held: your account data in your home cell and the named processors (Stripe holds your organisation id and the amounts of card payments; the mail provider holds the address of each notice and a bare notice), and your content in each cell that ran your jobs. Add --save residency.json to keep the signed report for an insurer or an auditor. The route is GET /v1/organisation/residency-report.
Each cell also checks itself every hour: no organisation of another cell holds account data there, no visiting row holds account data, no "only" organisation's job visits, and every report that leaves the cell passes its export gate. Totals leave a cell only as monthly aggregates with no organisation named and no group of fewer than 5 organisations. A report about one named organisation leaves only with that organisation's written consent or a legal ground, approved by a person with a hardware key and recorded on that organisation's chain.
Help#
hangar help hangar help book hangar book --help
hangar help lists the commands in the order that you use them. The order is the five most used commands, then jobs and money, then More, then the older names. hangar help <command> prints the options of that command.
Shell completion#
source <(hangar completion zsh) # in ~/.zshrc source <(hangar completion bash) # in ~/.bashrc hangar completion fish > ~/.config/fish/completions/hangar.fish
Homebrew installs these scripts for you.
Coding agents#
hangar mcphangar mcp gives nights, book, upload, run, status, certificate and verify to a coding agent over the Model Context Protocol, on standard input and output. The agent gets the same results and the same sentences as the commands. The agent acts as the person who is signed in on this machine. book takes night, at and hours. book only holds the hours, unless the agent passes confirm: true. confirm: true charges credit. run takes booking, or cpu and stop_after, with image and command.
Errors#
Every error has three lines and nothing else: what failed, the next step, and what to do if the next step fails. The third line is a second step to try, or the support address with what to quote. For an error from the API, the third line shows the reference of the request. With --json, the CLI prints the error as {"error": {"code", "sentence", "next_step", "if_that_fails", "reference", "detail"}} on standard output. reference and detail appear only when the API sent them. The code does not change, so scripts can use the code. The website shows the same sentences for the same error.
Settings#
| Variable | What it does |
|---|---|
HANGAR_CONFIG_DIR | Keeps the session, cache and certificates in another folder, for a second account |
HANGAR_API | Another Hangar address, for development. The CLI accepts http:// for this machine only. Without it, the CLI sends each request to the API of the cell that the session or key names |
HANGAR_CA_FILE | A PEM file of extra certificate authorities, for a development address with its own certificate authority |
HANGAR_NO_BROWSER=1 | Prints the sign-in and payment addresses and does not open a browser |
HANGAR_KEY_ID | Signs each request with this request key instead of the signed-in session |
HANGAR_KEY_FILE | The file that contains the secret of that key. The CLI refuses the file unless the mode is 0600 |
HANGAR_TENANT | The tenant that the requests of a request key act for |
HANGAR_NO_INPUT=1 | Turns off every question, also on a terminal. A missing value is an error that shows the flag to add |
CI | CI systems set this variable. It has the same effect as HANGAR_NO_INPUT: the CLI asks no question |
SSL_CERT_FILE | The certificate authority bundle, when your system keeps the bundle in an unusual place |
NO_COLOR | Turns off colour on every stream |
CLICOLOR_FORCE=1 | Turns colour on in a pipe. NO_COLOR overrides CLICOLOR_FORCE=1 |
COLORTERM=truecolor | Gives the exact gold. Most modern terminals set this variable |
COLORFGBG | Some terminals set this variable. A light background uses the gold of the light theme |
The connection to Hangar uses TLS 1.3 (an encrypted connection). The CLI checks the connection against the certificate authorities that your system trusts.