Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

747 linesCodeBlameRaw
1---
2title: The g1t CLI
3description: Install the g1t command line, sign in, and work with repositories, work items, pull requests, runs, workflows, deployments, secrets and logs from a terminal, a script or an agent.
4---
5
6`g1t` is the command line for g1t. It does the work you would otherwise do on
7the site: open and review pull requests, wait on checks, read a failing run's
8logs, set secrets, read a project's logs, and call any operation of the
9[API](/reference/api/). It is one file with nothing to install alongside it,
10and it is built to be run by agents as much as by people: every command can
11print JSON, nothing waits for input unless a person is at the terminal, and
12exit codes say what happened.
13
14```sh
15g1t work list --label bug
16g1t pr create --fill
17g1t pr checks --watch --fail-fast
18g1t run logs --failed
19```
20
21Every command and flag is listed in the [command reference](/reference/cli/).
22
23## Install
24
25### Homebrew
26
27On macOS or Linux, add the official tap hosted on g1t, then install:
28
29```sh
30brew tap flagon-io/tap https://g1t.sh/flagon-io/homebrew-tap.git
31brew install flagon-io/tap/g1t
32```
33
34The [tap source](https://g1t.sh/flagon-io/homebrew-tap) pins each platform's
35binary and SHA-256 checksum to a release. Update Homebrew installations with
36`brew update && brew upgrade flagon-io/tap/g1t`.
37
38### Install script
39
40On Linux or macOS:
41
42```sh
43curl -fsSL https://g1t.sh/install | sh
44```
45
46On Windows, in PowerShell:
47
48```powershell
49irm https://g1t.sh/install.ps1 | iex
50```
51
52The script picks the build for your system, checks it against the
53release's `SHA256SUMS`, and puts `g1t` in `~/.local/bin` (Windows:
54`%LOCALAPPDATA%\g1t\bin`, which it adds to your `PATH`). Set
55`G1T_INSTALL_DIR` to put it elsewhere, or `G1T_VERSION` to install a
56version other than the latest.
57
58### Upgrade
59
60From 0.3.4 on, `g1t upgrade` updates g1t to the newest release:
61
62```sh
63g1t upgrade # download and install the newest release
64g1t upgrade --check # only say whether there is one
65```
66
67It reads the newest release's manifest, `latest.json`, and checks its
68signature (`latest.json.sig`) against g1t's release key, which is built
69into every release. It then downloads the build for your system, checks
70its SHA-256 against the manifest, and puts it where the running `g1t` is.
71If anything does not check out, nothing changes. Releases come from
72`https://g1t.sh/downloads/cli`, or from `G1T_DOWNLOAD_URL` if you set it.
73
74In a terminal, g1t looks for a newer release about once a day, in the
75background, and says so after a command when there is one. It never looks
76in CI or when its output is not a terminal. Set `G1T_NO_UPDATE_NOTIFIER=1`
77to turn it off.
78
79A g1t built from source has no release key and cannot upgrade itself.
80Neither can versions before 0.3.4. Update those by running the install
81script again.
82
83### Without the script
84
85Each release is a single file per platform, at
86`https://g1t.sh/downloads/cli/latest/`:
87
88| Platform | File |
89| --- | --- |
90| Linux, x64 | `g1t-linux-x64` |
91| Linux, ARM | `g1t-linux-arm64` |
92| macOS, Apple silicon | `g1t-macos-arm64` |
93| macOS, Intel | `g1t-macos-x64` |
94| Windows, x64 | `g1t-windows-x64.exe` |
95
96```sh
97curl -fsSLo g1t https://g1t.sh/downloads/cli/latest/g1t-linux-x64
98chmod +x g1t && mv g1t ~/.local/bin/
99```
100
101Check a download against `https://g1t.sh/downloads/cli/latest/SHA256SUMS`.
102`latest.json` beside it names the version and each file's SHA-256, and
103`latest.json.sig` is its signature. A given version's files are at
104`/downloads/cli/<version>/` and never change.
105
106To build it from source, with [Rust](https://www.rust-lang.org/tools/install):
107
108```sh
109git clone https://g1t.sh/flagon-io/g1t
110cargo install --path g1t/crates/g1t
111```
112
113`g1t --version` prints the version you have.
114
115### Behind a TLS proxy
116
117From 0.3.5 on, g1t trusts the certificates in your system's store, as
118curl and git do. A sandbox or corporate network that inspects HTTPS (a
119Claude Managed Agents sandbox, a guarded runner) adds its proxy's
120certificate there, so g1t works through it with nothing to set. Earlier
121versions trusted only a list built into the CLI and refused such a proxy.
122
123## Sign in
124
125```sh
126g1t auth login
127```
128
129`g1t` shows a one-time code and opens your browser at
130[g1t.sh/device](https://g1t.sh/device). Sign in there if you are not
131already, check the code matches, and approve. The command finishes on its
132own once you have. Where there is no browser (a server, a container, a
133remote shell), it prints the link instead: open it on any device.
134
135To use an [access token](/guides/authentication/#access-tokens) you already
136have, pipe it in:
137
138```sh
139g1t auth login --with-token < token.txt
140```
141
142The token is kept in your system's credential store: the Keychain on
143macOS, Credential Manager on Windows, the Secret Service on Linux. Where
144there is none, as on most servers, it goes in the [config
145file](#settings-and-environment), readable only by you; `--insecure-storage`
146puts it there on purpose.
147
148| Command | What it does |
149| --- | --- |
150| `g1t auth status` | Each account you are signed in as, on each host, whether its token still works, and its scopes. Exits `4` when the active account's token does not work. |
151| `g1t auth token` | Prints the token in use, for another program. |
152| `g1t auth logout` | Forgets an account's token. |
153| `g1t auth switch` | Makes another signed-in account on the same host the active one. |
154
155### G1T_TOKEN
156
157When `G1T_TOKEN` is set, every command uses it instead of a stored token.
158This is how to give `g1t` a token in containers, in agents' sandboxes, and
159in [workflows](/guides/actions/), where the job's own token is
160`secrets.G1T_TOKEN`:
161
162```yaml
163- run: g1t pr comment ${{ github.event.pull_request.number }} -b "Preview is up."
164 env:
165 G1T_TOKEN: ${{ secrets.G1T_TOKEN }}
166```
167
168### Self-hosted g1t
169
170`g1t` works with any g1t, not only g1t.sh. Sign in to yours with its
171address:
172
173```sh
174g1t auth login --hostname git.example.com
175```
176
177`g1t` asks it where its API is (its `/.well-known/g1t.json`), and remembers.
178After that, commands in a clone of one of its repositories talk to it on
179their own. Elsewhere, name it with `--hostname` or `G1T_HOST`; the first host
180you sign in to is the default. You can be signed in to several hosts, and
181as several accounts on each.
182
183## Use it with git
184
185```sh
186g1t auth setup-git
187```
188
189This makes `g1t` git's credential helper for each host you are signed in
190to, so `git push`, `git fetch` and `git clone` over HTTPS use the same
191token, with nothing more to type. It changes your global git config only for
192those hosts' addresses (`credential.https://g1t.sh.helper`). `g1t auth login
193--git` does both at once. To see the config lines without changing anything,
194add `--dry-run`.
195
196[`g1t push`](/guides/containers/#push-large-layers-with-g1t-push), which sends container
197images to g1t's registry, uses the same signed-in token.
198
199## Which repository
200
201Commands about a repository work on the one the current directory is a
202clone of, found from its git remotes: `upstream` if it is on g1t, then
203`origin`, then the first one that is. In a pull request's own [working
204copy](/concepts/forks/#working-copies-for-pull-requests), they work on the repository the pull request
205is for.
206
207Anywhere else, or to choose another, pass `--repo` (`-R`), or set
208`G1T_REPO`:
209
210```sh
211g1t pr list -R acme/web
212g1t pr view 14 -R git.example.com/acme/web
213```
214
215## Everyday work
216
217### Repositories
218
219```sh
220g1t repo create my-project --source . --remote g1t # make it, add it as a remote, push
221g1t repo create acme/web --public --clone
222g1t repo create acme/site --deploy # its g1t.page deployments on from the start
223g1t repo list acme
224g1t repo view acme/web --web
225g1t repo clone acme/web
226g1t repo fork acme/web --clone
227g1t repo sync # bring your fork's default branch up to date
228```
229
230A repository is private unless `--public` says otherwise, and is made in
231your own workspace unless its name says `WORKSPACE/NAME`. `--source`
232adds it as a remote of a local repository (`origin` unless `--remote`
233names another) and pushes its current branch. `g1t repo fork` forks into
234your own workspace, or `--workspace`; see
235[forking a repository](/guides/forking-repositories/).
236
237### Work items
238
239```sh
240g1t work list # open work items, newest first
241g1t work list --label bug --assignee @me
242g1t work list -R acme/web # those linked to one repository
243g1t work list -R acme/web --role target # those it is a target of
244g1t work view 12 --comments
245g1t work new --title "Greeting should name the caller" --body "Take a name from the first argument."
246g1t work new --title "Rename the flag" --target acme/api --target acme/docs
247g1t work comment 12 -b "Fixed in #14."
248g1t work edit 12 --add-label p1 --add-assignee @me
249g1t work link 12 --role target -R acme/api
250g1t work unlink 12 -R acme/api
251g1t work close 12 --reason not_planned
252g1t work reopen 12
253```
254
255[Work items](/work/work-items/) belong to the workspace, and `g1t work`
256works on the current repository's workspace, or the one in `--workspace`
257(or `G1T_WORKSPACE`). `-R` filters `g1t work list` to the work items
258linked to that repository, and names the repository `g1t work link` and
259`g1t work unlink` act on.
260`g1t work new` makes the current repository the new work item's origin,
261and `--target` names each repository it should land in.
262`g1t work view` shows the work item with its whole work context (see
263[Claims and context](#claims-and-context)). `@me` is you. At a terminal,
264`g1t work new` without `--title` asks for one and opens your editor for
265the body.
266
267### Images in descriptions and comments
268
269`g1t attach` uploads images, such as a screenshot of a preview, and prints the
270Markdown that shows each, to paste into a description or a comment:
271
272```sh
273g1t attach preview.png # prints ![preview.png](https://g1tusercontent.com/attachments/…)
274g1t attach before.png after.png --json # id, name, url, markdown, content_type and size of each
275g1t pr comment 14 -b "The preview, after the fix:" --attach preview.png
276g1t pr ready --summary "Names the caller." --attach preview.png
277```
278
279`--attach FILE` (repeat it for more) on `g1t work new`, `g1t work comment`,
280`g1t pr create`, `g1t pr comment` and `g1t pr ready` uploads each file and adds
281its Markdown after the text. `g1t attach` and the `g1t pr` commands upload to
282the repository. `g1t work comment --attach` uploads to the work item, which
283keeps the files. `g1t work new --attach` uploads to the repository the work
284item is filed from; filed in the workspace alone (with `--workspace` and no
285repository of it here), it opens the work item first, then uploads to it and
286adds the Markdown to its description. An attachment is a PNG, JPEG, GIF or WebP image of
287at most 10 MB, judged by its bytes. It is served from g1t's usercontent address,
288never from g1t.sh, and its address is its permission: anyone given it can see
289the image, even from a private repository. Never commit an image to the
290repository just to link it. Through the API it is
291[`upload_attachment`](/reference/api/work-items/upload-attachment/)
292(`POST /repos/{owner}/{name}/attachments`) for a repository, and
293[`upload_work_item_attachment`](/reference/api/work-items/upload-work-item-attachment/)
294(`POST /workspaces/{workspace}/work/{number}/attachments`) for a work item.
295
296### Pull requests
297
298From a branch with your commits on it:
299
300```sh
301git switch -c greet-by-name
302# ...commit...
303g1t pr create --fill --item 12
304```
305
306`g1t pr create` pushes the branch, then opens the pull request into the
307default branch (`--base` for another). `--fill` takes the title and body from
308the branch's commits; `--item` says which work item it is for, by its
309number in the workspace; `--draft` opens it as a draft.
310
311To start a pull request for a work item without a branch of your own, as
312coding agents usually do, run it with `--item` from the default branch. g1t opens a draft
313with a [working copy](/concepts/forks/#working-copies-for-pull-requests) of its own and prints the
314copy's git remote. Push your commits there, then mark it ready with a
315summary of what changed and why:
316
317```sh
318g1t pr create --item 12
319git push https://g1t.sh/pulls/pr_….git HEAD:main
320g1t pr ready --summary "Reads a name from the first argument."
321```
322
323Then, for any pull request:
324
325```sh
326g1t pr list
327g1t pr view 14 # the current branch's when left out
328g1t pr diff 14
329g1t pr checkout 14 # check its head out locally
330g1t pr checks 14 --watch
331g1t pr review 14 --approve -b "Reads well."
332g1t pr review 14 --request-changes -b "Trim the name first."
333g1t pr merge 14 --delete-branch
334```
335
336`g1t pr merge` merges the way the repository is set to, once
337[required checks](/guides/checks/) pass and [rules](/guides/rules/) allow;
338`--admin` merges past them, with the Admin role.
339
340### Checks and runs
341
342`g1t pr checks` lists a pull request's checks: g1t Actions jobs, check runs
343and commit statuses. With `--watch` it waits until they have all finished,
344redrawing at a terminal and printing a line per change when piped.
345`--fail-fast` stops at the first failure instead of waiting for the rest. It
346exits `0` when every check passed, `1` when one failed, and, without
347`--watch`, `8` while any are still running.
348
349```sh
350g1t run list --branch main
351g1t run view # the current branch's latest run
352g1t run watch run_01kpx7b3c6d9e2f5g8h1j4k7mr
353g1t run logs --failed
354g1t run rerun --failed
355```
356
357A run is named by its id (`run_…`), its number, or its address; left out,
358it is the current branch's latest. `g1t run logs --failed` prints only the
359steps that failed, each with its last 60 lines (`-n` for more or fewer):
360what you need to see why, without the rest of the log. `g1t run watch`
361exits `1` if the run fails.
362
363### Workflows
364
365`g1t workflow` works with the workflows in `.g1t/workflows`, as the
366repository's **Actions** page does.
367
368```sh
369g1t workflow list # those turned on; --all for every one
370g1t workflow view ci.yml # its triggers, inputs and latest runs
371g1t workflow view release.yml --yaml --ref v1.4.0
372g1t workflow run release.yml -f channel=stable
373g1t workflow disable Nightly
374g1t workflow enable nightly.yml
375```
376
377A workflow is named by its file name (`ci.yml`), its id (`wfl_…`) or its
378name (`CI`, in any case). When more than one has that name, name it by its
379file. Left out at a terminal, g1t asks which; in a script it is an error
380that names what to pass.
381
382`g1t workflow run` runs a workflow that has `on: workflow_dispatch`, on the
383default branch or the branch or tag `--ref` names, and prints its run's
384address once the run is there, so `g1t run watch` can follow it. Give its
385inputs with `-f key=value` (or `-F key=@file` to read a value from a file),
386or as one JSON object on stdin with `--json`:
387
388```sh
389echo '{"channel":"stable","dry_run":true}' | g1t workflow run release.yml --json
390```
391
392At a terminal with no inputs given, g1t asks for each, offering its
393default. Only the inputs the workflow declares are taken, as on the
394[Actions page](/guides/actions/#runs-and-logs). `g1t workflow view --yaml`
395prints the workflow's file as it is on the default branch, or on `--ref`.
396Turning a workflow off keeps its file: nothing starts it until it is
397turned on again, and a workflow the workspace requires stays on.
398
399### Deployments, logs and secrets
400
401```sh
402g1t deploy list --env production
403g1t deploy view dep_01kq8m3t5v7x9z1b3d5f7h9k2m
404g1t deploy enable # turn on this project's g1t.page deployments
405g1t deploy settings --project acme/web --previews off --build-command "npm run build:site"
406
407g1t logs --since 1h --level error,fatal
408g1t logs -q '"payment failed"' --follow
409g1t logs --errors --state open
410
411g1t secret list
412echo "$NPM_TOKEN" | g1t secret set NPM_TOKEN
413g1t secret set STRIPE_KEY --env production < stripe-key.txt
414g1t secret set NPM_TOKEN --brokered-host registry.npmjs.org < npm-token.txt
415g1t secret delete STRIPE_KEY --env preview
416g1t secret list --workspace acme
417```
418
419`g1t logs` reads the [observability](/guides/observability/) data of the
420current repository's project, or of `--project WORKSPACE/SLUG`. A secret's
421value is read from stdin, so it stays out of your shell's history; at a
422terminal with nothing piped, `g1t` asks for it without echoing. Values are
423never printed. `--brokered-host` makes it a [brokered
424secret](/guides/secrets-and-variables/#brokered-secrets).
425
426### What needs you
427
428```sh
429g1t status
430```
431
432Your open pull requests and their checks, reviews asked of you, what is
433assigned to you, and failing checks, across every repository you can see.
434Inside a working copy it also lists your active sessions and claims in that
435repository.
436
437## Coordinating work
438
439When several people and agents work in one repository, `g1t session` and
440`g1t work` say who is on what, so nobody starts work that is already under
441way and everyone hears what changes under them. Claims are advisory: a
442claim never stops anyone, it tells them.
443
444### Sessions
445
446A session is one run of an agent's harness, such as one Claude Code
447session. Starting one remembers it for the working copy, and the commands
448after it use it:
449
450```sh
451g1t session start --harness claude-code --item 12
452g1t session log "Split the parser before touching the lexer."
453g1t session attach --pull 14 --head-commit "$(git rev-parse HEAD)"
454g1t session heartbeat
455g1t session end --reason done
456```
457
458| Command | What it does |
459| --- | --- |
460| `g1t session start` | Starts a session and prints its id. `--harness` (`claude_code`, `codex`, `cursor`, `copilot` or `other`; `claude-code` works too), `--harness-session-id`, `--item`, `--pull`, `--branch` (the current one by default) and `--title`. Starting again with the same `--harness-session-id` returns the same session. For a subagent, `--parent` (the session that started it), `--agent-type`, `--task`, `--prompt` and `--model`; a subagent's session is not kept as the working copy's (nor is one with `--no-remember`). |
461| `g1t session heartbeat` | Says the session is still working, and renews its claims. A session with no heartbeat for 15 minutes reads as idle, and after 30 minutes as ended; a heartbeat brings it back. |
462| `g1t session log TEXT` | Records a note. `--kind` takes `note`, `prompt`, `message`, `tool_call` (or `tool-call`) or `skill` (a skill's name), `--tool` names the tool, and `--key` makes recording the same entry twice do nothing. `-` reads the text from stdin; put `--` before text that starts with a dash. |
463| `g1t session attach` | Points the session at an `--item`, a `--pull`, a `--branch` or its latest `--head-commit`, or gives it a `--title`: what it is for, which replaces the title it had. |
464| `g1t session touch` | Says what the session touched: `--file PATH`, `--commit SHA`, `--branch NAME`, `--pull N` (one it opened), `--item N`, each repeatable. Ties the session to the pull requests and work items they lead to; a file another active session touched too is an `overlap.detected` for both. |
465| `g1t session updates [ID]` | What other sessions did that concerns this one (claims, overlaps, dependency changes, decisions, merge queue results), oldest first, up to 100. Reading never clears them. It first says which files the working copy changed, so overlapping edits are noticed (`G1T_TOUCH=0` turns that off). |
466| `g1t session acknowledge ID... --note TEXT` | Records your decision about those updates (what changes in your plan, or why nothing does) and clears exactly the IDs given, for this session only; `--session` names another of yours. Saying the same again does nothing. |
467| `g1t session end` | Ends it, with an optional `--reason` and `--result` (what it reported; `-` reads it from stdin), and forgets it. Its subagents still going end with it. |
468| `g1t session list` | The repository's sessions; `--state active`, `--item`, `--pull` (any session tied to it), `--path` (those that touched a file, or a folder ending in `/`), `--subagents` to list subagents under the sessions that started them. `--workspace` (this repository's workspace) or `--workspace SLUG` lists the sessions of every repository of a workspace instead, narrowed by `--harness`, `--person`, `--in NAME` (a repository of it), `--state`, `--item` and `--subagents`; see [the Sessions page](/work/sessions/). |
469| `g1t session view [ID]` | A session and what it recorded, its subagents and their results, the work items and pull requests it worked on, and the skills used; the current one without an id. |
470
471The id is kept in `.git/g1t/session`, in the working copy's own git
472directory, so each worktree has its own. `G1T_SESSION` overrides it, for
473a harness that runs several sessions in one working copy.
474
475### Claims and context
476
477```sh
478g1t work view 12 # everything about #12's work
479g1t work claim 12 --note "Taking the parser" --ttl 1h
480g1t work claim --title "Preview builds time out" --body "Over 1 GB, the build stops at 10 minutes."
481g1t work release 12 --reason done
482g1t work handoff 12 --to ana --note "Parser done; lexer tests still fail."
483g1t work status # active claims and sessions here
484```
485
486`g1t work view` is the one call to make before starting: the work item and
487its definition of done, its repositories with their roles and which have
488landed, who has claimed it, its sessions, its pull
489requests with their checks, overlaps and place in the merge queue, what it
490waits on and what waits on it, its decisions, its last integration failure
491and its recent events.
492
493`g1t work claim` says you are working on a work item. It lasts 30 minutes
494unless `--ttl` says otherwise (at most `4h`), and a heartbeat of the session
495it was made in renews it. It is made in the current session, if there is
496one. If others have claimed the work item too, or it waits on work items
497that are not done, the answer says so. `g1t work handoff` ends your claim and asks
498`--to` someone, or anyone without it, to take the work item over, with a
499`--note` saying where it stands. Claims, releases and hand-offs are the
500current session's, so two sessions of yours (sibling subagents) each hold
501their own.
502
503For work that has no work item yet, `g1t work claim --title "…"` (with
504`--body` for its description) opens the work item, with the current
505repository as its origin, and claims it in one step, and attaches the
506current session to it; it prints the new work item's number. Use it once
507the work is a change others should know about, after looking for a work
508item that already covers it; questions, exploration and trivial
509fixes need none. A number and `--title` together are refused.
510
511### Starting a session on a work item
512
513```sh
514g1t work dispatch 12 # on the workspace's Anthropic account
515g1t work dispatch 12 --mode plan --instruction "Keep the old flag"
516g1t work dispatch --title "Add a healthcheck" --handoff # open the work item; print a claude command
517```
518
519`g1t work dispatch` starts work on a work item in a session on your own
520Claude: with the workspace's Anthropic [AI provider](/guides/ai/), a Claude Managed Agents
521session on that account (it prints the session's page on g1t); without
522one, or with `--handoff`, the `claude` command line to run in your working
523copy with g1t's [Claude Code plugin](/guides/claude-code-plugin/).
524`--managed` fails rather than hand off. `--mode` is `plan`, `implement` or
525`review`. See [Start a session on your Anthropic account](/guides/sessions/#start-a-session-on-your-anthropic-account).
526
527`g1t work edit 12 --add-assignee g1t` does the same as **Assign to g1t**
528on the site: g1t starts a session on the work item on the workspace's
529Anthropic account, as you. See
530[Assign g1t](/guides/sessions/#assign-g1t-or-ask-it-in-the-thread).
531
532### Dependencies
533
534```sh
535g1t work block 12 --by 9 --by 10 # #12 waits on #9 and #10
536g1t work unblock 12 --by 9
537```
538
539These change the work item's `blocked_by` through `update_work_item`. A
540work item waits only on work items of its workspace, never on itself, and
541g1t refuses a cycle.
542
543### Following events
544
545`g1t work events` prints the repository's recent events, oldest first.
546With `--follow` it keeps printing them as they happen, without a webhook or
547a public address, until you stop it with Ctrl-C:
548
549```sh
550g1t work events --follow --item 12
551g1t work events --follow --type integration.failed --type overlap.detected --json
552```
553
554| Flag | |
555| --- | --- |
556| `--type`, `-t` | Only events of this type, such as `work.claimed`; repeat for more. |
557| `--item`, `-i` | Only events about this work item or pull request; repeat for more. |
558| `--since`, `-s` | Only events since then: `15m`, `2h`, `1d`, or an RFC 3339 time. |
559| `--after` | Start after this event id, to resume where an earlier follow stopped. |
560| `--limit`, `-L` | How many past events to show first; 20 by default. |
561
562Each event is one line: its time, type, work item or pull request, a summary
563and its id. With `--json`, each is one compact JSON object on a line of its
564own, so a program can read them as they come. Following asks
565[`list_events`](/reference/api/repositories/list-events/) with `after` and
566`wait`, so the server holds each request until something happens; when a
567call fails, `g1t` waits (1 second, then longer, up to 30) and resumes from
568the last event it printed. A refused token stops it with exit code `4`.
569
570### Why a line is as it is
571
572```sh
573g1t why src/parser.rs:120
574g1t why src/parser.rs --ref main
575```
576
577`g1t why` follows a line to the commit that last changed it, the pull
578request that merged that commit, the work item the pull request was for, and
579the decisions and sessions recorded on them. A path is read from where you
580are in the working copy.
581
582### In an agent's hooks
583
584These commands are made to be run by a harness's hooks in the background:
585they never ask anything, they fail at once with exit code `4` when there is
586no token, and they give up on a call after 15 seconds. Against a g1t server
587older than the CLI, a command it cannot do yet fails saying so.
588
589## Scripting with JSON
590
591Every command takes `--json`. Alone, it prints every field the API returns;
592with a comma-separated list, only those (`g1t workflow run` is the one
593exception: there, `--json` alone reads the inputs from stdin):
594
595```sh
596g1t pr list --json number,title,check_status
597```
598
599```json
600[{"check_status":"passed","number":14,"title":"Greeting should name the caller"}]
601```
602
603The fields are the API's own, named as in the [API reference](/reference/api/)
604and always `snake_case`. A field that does not exist is an error that lists
605the ones that do. Piped, JSON is one compact line with its keys in a fixed
606order, so the same input gives the same output; at a terminal it is
607indented.
608
609`--jq` runs a [jq](https://jqlang.org/manual/) expression over the JSON,
610with nothing else to install. Strings come out bare, everything else as
611JSON:
612
613```sh
614g1t pr list --jq '.[] | select(.check_status == "failed") | .number'
615g1t run list --jq '.[] | [.id, .conclusion] | @tsv'
616```
617
618Without `--json`, output piped to another program is one record per line,
619fields separated by tabs, with no header and no color, ready for `cut`,
620`awk` or `while read`. Lists show 20 entries unless `--limit` (`-L`) says
621otherwise.
622
623### Exit codes
624
625| Code | Meaning |
626| --- | --- |
627| `0` | It worked. |
628| `1` | It failed: the API refused it, the network failed, checks or a run failed. |
629| `2` | The command was used wrongly: an unknown flag, a missing argument, a JSON field that does not exist. |
630| `4` | Signing in is needed, or the token was refused. |
631| `8` | Checks are still running (`g1t pr checks` without `--watch`). |
632
633An error is one line on stderr, starting `g1t:`. When a token lacks a
634[scope](/guides/authentication/#scopes) the call needs, the line names it.
635
636### No questions when piped
637
638`g1t` asks for a missing title, opens an editor for a body, or offers a
639choice only when stdin and stderr are both a terminal. Anywhere else, and
640whenever `G1T_PROMPT_DISABLED` is set, a command missing something fails at
641once with exit code `2` and names the flag that supplies it.
642
643## Call any operation
644
645`g1t api` calls any operation of the [API](/reference/api/) by its name,
646with your token, and fills the repository in from where you are:
647
648```sh
649g1t api list_work_items -f state=closed --jq '.[].title'
650g1t api create_label -f name=p1 -f color=d73a4a
651g1t api get_workflow_run -f id=run_01kpx7b3c6d9e2f5g8h1j4k7mr
652g1t api --list label # the operations about labels
653```
654
655A path works too, with `{owner}`, `{name}` and `{workspace}` filled in:
656
657```sh
658g1t api /workspaces/{workspace}/labels
659g1t api user --jq .username
660```
661
662`-f key=value` sends a string, `-F key=value` sends `true`, `false`, `null`
663and numbers as JSON and `@file` as a file's contents, and `key[]=value` adds
664to a list. Fields go in the query of a `GET` and in the JSON body otherwise.
665`-X` sets the method, `-H` adds a header, and `--input file` sends a file as
666the body. `--paginate` follows each next page, and with `--slurp` puts every
667page's items in one array. A request the API refuses prints its error body
668and exits `1`.
669
670In Git Bash on Windows, an argument starting with `/` is turned into a
671Windows path before `g1t` sees it: leave the leading slash off
672(`g1t api repos/{owner}/{name}`), or set `MSYS_NO_PATHCONV=1`.
673
674## From agents and harnesses
675
676An agent with a shell, such as Claude Code, Codex or Cursor, can use `g1t`
677the way you do. A command and its JSON cost an agent less of its context
678than a set of tool definitions, and the agent finds what it needs with
679`--help`. For clients without a shell, use the [MCP server](/reference/mcp/).
680
6811. Install `g1t` where the agent runs, as [above](#install).
6822. Give it a token. Either sign in once with `g1t auth login` as the user
683 the agent runs as, or set `G1T_TOKEN` in its environment. Make a token
684 with only the [scopes](/guides/authentication/#scopes) it needs.
6853. Tell it `g1t` is there. A few lines in the project's `CLAUDE.md` or
686 `AGENTS.md` are enough:
687
688```md
689This repository is on g1t. Use the `g1t` CLI for work items, pull requests,
690checks and runs; add `--json` to read results, and see `g1t <command> --help`.
691
692- Open a pull request: `g1t pr create --fill --item <n>`
693- Wait for checks: `g1t pr checks --watch --fail-fast` (exit 0 passed, 1 failed)
694- See why a run failed: `g1t run logs --failed`
695- Run a workflow by hand: `g1t workflow run <file> -f key=value`
696- Anything else: `g1t api --list <word>`, then `g1t api <operation>`
697```
698
699`g1t` never waits for input in an agent's shell, since its stdin is not a
700terminal. Its JSON is compact and in a stable order, its lists are short
701by default, and `g1t pr checks --watch --fail-fast` and `g1t run logs
702--failed` give an agent the one thing it is waiting for, and no more.
703
704## Aliases and completion
705
706An alias is a shortcut for a command you type often. `$1`, `$2`… take the
707arguments after it, and the rest go on the end:
708
709```sh
710g1t alias set bugs 'work list --label bug'
711g1t alias set co 'pr checkout'
712g1t alias set mine '!g1t pr list --author @me --json number,title'
713g1t bugs --limit 5
714```
715
716An alias starting with `!` runs in `sh`. `g1t alias list` lists them, and
717`g1t alias delete` removes one.
718
719`g1t completion <shell>` prints a completion script for `bash`, `zsh`,
720`fish`, `powershell` or `elvish`:
721
722```sh
723g1t completion bash > ~/.local/share/bash-completion/completions/g1t
724g1t completion zsh > "${fpath[1]}/_g1t"
725g1t completion fish > ~/.config/fish/completions/g1t.fish
726g1t completion powershell >> $PROFILE
727```
728
729## Settings and environment
730
731`g1t` keeps the hosts you are signed in to, their accounts and your aliases
732in `config.json`, in `~/.config/g1t` (`%APPDATA%\g1t` on Windows;
733`$XDG_CONFIG_HOME/g1t` when that is set).
734
735| Variable | |
736| --- | --- |
737| `G1T_TOKEN` | A token to use instead of the stored one. |
738| `G1T_HOST` | The host to use when no repository names one. |
739| `G1T_REPO` | The repository, as `[HOST/]OWNER/NAME`. |
740| `G1T_WORKSPACE` | The workspace `g1t work` works on, as `--workspace` says. |
741| `G1T_CONFIG_DIR` | Where to keep `config.json`. |
742| `G1T_KEYRING` | `off` keeps tokens out of the system's credential store. |
743| `G1T_PROMPT_DISABLED` | Never ask anything. |
744| `G1T_EDITOR`, `VISUAL`, `EDITOR` | The editor for bodies and summaries. |
745| `G1T_BROWSER`, `BROWSER` | The browser `--web` and `g1t browse` open. |
746| `NO_COLOR` | Plain output at a terminal too. |
747| `G1T_DEBUG` | Print each request's method, address and status on stderr. |