Skip to main content
@pierre/cli installs the pierre command. Each API command calls one operation of the HTTP API through @pierre/sdk, with the same name and the same fields as the SDK method. The helpers sign tokens and let plain Git work with each Code Storage repository. The reference page of each operation shows its CLI command. This page gives the parts that every command shares.

Install

The CLI needs Node.js 22.23.4 or a later 22 release, 24.22.1 or a later 24 release, or 26.12.1 or later. To run one command with no install, use npx @pierre/cli version. Use a global install for pierre auth setup-git: Git stores the path of the pierre that it runs, and npx runs the CLI from a cache that can change.

Sign in

Create a key on the Keys page of your organization dashboard. Authentication explains keys. Then store the private key for your Git host:
With --with-key, the CLI reads the PEM from stdin. You can also pass --from-file key.pem, or paste the key at the prompt. The CLI checks the key with repos.list, then stores it. --no-verify skips the check. The command prints the host, the organization, the key file, the key ID, and the result of the check. The CLI keeps one entry for each Git host in ~/.config/pierre/hosts.yml. It keeps the private key in ~/.config/pierre/keys/<host>.pem, with mode 600. When XDG_CONFIG_HOME is set, it replaces ~/.config. PIERRE_CONFIG_DIR replaces the whole ~/.config/pierre path. A host in the <org>.code.storage shape gives the organization and the API URL. For a Git host on another domain, pass --org and --api-url once, at login. The Settings page of the dashboard shows the Git host and the API URL.

Check the credential

pierre auth status reports each saved host: the organization, the API URL, the key source, the key ID, a live check, and the Git helper settings. --hostname <host> reports one host, and --json prints the report as JSON. When a check fails, the command exits with the code of the problem. To rotate a key, run pierre auth login again for the same host with the new key. Then delete the old key on the dashboard. pierre auth logout deletes only the local key file and the host entry, so also revoke the key on the dashboard.

Select a host

Each command uses one Git host. The CLI takes the first match:
  1. --hostname <host>.
  2. PIERRE_GIT_HOST.
  3. The Code Storage remote of the current Git repository: an HTTPS remote on a saved host or on a *.code.storage host. When several remotes match, a saved host comes first, then the remote named storage.
  4. The single saved host.
  5. <org>.code.storage, for the organization in PIERRE_ORG or in the iss claim of PIERRE_TOKEN.
When hosts.yml holds more than one host, and the first three give no host, the command stops with exit code 2. The error lists the saved hosts:
Pass the Git host with --hostname for one command, or set PIERRE_GIT_HOST for the shell or the job:
  • --hostname takes the Git host, such as acme.code.storage, not the API URL. It accepts an http:// or https:// prefix.
  • --hostname is a global flag. Put it before or after the command.
  • --hostname wins over PIERRE_GIT_HOST, and both win over the remote of the current repository.
  • A saved host uses its host entry. Another host uses the variables of CI and containers, as the SDKs do.
  • pierre auth status reports every saved host, so it needs no host.

CI and containers

A CI job usually has no hosts.yml. Give the credential in environment variables:
The CLI uses the first credential that it finds: PIERRE_TOKEN, PIERRE_PRIVATE_KEY, PIERRE_PRIVATE_KEY_FILE, then the key file of the host entry. A saved host entry sets the organization and the API URL, so PIERRE_ORG and PIERRE_API_BASE_URL apply only to a host with no entry. When the runner has a hosts.yml with several hosts, also set PIERRE_GIT_HOST. In a container, configure Git when you build the image, and put no secret in the image:
At runtime, set PIERRE_PRIVATE_KEY. For a host in the <org>.code.storage shape, Git needs nothing else: the helper gets the organization from the host. Also set PIERRE_ORG for a host on another domain, and for an API command outside a clone. An API command on a host on another domain also needs PIERRE_GIT_HOST and PIERRE_API_BASE_URL.

Command form

The catalog ID of an operation gives its command. Join the resource path with :, then add the method. A name in camel case, such as createFromDiff or gitCredentials, becomes kebab case. The reference page of each operation shows its command, for example repos.branches.create. pierre --help lists the resources and their methods. pierre <resource> <method> --help gives the flags, the catalog ID, the HTTP route, and the scopes of one command:
The resource path is one word. pierre repos branches create is a usage error that names pierre repos:branches create.

Singular nouns

Each resource also has a singular name. pierre repo list runs pierre repos list, and pierre repo:branch create runs pierre repos:branches create. pierre repo view runs pierre repos get.

Flags

The flags are the fields of the SDK method, with the wire names in kebab case. target_branch is --target-branch, and base_ref is --base-ref.
  • A boolean is --force or --no-force.
  • An array takes its flag once for each item.
  • An object takes JSON, @file, or @- for stdin. Each scalar field of the object also has a dotted flag, such as --author.name and --author.email.

The argument

A command takes at most one positional argument: the resource that it acts on. The argument and its flag do the same thing:
Pass each other value with its flag. A second argument is a usage error.

The repository

-R is the short form of --repo-name. Inside a clone with a Code Storage remote, --repo-name defaults to the repository of that remote:
The default needs an HTTPS remote on the selected host. pierre repos delete has no default, so name the repository. --debug prints the repository that the CLI took from the remote.

Global flags

Output

Without --json, an object prints its main fields, one row for each field. A list prints a table. When an operation can answer with more than one success status, the output starts with the status. pierre repos create prints 201 Created for a new repository, and 200 OK for an existing one. --json prints the response body, with every field. Use it in scripts:
Warnings and errors go to stderr, so stdout holds the result.

Lists

A list command prints one page. --limit and --cursor are the wire fields of the operation. When more items exist, the CLI writes the next cursor to stderr: More items: pass --cursor <cursor>, or --paginate.
--paginate reads every page. Without --json, it prints one table of all the items. With --json, it prints one response body for each page.

Bytes

A byte response, such as the file of pierre repos:files get, goes to stdout or to the file that --output names:
When stdout is a terminal and you give no --output, the command stops with a usage error. It sends no request.

pierre api

pierre api <catalog-id> calls any operation through its SDK method, and prints the JSON response body. As in gh api, path parameters are fields, with their wire names:
  • -F key=value sends a typed value: true, false, null, an integer, the text of @file, stdin for @-, or text.
  • -F 'key[name]=value' sets one field of an object. For an array, repeat -F once for each item.
  • -f key=value always sends a string.
  • --input <file> gives the body fields as one JSON object. --input - reads stdin. Then -F and -f set only path, query, and header fields.
  • --paginate reads every page of a list, and prints one body for each page.
  • --output <file> writes a byte response to the file.
A field that the operation does not have is a usage error, and the error lists the fields. An unknown catalog ID is a usage error that names the nearest ID. pierre api cannot call repos.commits.create or repos.commits.createFromDiff, because their body is file content. Use pierre repos:commits create and pierre repos:commits create-from-diff.

Exit codes and errors

The exit code comes from the class of the SDK error, never from the message text. An API error prints its status, its problem code, its detail, the request ID, and the docs of the code:
For a 401 or a 403, the CLI also tells you to check the key on the dashboard Keys page, or to run the pierre auth login command again. With --json, the CLI also prints the problem details body on stdout. Error codes lists each code. A usage error stops the command before it sends a request.

Debug output

--debug, or PIERRE_DEBUG=1, writes these lines to stderr:
  • The repository that the CLI takes from the Git remote when you do not give --repo-name. See The repository.
  • The steps of the Git credential helper: an operation that it ignores, the source of a token that it sends, or the scopes, the repository, the host, the organization, and the lifetime of a token that it signs.
  • The scopes, the repository, the host, the organization, and the lifetime of a token that pierre auth token signs.
--debug also prints the stack of an unexpected error. PIERRE_DEBUG=1 does not. An API error and a usage error print no stack. Debug output has no request and no response, and it never has a token or a key.

Helpers

pierre auth token

pierre auth token prints a token that your private key signs, for a script or for curl:
  • --scope adds a scope. Repeat it for more. The scopes are git:read, git:write, org:read, and repo:write. The default is git:read and git:write.
  • A token whose scopes all cover the organization, such as org:read, has no repo claim. Another token needs --repo, which defaults to the Code Storage remote of the current repository.
  • --ttl sets the lifetime, such as 15m, 1h, or 900s. The default is 15 minutes, and the maximum is 1 hour.
When PIERRE_TOKEN is set, the CLI signs no token, so pierre auth token stops. Scopes gives the access of each scope.

pierre auth setup-git

pierre auth setup-git configures Git to get its credential for the host from pierre. Then git clone, git fetch, and git push work, and no token appears in a URL or in a file. The command writes these settings once for each host:
The blank helper line stops Git from asking another helper, such as a keychain, for this host. useHttpPath makes Git send the repository path, which the helper needs.
  • --hostname <host> selects the host. With several saved hosts, run the command once for each host.
  • --local writes the settings of the current repository instead of the global settings.
  • --read-only makes the helper sign git:read only, so the machine cannot push.
  • --uninstall removes the settings.
When the pierre on your PATH is this CLI, the helper runs that path. Otherwise, the helper names the Node.js executable and the CLI script. Then run pierre auth setup-git again after you update Node.js or move the CLI.

The Git credential helper

Git runs pierre auth git-credential get for each operation on the host. Do not run it yourself. On each call, the helper:
  1. Takes the host and the repository from the URL that Git sends. It removes .git, and a +ephemeral or +import suffix.
  2. Finds the organization and the credential by the rules of CI and containers. Git gives the host, so the helper needs no --hostname and no PIERRE_GIT_HOST.
  3. Signs a token for that repository with git:read and git:write, or with git:read only in read-only mode. The token lives for 1 hour. PIERRE_TOKEN_TTL sets another lifetime in seconds, from 1 to 3600. When PIERRE_TOKEN is set, the helper sends that token instead.
  4. Gives Git the username t and the token as the password. It stores nothing.
On a failure, the helper tells Git to stop, so Git never shows a password prompt. The helper writes one line to stderr that names the cause. Set PIERRE_DEBUG=1 to see the diagnostics of the helper.

pierre mcp

pierre mcp prints the docs MCP server, the index of the Markdown pages, the auth note, and the command that installs the pierre agent skill. When a host is selected, it also prints the organization and the API URL of that host. pierre mcp --json prints a config block for an MCP client:
Agent Setup shows how to connect each agent.

SDKs

The CLI calls the methods of @pierre/sdk. To call the same operations from your code in TypeScript, Python, or Go, read the SDK page.