Docs / Reference

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.

Install

npm install -g @strangenoob/colophon

Node 18 or newer. Or without installing: npx @strangenoob/colophon publish ./site.

GitHub Action

- uses: StrangeNoob/colophon@main
  id: site
  with:
    path: ./dist
    token: ${{ secrets.COLOPHON_TOKEN }}
    slug: docs
- run: echo "${{ steps.site.outputs.url }}"

publish through npx, so nothing is installed on the runner, with the URL as outputs.url for a PR comment or a deployment. name,visibility and domain are inputs too. Pin uses: to a commit SHA, as with any action: version defaults to the CLI release current at that commit, so the one pin covers the CLI as well, and version: latest opts out. The key goes in a repository secret — mint it with create-token. COLOPHON_API in the workflow’s env reaches it as it would in a shell.

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. Run it again to update. Needs CLI 0.3.0 or newer.

How the CLI is signed in

Two ways, checked in this order:

CredentialForWhere it lives
COLOPHON_TOKENAgents, CI, servers — anything without a browser. An API key.The environment only. Nothing is written to disk.
colophon loginA person’s own machine. A session that acts as you.~/.config/colophon/credentials.json (%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. whoamialways 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.

colophon login

colophon login [--no-browser]

Prints a code and a link, opens the link in your browser, and waits. Sign in there if needed, confirm the code matches, click Approve. The terminal receives a session for the workspace that was active in your browser; 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

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

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 one

Changes 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]

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 all three. 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] [--domain H] [--draft] [--expires T|none]

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.

FlagDefault
--nameThe directory name
--slugDerived from the name
--visibilityunlisted — or public, restricted, private
--domainNone. 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.
--draftOff. Store the version and print its preview URL without making it live; the site, its name and its visibility do not change. Make it live from the dashboard. See Drafts.
--expiresLeft as it is. An ISO 8601 moment after which the site answers 410 on every path, nothing deleted; none clears one. The same change expire below makes, in one step. See Expiry.

Skips .git, .env, node_modules, .next,.venv, __pycache__, .DS_Store and ._*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.

colophon list

colophon list

One line per site: slug, visibility, URL.

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.

colophon visibility

colophon visibility <slug|id> <public|unlisted|restricted|private>

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. See Access & sharing.

colophon expire

colophon expire <slug|id> 2026-10-01T00:00:00Z    # set or move the moment
colophon expire <slug|id> none                    # clear it

The moment a site stops answering. Past it, every path answers 410 Gone, previews included, and nothing is deleted: the versions stay, and none or a later moment brings the site back. A moment already past takes it down now, which is the takedown that keeps everything. See Expiry.

colophon delete

colophon delete <slug|id>

Permanently removes the site and every version. Accepts a slug (what list prints) or a site id. Does not ask for confirmation.

colophon link <url> [--code C] [--title T]

Creates a short link and prints it. Owner-only. See Short links for the rules on codes.

Environment

VariablePurpose
COLOPHON_TOKENAn API key. Takes precedence over any login.
COLOPHON_APIAPI origin. Defaults to https://api.usercontent.colophon.fyi; only a self-hosted instance needs it.
COLOPHON_APPDashboard origin, used by login. Defaults to https://app.colophon.fyi.
XDG_CONFIG_HOMEMoves the credentials file, if you keep config somewhere else.

Errors

Every failure exits 1 with one line on stderr beginning error:.

MessageMeaning
not signed inNo login and no COLOPHON_TOKEN. Run colophon login, or set a key.
your session has expired30 days without use, or revoked from Account. Run colophon login.
invalid or revoked keyThe key in COLOPHON_TOKEN was revoked or copied wrong.
key lacks the 'links' scopeThe key exists but was created without that scope.
your role in acme does not allow 'links'A member’s login tried something only owners can do.
this command needs a signed-in sessioncreate-token or switch was run with a key. Keys cannot mint keys.
quota exceeded: sites (4 > 3)A workspace limit; see Limits.
archive contains no filesThe directory is empty, or everything in it was skipped.
could not reach …Network, or a wrong COLOPHON_API / COLOPHON_APP.
The CLI is a thin wrapper over the HTTP API. Anything it does with a key, you can do with curl.
CLI reference — Colophon docs