On this page
CLI reference
One binary. Sign in once with the browser, or hand a machine an API key. Every command prints its result on stdout and anything else on stderr, so it composes in scripts.
Set up#
Install#
npm install -g @strangenoob/colophonNode 18 or newer. Or without installing: npx @strangenoob/.
No account yet#
npx @strangenoob/colophon publish ./site --name "Q3 report"With no key and no login, publish still returns a URL. It answers for 24 hours, at a shared address, and comes with a claim link. Open that link and you see the page with a Claim this page slip in the corner; run the command yourself and the CLI opens it for you (--no-browser skips that). Claiming asks you to sign in, then moves the site into a workspace you own, for good, at /<name>/ when that is free. Only --name works without an account. The claim link is what claims the site, so share the URL instead. Needs CLI 0.10.0 or newer. A COLOPHON_TOKEN that is set but empty is not “no key”: it is refused, so a CI secret that is missing never publishes this way (see From CI).
From CI#
- id: site
run: |
url=$(npx -y @strangenoob/colophon@0.11.1 publish ./dist --slug docs)
echo "url=$(tail -n 1 <<< "$url")" >> "$GITHUB_OUTPUT"
env:
COLOPHON_TOKEN: ${{ secrets.COLOPHON_TOKEN }}
- run: echo "Published to ${{ steps.site.outputs.url }}"One step, in GitHub Actions or any CI: npx runs the CLI without installing it, and the URL it prints becomes steps.site.outputs.url for a PR comment or a deployment. Pin the version, so a CLI release never changes a workflow under you, and set --slug, so every run updates the same URL instead of adding a site. The key goes in a repository secret — mint it with create-token. A secret that is missing, or withheld from a pull request from a fork, arrives as an empty COLOPHON_TOKEN, and the CLI refuses it: the step fails rather than publishing without an account (CLI 0.11.1 or newer). COLOPHON_API in the step’s env points it at a self-hosted instance.
How the CLI is signed in#
Two ways, checked in this order:
| Credential | For | Where it lives |
|---|---|---|
COLOPHON_TOKEN | Agents, CI, servers — anything without a browser. An API key. | The environment only. Nothing is written to disk. |
colophon login | A person’s own machine. A session that acts as you. | ~/ (%APPDATA%\colophon\ on Windows), mode 0600. |
When the variable is set it wins, even on a machine that is also logged in — so an agent running in your shell can never accidentally act as you. whoami always says which of the two is in use. The full flow, with what the approval page shows and how to revoke a machine, is in Signing in.
Commands#
colophon skill install#
colophon skill install [agent ...]Teaches your coding agents to publish. With no arguments it finds every supported agent on this machine — Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and more — and installs the skill into each; name agents to be selective, for example codex cursor. Claude Code gets it as a plugin; the others get a copy placed by npx skills, so npx must be on the path. Each CLI release from 0.16.1 names one release of the skill, a tag and the commit it points to; after updating the CLI, run it again to move every agent to that release. Needs CLI 0.3.0 or newer.
colophon login#
colophon login [--no-browser]Prints a code and a link, opens the link in your browser, and waits. From CLI 0.16.1 it opens a link only on the addresses it is set to (COLOPHON_APP, COLOPHON_API), where Colophon’s links always are; any other link is printed and left alone. Sign in there if needed, confirm the code matches, click Approve. The terminal receives a session for the workspace you pick on that page (the one active in your browser is picked to start with); switch changes it later. The link is valid for ten minutes and works once. --no-browser only prints the link, for a machine you are reaching over SSH.
Sessions last 30 days from their last use and appear under Account → CLI sessions in the dashboard, where any of them can be revoked.
colophon logout#
Revokes this machine’s session on the server and deletes the credentials file. If the server cannot be reached the file is removed anyway; revoke the session from Account.
colophon whoami#
Who you are, which workspace commands will act on, and whether that comes from a login or from COLOPHON_TOKEN. The quickest way to check before publishing.
colophon switch#
colophon switch # list your workspaces
colophon switch acme # work in this oneChanges the workspace this login acts on. Only for sessions — a key belongs to one workspace by construction.
colophon create-token#
colophon create-token --name publishing-agent [--scopes publish,links,stats,audit]Mints an API key for an agent or a CI job and prints it once on stdout. Needs a login (a key cannot mint keys) and the owner role. Scopes default to publish, links and stats; audit, which exports the audit log, only when named. A scope it does not know is refused, not dropped; an empty --scopes is the same as leaving it out. The key is recorded as created by you, and shows up under API keys like any other.
colophon publish#
colophon publish <dir> [--name N] [--slug S] [--visibility V] [--password-stdin] [--domain H] [--draft | --review [--note N]] [--expires T|none] [--spa[=off]]Packs the directory, uploads it, and prints the live URL. The summary — file count, size, how many files were new, what changed since the last version — goes to stderr. Same slug again means a new version at the same URL. A login needs the publisher role, or editor with --draft. Changing an existing site’s visibility, password, expiry or --spa, or attaching a --domain, needs owner.
Flags and their defaults:
--name- The directory name
--slug- Derived from the name
--visibilityunlisted— orpublic,password,restricted,private--password-stdin- Off. With
--visibility password, read the readers’ password from a pipe —printf '%s' "$PW" | colophon publish …— dropping one trailing newline. In a terminal you are asked for it instead, twice and without echo. Never an argument, which would sit in your shell history and inps. See Password-protected sites. Needs CLI 0.12.0 or newer. --domain- None. A hostname you control for this one site, served at its root. Until its two DNS records resolve they are printed after the URL; once they do, the URL is
https://<hostname>/. Passing it on every publish is fine — it re-checks rather than fails. --draft- Off. Store the version and print its preview URL without making it live; the site, its name, its visibility and its password do not change. Once it is approved,
make-livemakes it live — the reply prints the exact command — or the dashboard does. See Drafts. --review- Off. A draft, sent for review in the same step: stdout is its preview URL, the workspace’s publishers and owners are told, and one of them approves it (which makes it live) or asks for changes with a note. A version sent while another is in review replaces it. Needs the editor role, as
--draftdoes. See Review and approval. Needs CLI 0.14.0 or newer. --note- None. With
--review, what you want the reviewers to look at, up to 2000 characters. --expires- Left as it is. An ISO 8601 moment after which the site answers
410on every path, nothing deleted;noneclears one. The same changeexpirebelow makes, in one step. See Expiry. --spa- Left as it is; off for a new site. Turns on the single-page-app fallback, for a built React, Vite or Vue app: a page path with no file answers with the root
index.html.--spa=offturns it off (with the=:--spa offis refused). The same changespabelow makes. Needs CLI 0.15.0 or newer.
A _redirects file at the root of the directory is read by the server, not the CLI (Redirects): stderr says how many rules it holds, and a line that is wrong fails the publish with error: _redirects line N: ….
Skips .git .env node_modules .next .venv __pycache__ .DS_Store ._* files. A single file — colophon publish plan.md — is a site of one page. If the version is held for review it says so and still prints the URL it will have. In a workspace that needs approval before a version goes live, a publish from an API key or a member below owner is sent for review as if --review were given: stdout is the preview URL, and stderr says why it is not live.
The archive is packed into the temporary directory (TMPDIR) and uploaded from there as it is read, so a large publish needs its size in free disk rather than in memory, and the file is removed when the command ends, Ctrl-C included. Needs CLI 0.13.0 or newer; before that the archive was held in memory, several times over.
colophon list#
One line per site: slug, visibility, URL.
colophon search#
colophon search board deck
colophon search '"churn fell"' --limit 5Which live page says it: the text of every site in the workspace, restricted and private included, best match first. Each result is the page’s title and site, its URL, and the passage that matched. Words, "a phrase" (quoted once more for the shell), -word to leave one out, and or. --limit is 20 by default and at most 50. Drafts and earlier versions are not searched. A page is found a few seconds after its publish answers, once it has been indexed. Needs CLI 0.11.0 or newer.
colophon versions#
colophon versions <slug|id>
colophon versions <slug|id> --diff <n>
colophon versions <slug|id> --diff <n> --patch <path>Every version of a site, newest first, each with what it changed against the one before: +2 ~1 -1 is files added, changed, removed; identical is a republish that moved nothing. --diff <n> lists what making vn live would change against what is live now, and --patch <path> prints that one file’s unified diff in the shape git diff writes. Files that are not text, or over 1 MB, are refused with their sizes. The dashboard shows the same, side by side. See Updating a site.
A version sent for review ends its line with its state: in review, changes requested, approved or superseded. After the list, stderr names the version in review with its note and preview URL, and the last decision with the reviewer’s note: what an agent reads before revising. A decision by an outside approver names them as one, with their address (CLI 0.14.1). Needs CLI 0.14.0 or newer.
colophon review#
colophon review <slug|id> 3 --note "Shorter intro" # v3, as versions numbers them
colophon review <slug|id> <version id>Sends a version already published for review: a draft, or an earlier version to put back. The same as Send for review on the site’s Versions list and publish --review for a version that is already up. Prints the preview URL. One version per site is in review at a time, so this replaces any other; the version already in review is left as it is, and it says so. Needs the editor role, or an API key. Approving is a person’s, in the dashboard, or an outside approver’s, from the page. Needs CLI 0.14.0 or newer.
colophon make-live#
colophon make-live <slug|id> 3 # v3, as versions numbers them
colophon make-live <slug|id> <version id> # or by id
colophon rollback <slug|id> 3 # the same commandMakes one version of a site the live one — the dashboard’s Make live: an earlier version after a bad publish, or a draft once it is approved. Prints the URL, and on stderr what that changed against the version that was live, in publish’s +added ~changed -removed. Nothing is deleted: the version it replaces stays, and comes back the same way. The version already live is left as it is, and it says so. A version held for review or rejected in it cannot go live. The expiry does not move, so an expired site stays down until expire brings it back. A login needs the publisher role. Needs CLI 0.12.0 or newer. In a workspace that needs approval, only an owner may; anyone else, and every API key, is told to send the version for review with review instead. A version in review made live this way counts as approved by whoever made it live.
colophon visibility#
colophon visibility <slug|id> <public|unlisted|password|restricted|private> [--password-stdin]Who can open a site, changed without republishing it; the next request is answered under the new level. Prints the level it had and the one it has. Widening is deliberate here — you named the level — so check before making a restricted site public. A login needs the owner role. See Access & sharing.
password asks for the readers’ password in the terminal, or reads it with --password-stdin, as publish does. Run it again on a site that is already password to change the password; leave the prompt empty to keep it. Colophon keeps only a hash, so give the password to your readers yourself.
colophon expire#
colophon expire <slug|id> 2026-10-01T00:00:00Z # set or move the moment
colophon expire <slug|id> none # clear itThe moment a site stops answering. Past it, every path answers 410 Gone, previews included. For thirty days the versions stay, and none or a later moment brings the site back; after that it is deleted. A moment already past takes it down now. A login needs the owner role. See Expiry.
colophon spa#
colophon spa <slug|id> on # deep links answer with the root index.html
colophon spa <slug|id> offTurns a site’s single-page-app fallback on or off without publishing, from the next request. A login needs the owner role. Needs CLI 0.15.0 or newer.
colophon delete#
colophon delete <slug|id>Permanently removes the site and every version. Accepts a slug (what list prints) or a site id. A login needs the owner role.
colophon expire <slug|id> <a past moment>.colophon link#
colophon link <url> [--code C] [--title T]Creates a short link and prints it. Owner-only. See Short links for the rules on codes.
colophon audit#
colophon audit export [--from T] [--to T] [--format jsonl|csv] [--out FILE]
colophon audit verify <file> [--keys URL|FILE]export writes the workspace’s audit log, signed, to stdout or to --out: JSON Lines unless --format csv, from --from up to --to (ISO moments, or dates meaning midnight UTC; --to is not included). A login needs the owner role, a key the audit scope. verify checks a file against Colophon’s published key and prints what it covers, or names the entry that fails and exits 1. It needs no login, so whoever you give an export to can run it. Audit log & export says what is checked. Needs CLI 0.16.0 or newer.
Environment#
| Variable | Purpose |
|---|---|
COLOPHON_TOKEN | An API key. Takes precedence over any login. |
COLOPHON_API | API origin. Defaults to https:/; only a self-hosted instance needs it. |
COLOPHON_APP | Dashboard origin, used by login. Defaults to https:/. |
XDG_CONFIG_HOME | Moves the credentials file, if you keep config somewhere else. |
Errors#
Every failure exits 1 with one line on stderr beginning error:.
| Message | Meaning |
|---|---|
not signed in | No login and no COLOPHON_TOKEN, for a command other than publish. Run colophon login, or set a key. |
--slug needs an account | A flag only a workspace can honour, on a publish with no login. Sign in first, or leave the flag off. |
your session has expired | 30 days without use, or revoked from Account. Run colophon login. |
invalid or revoked key | The key in COLOPHON_TOKEN was revoked or copied wrong. |
key lacks the 'links' scope | The key exists but was created without that scope. |
your role in acme does not allow 'links' | Your login’s role does not allow it: links, keys and sharing need an owner. |
this command needs a signed-in session | create-token or switch was run with a key. Keys cannot mint keys. |
quota exceeded: sites (4 > 3) | A workspace limit; see Limits. |
a publish is already running in this workspace | Another publish to the same workspace was still writing after 10 seconds. Nothing was published; run it again. |
archive contains no files | The directory is empty, or everything in it was skipped. |
archive is over … bytes | More than the plan takes in one publish: 200 MB, or 1 GB on Pro. See Limits. |
could not reach … | Network, or a wrong COLOPHON_API / COLOPHON_APP. |
… redirected the upload | COLOPHON_API answers with a redirect, which an upload does not follow; usually http:// where it should be https://. |
The CLI is a thin wrapper over the HTTP API. Anything it does with a key, you can do with curl.