@solidnumber/cli
Run an AI-powered business from your terminal.
177 top-level commands, 930 verbs. One CLI, built for an AI agent to drive.
What a verb tells you before you call it
Every action in Solid# is a verb (page.publish, contact.update,
appointment.book). Each one publishes its own contract, so an agent can
decide before it acts:
solid verbs describe page.publish --json
{
"name": "page.publish",
"side_effects": "write",
"requires_consent": true, // refused without --confirm
"undone_by": "page.unpublish", // the way back, named before the write
"refuses_when": [ // what it will refuse, and the override if there is one
{ "code": "publish_requires_subscription", "override": null },
{ "code": "fidelity_below_threshold", "override": "accept_fidelity" },
{ "code": "blocked_by_guardrails", "override": null }
],
"output_schema": { // what comes back
"required": ["success"],
"anyOf": [
{ "title": "worked", "required": ["message", "page", "promoted_fields", "published_url", "success"] },
{ "title": "did not", "required": ["error", "success"] }
],
"x-solid-derivation": "proven-from-return-paths"
}
}
- Refusals up front.
refuses_whenlists each refusal code, the condition and the override. - The undo, before the write.
undone_bynames the verb that takes a write back;nullmeans none is known, never a guess. - What comes back.
output_schemasays which keys are on every result.proven-from-return-pathsmeans every return path of the handler was read;observed-in-receiptsandinferred-from-return-literalsmean keys worth looking for, none promised. - A dry run that tells the truth.
solid verbs invoke <verb> -p '{…}' --dry-runvalidates the payload locally, shows the exact request,undone_byand what would come back, and exits 1 when the call is invalid. It needs no consent. - Consent is part of the contract. A write needs
--confirm. Without it the call is still sent, the server refuses it, and the refusal is on record. - Every call hands back its receipt.
solid verbs invokeprints_receipt, the handle of the record that call left, and a refusal prints one too.solid verbs receipts <ref>reads it back: who, what, outcome, duration, and whether the result matched the verb's published schema (contract: keptorbroken).--session <id>reads a whole run; setSOLID_SESSION_IDto join several invocations into one. - What changed since the catalog you were holding.
solid verbs snapshot > verbs.snap.json, thensolid verbs list --changed-since verbs.snap.jsonreturns the verbs added, removed or changed — inputs, outputs and refusals. - A list is a page.
solid verbs listreturns 100 working verbs, one name per operation, leading with the ones an AI is handed as tools.solid map, a prefix orsolid find "<task>"reaches the rest.
Release notes are in CHANGELOG.md.
npx @solidnumber/cli clone plumber
Install
Easiest — one paste, everything handled (installs Node if needed, runs setup, connects your AI). Or just visit solidnumber.com/install:
# macOS / Linux
curl -fsSL https://solidnumber.com/install.sh | sh
# Windows (PowerShell)
iwr -useb https://solidnumber.com/install.ps1 | iex
Other ways, if you already have a package manager you trust:
# any platform with Node 20+
npm install -g @solidnumber/cli
# macOS / Linux — note: on macOS older than 13 (Ventura), brew may compile
# Node from source (slow). Prefer the one-paste installer there.
brew install solidnumber/tap/cli
# Windows
scoop bucket add solidnumber https://github.com/Solidnumber/scoop-bucket
scoop install solidnumber/solid
# one-paste install + magic-link auth (logged-in dashboard users only)
# get your personal command at https://app.solidnumber.com/dashboard/install-command
curl -fsSL https://solidnumber.com/install.sh | SOLID_INSTALL_TOKEN=ist_xxx sh
Quick Start
# Login to your company
solid auth login
# Clone an industry template (52 available)
solid clone plumber
# Download your business data as local files
solid pull
# Edit pages, KB, settings in VS Code / Cursor / any editor
# Upload changes (they land as drafts / unpublished pages)
solid push
# Make them live — publish is the step that goes live, not push or deploy
solid publish <page_id> # or: solid publish --all
# Give your AI full context about this company
solid context --claude # Claude Code
solid context --cursor # Cursor
solid context --save # Any AI (paste into project)
# Talk to your AI agent
solid train chat sarah
# Natural language site edits
solid vibe "Add a hero section with our phone number"
# See your agents' consciousness
solid agent dashboard
# View an agent's soul — identity, emotions, growth
solid agent soul sarah
# Launch a multi-agent mission
solid agent mission "Create a Valentine's campaign for VIP customers"
Commands
Core Workflow
Import & Sandbox
Multi-Company & Droplets
AI Training
Business Data
Money & Orders
The offer is one shape whether it comes from a cart, an order or a link, and its total is quoted by the pricing engine — the same call the charge path makes — so what you read is what gets charged.
--jsonon any of these for agent consumption.
AI Context
Graph (v2 — vendor-portable JSON-LD)
Your business is a typed graph. Every entity has a globally-resolvable IRI. Walk it, query it, diff it, export it, take it offline.
Auto-magic: lose wifi mid-mutation, the CLI auto-queues. Regain
wifi, the next mutation auto-replays the queue. Zero flags, zero
ceremony — [QUEUED — offline] and [auto-flush] lines on stderr
are your only signal.
Dereferenceable IRIs — every @id resolves:
curl -H 'Accept: application/ld+json' https://solidnumber.com/co/61/service/3
Returns the typed JSON-LD node. Public allowlist applied unless your JWT matches the path's company.
AI Discovery (llms.txt)
Analytics & SEO
Operations
Platform
Agent Consciousness
Dev Tools
Bring an existing site live
The whole journey, in order. Each command's reply names the next one.
1. solid bring <folder> → What is this — a page or an app — and which command?
2. solid nest <file|folder|url> → Import it. Lands in your Sandbox, private.
The reply says whether your design was KEPT as written
or CONVERTED to editable blocks (import_mode), why, and
how close it is to the original (a score out of 100).
3. solid drafts preview <page_id> → A private link to look at it first
4. solid nest promote <import_id> → Put it on your site — still a draft
5. solid publish <page_id> → Make it live
6. solid domains add <your-domain> → Your own domain (solid domains dns <id> lists the records)
7. solid leads test → ONE labelled TEST lead through the live form
A publish refused for fidelity. An imported page that scores under the bar against its
original is refused, with the score. Import again (solid nest …), or take it deliberately:
solid publish <page_id> --accept-fidelity <score>.
Testing the form. solid leads test runs the real path — the site's form address, the
CRM record, every new-lead alert the business has on — and labels all of it TEST, so nobody
calls a customer who does not exist. The contact is tagged website_contact_form_test;
delete it with solid crm contacts delete <id>. By hand, the same mode is the field
_solid_test_lead=1 on any form post to the lead address. Never type a made-up person into
a client's live form to see if it works.
Workflow
1. solid pull → Download pages, KB, services
2. solid serve --open → Preview locally at localhost:4000
3. solid context --claude → Give your AI full company knowledge
4. Edit files / solid import / vibe → Make changes any way you want
5. solid diff → Preview what will change
6. solid push → Upload (drafts / unpublished)
7. solid publish --all → Go live
Agency Workflow (Sandbox Mode)
1. solid pull → Get the client's site
2. solid sandbox create → Fork into .sandbox/
3. solid serve --dir .sandbox → Preview sandbox locally
4. solid import promo.html --page "Ad" → Add ChatGPT landing page
5. solid sandbox diff → Review all changes
6. solid sandbox push → Promote to main files
7. solid push → Upload (drafts / unpublished)
8. solid publish --all → Go live
File Formats
After solid pull, your project looks like:
.solid/
├── manifest.json # File → ID mappings
├── pages/
│ ├── home.json # Page with layout_json sections
│ └── about.json
├── kb/
│ ├── hours.md # Markdown with YAML frontmatter
│ └── services.md
└── settings/
└── company.json # Business settings
Industry Templates
52 templates across 8 categories:
- Home Services — Plumber, HVAC, Electrician, Roofing, Landscaping...
- Health & Wellness — Dentist, Chiropractor, Med Spa, Veterinarian...
- Food & Hospitality — Restaurant, Bakery, Catering, Food Truck...
- Professional Services — Accountant, Law Firm, Insurance, Realtor...
- Automotive — Auto Repair, Car Wash, Detailing, Towing...
- Tech & Digital — IT Services, Web Agency, SaaS, Cybersecurity...
- Education & Creative — Tutoring, Photography, Music School...
solid clone --list # Browse all templates
solid clone plumber # Scaffold instantly
MCP Editor Integration
Add to your Claude Code or Cursor MCP config:
{
"mcpServers": {
"solid": {
"command": "npx",
"args": ["@solidnumber/cli", "mcp"]
}
}
}
Security
Credential storage
solid auth login writes your access token, refresh token, and company
context to ~/.solid/config.json in plaintext. The file is chmod 600
(owner-readable only), but that's the only protection — anything running
as your UID can read it.
On a shared or unattended machine:
- Don't run
solid auth loginon it. Use an API key instead:export SOLID_TOKEN=sk_solid_xxx... # (or SOLID_API_KEY) solid kb list - Or pass per-invocation and never touch disk:
solid --token sk_solid_xxx kb list - Create short-lived, scoped keys for anything automated:
solid auth token create -n "CI readonly" -s kb:read,pages:read -e 30
On a dev laptop that might leak:
- Rotate your token any time with
solid auth refresh, or revoke all sessions withsolid auth logout --all-devices. - For agency operators: a compromised laptop is a multi-tenant breach —
your CLI can touch every client company you've been invited to.
Inventory your access with
solid company listand drop what you don't need via the dashboard.
Exit codes
Stream discipline for scripts
- stdout = data only (
--jsonpayloads, command output). - stderr = spinners, progress, warnings, errors.
solid X --json | jqis always safe — the spinner writes to stderr.
Full contract: see the Scripting Contract doc (or Owners-Manual/45-Developer-CLI/21-SCRIPTING-CONTRACT.md in the Solid# platform repo).
Update notifier
When it says there's a new version, run:
solid update # bring everything Solid# on this machine current
solid update --check # say what would happen, change nothing
solid update --json # do it, and report it as JSON (for an agent)
solid update --check --json # report only, as JSON
Besides the CLI it keeps the MCP server current: any AI-tool config (Claude
Desktop, Cursor, Windsurf, Claude Code — including per-project servers) that
launches a bare @solidnumber/mcp, which npx serves from its cache forever, is
switched to @solidnumber/mcp@latest, and a global npm install is upgraded. A
version someone pinned on purpose is left alone and reported. The MCP SDK ships
inside the server, so it moves with it.
It then brings everything else the CLI set up up to date: the Claude Code
session hook, your shell completion, the agent skills and plugin in every
project where you ran solid agent setup, and the render browser. The
freshly installed CLI does this part, so the files come from the new version.
Only what is already installed is refreshed; an update never adds something
you did not set up.
It works out how this copy was installed and runs the right thing —
npm install -g, brew upgrade, or scoop update. If that guess is wrong, or
the command fails, it tries the next way, and it calls the update done only
when the solid your shell runs reports the new version. You never have to
pick between commands. If Homebrew's formula has not caught up with npm yet
(it checks every 4 hours), it says so and does not put a second copy on top.
You only get a command to run yourself when every route has failed. It also warns when a
second solid is on your PATH at a different version: an npm global under
nvm in front of a Homebrew formula is easy to end up with, whichever comes
first in PATH wins, and upgrading one leaves the other lying in wait. The
notifier cannot see that — it only ever looks at the copy that is running.
The CLI checks npm once every 4 hours for a newer release and prints a boxed notice on the next run. Suppress it:
NO_UPDATE_NOTIFIER=1 solid … # whole shell session
solid … --no-update-notifier # single invocation
The check runs in a detached process, never blocks your command, and writes to stderr so pipelines are unaffected.
Requirements
- Node.js >= 20.0.0 (the one-paste installer above sets this up for you)
- A Solid# account (solidnumber.com)
Verb taxonomy
The 12 verb shapes (aggregate, explain, preview, suggest, transaction, receipt, revert, subscribe, discovery, trail, reputation, macro) are defined in the verb spec bundled with @solidnumber/mcp:
- Spec docs: solidnumber.com/docs/spec — shapes, manifest, transport, receipts, consent
- Live manifest:
/api/v1/agent/verbs— every VerbRecord, filterable by?surface= - Docs: solidnumber.com/docs/verbs
The CLI is one of four transports projecting the same UNIFIED_VERB_REGISTRY. The spec defines the contract; this CLI is one implementation.
License
Business Source License 1.1 (BUSL-1.1).
Plain English: read the source, run the CLI, build on top of the SDK, ship internal tools, run it in production for your own business — all permitted. What's not permitted: offering a substantially similar command-line interface for managing AI-powered business infrastructure as a competing commercial product or service.
On 2030-04-14 (the Change Date), this license converts automatically to Apache 2.0 and all restrictions drop. No "phone home" required.
The full license text and the additional use grant are in LICENSE. Background on BSL: https://mariadb.com/bsl11/.