Skip to content

Output

Every command renders one semantic view. The human-readable preview is the default, and --json and --porcelain are alternative renderers over exactly the facts the graph shows, so nothing has to parse decorated terminal text.

These are root flags, accepted by every command:

Flag Does
--json emit one JSON document instead of the human-readable preview
--porcelain emit stable tab-separated records instead of the human-readable preview
--no-links do not attach hyperlinks to pull request numbers
--debug write safe diagnostic events to stderr
--timeout <duration> the maximum duration for each phase, discovery and mutation separately

Colour is enabled only for an interactive terminal. It is disabled for redirected output, CI, NO_COLOR, and TERM=dumb, so the plain graph is deterministic for scripts. In colour output, headers, trunks, branches, pull request numbers, unresolved state, and success use distinct, restrained roles; the renderer keeps plan data separate from the ANSI decoration.

Pull request numbers are hyperlinks where the terminal supports them. The text is unchanged, so #42 reads as #42 either way and a terminal without OSC 8 support loses nothing. Links follow the same interactive-terminal rule as colour but deliberately ignore NO_COLOR, which asks for output without colour, and a hyperlink is not colour. --no-links turns them off; --json and --porcelain never emit them.

A number points at GitHub when GitHub reported an address for it. That address came back from the API rather than being assembled, so it cannot be wrong about the repository. Otherwise it points at Graphite’s view of the same pull request (https://app.graphite.com/github/pr/<owner>/<name>/<number>), which a repository that does not use Graphite never produces.

Nothing but whitespace ever shares the line holding a copyable command: no prompt character, border, or annotation. A loose, wrapped, or whole-line selection can only pick up spaces, which a shell ignores. In colour output the highlight is padded a few columns past the command to widen the click target, and every highlighted command, on its own line or inside a sentence, carries a column of background on each side. Those columns are painted rather than written: without colour the text reads exactly as it was typed.

A hint that names a command mid-sentence draws it with the same highlight, so you can see where it starts and ends without reading the prose around it. Which words are a command is recorded when the sentence is written rather than found by a pattern afterwards, so what is highlighted is exactly what can be copied and run. Plain output, --json, and --porcelain carry the sentences unchanged.

--json and --porcelain both suppress colour and every human-facing line, emitting only the document. They are mutually exclusive, and the default stays the human-readable preview.

Terminal window
# One JSON object with a schemaVersion, the operation, the trunk, each
# branch's pull request and state, and the validated command when one applies.
g2g github status --json
# Stable tab-separated records, each led by its type:
# target <branch> <source>
# trunk <branch>
# branch <name> <pr> <state> <severity> <url> <target?> <parent?>
# blocked <reason>
# repair <reason>
# way <command> <effect>
# command <argv>...
# step <n> <command> <effect>
# note <severity> <text>
# comment <pr> <branch> <action> <reason>
g2g github link --porcelain
  • operation is the command’s path as you would type it after g2g: status, pull, github link, graphite adopt.
  • parent is populated by g2g status, where order alone cannot express structure once a graph forks. The linear commands leave it empty, and their order still holds. In porcelain it is appended after the fields that shipped before it, so an existing reader keeps working.
  • blocked is reported alongside command, not instead of it, so a consumer can see the destination and decide for itself. Check blocked before acting on command.
  • repair is what to do about blocked, with each way out carried as a command and what running it achieves, so a consumer does not have to find the command inside a sentence. A way out with no command is a whole answer that is not a thing to run, such as “fetch and reconcile first”, rather than a step with a field missing. A refusal that nothing here fixes carries no repair at all. It is also reported where nothing is blocked and there is still something to do: a branch no source describes is a state, not a refusal. See When a command refuses.
  • sequence is the ordered recipe for a command whose work is several steps (land, create).
  • comments carries each pull request comment a github comment run writes, with its body in --json. Porcelain says what happens to each comment but not its text, since a body is many lines.

pull --prune refuses both formats, because it produces two reports and those formats are one document.

schemaVersion is bumped when a field changes meaning or disappears; adding a field is not a breaking change.

  • Schema 2 narrowed blocked to the reason alone. It used to carry the label a person is shown in front of it, which differed between commands; that label is the renderer’s now.
  • Schema 3 made operation the command’s path, because the commands moved: graph became status, sync became pull, and what reads or writes GitHub is github link, github status and so on. A consumer switching on the old names would have read the offline status as the pull request one.

The JSON schemaVersion is separate from the storeSchemaVersion of g2g’s graph; see Compatibility and storage.

Terminal window
g2g --debug github link --branch feature/top

--debug is a root flag and may appear before or after any command. Its output goes only to stderr, so stdout keeps the normal preview. It does not change discovery, timeouts, checkout behaviour, or mutations.

Its records summarise supported Graphite discovery, the selected path, batched GitHub pull request facts for github link (including native stack number and position), or the selected remote and the atomic, leased Git arguments for push, plus plan and revalidation decisions and bounded subprocess status. It never logs environment values, credentials, auth headers, cookies, or GraphQL query payloads.

Terminal window
g2g --timeout 3m submit --spec "$spec_dir/submission.json" --apply

Discovery and mutation are bounded separately:

Phase Default budget
discovery and revalidation 45 seconds
mutation 60 seconds plus 30 per selected branch
mutation, for land 60 seconds plus 180 per selected branch, because it waits on GitHub between its calls

The mutation budget is taken fresh rather than from whatever discovery left over, so a slow read can never cancel a push or a pull request creation halfway. The root --timeout flag replaces both ceilings, for a slow network or a deep stack.

A mutation that does expire says so explicitly and states what may already have happened, because an interrupted submit can leave refs pushed and some pull requests created. Re-running it with the same spec is safe and creates only what is missing.