CLI reference
flostep creates, edits and shares Flostep diagrams from a terminal. Steps go in on a pipe,
a link comes back, and nothing is written to your disk.
It is also the interface for coding agents. Anything with a shell can drive it, with no client support and nothing to configure — see Coding agents.
Installation
Run it without installing
npx fetches and runs the latest version. Nothing is left on your machine.
npx flostep --version
Install globally
Puts flostep on your PATH, which is worth it if you use it daily.
npm install -g flostep flostep --version
Add it to a project
Pins the version for everyone working in the repo, and for CI.
npm install --save-dev flostep npx flostep --version
The package has no runtime dependencies, so an install pulls down one small package and audits clean.
flostep …, assuming it is installed. If you would
rather not install it, prefix any of them with npx —
npx flostep create … — which is what the CI and agent examples do.
Quickstart
From nothing to a link you can send someone, in two commands.
flostep login flostep create --title "Checkout" --share <<'EOF' Customer -> API: POST /checkout API -> Payments: charge card Payments -> API: authorized API -> Customer: order confirmed EOF ✓ Created #Xk3p9QvA2wE Checkout https://flostep.dev/s/rEFdW8GSDwQ
That wrote nothing to your disk. Send the link to anyone — they can step through the flow without an account.
Changing it later
Keep the id. Every other command takes it, and show pipes the diagram back out, so an edit
is a read, a transform and a write:
flostep show Xk3p9QvA2wE | sed 's/Redis/Session Cache/' | flostep update Xk3p9QvA2wE
If you would rather keep the steps in a file in your repository, keep the file yourself and pipe it in
with flostep update Xk3p9QvA2wE < docs/checkout.flostep. The CLI tracks nothing on disk.
Edits made elsewhere are never silently overwritten. step and node send the
version they read, and are refused (exit 1) if the diagram changed in between — in the
browser, by a teammate, or by another agent. For update, take version from
flostep show Xk3p9QvA2wE --json and pass it as --if-version. After a refusal,
show the diagram again and redo the change.
Authentication
Two ways in, for two situations.
On your own machine
flostep login runs an OAuth device flow: it prints a short code, opens your browser, and
waits while you approve it. The code works from any device, so nothing has to open on the
machine running the CLI — which is what makes it work over SSH and inside containers.
flostep login ╭─────────────────────────╮ │ Your code: WDJB-MJHT │ ╰─────────────────────────╯ Opening https://flostep.dev/device — approve the code there. ⠋ Waiting for approval… ✓ Connected Account you@example.com Workspace Acme Corp (team) Plan team Expires 28 Nov 2026
This creates an API key named after your machine, valid for 90 days. It appears on your
API keys page and can be revoked there at
any time. Run flostep login again to renew it.
In CI, or for an agent
There is no browser in a build, so the device flow does not apply. Create a key on the
API keys page, leave its expiry as
Never, and set it as FLOSTEP_TOKEN.
export FLOSTEP_TOKEN=fls_your_api_key_here npx flostep whoami
FLOSTEP_TOKEN always takes precedence over a stored login, so you can run a one-off command
as a different account without logging out.
Commands
Every command takes the global flags as well.
A diagram is always named by its id (like Xk3p9QvA2wE), from flostep list or from create.
create and update read steps
from stdin; show prints them to stdout. Redirect it yourself if you want a file.
| Command | What it does | Options |
|---|---|---|
| flostep login | Signs in from this machine via the browser. Creates a key valid for 90 days. | --token <fls_…> store a key you already have--no-browser print the URL instead of opening it |
| flostep logout | Forgets the stored credentials. The key keeps working until you revoke it. | — |
| flostep whoami | Which account and workspace the key writes to. | — |
| flostep init | Writes instructions for this repo's coding agent, telling it this tool is available and how to call it. Run once per repo; no login needed. Re-run after upgrading to refresh the block it wrote. | --file <path> write somewhere other than the default agent file--print print the instructions instead of writing them-y, --yes skip the confirmation prompt |
| flostep list | Diagrams in the workspace, most recently updated first, with the folder each is in. | --folder <name> only that folder, or uncategorized |
| flostep show <id> | Prints the steps to stdout and nothing else, so it pipes and redirects cleanly. | — |
| flostep create | Reads steps from stdin and creates a diagram. Writes no files. | --title <title> diagram title--share turn on the public link and print it, same call |
| flostep update <id> | Reads steps from stdin and replaces every step in the diagram. | --title <title> also rename it--if-version <n> refuse the write if the diagram changed since that version |
| flostep share <id> | Turns the public link on and prints it. | --off stop sharing--embed print the iframe URL--markdown print a markdown image that links to the diagram, for a GitHub README, ADR or PR (paid plans) |
| flostep open <id> | Opens the diagram in the editor in your browser. | — |
| flostep delete <id> | Deletes the diagram and its comments. Cannot be undone. | -y, --yes skip the confirmation |
| flostep folder list | Folders, alphabetically, with how many diagrams each holds. | — |
| flostep folder create "<name>" | Makes a folder. An existing name, ignoring case, is returned rather than duplicated. | — |
| flostep folder rename "<old>" "<new>" | Renames a folder for everyone in the workspace. | — |
| flostep folder delete "<name>" | Deletes the folder. Its diagrams are kept and become uncategorized. | -y, --yes skip the confirmation |
| flostep move <id> "<folder>" | Files a diagram in an existing folder. Doesn't change the diagram, so it works on read-only ones. | --none take it out of its folder |
| flostep step add <id> "<step>" | Appends a step. Naming a new component here is how a box appears. | --at <n> insert before step n |
| flostep step rm <id> <n> | Removes step n. Steps are numbered from 1, matching the canvas badges. | — |
| flostep step list <id> | Numbered steps. | — |
| flostep node list <id> | Components, in the order they first appear. | — |
| flostep node rename <id> "<old>" "<new>" | Rewrites every step that mentions the component. Case-insensitive. | — |
| flostep syntax | The step grammar, fetched from the server so it cannot drift. | — |
Examples
flostep create --title "Checkout" --share < flow.txt no files, returns a link flostep show Xk3p9QvA2wE | sed 's/Redis/Cache/' | flostep update Xk3p9QvA2wE flostep share Xk3p9QvA2wE public link flostep share Xk3p9QvA2wE --markdown image for a README, follows the diagram flostep show Xk3p9QvA2wE > docs/checkout.flostep keep a copy in the repo flostep update Xk3p9QvA2wE < docs/checkout.flostep and send it back up flostep step add Xk3p9QvA2wE "API -> Cache: read session" flostep step add Xk3p9QvA2wE "Client -> API: retry" --at 3 flostep node rename Xk3p9QvA2wE "Redis" "Session Cache"
update, step and node
all send the whole diagram back. Anything the text format cannot express — notes, component positions,
hand-dragged curves, chosen icons — is not carried by the steps and will not survive.
show first if a colleague may have edited it in the browser.
node add and no --type. The format cannot express a
component with no connections, and a component's type is inferred from its name rather than written
down — so a --type flag would be discarded on the next write. Add a component by naming it
in a step.
update only sends the title when you pass --title, so renaming a diagram in the
editor sticks. delete refuses without a terminal unless you pass --yes:
assuming yes would delete work from a script that stalled, and assuming no would make the command
useless in CI.
Per-command help is in the tool itself: flostep <command> --help.
Global flags
Accepted by every command.
| Flag | Description |
|---|---|
| --json | Machine-readable output on stdout, with stable key names. Never mixed with human text. |
| -h, --help | Help for the command, including runnable examples. Exits 0. |
| -v, --version | Print the version and exit. |
An unrecognised flag is a usage error rather than being ignored — a silently dropped
--tittle would push under the wrong title and look like it worked.
flostep --help --json prints the whole command and flag surface as JSON, built from the same
definitions the CLI dispatches. It is there for tooling — this page is checked against it, so a flag that
exists but is missing here fails a test rather than quietly making the docs wrong.
Exit codes
Stable, so a script or an agent can branch on them without reading the message.
| Code | Meaning |
|---|---|
| 0 | Success. Also returned by --help and --version. |
| 1 | The command was right and something else went wrong — not authenticated, diagram not found, plan limit reached, network failure. |
| 2 | Usage error — unknown command, unknown flag, missing argument. |
Errors are written to stderr, so redirecting stdout never swallows the reason something failed.
Environment variables
| Variable | Description |
|---|---|
| FLOSTEP_TOKEN | API key to authenticate with. Takes precedence over a stored login. This is how CI and agents authenticate. |
| NO_COLOR | Disable colour. Colour is already off automatically when output is not a terminal. |
| XDG_CONFIG_HOME | Where the config file lives, if you have moved your config directory. |
Config file
Written by flostep login to ~/.config/flostep/config.json with mode
0600, since it holds a credential.
{
"host": "https://flostep.dev",
"token": "fls_…"
}
The host is stored next to the token because the two belong together — a key means nothing against a different server.
Step format
One step per line, in the order it happens:
Customer -> API: POST /checkout API -> Payments: charge card Payments -> API: authorized API -> Customer: order confirmed
Components are created the first time they are named, so reusing a name points at the same box and
genuinely different components need genuinely different names. The : description after the
arrow is optional. Point a component at itself for internal work.
Participants do not have to be software. A refund escalating from a customer to support to finance models exactly as well as a request crossing three services.
A diagram holds up to 40 components and
120 steps. Past that, split it — it reads better anyway.
Lines beginning # or %% are ignored.
Run flostep syntax for the authoritative version, served by the API.
Continuous integration
Store a key as a secret called FLOSTEP_TOKEN. Leave its expiry as Never — a
key that lapses takes the pipeline down on a date nobody chose, with a 401 that reads like a typo.
Publish on change
Keep the steps in a file if you want them reviewed alongside the code, and pipe the file up on every run. The id is the only thing the job needs to remember.
- name: Publish diagram
run: npx flostep update Xk3p9QvA2wE < docs/checkout.flostep
env:
FLOSTEP_TOKEN: ${{ secrets.FLOSTEP_TOKEN }}
GitLab CI
diagrams:
image: node:24
script:
- npx flostep update Xk3p9QvA2wE < docs/checkout.flostep
variables:
FLOSTEP_TOKEN: $FLOSTEP_TOKEN
Coding agents
Your assistant can also connect over MCP, which is smoother where the tool supports it. The CLI is the one that works everywhere else: anything with a shell can use it, with no client support and nothing to configure.
What makes it drivable:
--jsonon every read command, with stable key names.- Errors on stderr, and deterministic exit codes.
flostep --helpis self-contained — every command's help carries a runnable example.flostep syntaxreturns the grammar, so the format never has to be guessed.
npx flostep list --json npx flostep show Xk3p9QvA2wE npx flostep step add Xk3p9QvA2wE "API -> Cache: read session"
create or update, rather than a
sequence of step add calls — it is atomic, and it is what the text format is for. Use the
granular commands for a one-line change to a diagram you have no copy of.
Troubleshooting
“Not logged in” or “Invalid API key”
No credential, or one that has been revoked. Run flostep login, or check
FLOSTEP_TOKEN is set to a key that still exists on your
API keys page.
“This API key expired on …”
Different from an invalid key, and it says so on purpose. The key was correct but has lapsed — run
flostep login again, or create a new one with no expiry for CI.
“Could not reach …”
Network failure, or a connection blocked by a proxy or firewall. The message names the host it tried.
“No valid steps found”
The file has no lines matching From -> To: description. Run flostep syntax
to see the format.
“Free plan limit … reached”
Delete a diagram, or move to a paid plan. See pricing.
“Refusing to delete without confirmation”
There is no terminal to prompt on. Pass --yes if you are sure.
The login code expired
Codes are valid for ten minutes. Run flostep login again for a fresh one.
Something else
An unexpected error prints a stack trace. Email it to support@flostep.dev.