From the terminal
supi is SuperPipeline from a terminal. It is also installed as superpipeline — the same program
under its full name, for scripts that should read plainly. It is a client: it adds no authority of
its own and renders the board’s answers, including its refusals.
This page is a tour. Every command, flag, default and environment variable — and who may run each
one — is in the command reference, generated from the CLI itself; supi help <verb> prints the same entry in a terminal.
Installing
Section titled “Installing”curl -fsSL https://github.com/SuperJackfruitLabs/superpipeline/releases/latest/download/install.sh | bashOne binary under two names, into ~/.local/bin by default (BIN_DIR to change it). VERSION pins
a release tag. The installer sets up no service, enrolls nothing, and never asks for sudo — a
CLI that needs root to update itself is a CLI that stops updating itself.
supi update # replace this binary with the newest releasesupi update --check # just say whether one existssupi versionAn update resolves the latest tag, downloads the asset for your platform, verifies it against the release’s checksums, and swaps it in atomically. A download it cannot verify is refused rather than installed.
To run it from a checkout while working on the CLI, packages/cli/install.sh links the two names
at the source instead. It requires bun and never replaces a file it did not put
there.
Signing in
Section titled “Signing in”People sign in to SuperPipeline with their account at accounts.superjackfruit.com — the same account the web app uses. From a terminal that is one command:
supi login # prints a link and a code; confirm the code in your browsersupi whoami # who you are signed in as, and when the token expiressupi boardssupi login keeps a device credential of its own and exchanges it for a short-lived token on every
command, so you are not asked for a browser again until that device is revoked. supi logout
forgets it on this machine.
If you already ran AgentPod’s fleet login on this machine, supi can use that sign-in instead
and needs no second one. Or supply a token directly:
SUPERPIPELINE_TOKEN=… supi boards| variable | meaning |
|---|---|
SUPERPIPELINE_TOKEN |
a person’s token, used exactly as supplied |
SUPERPIPELINE_URL |
the deployment to talk to. Defaults to https://app.superpipeline.dev. |
Explicit environment tokens are used as supplied and are never renewed or replaced with a disk
identity. If one expires, replace or unset the variable. The full resolution order, every file
supi writes and every variable it reads are in the
command reference.
When an agent is the one running it
Section titled “When an agent is the one running it”An agent acts with SUPERPIPELINE_AGENT_TOKEN_FILE — a file, re-read every run — or
SUPERPIPELINE_AGENT_TOKEN, either outranking every person’s credential.
This distinction is load-bearing. An spa_ token reads and plans. Only an agent JWT — a station
token — carries the dispatch grant that queues work and moves cards, and it lives for minutes — so
point the file at something that keeps it fresh, rather than at a value that was true when you set
it.
Looking at work
Section titled “Looking at work”supi boards # the workspace's boardssupi board <boardId> # one board: its stages and their cardssupi card <boardId> <cardId> # one card in fullsupi log <boardId> <cardId> # what an agent did on a card, and its handoffsupi capabilities # the capability registry, with each one's originsupi implications # what one capability implies about anothersupi agents # the workspace's agents and what they declareDeciding
Section titled “Deciding”supi gates <boardId> # approval gates waiting on a humansupi approve <boardId> <gateId> [--comment "why"]supi reject <boardId> <gateId> [--comment "why"]supi request-changes <boardId> <gateId> --comment "what to change"request-changes requires a comment. “Changes requested” with nothing said is a card nobody can
act on.
Moving work
Section titled “Moving work”supi create-card <boardId> "<title>" [--spec <file|->] [--priority <n>] [--due YYYY-MM-DD] [--label <id>]...supi edit-card <boardId> <cardId> [--title <text>] [--spec <file|->] [--merge-spec <file|->] [--priority <n>] [--due YYYY-MM-DD|none]supi move <boardId> <cardId> <stageKey>supi archive <boardId> <cardId>A card created here carries this token as its grant — the record of who asked for the work.
--spec takes the card’s brief as a JSON object. Begin it with a plain-language description;
plan and acceptanceCriteria get their own sections in the card drawer and every other field is
shown under Details. The agent receives the whole spec either way — see
The spec.
edit-card changes a card through the same edit the card drawer makes, with the same authority:
member for a person, plan for an agent token. Only the fields you name change. --spec
replaces the spec whole. --merge-spec merges one level deep — each top-level key you give
replaces that key, null removes it, everything else is kept:
echo '{"acceptanceCriteria": ["Covers the expired-token path"], "draftNotes": null}' \ | supi edit-card brd_8f2c… crd_41aa… --merge-spec -A merge reads the card first and writes back only if the card is unchanged since that read. If
someone edited it in the drawer, or an agent claimed it, in between, the write is refused with a
409 and nothing changes; run the command again to merge into the card as it now is. --due none
clears the due date.
Order and grouping
Section titled “Order and grouping”supi label listsupi label add <name> <colour>supi label rm <id>
supi project listsupi project add <name> [--description <text>] [--target YYYY-MM-DD] [--lead <userId>]supi project show <projectId>supi project rm <projectId>supi milestone add <projectId> <name> [--target YYYY-MM-DD] [--sort <n>]supi milestone rm <milestoneId>
supi link add <boardId> <fromCardId> <toCardId> --kind blocks|relates|parent [--to-board <boardId>]supi link rm <boardId> <fromCardId> <toCardId> --kind blocks|relates|parent [--to-board <boardId>]supi link list <boardId> <cardId>--to-board names another board, which makes the edge advisory — shown, never enforced.
link list keeps the enforced and advisory edges apart rather than presenting them as one set.
Removing a label, project or milestone leaves its id on the cards that carried it; they show nothing rather than a dangling name. See Planning work.
Shaping a board
Section titled “Shaping a board”supi templates # the starting pipelines --template acceptssupi create-board <name> [--template <id>] [--stages <file|->]supi set-stages <boardId> <file|-> # replace the whole pipelinesupi set-stage <boardId> <stageKey> [--instructions <file|->] [--clear-instructions] [--name <name>] [--gate none|approval] [--wip <n>|none] [--owner <capability>] [--completion <file|->] [--clear-completion]Prefer set-stage. It changes one stage and leaves the others alone, including a concurrent
edit to a stage you did not mean to touch. set-stages replaces the pipeline and discards whatever
it was not told about — it has destroyed a board’s stage instructions once. See
Stage runbooks and completion.
Recurring work
Section titled “Recurring work”supi schedule list <boardId>supi schedule add <boardId> --title <t> --rule <r> --tz <tz> [--stage <key>] [--priority <n>] [--overlap skip|allow]supi schedule pause <boardId> <scheduleId>supi schedule resume <boardId> <scheduleId>supi schedule rm <boardId> <scheduleId>A rule is every <n> minutes|hours|days, daily at HH:MM, weekly on <mon-sun> at HH:MM, or
monthly on <1-28> at HH:MM. Checked every five minutes, so a card may appear up to five minutes
after its stated time. See Recurring cards.
Agents and forge
Section titled “Agents and forge”supi forge [<host>|none] # this workspace's forge host, shown or setsupi agent queueing <agentId> [--owner <userId>|none] [--boards <id,id,…>|none] [--ceiling <n>]agent queueing sets what an agent may queue of its own: whose work it owns, which boards may
receive it, and how many cards an hour. --boards none is the default and means no board — not
every board. See Agents that plan.
Output
Section titled “Output”--json on any command gives machine-stable output. The default is readable; a shape with no
renderer prints JSON either way. Everything prints the board’s own answer rather than a summary, so
nothing you needed is dropped in the retelling.
Teaching an agent to use it
Section titled “Teaching an agent to use it”The installer can place an agent skill alongside the binary:
curl -fsSL https://github.com/SuperJackfruitLabs/superpipeline/releases/latest/download/install.sh | SKILL_DIR=~/.claude/skills bashsupi carries its own skill, so it always matches the binary’s verbs and works offline. Print it
with supi skill, or place it yourself with supi skill install [--dir <dir>] (default
~/.claude/skills; it writes <dir>/superpipeline-boards/SKILL.md and is safe to repeat). With
SKILL_DIR set, the installer runs exactly that; pinned to an older release (VERSION) with no
skill verb, it fetches that release’s SKILL.md asset instead.
Omitted by default, because most callers are people and a person needs no skill. The skill describes the surface an agent credential actually has, and which verbs change shared state, so an agent asks first.
Workspace authority
Section titled “Workspace authority”You act with your own workspace role, the same one the web app uses. The API checks permissions; the CLI adds none and bypasses none. Each command’s entry in the reference says which role, or which agent scope, it needs.
An admin can also register an agent from here — define its capability, create its record linked
to its principal, and mint its tokens (supi capability define, supi agent create,
supi agent mint-token); Registering an agent walks through it. An
agent credential is refused on all three.
Not here: revoking a token or deleting an agent, changing the fleet link, and deciding a gate as anyone but yourself. What you may do is your seat in the workspace, which the server decides.
What it will never mix up
Section titled “What it will never mix up”A person’s credential and an agent’s are never interchangeable. supi refuses a person’s token in
an agent variable, and an spa_ agent token in a person’s — rather than quietly acting as whoever
the token names — and a token file that is named but missing or empty is a refusal, never a
fall-back to the operator’s sign-in. The board records who asked for each card, and a CLI that
swapped identities would make that record a lie.
Reading a refusal
Section titled “Reading a refusal”401 means sign in (supi login). 403 means your role or your scopes do not permit this. They are never
conflated — a member meeting an admin verb gets the second, and being told to sign in again
would send you round a loop. A refusal is printed as it arrives, in the server’s own words.