CLI

Last updated

terminus is how you build on Terminus from your own machine, the way Git works with GitHub: sign in, bring a creation down, run it, push its draft — then publish it on the web. It needs Node.js 22.16 or newer, and nothing else.

On this page⌄

Install#

npm install -g @terminus-ai/cli
terminus help

terminus help <command> shows a command's options and examples. One-off runs work too: npx @terminus-ai/cli status.

Sign in#

terminus login              # approve this computer in the browser
terminus login --no-browser # print the sign-in link instead of opening it
terminus account            # who you are, with your notifications and creations
terminus notifications      # what is waiting for you
terminus logout             # revoke this computer's session

Signing in gives this device a session that lasts seven days, kept at ~/.terminus/session.json and readable only by you. System Settings → General → Devices on the web lists every device and can revoke any of them. The link --no-browser prints is opened on the same computer.

Signed out, terminus account says so and exits with status 3 — the check a script or a coding agent makes before anything else. A coding agent cannot approve a sign-in: when it sees 3, it asks you to run terminus login.

There are no API keys. For automation — a script, a coding agent in a container — set TERMINUS_TOKEN to a session token; it takes precedence over the saved login, and it expires and is revoked like any other session.

The development loop#

It works like Git and GitHub. A creation is made on the web — Creations → New creation — which gives it its address, the way a new repository gets its URL. It has one draft online, shared by the editor and every working copy; its id in terminus.json says which creation a folder belongs to, and Git stays your local history. Publishing happens on the web too, from the creation's page: the CLI never publishes.

terminus clone @you/my-app       # a working copy of a creation
terminus remote add @you/my-app  # or connect the folder you are in
terminus dev                     # run it on this machine
terminus status                  # this folder vs. the draft vs. the live release
terminus pull                    # bring in what changed in the draft
terminus push                    # replace the draft with this folder; then publish on the web
  • A push replaces the draft with this folder: the files that differ, and the ones the folder no longer has. A draft keeps no history — whatever it held is gone, and push says so when that included saves in the web editor, or a collaborator's push, that this folder never pulled. A push that changes nothing says Everything up to date.
  • terminus diff shows how this folder differs from the draft now — exactly what a push would change — and terminus log lists the creation's releases.
  • pull brings in what changed in the draft since this folder last matched it, file by file: a file only the draft changed is taken, one only you changed is kept, and one both changed stops the pull before anything is written, naming it. pull --force takes the draft's files; push sends yours.
  • .gitignore decides what counts as source, and .terminusignore leaves out more. Secrets, node_modules/ and local dev data are never uploaded, whatever the ignore files say.
  • For an app, push also runs the build and attaches it to the draft it pushed. A later source change leaves that build stale until the next push.
  • The version in terminus.json names the next release. A push whose version is already released, or below the live one, says so and names the version to use.

What they print

$ terminus status
@you/my-app · draft r4
Up to date with the draft.
Changes not pushed:
  modified:  src/main.js
Live: 0.1.0 (2026-09-20T10:12:00Z)

$ terminus push
Pushed @you/my-app to its draft (r5): 1 source file and 1 build file changed; 2.1 KB uploaded.
  build     current, ready to publish · 3 files, 48 KB
  publish   https://www.terminus.build/os?open=creation:…
A creation with no folder yet
terminus clone <address> — into a folder that does not exist or is empty. An empty creation arrives started from a template; --template picks an app's, or a service's language (Rust unless named).
Code already in a folder
terminus remote add <address>, then terminus status.
Nothing made on the web yet
terminus init <kind> [<dir>] scaffolds the package; make the creation on the web, then terminus remote add. In a folder cloned from an empty creation, terminus init <kind> . fills it in and keeps its link.
The draft moved
terminus pull to keep what changed there, then terminus push. A push alone replaces it.
A pushed change was wrong
Fix it in the folder and push again: a draft keeps no history to go back to, so earlier work lives in your own Git.
Build: stale in status
terminus push again: it builds.

terminus dev#

What it runs depends on the package:

An app
Serves dist/ on port 8868 against local test data, as Alan — or as several people with --members — and runs the app's server here. Its declared services reach the real ones, billed to you, except a hosted service of yours run beside it with --service. See Apps.
An agent
Opens a chat page to talk to it and watch its tools, or runs one turn or one trigger for a script. Needs you signed in. See Agents.
A service
A hosted one, in any of its languages, is built and run here as Terminus runs it — a fresh copy per call, its secrets from .env.local — behind its dev/ test page, or a page with a form per operation when it has none; --call makes one call from the terminal. An external one's page calls its endpoint through Terminus. No marketplace charges. See Services.

Its options, and the kind each is for:

--members 3, --members alice,bob
Apps: run as several people at once, each on a port of their own from 8868 up.
--profiles people.json
Apps: names, bios and avatars for those people.
--guest
Apps: add a port after the people's for someone who is not signed in, as a guest of an app open to guests. Signing in there picks one of the people.
--fresh
Apps: start from empty local data.
--service ../my-service
Apps and hosted services: run a hosted service's folder beside it, answering its calls to that service as Terminus does; repeat it for more. @you/my-service=../my-service names the service when the folder's terminus.json has no id. Needs a CLI newer than 0.0.4.
--call <operation>
Hosted services: build, make one call, print the answer and exit — non-zero when the service refused or failed. --input '<json>' is a JSON operation's input; --file <path> the bytes for one that takes a file, with --query '<json>' for its query. Needs a CLI newer than 0.0.4.
--port 5000
Serve here; with --members, the others follow.
--remote
Apps: your local build against your real account on Terminus. Agents: the conversation on Terminus itself, after pushing the folder to its draft.
--prompt "…"
Agents: send one message, print the reply, exit. --resume <id> continues a given conversation.
--trigger <name>
Agents: fire one declared trigger now; --payload file.json is what it carries.
--json
With --prompt or --trigger: every event as one line of JSON. With --call: the answer as JSON.
--model <model>
Agents: run on another model than the default.
--no-open
Agents and services: do not open the browser.

Every dev server listens on this computer only. terminus data handles an app's local data as the files people download — one simulated person's (--member bob; Alan by default), or one space's:

data export <file>
Write one person's local data as their data.sqlite; --space <id> writes that space's file.
data import <file>
Start one person's local data from a file — a data.sqlite downloaded from the desktop included — at the file's own data version. --force replaces what is there, keeping a backup.
data inspect
Summarize one person's local data.
data migrate --check <file>
Run your pending migrations on a copy of the file, never the file itself: rows added, changed and removed per table, and .out/migrations/report.json. See Migrations.

When terminus dev starts, it runs pending migrations on every person's and every space's local data, as Terminus does.

All commands#

Account

login
Sign in to Terminus in your browser.
logout
Sign out and revoke this device's session.
account
Your account's station.
notifications
Check your notifications.

Explore

search
Search the catalog.

Developing

init
Create a new app, agent, service, or skill.
clone
Copy a creation into a new folder.
fork
Fork an open-source app or agent, or a free skill, and clone it.
remote
Show or change the creation a folder is connected to.
dev
Run a package on this machine.
build
Build an app's browser bundle, or a hosted service's component.
validate
Check a package for problems before pushing.
status
Compare your working copy with its draft and live release.
diff
Show your changes, or compare two releases.
pull
Bring the draft's changes into your working copy.
push
Upload your working copy to its online draft.
log
Show a creation's releases.
logs
Show a published app's recent logs.
data
Export, import and inspect local app data files, and rehearse migrations.
service
Inspect services, test operations, and run jobs.
secrets
An app's or a service's secrets: list, set, delete. A value is read at a hidden prompt or from stdin.
settings
A service's settings: list, set, unset. Values its code reads by name, read back whole; see Settings.

Install Skills

skills
Install and use skills in Claude Code or Codex.
skills install
Add a skill to Claude Code or Codex.
skills list
List the skills you have installed.
skills update
Update the skills you have installed.
skills uninstall
Remove an installed skill.
skills use
Load a skill's instructions for your coding agent.
skills fetch
Download a skill's files to the local cache.
skills files
List a skill's files.
skills file
Print one of a skill's files.

Management

creations
Manage your published creations.
drafts
Manage your drafts.

Your published apps

apps
List apps, check access and use their tools.
mcp
Serve your apps' tools to coding agents over MCP.
inspect
Show a published app's runtime state.

Releases

outdated
Check a creation's dependencies for newer releases.

Your apps, for coding agents#

Your coding agent can use the apps you have installed, and the Terminus desktop itself, as you let it in System Settings → App access, under Coding agents: Off, Read only, or Read and write, and Send for tools that reach other people, in your own data and the shared spaces you choose. The CLI never gives itself access.

terminus mcp is an MCP server on stdin and stdout. Add it to your agent once:

claude mcp add terminus -- terminus mcp
codex mcp add terminus -- terminus mcp

It serves each tool you allow as <app>__<tool> — notes__search_notes, notes__digest — describing what it may change; where you allowed shared spaces, a tool takes a space. A change in Settings applies at the agent's next look at its tools, and every call is checked again. It signs in as you (terminus login, or TERMINUS_TOKEN); --dev serves the app terminus dev is running in this folder instead.

With the Terminus desktop open on the same computer, signed in to the same account, it also serves what runs there. For the apps you allow, that is their window commands and each one's whats_open and open; an app that is not open is opened out of sight for the call, and when one has more than one window open, its tools take a window. As the Terminus row in App access allows, it is also the desktop's own tools, as desktop__<tool>: desktop__list_windows, desktop__screenshot, desktop__open_app, desktop__focus_window and desktop__close_window. Your agent is told whenever the list changes — the desktop opening or quitting included — and everything else keeps working without the desktop.

terminus apps does the same from a terminal or a script:

terminus apps                                        # your installed apps
terminus apps notes                                  # its tools, and what is allowed
terminus apps notes search_notes --query "launch"    # call one
terminus apps notes create_note --args '{"value":{"title":"Hi"}}' --space <id> --json

A tool's arguments come from its schema: page_id becomes --page-id. A refused call exits 77 and says to ask you in Settings. --invocation <uuid> keeps a call's identity across retries, so an uncertain answer never runs a tool twice; --status <uuid> reads what became of it.

Versions and releases#

Every creation versions the same way: MAJOR.MINOR.PATCH, starting at 0.0.1 — in terminus.json, a skill's included. You choose the version when you publish on the web, with a note that annotates the release like a commit message; each release must be above the last, and a version is never reused for different content.

terminus log @publisher/app                          # its releases and their notes
terminus diff @publisher/app                         # the latest release against the one before
terminus diff @publisher/app --from 1.0.0 --to 1.2.0  # any two, by version or release number
terminus fork @publisher/app                         # your own copy on Terminus, cloned here

terminus fork makes the fork on Terminus, the way GitHub's Fork does — a draft at @you/<slug> (an app or agent stays open source like its original) — then clones it; --version forks an earlier release, --slug names yours, and --no-clone stops after the fork. Only open-source apps and agents fork, and free skills that aren't restricted; each account has one fork of a creation: forking again answers with yours. A fork that costs credits is made on the creation's page on the web, where you see the price and agree to it; the CLI prints both and stops.

Someone else's open-source creation also clones read-only: terminus clone @publisher/app brings its latest release down, and terminus pull brings newer ones. It never pushes.

terminus outdated @you/my-app    # each dependency's pinned version against its latest

terminus outdated reads a published creation's dependencies — the services, skills and agents its release names — and says for each whether it is up to date, how far behind it is, or that its address no longer resolves. Dependencies are recorded when a release is published.

Scripting#

Most commands take --json. With it, a failure prints one JSON object to stderr — {"error":{"code":…,"message":…}} — so a script or an agent can branch on the code instead of parsing prose. When Terminus refused the request, the object also carries its status, Terminus's own api_code — price_confirmation_required, say — and any details. terminus dev --prompt … --json is the exception that streams: one JSON object per line, one per event.

Reads, and any request carrying an idempotency key, are retried when Terminus is briefly unavailable; other writes are sent once. Options are checked strictly: a typo such as --limt fails before anything is sent.

Exit codes

0
Success.
1
Anything else that failed: an API error, an invalid package. Code error.
2
Bad usage: an unknown command or option, a missing argument. Code usage.
3
Not signed in, or the session expired or was revoked. Code auth.
69
Terminus unreachable: a connection failure, a timeout, or a 502, 503 or 504. Code unavailable.
75
Rate limited; the message says when to retry. Code rate_limited.
77
Not allowed: Terminus answered forbidden or grant_required, or a closed skill's content was asked for. Code forbidden.

Environment

TERMINUS_TOKEN
A session token to use instead of the saved login.

For your coding agent

https://www.terminus.build/docs/SKILL.md