Skip to content

CLI overview

gpilot is the command-line interface for GraphPilot. You use it to authenticate, manage organizations and services, deploy your schema and configuration, list and cancel deployments, purge cached responses, read request telemetry, and manage persisted queries. Everything it does fits in a script or a CI job.

A few tasks live only in the portal: deleting an organization, for example. Deleting a service works in both: gpilot service delete asks for the confirmation code sent to you by email, as the portal does.

To install it, see installing the CLI.

GroupAliasesWhat it does
gpilot authNoneLog in and out, and inspect the current session
gpilot profilep, profList, switch, inspect, rename, and delete profiles
gpilot organizationo, orgList, create, edit, and select organizations
gpilot services, svcManage the services in the active organization, read request telemetry, and purge the cache
gpilot deploymentd, dplCreate, list, and cancel deployments
gpilot persisted-querypqManage the operations you declared for a service
gpilot apqNoneList and revoke what clients registered through APQ
gpilot configc, cfgRead and convert the service configuration
gpilot runtimeNoneList proxy runtime versions and read their changelog (no login needed)
gpilot completionNoneGenerate shell completions

A few common actions also have top-level shortcuts, such as gpilot deploy for gpilot deployment create; they are listed under shortcuts.

See the full command reference for every subcommand and flag.

These options are accepted by every command:

OptionDescription
--profile <name>Act as this profile instead of the active one. Accepted before or after the subcommand.
-o, --format <pretty|json|jsonl|yaml>Output format for data display. Defaults to pretty.
--no-interactiveForce non-interactive mode (no prompts or spinners). Usually unnecessary: the CLI auto-detects CI and non-terminal contexts. See interactive vs. non-interactive.
--no-colorDisable colored output. Color is on by default when stdout is a terminal; also respects the NO_COLOR environment variable.
-q, --quietSuppress non-essential output.
-h, --helpPrint help for any command (append --help to any subcommand).
-V, --versionPrint the CLI version.

The machine-readable formats differ in how they print a list:

  • json prints one JSON document. A list is a single array.
  • jsonl prints JSON Lines: one compact JSON value per line. Use it to pipe into jq, awk or a while read loop, since each line can be processed as it arrives.
  • yaml prints one YAML document.

In json, jsonl and yaml, stdout carries only the document. Every status, progress and hint line goes to stderr, including the device URL and code of gpilot auth login, which still reach you there. That includes the confirmation line of deployment cancel, auth logout, profile use, profile rename, profile delete, organization select and service select. In pretty nothing changes.

Terminal window
gpilot auth status --format json
gpilot requests --status 500 -o jsonl | jq -r '.path'

The CLI runs interactively (prompts, spinners, colored output) when it detects a terminal. It automatically switches to non-interactive mode when any of the following is true, so you rarely need to pass --no-interactive yourself:

  • --no-interactive is set.
  • The CI environment variable is set to any value other than empty, 0 or false, as most CI systems do (GitHub Actions, GitLab CI, CircleCI, and others).
  • GPILOT_NO_INTERACTIVE (or GPILOT_NONINTERACTIVE) is set to any non-empty value.
  • TERM is dumb.
  • stdin or stdout is not a terminal.

In non-interactive mode, spinners become plain log lines and prompts cannot be shown. What a command does when it would have asked for confirmation depends on the command:

CommandWithout -y, --yes in non-interactive mode
gpilot deploy (deployment create)Proceeds, so deployments run unattended in CI.
gpilot purge (service purge)Refuses and exits 1.
gpilot pq rm (persisted-query rm)Refuses and exits 1.
gpilot apq rmRefuses and exits 1.
gpilot profile deleteRefuses and exits 1.
gpilot service destroyRefuses and exits 1, naming the command to re-run with --yes.
gpilot service deleteRefuses and exits 1, naming the two commands that finish the deletion: one with --yes to request the code, one with --code to spend it.
gpilot cancel (deployment cancel)Refuses and exits 1, naming the command to re-run with --yes.

Pass -y, --yes to run any of these from a script or a CI job. A “no” typed at a real prompt still exits 0.

gpilot organization create asks a different question: whether you accept the GraphPilot terms. --yes does not answer it, --accept-terms does. Without that flag the command creates nothing and exits 1 in non-interactive mode, and also after a “no” at the prompt. See organization create.

When the keys come from a pipe (cat keys.txt | gpilot purge) but you are at a terminal, purge still asks you there before it purges anything.

Exit codes are stable, so scripts can branch on them: 0 success, 1 a general error, 2 a usage error, 3 an authentication failure, 4 a network or GraphPilot API error, 6 a CLI too old to run, 7 a deployment whose outcome is unknown. The full table is on codes.

The CLI reads its configuration from GPILOT_-prefixed environment variables. Settings grouped into a section follow the pattern GPILOT_<SECTION>_<KEY> (for example GPILOT_API_URL); the others have a name of their own.

VariablePurpose
GPILOT_TOKENAn API key (sk_…) used for non-interactive authentication. When set, it takes precedence over the stored profile. See signing in.
GPILOT_PROFILESelects the active profile without changing the on-disk default.
GPILOT_NO_INTERACTIVEForce non-interactive mode regardless of terminal detection (alias GPILOT_NONINTERACTIVE). The generic CI variable has the same effect. See interactive vs. non-interactive.
GPILOT_CONFIG_DIRStores profiles and credentials in this directory instead of the default location.
GPILOT_OPEN_BROWSERSet to 0 or false to stop auth login from launching a browser. The CLI still prints the URL to open.
GPILOT_SKIP_VERSION_CHECKSet to 1, true, yes or on to skip the minimum-version check for this run. A temporary escape hatch, see Staying up to date.
GPILOT_INSTALL_DIRRead by the install scripts, not by gpilot: the directory they install to. See installing the CLI.
GPILOT_VERSIONRead by the install scripts, not by gpilot: the release to install instead of the latest. See install a specific version.
GPILOT_REQUIRE_SIGNATURERead by the install scripts, not by gpilot: set to 1 to refuse an install whose signature cannot be checked. See verify a download.

These point the CLI at other endpoints, and are for support use only: set them when GraphPilot support asks you to. With them unset, the CLI talks to GraphPilot’s production services.

VariableOverridesDefault
GPILOT_API_URLThe GraphPilot API endpoint.The production GraphPilot API.
GPILOT_UPDATE_MANIFEST_URLWhere the minimum-version check reads the published version policy.https://raw.githubusercontent.com/GraphPilot/gpilot/main/version.json

From gpilot 1.1.0, GPILOT_API_URL must be an https:// address, because the requests sent to it carry your credential. Plain http:// is accepted only for a loopback host (localhost, or a loopback address such as 127.0.0.1 or [::1]). Any other address is refused before a request is made, with an error that names the variable, and the command exits with 1.

The CLI keeps configuration and credentials in your platform’s standard config directory:

  • macOS: ~/Library/Application Support/io.graphpilot.cli/
  • Linux: ~/.config/gpilot/, or $XDG_CONFIG_HOME/gpilot/ when XDG_CONFIG_HOME is set
  • Windows: %APPDATA%\graphpilot\cli\config\

gpilot 1.0 kept the Linux store in ~/.config/cli/; newer versions move it on their first run, so an existing login keeps working.

Set GPILOT_CONFIG_DIR to use a different directory. With it set, nothing is moved.

<config dir>/
├── config.toml # active profile + per-profile settings
└── credentials/ # one file per profile (permissions 0600)
├── default.json
└── work.json

config.toml records the active profile and, for each profile, its selected service and any per-profile api_url override. The organization is not copied here: it is carried by the credential itself. The credentials/ files hold the OAuth tokens or API keys and are written with owner-only (0600) permissions. You rarely edit these by hand; the gpilot auth and gpilot profile commands manage them for you, and gpilot profile show prints what a profile holds.

Commands that act on an organization or a service print a dimmed context line on stderr before their output, so the profile, organization and service being acted on are never a guess:

profile acme · org acme-corp · service checkout-api

The organization is the one the credential is scoped to, as the credential names it: its slug for an API key profile, its organization id (org_…) for a browser or device login. A field with nothing in it reads as a dash, and a service the CLI cannot determine reads unknown. Under GPILOT_TOKEN there is no profile, and the line names the token instead:

profile — (GPILOT_TOKEN) · org org_01H… · service checkout-api

It is read from local state before the first request, and goes to stderr so that gpilot deployment list -o json | jq stays a stream of JSON. It is suppressed by --quiet and by any machine-readable --format, but not in CI, where which profile a pipeline deployed as is worth having in the log.