---
title: "CLI reference"
description: "Every pando command, its arguments and flags."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.gitpando.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI reference

`pando help` prints every command, as below. Flags can go before or after a command's other arguments. Commands that read the API take `--json` and print the API's own JSON; see [For scripts and agents](#for-scripts-and-agents). [`pando api`](#pando-api) reaches every route of the [API](/api/).

## Every command

```text
usage: pando <command> [args]

  pando login [--server <url>] [--bootstrap | --with-credential]   sign this machine in (in the browser)
  pando logout [--server <url>]                                   sign this machine out
  pando auth status                                               who this machine is signed in as
  pando init [folder] [--name <name>] [--owner <org>] [--yes] [--dry-run]   make a Pando repo or monorepo from a folder
  pando clone <owner/name | name> [folder] [--text-only]         set up a Pando repo or monorepo on this machine
  pando worktree add <repo> <branch> [--issue n] | list | remove <path> | follow | mount   one branch, one folder
  pando branch list [--repo <path>] [--all]                       branches with ahead, behind and checks
  pando branch view [<branch>] [--commits]                        one branch: checks, merge, reviews, head commit
  pando diff [<branch>] [--json | --patch] [paths...]             the branch diff against main
  pando review [<branch>] [-m <comment>]                          review in Plannotator, or comment
  pando merge [<branch>] [--force]                                land a branch on main with a merge commit
  pando reference update <path> | sync                            move a reference to its newest commit
  pando status                                                    this folder, its worktrees and references
  pando status <pending|success|failure|error> [--context ci] [--target-url u] [--description d]
                                                                  in a CI build: a check on its commit (PANDO_STATUS_TOKEN)
  pando issue list [--state s] [--label l] [--assignee a] [--search w]   a monorepo's issues, newest first
  pando issue view <n> [--comments]                               one issue: its body, branches and timeline
  pando issue create --title t [--body b] [--label l] [--key k]   open an issue
  pando issue comment <n> --body b [--key k]                      comment on one
  pando issue close <n> [--reason not-planned] | reopen <n>       close or reopen one
  pando issue edit <n> [--title t] [--body b] [--base-version v]   edit, label, assign one
  pando issue link | unlink <n> [<branch>]                        merging the branch closes the issue
  pando issue react <n> <reaction> [--comment id] [--remove]      +1, -1, laugh, hooray, confused, heart, rocket, eyes
  pando monorepo list | view [<owner/name>]                       your monorepos; one with its repos and members
  pando monorepo rename <new-name>                                rename one (owners); the old name keeps working
  pando monorepo edit --description <text>                        its one line under the name on the web (owners)
  pando monorepo transfer <owner/name> <new-owner> [--yes]        move one to an org, or back to a person (owners)
  pando monorepo delete <owner/name> [--yes]                      delete one (owners)
  pando members list | invite <email> [--owner] | remove <who>    who belongs to a monorepo
  pando members invites | revoke <email>                          invites still waiting; withdraw one
  pando org create <login> [--name n] | list | view <org>         organizations: a namespace many people share
  pando org members [<org>] | add <org> <email | login> [--owner]   who is in one; add someone (owners)
  pando org remove <org> <login | email> | leave <org>            take someone out (owners), or leave
  pando mac broker [--dry-run]                                    load Pando.app's broker (before FSKit mounts)
  pando ci connect --org <slug> | status | disconnect --org <slug>   a monorepo's Buildkite connection [--monorepo <owner/name>]
  pando ci pipeline add <repo> <pipeline> | list | remove <repo> <pipeline>   the pipeline pushes and merges start
  pando ci build list [--pipeline p] [--branch b] [--state s]     builds, newest first
  pando ci build view | log | rebuild | cancel <build>            one build: its jobs, a job's log [--job j] [--follow]
  pando ci job retry <build> <job>                                run a job again
  pando ci run <pipeline> [--branch b]                            start a build of a branch (default: main)
  pando mirror status [--json]                                    mirroring to GitHub: on or paused, one row per project [--monorepo <owner/name>]
  pando mirror on | off [<project>]                               turn mirroring on or pause it, or one project's (owners)
  pando mirror retry [<project>...]                               try again now, with the wait reset (owners)
  pando mirror connect                                            set it up: opens the repository's Settings (GitHub needs a browser)
  pando release list | view [<tag>]                               a project's releases, newest first; one with its notes [--repo <path>]
  pando release create <tag> [--generate] [--title t] [--notes n] [--draft]   tag main and publish it (checks green, or --force)
  pando release create <tag> <file>...                            with files: a draft, its files, then published
  pando release upload <tag> <file>... | download [<tag>]         a release's files (checked by SHA-256) [--pattern p] [--dir d]
  pando release publish <tag> [--force] | delete <tag>            publish a draft; delete one (its tag stays)
  pando artifact add [<branch>] <file> [<image>...]               a document (and its images) on a branch's page; the same name again is v2
  pando artifact list [<branch>]                                  the branch's artifacts, their versions and open comments
  pando artifact get [<branch>] <name> [--version n] [-o dir]     download a version's files (checked by SHA-256)
  pando artifact open [<branch>] <name>                           its page in the browser
  pando artifact comments [<branch>] [<name>] [--all]             open threads: the quote, the comment, replies, ids
  pando artifact comment [<branch>] <name> [--quote words] -m c   comment on words, or on the whole file
  pando artifact reply <id> -m c | resolve <id> [--reopen]        answer a thread; resolve or reopen it
  pando credential create --name <sandbox> | list | revoke <id>   credentials that act as you
  pando hook list | create <url> | delete <id>                    a repo's web hooks [--repo <path>] (owners write)
  pando hook deliveries <id> | redeliver <delivery-id>            what a hook sent; send one again
  pando machine list                                              machines that acted in the monorepo, and which are connected
  pando profile [<login>] [--json]                                a person's profile: their graph for the last year, by month
  pando activity [--monorepo <owner/name> | --all] [--limit n]    what happened, newest first
  pando session enable | disable                                  record coding sessions on this machine, or stop
  pando session status                                            what this machine records, from where, and what it skips
  pando session paths [add <folder> --program <name> | remove <folder>]   where Claude Code, Codex, Pi or OpenCode keep sessions
  pando session exclude | include [<owner/name>] [--project <path>]   a repository or project you do not record, on every machine
  pando session delete <id> [--monorepo <owner/name>]             delete a session at once and for good
  pando api <path> [-X method] [-f k=v] [-F k=v] [--paginate]     any API call, signed as this machine (like gh api)
  pando sync [--once]                                             keep the monorepo's files outside projects/ live (the daemon)
  pando history <path> [--limit n] [--json]                       every saved version of a file outside projects/
  pando restore <path> --to <version | HH:MM>                     write an old version back, as a new save
  pando resolve [<path>...]                                       unfreeze a file after a conflict
  pando fetch <path>...                                           download large files outside projects/ kept as pointers
```

The CLI names a repository a monorepo in its own words: the `pando monorepo` command, the `--monorepo` flag and its help text. They mean the repository.

## Sign in

### pando login

```sh
pando login [--server <url>] [--bootstrap | --with-credential]
```

Signs this machine in. It shows a code and a link, opens your browser when it can, and waits for you to confirm. git and `pando` on this machine then act as you.

| Flag | What it does |
| --- | --- |
| `--server <url>` | The Pando server. Default: the one in `~/.pando/config.toml`, or `PANDO_SERVER`, else `https://app.gitpando.com`. |
| `--with-credential` | Sign in with a credential made by `pando credential create`, typed with no echo or piped in. No browser. |
| `--bootstrap` | Self-hosted servers only: make your user with the server's bootstrap secret, typed with no echo. |
| `--login <login>` | With `--bootstrap`: the login to make. Default: your user name on this machine. |
| `--kind <kind>` | With the browser sign-in: `machine` (the default) or `sandbox`. |
| `--name <name>` | Your name on commits. Default: the account's, else `git config user.name`. |
| `--email <email>` | Your email on commits. Default: the account's, else `git config user.email`. |

The credential is kept in `~/.pando/credentials/`, readable only by you.

### pando logout

```sh
pando logout [--server <url>]
```

Deletes this machine's credential. The credential keeps working on the server until you revoke it with `pando credential revoke`.

### pando auth status

```sh
pando auth status
```

Shows the server, where the credential comes from, this machine's name, and who the server says you are. It takes `--server <url>` too.

## Set up a repository

### pando init

```sh
pando init [folder] [--name <name>] [--owner <org>] [--yes] [--dry-run]
```

Makes a Pando repository from a folder (default: the current folder), and you become its owner. A git repo becomes a plain repository. Any other folder becomes a repository with projects: each git repo under `projects/` becomes one of its projects, other git repos inside it become [references](/references/), and the rest of the folder becomes its shared files. Run it again after a failure: it skips what is done.

| Flag | What it does |
| --- | --- |
| `--name <name>` | The name on the server. Default: the folder's name, in lower case. |
| `--owner <org>` | Make it in an [organization](#organizations) you are in, as `org/name`. Default: your own account. |
| `--yes` | Take the default answer to every question. |
| `--dry-run` | Show what would happen and change nothing. |
| `--server <url>` | The Pando server. Default: the configured one. |

A name is lower-case letters, digits, `.`, `_` and `-`, at most 39 characters, with no `--`.

### pando clone

```sh
pando clone <owner/name | name> [folder] [--text-only]
```

Sets up a repository on this machine: the shared files outside `projects/` and a read-only main for every project, each a git clone. References are cloned when you ask, with `pando reference sync`. The folder defaults to the name. A bare `name` means the one in your own account, else the only one so named that you belong to.

| Flag | What it does |
| --- | --- |
| `--text-only` | Keep large shared files and binaries as pointers until `pando fetch`. For sandboxes. |
| `--kind <kind>` | How to check out each read-only main: `sparse` (a git clone, the default), or a mount, `fuse` (Linux with ArtifactFS) or `fskit` (a Mac with Pando.app on). |
| `--server <url>` | The Pando server. Default: the configured one. |

### pando status

```sh
pando status
```

Run inside a repository: shows the server and your role, then each project with this machine's worktrees (branch, kind, commit, changed files, unpushed commits) and each reference. With a state it posts a check instead; see [pando status in a CI build](#pando-status-in-a-ci-build).

## Worktrees and branches

One branch, one folder. See [Worktrees](/worktrees/).

### pando worktree

```sh
pando worktree add <repo> <branch> [--issue n] | list | remove <path> | follow | mount
```

| Subcommand | What it does |
| --- | --- |
| `add <repo> <branch> [folders...]` | Makes the branch off main if it is new, and checks it out at `<repo>/worktrees/<branch>` (a `/` in the branch name becomes `-`). Branch `main` gives a read-only main. Folders, with the sparse kind, check out only those folders and the top-level files. |
| `list` | Every worktree of the repository on every machine: path, branch, machine, kind, ahead, behind, and when it was last seen. |
| `remove <path>` | Takes a worktree off this machine. It refuses when there is uncommitted or unpushed work. The branch stays on the server until it merges. |
| `follow` | Keeps this machine's read-only mains at the server's main until stopped. `pando sync` runs the same follower. |
| `mount` | Mounts again the worktrees whose mount stopped, after a restart for example. Sparse worktrees need nothing. |

| Flag | What it does |
| --- | --- |
| `--kind <kind>` | With `add`: `sparse` (a git clone with every file of the branch, the default on every machine), or a mount: `fuse` (Linux with ArtifactFS) or `fskit` (a Mac with Pando.app on). Pando's cloud agents get `fuse`. |
| `--issue <n>` | With `add`: link the branch to issue `n`, so merging it closes the issue. A wrong number stops before anything is made. |
| `--json` | With `list`: print JSON. |
| `--force` | With `remove`: remove even with uncommitted or unpushed work, which is lost. |
| `--once` | With `follow`: move the mains once and stop. |
| `--poll <duration>` | With `follow`: how often to read the branch lists besides the live updates. Default `5m`. |

### pando branch list

```sh
pando branch list [--repo <path>] [--all]
```

Lists open branches with ahead, behind, author, checks, whether they merge cleanly, state and head.

| Flag | What it does |
| --- | --- |
| `--repo <path>` | One repo. Default: the repo you are in, or every repo. |
| `--all` | Include merged branches. |
| `--json` | Print JSON: for each repo, its branches as the API lists them. |

### pando branch view

```sh
pando branch view [<branch>] [--commits]
```

Shows one branch as its page does: its state and title, its head commit, who made it and the machine that last pushed it, how far it is ahead of and behind main, whether it merges cleanly (and, when not, the paths changed on both sides), each check, and its reviews. With no branch, the branch of the worktree you are in.

| Flag | What it does |
| --- | --- |
| `--commits` | Also list the commits the branch adds (those not on main), newest first, at most 250. |
| `--repo <path>` | The repo. Default: the one you are in. |
| `--json` | Print `{"branch", "reviews", "commits"}`: the API's answers for the [branch](/api/branches/getBranch/), its [reviews](/api/reviews/listReviews/) and its [commits](/api/branches/branchCommits/) (the newest only, without `--commits`). |

## Review and merge

`diff`, `review` and `merge` take the branch of the worktree you are in when you name none.

### pando diff

```sh
pando diff [<branch>] [--json | --patch] [paths...]
```

Shows the branch diff against main: the changes since the branch left main, as GitHub shows a pull request. Name paths to see only those.

| Flag | What it does |
| --- | --- |
| `--patch` | Print a unified diff, for `git apply` or a review tool. |
| `--json` | Print the API's JSON. |
| `--repo <path>` | The repo. Default: the one you are in. |

### pando review

```sh
pando review [<branch>] [-m <comment>]
```

With no `-m`, opens the branch diff in Plannotator (it must be installed). Approving there posts an approval; annotations post a request for changes. With `-m`, posts the comment with no Plannotator. Reviews are comments and approvals, not a gate on merging.

| Flag | What it does |
| --- | --- |
| `-m <comment>` | Post this comment. |
| `--approve` | With `-m`: post it as an approval (people only). |
| `--request-changes` | With `-m`: post it as a request for changes. |
| `--repo <path>` | The repo. Default: the one you are in. |

### pando artifact

```sh
pando artifact add [<branch>] <file> [<image>...]
pando artifact list [<branch>]
pando artifact get [<branch>] <name> [--version n] [-o dir]
pando artifact open [<branch>] <name>
pando artifact comments [<branch>] [<name>] [--all]
pando artifact comment [<branch>] <name> [--quote "<words>"] -m "<comment>"
pando artifact reply <id> -m "<reply>"
pando artifact resolve <id> [--reopen]
```

Documents on a branch's page, never in git: a plan, a diagram, a design, an exported guided review. `add` uploads the first file and the images it uses, kept by their paths from the document's folder; the same name again is its next version. An agent reads the comments people leave with `comments`, uploads the next version with `add`, and answers with `reply` and `resolve`. With no branch, the branch of the worktree you are in. See [Artifacts](/artifacts/).

| Flag | What it does |
| --- | --- |
| `-m <text>` | `comment`, `reply`: the comment, Markdown. |
| `--quote <words>` | `comment`: the words it is on, plain, from one line. Default: the whole file. |
| `--version <n>` | `get`: the version. Default: the newest. |
| `-o <dir>` | `get`: the folder to write its files in. Default: this folder. |
| `--all` | `comments`: resolved threads too. |
| `--reopen` | `resolve`: open the thread again. |
| `--json` | Print the API's answer. |
| `--repo <path>` | The repo. Default: the one you are in, or the only one. |
| `--monorepo <owner/name>` | The monorepo. Default: the one you are in. |

### pando merge

```sh
pando merge [<branch>] [--force]
```

Lands the branch on main with a merge commit, and names the issues the merge closes (each closes about a second later). It stops when checks are not green, when the branch and main both changed a file in different ways (Pando merges whole files, with no line-by-line merge), or, run in the branch's worktree, when the branch on the server is not what you pushed. This machine's read-only main then follows within a moment.

| Flag | What it does |
| --- | --- |
| `--force` | Merge past red or missing checks. The merge is recorded as forced. |
| `--wait` | Return only once this machine's read-only main has the merge. For scripts. |
| `--repo <path>` | The repo. Default: the one you are in. |

## Issues

A repository has one list of issues, numbered `#1`, `#2`, ... An issue can be about one of its projects. A branch is linked to an issue by "Fixes #12" in its title, its description or one of its commits, or by `pando issue link`; merging the branch into main closes the issue.

### pando issue

```sh
pando issue list [--state s] [--label l] [--assignee a] [--search w]
pando issue view <n> [--comments]
pando issue create --title t [--body b] [--label l] [--key k]
pando issue comment <n> --body b [--key k]
pando issue close <n> [--reason not-planned] | reopen <n>
pando issue edit <n> [--title t] [--body b] [--base-version v]
pando issue link | unlink <n> [<branch>]
pando issue react <n> <reaction> [--comment id] [--remove]
```

A number can be written `12` or `#12`.

| Subcommand | What it does |
| --- | --- |
| `list` | The issues, newest first, and how many are open and closed for the same filters. |
| `view <n>` | One issue: its state, who opened it and from which machine, labels, assignees, project, tasks, the branches linked to it, its reactions, then its body as written (Markdown). With `--comments`, then its timeline: comments and events, oldest first. |
| `create --title <title>` | Opens an issue. |
| `comment <n>` | Comments on an issue. |
| `close <n>` | Closes it, as completed or as not planned. |
| `reopen <n>` | Opens it again. A later merge that names it closes it again. |
| `edit <n>` | Changes its title, body or project, and adds or removes labels and assignees, in one call. |
| `link <n> [<branch>]` | Links a branch (default: the branch of the worktree you are in), so merging it closes the issue. |
| `unlink <n> [<branch>]` | Takes that link away. A closing keyword in the branch's title or commits still links it. |
| `react <n> <reaction>` | One of GitHub's eight reactions: `+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes` (or the emoji). |

| Flag | What it does |
| --- | --- |
| `--state <state>` | With `list`: `open` (the default), `closed` or `all`. |
| `--label <label>` | With `list`: issues with this label; repeat it, and every one must match. With `create`: a label to put on it; repeat it. |
| `--assignee <login>` | With `list`: issues assigned to this person, `@me`, or `none`. With `create`: assign this member, or `@me`; repeat it. |
| `--author <login>` | With `list`: issues opened by this person, or `@me`. |
| `--project <path>` | With `list`: issues about this project, or `none`. With `create` and `edit`: the project it is about (`none` with `edit` takes it away). |
| `--search <words>` | With `list`: these words in the title or body. |
| `--sort <order>` | With `list`: `created` (the default), `updated` or `comments`. |
| `--limit <n>` | With `list`: how many issues. Default 30. |
| `--comments` | With `view`: also print the timeline. |
| `--title <title>` | With `create` and `edit`: the title, 1 to 256 characters. |
| `--body <text>`, `--body-file <file>` | With `create`, `comment` and `edit`: the text, Markdown, at most 65,536 characters. `--body-file -` reads standard input. |
| `--key <key>` | With `create` and `comment`: an idempotency key, up to 64 characters. Run again with the same key, the command makes nothing new and answers the first issue or comment. |
| `--reason <reason>` | With `close`: `completed` (the default) or `not-planned`. |
| `--comment <text>` | With `close` and `reopen`: comment first. |
| `--base-version <v>` | With `edit` and a body: the `body_version` your text was written from. If someone changed the body since, the edit is refused (`edited`) and nothing is overwritten. |
| `--add-label`, `--remove-label <label>` | With `edit`: repeat them. |
| `--add-assignee`, `--remove-assignee <login>` | With `edit`: members, or `@me`; repeat them. |
| `--repo <path>` | With `link` and `unlink`: the branch's project. Default: the one you are in. |
| `--comment <id>` | With `react`: react to that comment (`ic_...`, from `view --comments`) instead of the issue. |
| `--remove` | With `react`: take your reaction back. |
| `--json` | Print the API's answer: [list](/api/issues/listIssues/), [view](/api/issues/getIssue/) (with `--comments`, the issue with its [timeline](/api/issues/issueTimeline/) under `timeline`), [create](/api/issues/createIssue/), [comment](/api/issues/addIssueComment/), close, reopen, edit, link and unlink ([the issue now](/api/issues/updateIssue/)), react ([its reactions now](/api/issues/addIssueReaction/)). A refusal prints the API's error object on stderr. |
| `--monorepo <owner/name>` | The repository. Default: the one you are in. |

Labels are made and changed by owners in the web's Settings, or with [`pando api`](#pando-api) on `/monorepos/{owner}/{monorepo}/labels`.

A task, start to end:

```sh
n=$(pando issue create --title "Merge refuses when pando.toml has a trailing comma" \
      --body-file report.md --label bug --project projects/pando --key task-41 --json | jq .number)
pando worktree add projects/pando toml-error-line --issue "$n"
# work, commit, git push
pando merge          # This merge closes #41 (each within about a second).
```

## References

### pando reference

```sh
pando reference update <path> | sync
```

A reference is someone else's repo inside the repository, kept as a pointer to one commit. See [References](/references/).

| Subcommand | What it does |
| --- | --- |
| `update <path>` | Moves the reference to the newest commit of its branch. The pointer is a shared file, so every machine running `pando sync` follows. |
| `sync` | Clones each reference that is not on this machine, read-only at its pointer's commit, and moves the others to it. |

`--kind <kind>` (`sparse`, the default, `fuse` or `fskit`) sets how a new reference folder is checked out.

## Members, credentials and repositories

### pando members

```sh
pando members list | invite <email> [--owner] | remove <who>
pando members invites | revoke <email>
```

Each subcommand takes the repository as `owner/name` before its other arguments, or uses the repository you are in.

| Subcommand | What it does |
| --- | --- |
| `list` | Members and their roles, then invites still waiting. |
| `invite <email>` | Adds the person now if they have an account, else they join when they first run `pando login`. |
| `remove <who>` | A login removes that member; unless they have the repository through its organization, their open pages and `pando sync` stop at once. An email withdraws that invite. |
| `invites` | Invites still waiting, with who sent them. |
| `revoke <email>` | Withdraws the invite for that email. |

| Flag | What it does |
| --- | --- |
| `--owner` | With `invite`: invite as an owner. Default: member. |
| `--json` | With `list` or `invites`: print the API's answer ([members](/api/monorepos/listMembers/), [invites](/api/monorepos/listInvites/)). |
| `--server <url>` | The Pando server. Default: the configured one. |

### pando credential

```sh
pando credential create --name <sandbox> | list | revoke <id>
```

Credentials that act as you, for another machine or a cloud sandbox.

| Subcommand | What it does |
| --- | --- |
| `create --name <name> --out <file>` | Makes a credential and writes its secret to the file, readable only by you. `--out -` writes it to a pipe instead (never to a terminal). In the sandbox, set `PANDO_TOKEN` from it. |
| `list` | Your credentials: ID, name, kind, created, last used. |
| `revoke <id>` | Stops a credential working. |

| Flag | What it does |
| --- | --- |
| `--kind <kind>` | With `create`: `sandbox` (the default) or `machine`. |
| `--server <url>` | The Pando server. Default: the configured one. |

git also runs `pando credential` as its credential helper for Pando URLs. You never run that part yourself.

### pando monorepo

```sh
pando monorepo list | view [<owner/name>]
pando monorepo rename <new-name>
pando monorepo transfer <owner/name> <new-owner> [--yes]
pando monorepo delete <owner/name> [--yes]
```

| Subcommand | What it does |
| --- | --- |
| `list` | Your repositories, with your role in each. |
| `view [<owner/name>]` | The repository you name, or the one you are in: its id, your role, how many members, and each project with main's head and its clone URL. |
| `rename <new-name>` | Owners only. Renames the repository within its owner. The old `owner/name` keeps leading to it, for the API and for git, until it is given to another repository. Run in the repository's folder, the folder takes the new name and its git remotes the new clone URLs. A `pando sync` already running keeps the old name until it restarts. |
| `transfer <owner/name> <new-owner>` | Owners only. Moves the repository to an [organization](#organizations) you are in, or back to a person who is already its owner directly. Its own members stay; the organization's people gain it, and the old owner's lose it. The old `owner/name` keeps leading to it, for the API and for git. You type its full name to confirm. Run in the repository's folder, the folder and its git remotes follow, as with `rename`. Run again, it changes nothing. |
| `delete <owner/name>` | Owners only. Deletes every project in it, their history, and its shared files. There is no undo. You type the full name to confirm. Folders on this machine stay. |

| Flag | What it does |
| --- | --- |
| `--monorepo <owner/name>` | With `rename`: the repository. Default: the one you are in. |
| `--json` | With `view`: print `{"monorepo", "repos", "members"}`, the API's answers for the [repository](/api/monorepos/getMonorepo/), its [projects](/api/repos/listRepos/) and [members](/api/monorepos/listMembers/). With `rename` and `transfer`: the API's [answer](/api/monorepos/renameMonorepo/). |
| `--yes` | Delete or transfer without typing the name. For scripts. |
| `--server <url>` | The Pando server. Default: the configured one. |

## Organizations

An organization is a namespace many people share, like a person's login: its repositories are `org/name`. Everyone in it can open and push to every repository it owns; its owners own them all. People are added at once, or by email at their first sign-in.

### pando org

```sh
pando org create <login> [--name n] | list | view <org>
pando org members [<org>] | add <org> <email | login> [--owner]
pando org remove <org> <login | email> | leave <org>
```

| Subcommand | What it does |
| --- | --- |
| `create <login>` | Makes an organization; you are its first owner. The login follows the rule for people's logins (lower-case letters, digits and single dashes, at most 39) and shares their namespace, so a person's login can't be taken. Run again, it changes nothing. |
| `list` | The organizations you are in, with your role and how many people each has. |
| `view <org>` | Its login, name, description and website, your role, and its repositories you can open. |
| `members [<org>]` | Its people and their roles, then invites still waiting. Default: the organization that owns the repository you are in. |
| `add <org> <email \| login>` | Owners only. A login is added at once. An email adds the person now if they have signed in with it, else at their first `pando login`. Run again, it changes nothing. |
| `remove <org> <login \| email>` | Owners only. A login takes that person out: their access to its repositories ends within about 15 seconds, except where they are a member of one directly, and their open pages and `pando sync` there stop at once. An email withdraws that invite. |
| `leave <org>` | Takes you out. An organization keeps at least one owner. |

| Flag | What it does |
| --- | --- |
| `--name <name>` | With `create`: its display name, up to 100 characters. |
| `--owner` | With `add`: as an owner. Default: member. |
| `--json` | Print the API's answer: [create](/api/orgs/createOrg/), [list](/api/orgs/listMyOrgs/), [view](/api/orgs/getOrg/), [members](/api/orgs/listOrgMembers/), and add ([by login](/api/orgs/putOrgMember/) or [by email](/api/orgs/orgInvite/)). |
| `--server <url>` | The Pando server. Default: the configured one. |

An organization's display name (up to 100 characters), description (up to 160) and website (an `https` address, up to 2,048) are changed by its owners in the web, or with [`pando api`](#pando-api): `pando api -X PATCH /orgs/<org> -f description="..."`. Make a repository in one with `pando init --owner <org>`, or move one in with `pando monorepo transfer`.

## CI

Pando starts builds on Buildkite and shows their checks. See [CI with Buildkite](/ci/buildkite/).

### pando ci

```sh
pando ci connect --org <slug> | status | disconnect --org <slug>
pando ci pipeline add <repo> <pipeline> | list | remove <repo> <pipeline>
```

| Subcommand | What it does |
| --- | --- |
| `connect --org <slug>` | Connects a Buildkite organization to the repository. It prints the webhook URL and token to put in Buildkite, and the steps. The token is shown once, only on a terminal. |
| `status` | The connections, the last event Pando received, and each pipeline with its last build. |
| `disconnect --org <slug>` | Removes the connection. Its builds leave Pando; its checks stay. |
| `pipeline add <repo> <pipeline>` | Owners only. Each push to a branch of the repo, and each merge into its main, then starts a build of that Buildkite pipeline. A merge builds main's new merge commit, on main. |
| `pipeline list` | Which pipeline each repo starts. |
| `pipeline remove <repo> <pipeline>` | Owners only. Pushes and merges stop starting that pipeline. |

| Flag | What it does |
| --- | --- |
| `--monorepo <owner/name>` | The repository. Default: the one you are in. |
| `--org <slug>` | The Buildkite organization, as in `buildkite.com/<slug>`. With `pipeline`, the default is the repository's one connected organization. |
| `--out <file>` | With `connect`: write the webhook token to this file, readable only by you, instead of the terminal. |
| `--paste-token` | With `connect`: use the token Buildkite made, typed with no echo, instead of a new one. |
| `--server <url>` | The Pando server. Default: the configured one. |

### pando ci build

```sh
pando ci build list [--pipeline p] [--branch b] [--state s]
pando ci build view | log | rebuild | cancel <build>
```

Builds as Pando has them from Buildkite's webhooks, newest first. Name a build by its number (`12` or `#12`, with `--pipeline` unless the repository has one pipeline), by its pipeline and number (`pando-ci/12`, as in its page's address), or by its id (`cib_...`).

| Subcommand | What it does |
| --- | --- |
| `list` | Builds: number, pipeline, state, repo, branch, commit, who pushed it, when, how long it took, and its id. |
| `view <build>` | One build and its jobs: each job's state, check, exit status and time. |
| `log <build>` | Each job's log, its last 1 MiB, from Buildkite. Buildkite's timestamps are taken out, and colours too when the output is not a terminal. |
| `rebuild <build>` | Starts a new build of the same commit, with fresh tokens. |
| `cancel <build>` | Cancels a build that is running. |

| Flag | What it does |
| --- | --- |
| `--pipeline <slug>` | With `list`: that pipeline's builds. With a build number: the build's pipeline. |
| `--branch <name>` | With `list`: builds of that branch. |
| `--state <state>` | With `list`: builds in that state: `queued`, `running`, `blocked`, `passed`, `failed`, `canceled` or `skipped`. |
| `--repo <path>` | With `list`: builds of that repo. |
| `--limit <n>` | With `list`: how many builds. Default 30. |
| `--job <job>` | With `log`: one job, by its key, name or id. |
| `--follow` | With `log`: keep printing the job's log as it grows, until the job finishes. It follows one job. |
| `--json` | Print the API's answer: [list](/api/ci/listCiBuilds/), [view](/api/ci/getCiBuild/), [log](/api/ci/getCiJobLog/) (an array, one answer per job), [rebuild](/api/ci/rebuildCiBuild/), [cancel](/api/ci/cancelCiBuild/). |
| `--monorepo <owner/name>` | The repository. Default: the one you are in. |

### pando ci job retry

```sh
pando ci job retry <build> <job>
```

Runs a job again in Buildkite, with the build's first environment, so it can still clone for 24 hours after the build started. Name the job by its key, name or id. Its check goes back to pending. It takes `--pipeline`, `--monorepo` and `--json` (the API's [answer](/api/ci/retryCiJob/)).

### pando ci run

```sh
pando ci run <pipeline> [--branch b]
```

Starts a build of the pipeline for the head of a branch as Pando has it (default: its project's main), with fresh tokens, the way a push starts one. It takes `--monorepo` and `--json` (the API's [answer](/api/ci/startCiBuild/)).

### pando status in a CI build

```sh
pando status <pending|success|failure|error> [--context ci] [--target-url u] [--description d]
```

Only in a build Pando started. Posts a check on the build's commit, using `PANDO_STATUS_URL` and `PANDO_STATUS_TOKEN` from the build's environment. Pando shows the CI service's mark on the check.

| Flag | What it does |
| --- | --- |
| `--context <name>` | The check's name. Default `ci`. |
| `--target-url <url>` | A link for the check. Default: `BUILDKITE_BUILD_URL`. |
| `--description <text>` | A short line for the check. |

## Releases

A release is a tag on a project's main, with notes and files. See [Releases](/releases/).

### pando release

```sh
pando release list | view [<tag>]
pando release create <tag> [<file>...] [--generate] [--title t] [--notes n | --notes-file f] [--target <sha>] [--draft] [--force]
pando release publish <tag> [--force]
pando release upload <tag> <file>...
pando release download [<tag>] [--pattern p] [--dir d]
pando release delete <tag> [--yes]
```

| Subcommand | What it does |
| --- | --- |
| `list` | Releases, newest first: tag, title, draft or published (and forced), commit, when. |
| `view [<tag>]` | One release (default: the latest published): its state, commit, who published it, its commit's checks, its files and its notes. |
| `create <tag> [<file>...]` | Tags main (or `--target`, a commit on main) and publishes it. With files, it makes a draft, uploads them, then publishes. Refused while the commit's required checks are red or missing, unless `--force`. |
| `publish <tag>` | Publishes a draft, by the same rule. From then on git can't move or delete its tag. |
| `upload <tag> <file>...` | Adds files to a release, each at most 100 MB, 20 a release. A name sent again replaces the file. |
| `download [<tag>]` | Writes a release's files (default: the latest's) into the current folder, each checked against its SHA-256. |
| `delete <tag>` | Deletes the release and its files. Its tag stays, and git can move or delete it again. Asks first; `--yes` for scripts. |

| Flag | What it does |
| --- | --- |
| `--generate` | With `create`: write the notes from the branches merged since the last release, after `--notes`, if any. |
| `--title <text>` | With `create`: its title. Default: the tag. |
| `--notes <text>`, `--notes-file <file>` | With `create`: its notes, in Markdown (`-` reads standard input). |
| `--target <sha>` | With `create`: the commit on main to release. Default: main, or the tag's commit when the tag exists. |
| `--draft` | With `create`: keep it a draft. |
| `--force` | With `create` and `publish`: publish past red or missing required checks. The release says it was forced. |
| `--pattern <pattern>` | With `download`: only files whose names match, such as `pando-darwin-*`. |
| `--dir <folder>` | With `download`: where to write the files. Default: the current folder. |
| `--repo <path>` | The project. Default: the one you are in, or the only one. |
| `--json` | Print the API's answer: [list](/api/releases/listReleases/), [view](/api/releases/getRelease/), [create](/api/releases/createRelease/), [publish](/api/releases/publishRelease/). |
| `--monorepo <owner/name>` | The repository. Default: the one you are in. |

## Hooks

### pando hook

```sh
pando hook list | create <url> | delete <id>
pando hook deliveries <id> | redeliver <delivery-id>
```

A repo's web hooks: on a push, a new branch or a merge, Pando POSTs JSON to a URL, signed with a secret you choose (`X-Pando-Signature-256`). Buildkite hooks are added with `pando ci pipeline add` and show in the list too. Adding, deleting and sending again need an owner.

| Subcommand | What it does |
| --- | --- |
| `list` | The repo's hooks: id, type, where it sends, events, app, and who added it when. |
| `create <url>` | Adds a web hook. It asks for the signing secret with no echo, or reads it with `--secret-file`; the secret is never an argument. With a URL that has a hook already, it adds nothing. |
| `delete <id>` | Removes a hook. |
| `deliveries <id>` | What the hook sent, newest first (the last 100): event, seq, status, tries and the answer. |
| `redeliver <delivery-id>` | Sends one delivery again, with the same id and seq. |
| `redeliver <hook-id> --since <seq>` | After an outage: sends again every delivery of the hook after that seq, oldest first, at most 1,000. |

| Flag | What it does |
| --- | --- |
| `--event <event>` | With `create`: `push`, `branch.opened`, `merged` or `tag`. Repeat it. Default: all four. |
| `--app <slug>` | With `create`: the CI service behind the URL (`github-actions`, `circleci`, ...), shown on the checks its builds post. |
| `--secret-file <file>` | With `create`: read the secret from the file, or from standard input with `-`. |
| `--since <seq>` | With `redeliver`: send again every delivery after this seq. |
| `--repo <path>` | The repo. Default: the one you are in, or the only one. |
| `--json` | Print the API's answer: [list](/api/hooks/listHooks/), [create](/api/hooks/createHook/), [deliveries](/api/hooks/listDeliveries/), [redeliver](/api/hooks/redeliver/) or, with `--since`, [replay](/api/hooks/replayHook/). |
| `--monorepo <owner/name>` | The repository. Default: the one you are in. |

## Machines and activity

`pando worktree list` shows every worktree on every machine.

### pando machine list

```sh
pando machine list
```

Each machine (a credential: a laptop, a cloud sandbox) that acted in the repository or is connected to it, latest activity first: whose it is, its kind, whether it is connected now and since when, how many worktrees it has open, and its last action. It takes `--monorepo` and `--json` (the API's [answer](/api/worktrees/listMachines/)).

### pando activity

```sh
pando activity [--monorepo <owner/name> | --all] [--limit n]
```

What happened, newest first, one line each, as the home page shows it: pushes, new and deleted branches, merges, reviews, checks that changed, worktrees added and removed, and shared files saved. Inside a repository's folder, that repository's lines; elsewhere, or with `--all`, those of every repository you belong to.

| Flag | What it does |
| --- | --- |
| `--monorepo <owner/name>` | One repository's lines. |
| `--all` | Every repository's lines, even inside a repository's folder. |
| `--limit <n>` | How many lines. Default 30. |
| `--json` | Print the API's [answer](/api/monorepos/listActivity/), its pages joined. |

### pando profile

```sh
pando profile [<login>] [--json]
```

A person's [profile](/profiles/), yours by default: their name, bio and links, their contribution graph for the last year drawn in the terminal (a column a week, Sunday on top, `·` for a day with nothing and `░▒▓█` for busier days), then each month in a line. You see only their work in repositories you can open. `--json` prints the API's [answer](/api/users/getContributions/).

## The API

### pando api

```sh
pando api <path> [-X method] [-f k=v] [-F k=v] [--paginate]
```

Calls any route of the [API](/api/) with this machine's credential, like `gh api`, and prints the answer: indented on a terminal, on one line in a pipe. The path may leave out `/v1`. In the path, `{owner}` and `{monorepo}` stand for the repository you are in (or `--monorepo`), `{repo}` for the project you are in (or `--repo`), and `{branch}` for the branch of the worktree you are in.

```sh
pando api /monorepos/{owner}/{monorepo}/repos/{repo}/branches --paginate
pando api /monorepos/{owner}/{monorepo}/repos/{repo}/branches -f name=fix-login -f title="Fix the login page"
pando api -X PATCH /monorepos/{owner}/{monorepo}/repos/{repo}/branches/{branch} --input body.json
```

| Flag | What it does |
| --- | --- |
| `-X <method>` | The method. Default `GET`, or `POST` when there are fields or `--input`. |
| `-f key=value` | A string field. Repeat it. With `POST`, `PUT` and `PATCH` the fields make a JSON body; with `GET` and `DELETE` they go in the query. `a[b]=x` makes `{"a": {"b": "x"}}`, and `a[]=x` adds `x` to the array `a`. |
| `-F key=value` | A field with a type: `true`, `false`, `null`, a whole number, or `@file` (the file's text; `@-` for standard input). Anything else is a string. |
| `--input <file>` | Send the file as the body (`-` for standard input). Fields then go in the query. |
| `-H 'Name: value'` | A request header. Repeat it. |
| `--paginate` | Follow a list's cursor (`next_cursor`, or `next` in the activity log) and print every page as one answer: the lists end to end, the cursor null. `GET` only. |
| `-i` | Print the status line and the headers first. |
| `--monorepo <owner/name>` | The repository for `{owner}` and `{monorepo}`. |
| `--repo <path>` | The repo for `{repo}`: its path, or its name in URLs. |

It exits 0 on a 2xx or 3xx answer; a 3xx with no body (an artifact's download) prints where it leads. Any other answer puts the API's error body on stderr and exits 1. A full URL is refused: the credential goes only to the server you signed in to. There is no `--jq`; pipe the output to `jq`.

## For scripts and agents

- **`--json` is the API's JSON.** Each command above links the answer it prints, and the [API reference](/api/) holds every field. A few commands put several answers together under fixed keys: `branch view` (`branch`, `reviews`, `commits`), `monorepo view` (`monorepo`, `repos`, `members`), `issue view --comments` (the issue, with its timeline under `timeline`), and `ci build log` (an array, one answer per job). A list read in several pages comes out as one answer, the lists end to end. On a terminal the JSON is indented; in a pipe it is one line.
- **Exit codes.** 0 when the command worked. 1 when it did not, with one line on stderr that says why and ends with the API's code and HTTP status, as in `pando: no pipeline nope here (not_found, HTTP 404)`; `pando issue` with `--json` prints the API's error object there instead. 2 when the command was used wrongly, with its usage.
- **Running a write again.** Only issues and comments take an idempotency key: `pando issue create` and `pando issue comment` always send one (`--key`, else one made for the run), and try again with it after a network error or a 502, 503 or 504, so a lost answer never makes a second issue. An agent that may run the command again after a crash passes its own stable `--key`, such as its task id. The rest of the API takes none, so another write retried after a lost answer may happen twice. These are safe to run again; a second run changes nothing (a delete or revoke already done answers `not_found`): every other `pando issue` subcommand (states, labels, assignees, links and reactions are set, not added twice; a body edit with `--base-version` is refused, not repeated), `pando hook create` and `pando ci pipeline add` (they look first, and add nothing when it is there), `pando monorepo rename` and `transfer`, `pando org create`, `add`, `remove` and `leave`, `pando members invite`, `revoke` and `remove`, `pando hook delete`, `pando ci build cancel` and `pando merge`. These are not: `pando ci run` and `pando ci build rebuild` start another build (look with `pando ci build list --branch <b>` first); `pando review -m` posts another review; `pando credential create` makes another credential; `pando hook redeliver` sends again (the receiver sees the same `X-Pando-Delivery` id and can drop it). `pando ci job retry` with a job's key retries that job's newest run, so once a first retry has finished, a second runs it again; name the job by its id to retry it once.

## Shared files

A repository's shared files are every file outside `projects/` and outside references: notes, decisions, plans. They are plain files on every machine. While `pando sync` runs, a save on one machine goes to the others as soon as it is made, and becomes a git commit after 10 seconds without changes.

Each of these commands takes `--root <folder>` for a repository in another folder than the one you are in.

### pando sync

```sh
pando sync [--once]
```

Keeps the shared files live until stopped: it sends this machine's saves and writes everyone else's. It also keeps this machine's read-only mains at the server's main. `--once` sends and receives what is waiting, then exits.

If you lose access to the repository (an owner removes you, you leave the organization that owns it, or it moves out of that organization), `pando sync` stops at once and says so. The folder keeps its files.

### pando history

```sh
pando history <path> [--limit n] [--json]
```

Every saved version of a shared file, newest first: version, when, who, machine, what, and the commit.

| Flag | What it does |
| --- | --- |
| `--limit <n>` | How many versions. Default 50. |
| `--json` | Print JSON. |

### pando restore

```sh
pando restore <path> --to <version | HH:MM>
```

Writes an old version back as a new save, which every machine gets. `--to` takes a version number, a time today (`10:42`), or a date and time (`2026-10-03 10:42`). A time means the latest version at or before it.

### pando resolve

```sh
pando resolve [<path>...]
```

When two machines change a file at once, one keeps a conflict copy beside it and the file stops syncing there. `pando resolve <path>` makes it sync again: if you edited the file, your version goes out. With no path, it lists the files that are stopped.

### pando fetch

```sh
pando fetch <path>...
```

Downloads the bytes of large shared files that a `--text-only` clone keeps as pointers. See [Limits](/limits/) for file sizes.

## The Mac

### pando mac broker

```sh
pando mac broker [--dry-run]
```

macOS only. Loads Pando.app's background helper, which a worktree mounted through Pando.app (`--kind fskit`) needs. The first mount runs this step on its own.

| Flag | What it does |
| --- | --- |
| `--dry-run` | Print what it would load and the commands, and load nothing. |
| `--app <path>` | The installed Pando.app. Default: found on its own. |

## Environment

| Variable | What it does |
| --- | --- |
| `PANDO_SERVER` | The Pando server URL, over the one in `~/.pando/config.toml`. |
| `PANDO_HOME` | Where pando keeps this machine's config and credentials. Default `~/.pando`. |
| `PANDO_TOKEN` | A credential to use instead of the stored one, for sandboxes. Make one with `pando credential create`. |
| `PANDO_MACHINE` | This machine's name in Pando. Default: the host name up to its first dot. |
| `PANDO_NO_BROWSER` | Any value: `pando login` prints the link and opens no browser. |
| `PANDO_WORKTREE_KIND` | The default for `--kind`: `sparse`, `fuse` or `fskit`. |

Pando sets these in a build it starts:

| Variable | What it does |
| --- | --- |
| `PANDO_CLONE_URL` | The repo's clone URL. |
| `PANDO_READ_TOKEN` | A read-only token for that one repo. Clone with it as a bearer token. It lasts at least 24 hours, so a retried job can still clone. |
| `PANDO_STATUS_URL` | Where `pando status <state>` posts. It names the build's commit. |
| `PANDO_STATUS_TOKEN` | Lets `pando status <state>` post checks on that one commit, for 24 hours. |

Source: https://docs.gitpando.com/cli/index.mdx
