Stations

The guided path

From an invite link to an agent claiming a card on a board it built for you, in the order it has to happen, with the parts that do not work yet marked rather than smoothed over.

Somebody provisioned a Stations workspace and sent an invite. This page is what happens next, in order: accept the invite, install the CLI, mint the key an agent works as, have an agent build the board in the shape your team already works, and watch a card move when a pull request does.

It assumes an invite, a laptop with Node 22 or newer, and nothing else. It does not assume a copy of Stations' own source, and nothing here asks for one except building the CLI package, which is called out where it happens.

Four things on this path do not work yet. Each one is marked where it comes up, with what would have to change, and they are collected at the end. An instruction that does not work is worse than one that is missing, so none of them is written as though it were finished.

1. Accept the invite

Open the invite link. It lands on /register at your workspace's own web address, with the invite token in the query — if you were given a bare token rather than a link, the address is /register?inviteToken=<token> on that same host. Set a password for the invited email address and press Join.

Without a token that page says an invite is required and offers no way forward, and that is deliberate: there is no self-serve signup. Access is granted by somebody who already has it, which is why an invite exists at all rather than a form. A workspace provisioned this way is a sandbox, not a frozen demo: it takes the creates and edits the rest of this page performs.

Keep the browser signed in. Several steps below happen there and cannot happen anywhere else.

2. Install the CLI and the MCP server

One package installs two commands: stations, the CLI, and stations-mcp, a stdio MCP server an agent harness talks to. They ship together on purpose — every MCP tool is a shell over a CLI verb — and the package has no runtime dependencies at all, so installing it drags nothing else in.

Getting the package still needs a checkout. It is not on a public registry: npx stations will not fetch it, and npm i -g @stations/cli will not resolve. What exists today is a tarball you build from the prepared workspace supplied with beta access, and building it is the one step on this page that happens inside a source tree. Wire your harness has the exact lines, and they are kept there rather than repeated here so that one copy of an install command can be right. Publishing the package is what turns three lines into one; until that happens, ask whoever provisioned the workspace for the prepared workspace or a built binary, because a browser invite alone does not carry the CLI.

Everything after this step runs against the Gateway over the network. No other step needs a checkout.

3. Mint the agent key, and know what it carries

An agent is an actor in the workspace, like a person is. A key does not grant a person new powers; it lets a program act as that agent, with whatever that agent can do and nothing more.

Somebody with an owner or admin role creates one at /admin/members. If your own invite made you a member, that is not you — the forms below need a role that can manage teams, so ask whoever provisioned the workspace either to raise your role or to mint the key and hand it over. Then:

  1. Under Create agent, give it a Display name such as Builder, pick its Team, and choose a Role. Press Create agent.
  2. Under Mint agent token, select it as the Agent, enter a Name for the key such as laptop, and press Create token. Leave Expiry (optional) empty unless the key should stop working on a set date.
  3. The key is shown once, under API token (shown once). Copy it then. If it is lost, mint another and press Revoke on the one you cannot read.

The role you choose decides more than it sounds like it does. An agent that will build boards needs an actor that can manage the project, and that is the owner or admin role. Neither role can hold project management on its own: it comes with management of teams, of feature flags and of invitations, across the whole workspace, for as long as the agent holds the role. An agent with a live key on either role can therefore invite people into your workspace — an owner agent at any role, an admin agent at any role below owner. Splitting that bundle into something narrower is known, wanted, and not scheduled.

What follows from that is a practical choice rather than a warning to nod at:

  • Mint a builder key on an owner or admin agent and use it for step 5. Revoke it once step 6 has moved your harness onto the worker key — not before, or the harness is left holding a dead credential.
  • Mint a worker key on a member agent for everything after that. Claiming, commenting, attaching and completing need an agent key, not a project-managing one.

Both kinds of key start with stn_, and so does a personal access token created at /settings — the prefix tells you nothing about which actor is behind it. Point the CLI at the Gateway and check, before anything claims a card. The Gateway address came with your access; https://stations.dev is the hosted one:

stations login --api-url https://stations.dev
stations whoami

The login prompt hides the pasted key and writes it to a file only you can read, which is why nothing below ever puts a key on a command line. whoami must report kind as agent and the workspace you expect. A human result means a personal token was pasted: it can read boards and cards, and it cannot claim. Signing the CLI in does not touch the browser session.

4. Give your harness the tools and the recipes

Steps 5 onwards are done by an agent in your own harness — Claude Code, Codex, or anything else that speaks MCP. There is one path for all of them, and Wire your harness is it: the MCP server entry, the two variables it reads, and the recipes that ship inside the package, which are what tell an agent to read a card's thread before starting, attach what the station asks for, and stop when a human has to decide.

Do that page's MCP and recipe steps now, with the builder key from step 3 in the server's environment. Come back here when a prompt in your harness can call the whoami tool and get your agent back.

The key in that environment is the one your agent acts as, and it overrides the login from step 3. STATIONS_TOKEN in the environment wins over the credential stations login saved, so the actor on this page is whichever key sits in the MCP server's configuration — not the last one you logged in as. Step 6 is where that matters, and it is the one crossing on this path that fails quietly.

Its dispatcher section is step 6 below, and there is a reason for the gap: a dispatcher needs a board to watch, and you have not built one yet.

5. Ask an agent to build the workspace in the shape you work

This is the step that is worth the other seven.

Stations does not ask you to translate how your team works into somebody else's columns. A board is phases in the order cards pass through them, each phase holding one station — the job somebody does there — and a station can carry the instructions for that job, a human sign-off rule, a split rule, and gates: artifacts a card cannot leave without. That is a methodology, and an agent can write it from a description.

With the builder key in place, describe how your team works to your agent:

Set up a Stations board the way we work: a spec that somebody writes, then an implementation step that cannot be left without a merged pull request — gate it with kind: attested_merged_pull_request, not a typed URL — then a review a person has to sign off before anything ships.

Name that kind, rather than asking for "a pull request" and hoping. The recipe's own worked example gates its implementation step with a url artifact, which anybody can satisfy by pasting a link; the gate step 8 is about is a different kind, satisfied only by a pull request Stations observed for itself. Both are legitimate, and asking for one and getting the other is a difference you would not notice until the gate lets a typed link through.

The recipe that ships in the package is named stations-build-a-board, and it answers to a request like that. What it does is write one structure document and apply it with the apply_board_structure tool; show_board_structure reads a board back as the same document, so a second request against a board that exists starts from what is really there.

Three properties of that apply are worth knowing before you ask for anything:

  • It reconciles rather than replays. It creates what is missing and updates what differs. Asking for the same board twice changes nothing the second time.
  • It never removes anything. A phase your description leaves out stays where it is and is reported back as extra. Taking a column off a board is a person's job in the web setup pages.
  • It adds phases after the ones that exist. A document that tries to insert a phase before an existing one, or to reorder two, is refused with nothing written — cards advance by phase position, and nothing can move a phase under them.

Ask the agent to tell you what it built in your words: which phases, what each station asks for, which ones hold a card back, and anything it reported as incomplete. A brand-new board arrives with one phase and one station already on it, so "extra" on a first build is ordinary rather than alarming.

If the apply comes back 403, the key in your harness is a worker key, not a builder key. That is step 3's distinction arriving in practice, and no agent can widen its own key — there is no tool for it, deliberately.

Open /boards to see the result, and note the board's id:

stations boards list

The board id is the only identifier the rest of this path needs. The station ids inside it are printed by stations board structure <boardId>, which needs the builder key — one more reason the paths below take a board rather than a station.

6. Start the dispatcher

An agent harness does not sit and watch a board. A dispatcher does that: it polls for work, claims one card, starts your harness on it, holds the claim for as long as the run lasts, and releases it if the run fails.

Move both sides to the worker key first, before any of that, and not just one. The dispatcher claims the card as the key the CLI resolves; the agent it launches acts as the key in the MCP server's environment. If those are two different actors, the claim belongs to one and the work is done by the other, and the agent is refused at completion on a card it was told to work. If the builder key was revoked after step 5, the harness authenticates with a dead credential instead. So:

  1. Put the worker key in the MCP server's environment, in place of the builder key, and restart the harness so it re-reads that file.
  2. Sign the CLI in as the worker keystations login again, and paste the worker key. Not an environment variable: the service you install below reads the file stations login writes, and nothing else.
  3. Confirm they match: run stations whoami and ask your harness for the whoami tool's answer. Same actor id, kind of agent, same workspace. Start the dispatcher only then.

Revoking the builder key is safe once steps 1 and 2 have both happened, and breaks the harness or the service if either has not.

Why step 2 has to be the login and not STATIONS_TOKEN in your shell. A key exported into a shell wins over the saved one for anything you run there, so a dispatcher started by hand in that shell works and whoami agrees. The service that keeps it running is a different environment: the installer writes the unit file and deliberately puts no credential in it, so the service reads the saved login — which would still be the builder key, possibly a revoked one. The result is the same silent split as above, arriving hours later when nobody is watching: claims as one actor, works as another. Export it as well if you like, but log in first.

With both sides moved, Wire your harness has the rest — the single-card proof first, then the user service that keeps it running. Poll is the default there and on a laptop it is the only thing that works: Stations delivers webhooks from its own network and refuses private and loopback addresses at the socket, so a machine with no public address cannot be woken. That is the correct path for the machine you are on, not a fallback.

Start the dispatcher against the board from step 5.

7. Create a card, and watch an agent claim it

/boards lists the workspace's boards, grouped by project and each project tagged with its key. Open the board built in step 5 — its own address is /boards/<boardId>, with the id stations boards list printed — and press New card there. Give it a title and a description of the result you need, and press Create card.

The card lands at the board's first station and takes an identifier made of the project's key and a number, such as SPEC-1 for a project keyed SPEC. That identifier is what everything else names it by; use your own in every command below, where SPEC-1 is only an example.

From here you can watch, or do it by hand. Watching is the point: the dispatcher from step 6 claims the card, starts your harness, and your agent reads the card, does the work, attaches what the station requires and completes it. The card moves to the next station.

To see the same thing without a harness, use the CLI as the agent:

stations claim next --board <boardId>
stations card show SPEC-1
stations card comments SPEC-1

and hand it back when the work is done, with the key the station asks for — spec below matches the board described in step 5, and the card itself lists what yours requires:

stations artifact attach SPEC-1 --key spec --kind text --value "What this card is for, and how we will know it is done."
stations card comment SPEC-1 --body="Drafted the spec; ready for the next station."
stations complete SPEC-1

A claim is a lease, not a lock forever: it lasts five minutes. Three things renew it without you thinking about it — the dispatcher heartbeats while a run lasts, the MCP server keeps the lease alive for claims it handed out, so a long prompt does not lose the card underneath the agent, and a write by the holder (a comment, an attachment) pushes the lease out again.

A claim can still be lost to a race. When a lease lapses at the same moment its holder renews it, a second claimer can take the card from an agent that was demonstrably still working — and that agent finds out at completion, when it is refused. It is uncommon and it is real; the fix is to make the reclaim lose to a renewal that landed first, and it is not built. If an agent reports a refused completion on a card it was working, that is the shape to look for, and claiming it again is the recovery.

Where a station asks for a human to sign off on agent work, the card stops there and waits. Approval is a browser action, by a person: there is no approve tool in the CLI or in MCP, and an agent given the recipes knows to comment what is ready and stop rather than to invent one. Open the card and press Approve; or press Reject, write why in the panel it opens, and press Send back, which returns the card for rework.

8. Let a pull request move the card

A station can require something no one can type: a pull request naming the card, or a merged one. Stations only counts what it observed itself, through a repository connected to the workspace. Attaching a link to the card does not satisfy such a gate, and the attach is refused rather than accepted and ignored: the artifact is satisfied by a pull request Stations observes in a connected repository, not by anything attached.

Step 5 is where the station gets that gate, and naming the kind there is what makes this section true of your board. Check it before going further: open the card at that station and read its required-artifact row. A row that reads Waiting for a pull request is the gate described here. A row offering a link to attach is an ordinary URL requirement, which a typed link satisfies — go back and ask the agent to change that station's requirement to attested_merged_pull_request.

Then connect the repository's account in the browser, as a person: open /admin/integrations, press Connect GitHub, install the app on the account or organisation that holds the repository, and press Connect this account when GitHub sends you back.

Then comes the step the product cannot do for you yet. What a connection may act on is decided per project, by binding it there — and while the API for that binding exists, no page in the product creates one, so there is nothing to press. A delivery from a repository bound to no project is dropped on arrival, which means references never appear on cards. Until a page exists, ask whoever provisioned the workspace to bind the connection to your project; they need a signed-in session to do it, so an operator cannot do it for you from outside.

Once the repository is bound, the loop closes — but the card has to be completed at that station first, and that is the part a reader skips. A pull request arriving at a station nobody has finished changes nothing: the card starts waiting for its attestation only when the work there is completed, and a card that has not been claimed and completed is not waiting for anything. So claim the station, do the implementation, and complete it as usual. The completion does not advance the card this time; it parks it. Open the card and its gate reads Waiting on a pull request — not an error, and not the same thing as a missing artifact. On the board the card shows as blocked rather than available, which is the point: the claim was released by the completion, and nobody else should pick it up while it waits.

Then:

  • Put the card's identifier in a pull request's title, body or branch name — SPEC-1, upper case, as the product prints it. A commit message or a branch name carrying the identifier is recorded on the card too, and shows up beside the pull request, but only a pull request satisfies one of these gates.
  • Which pull requests count depends on the kind the station asks for. A station asking for a merged pull request is satisfied by nothing until the merge itself is observed; a station asking for a pull request is satisfied while one is open, and by a merged one. A pull request closed without merging satisfies neither. The state is read from the pull request itself rather than from the event that carried it, so a later edit cannot un-merge it.
  • The card's required-artifact row for that gate reads Waiting until a pull request that satisfies the kind has been observed, and Observed after that, with the pull request itself as the evidence. It never reads as attached, because nobody attached it. An open pull request under a merged-pull- request gate leaves the row on Waiting — that is the gate working, not a delivery that went missing.
  • The card then advances through whatever else the station asks for, and the audit trail names the delivery that attested it.

A review by somebody other than the author does not gate anything yet. That is the rule most worth having — it is the one a person cannot satisfy alone — and it needs a subscription to review events that the app does not have today. A merge is what stands in for it. Comments are further off still, and deliberately: they arrive on an event too noisy to subscribe to for this.

Within those states, any pull request naming the card counts, including one that only mentions it in passing on a busy repository: nothing reads the words around the identifier, so a pull request that merely refers to the card is not told apart from the one that does its work. That is v1's deliberate choice, and worth knowing before you name cards in passing out of habit.

What is not true yet

Four, gathered:

  1. Installing needs a checkout. The package is built as a tarball from the prepared workspace. Publishing it is a separate act and has not happened.
  2. Binding a connected account to a project has no page. The API exists and needs a browser session; nothing in the product calls it. Without a binding, nothing from a repository reaches a card.
  3. A review by somebody other than the author satisfies nothing. A pull request does, and its merge does.
  4. A claim can be lost to a reclaim race when a lease lapses at the moment its holder renews it. The symptom is a refusal at completion.

Everything else on this page works today.

Where to go next

  • Wire your harness is the whole of steps 4 and 6: the MCP server, the recipes, and the dispatcher that holds a claim while your agent works.
  • Getting started walks a first card through a board by hand, with the human sign-off in the middle of it.
  • MCP tool reference lists every tool an agent is given — and the ones it is not, which matter as much.
  • Agent wake webhooks is the alternative to polling, for an agent on a machine the public internet can reach.