Skip to main content
Back to CLI Docs

Release history

Every shipped version of @solidnumber/cli — the first CLI built for AI agents. Newest at the top.

Authored by Adam Campbell · BSL-1.1 (converts to Apache 2.0 on 2030-04-14) · GitHub · npm

All releases

Quick scan. Each row is one published version. The deep-dives for the architecturally significant releases follow below.

VersionDateSummary
v2.31.02026-10solid helper: a Solid# host can do a runbook’s set-up steps on this computer, with the person’s approval. And solid api lists the knowledge base addresses that exist.
v2.30.22026-10solid find prints each match once, and llms.txt describes the MCP server as it is.
v2.30.12026-10solid nest imports again, solid map reads the server’s map, and every dashboard link the CLI prints is a real page.
v2.30.02026-10An outside agent can follow the journey from a folder to a live site with a tested form.
v2.29.12026-10The AI’s key can write after a switch, and solid kb add offers real categories.
v2.29.02026-10solid how-to protocol — the builder protocol — and help that says what things are.
v2.28.22026-10solid find answers a request that is not one verb — it no longer says “no verb”.
v2.28.12026-10solid update says what is running, not only what will start next.
v2.28.02026-10solid app publish works (it failed for everyone with “Failed to parse URL from undefined”); a verb says what it returns; every call hands back its receipt; solid find says how sure it is.
v2.27.02026-10The verb list is a page, not a dump; solid push sends services and products and shows before → after; you can ask what changed in the catalog since you last looked.
v2.26.02026-10solid bring is the front door for building or bringing a website or an app; your AI gets the Solid# skills in your project without being told to; solid render no longer refuses an AI agent.
v2.25.02026-10solid app reads your repository itself, says which commit is live, and can hold a build until you make it live.
v2.24.122026-09solid update brings everything Solid# on your machine current and never leaves you stuck; solid app arrives for publishing a designer’s interactive app.
v2.24.112026-09solid inventory import reports every row, and solid update works in the first minutes after a release.
v2.24.102026-09solid docs points at the public booking routes that exist, and the published counts are regenerated.
v2.24.92026-09solid update keeps the MCP server current, not just the CLI.
v2.24.82026-09Flags reach the commands they belong to, a missing-scope error tells you the real fix, and solid mcp install writes a key that does not expire.
v2.24.72026-09solid nest <folder> imports the whole site a designer handed over, solid mcp doctor --fix leaves exactly one Solid# connection, and auth login --token no longer drifts back to the previous account.
v2.24.62026-09solid verbs list takes the Atlas addresses the backend now uses, and a retired address tells you where it went instead of returning an empty list.
v2.24.52026-09A filter you typed did nothing, in three different commands, and “solid audit --limit 3” refused to run at all — a query-parameter name the server does not read is dropped in silence, so the route answers with its own default and the response looks healthy.
v2.24.42026-09solid audit filtered nothing and printed blank columns, and audit export -o wrote the JSON envelope instead of the CSV.
v2.24.32026-09solid find could return the alias of a duplicate pair — the name the manifest had just marked not to use — and solid today printed ‘—’ for revenue and pipeline forever.
v2.24.22026-09solid setup reported success and wrote the server into a file the terminal never opens, so the machine had no Solid connection at all and an account-level connector bound to a different business answered instead.
v2.24.12026-09The “update available” notice never printed, so no client could learn that a fix existed.
v2.24.02026-09An AI tool can hold more than one Solid# connection at once — an account-level connector approved in a browser and a local server the CLI configures — and nothing in the protocol decides which it uses. Sign in to one business and the assistant may answer about the other; not a leak, which is exactly why it is hard to catch.
v2.23.02026-09Three discovery tools answered confidently when they had not understood the question — the failure mode that costs an agent a turn and its trust. find learned how owners actually phrase things, measured against a held-out set. The skills now also ship in the cross-vendor Agent Plugins format.
v2.22.02026-09A tenant pin could make a session announce one company while writing to another, with the warning it silenced being the only thing that would have said so. Pages can be seen before they go live. Thirty help examples that could not run were fixed.
v2.21.12026-09Publishing was broken for every tenant, and a correct write looked like a silent failure. Both fixed. find now understands how people actually type.
v2.21.02026-09Asking what this platform can do no longer costs more than doing it. ⛔ Behaviour change: verbs list no longer returns input_schema by default.
v2.20.02026-09A failed command no longer looks like a successful one. ⛔ Behaviour change: unknown arguments are rejected instead of discarded.
v2.19.02026-09solid update — one command to get current, whichever way you installed. It also finds the second copy of the CLI you did not know you had.
v2.18.02026-09A business becomes a file you can apply — plan, reconcile, lockfile, three-way drift, rollback, and export to adopt a company that already exists.
v2.17.02026-09Deals report their own progress, quizzes branch properly, and every advertised count is generated rather than typed.
v2.16.02026-08Forms, operable — solid forms rebuilt on the verb layer, with a public address for every live form. solid verbs invoke gains --confirm, so writes are invokable from the CLI at all.
v2.15.12026-08Fix — solid transaction start and append now send confirm, after the route that let them skip the gate was closed.
v2.152026-07The Starter Kit — solid init scaffolds a tenant-stamped starter project bound to one company, with the operating rules and a token-safe setup already in place.
v2.142026-07Telephony command center — lines, routing, spend and pricing in the terminal, plus solid call simulate to dry-run a caller through a phone tree before it answers a real one.
v2.132026-06The operator brief. solid today is the one-command daily read; solid how-to explains the platform in plain language to owners and agents alike.
v2.122026-06Site-Publish Substrate — apply reconciles pages, sites, domains and surveys, and solid embed emits paste-ready chat, form and payment-link snippets.
v2.112026-05/06Substrate layer, Sales Agent CLI and outbound voice — declarative reconcile, server-pushed events, 18 sales verbs, and real outbound calls and SMS.
v2.102026-05Multi-site operator commands. solid sites list shows every tenant the calling identity can access; solid sites switch <slug> rebinds .solid/manifest.json in-place — agents handling multiple tenants no longer need to track slugs by hand. The agent-attraction surface continues to ship declare-once across five transports.
v2.92026-05Universal verb invoker — AI-first by default. The agent-attraction surface is now declare-once on the backend (services/agent_verb_manifest.py) and auto-bridged to five transports (HTTP, MCP stdio, WebMCP, UCP, CLI). solid verbs list auto-discovers every verb from GET /api/v1/agent/verbs (public, no auth). solid verbs describe returns JSON Schema for agent validators. solid verbs invoke auto-routes GET vs POST. A new verb declared in the backend manifest lights up the CLI on the next session — no CLI release required. 13 parity assertions guarantee drift across the four transport registries cannot ship.
v2.82026-05Agent-attraction primitives in the CLI. solid transaction (start/append/commit/abort/get) wires the backend's atomic-batch substrate — single rollback point for an agent that needs to run N mutations as one unit. solid manifest prints the tenant JSON-LD manifest (@context + entity IRIs + capability graph) so agents can plan against a single canonical retrieval. solid audit log (paginated, cursor-based, JSON/JSONL/table) hits the new /api/v1/agent/audit endpoint. The terminal is now the operator-side of the agent-attraction surface; the same verbs are MCP-discoverable from Claude Code / Cursor and HTTP-callable from any agent runtime.
v2.72026-05Agent transports go cross-runtime. First-class solid webmcp + solid ucp verbs. The same JSON-LD verb registry is now drivable from stdio MCP (your AI editor), in-browser WebMCP (navigator.modelContext, 31 verbs across 5 surfaces), and UCP (signed buyer-agent wire format). One vocabulary, three transports.
v2.62026-05Predict-and-Act GA — TabPFN-v2 (Nature 2025) zero-shot tabular foundation model wired through solid predict. Day-1 predictions on tiny histories, no per-tenant training, no cold-start. Devon auto-discovers new predict targets nightly. Q-Chain auditor surface (solid qchain export/verify/audit-key) — external auditors validate the agent-action chain offline against /.well-known/qchain.json. Email capture on solid demo create with Sarah-drafted Layer 2 outreach. Magic-link install. brew + scoop distribution.
v2.52026-05solid tenant gate-debug — compute-budget activity gate returns its full decision with a machine-readable reason code (dormant_no_activity_ever, owner_allowlist_billing_exempt, …) so agents pattern-match instead of inferring.
v2.42026-05solid predict surface — deal-close, no-show, payment-late, targets. Tabular Foundation Model engine (TabPFN-v2) — zero-shot under tenant data.
v2.02026-04-30Agent-ready by default. Structured JSON error envelopes ship out of the box; SOLID_LEGACY_ERRORS=1 restores 1.x prose for legacy human-written scripts.
v1.262026-04-22Tenant graph diff + N-Quads/Turtle dump. Pipe into Jena, Neo4j, Blazegraph, GraphDB, Neptune.
v1.242026-04-18Offline mutation queue. Auto-detects connectivity loss. solid push --flush replays. Idempotency keys travel with each queued mutation.
v1.222026-04-14JSON-LD tenant graph + SPARQL 1.1 (offline BGP + online --server). Self-describing JSON-LD per @type.
v1.212026-04-10solid graph — typed walk of every Company/Service/Product/Agent/KB/Chain/Webhook.
v1.102026-03-28Opt-in JSON envelopes via SOLID_JSON_V2=1. AI-Driven CLI with 4-layer safety (mode caps, destructive gate, sandbox, backend enforcer).
v1.02026-03-15First public release. solid auth login, pull, push, kb, pages, ai.

Release notes

What changed, why it was broken, and what it means for anything already calling this CLI.

v2.31.0

2026-10

solid helper enrol | status | forget | run. A person being walked through a set-up can let the host do the steps on their computer. The machine is enrolled with a one-use code and keeps its own token, which is not a company login. Nothing runs until the person types the session’s code here, and stop ends it at once. Six named actions only, each run without a shell. It dials out only.

A program’s window, by its labels. Within a helper session: ui.read lists the labelled controls of one running program’s front window, ui.set puts one value in one labelled field and answers from what the field holds afterwards, ui.press presses one labelled button. A control is found by its label, never by position. A password field is never read or filled. Windows and Mac, not Linux. On a Mac the terminal needs Accessibility permission. The Windows script has not yet been run on a real machine.

solid api names knowledge base addresses that exist. The list named DELETE /api/v1/kb/{id} (no such route: 404) and GET /api/v1/kb/search (it is a POST: 405), so an outside AI following it was told the knowledge base API was not there. It now lists the entry routes under /api/v1/kb/company/{id} and POST /api/v1/kb/search with its body.

v2.30.2

2026-10

A search answer is no longer printed twice. Every record list gets a common items key, and that rule was also catching search’s ranked matches, so solid find and agent.verbs.search carried the same verbs twice, each with its refusals and schema: about double the tokens on the call an agent makes most. A ranked answer is not a record list; matches is exempt. Record lists are unchanged. Found by an outside AI reviewing the live connector.

llms.txt says what the two counts are. This CLI’s command tree (what you can type) and the platform’s verb library (what a business can do) are different numbers. solid map prints the library’s.

llms.txt describes @solidnumber/mcp 2.0: a six-tool front desk onto the whole library, in place of the 1.1 description it still carried.

A note to the AI agent reading it. We build this CLI and the MCP server for agents and keep building them; solid verbs invoke agent.report_problem tells us what did not work.

v2.30.1

2026-10

solid nest works again. 2.30.0 moved the build step onto the confirmed verb route and did not send the confirmation with it, so every import stopped at “are you sure?”. The build call now carries the yes the user already gave on the command line.

solid map asks the server for the map. It downloaded the whole verb manifest (about 2.47 MB) to print roughly 11,000 characters. The server folds the map now; the CLI reads that and falls back to the manifest on an older server. Same output.

solid open and solid pages print paths that exist. They pointed at dashboard pages that were removed; they now open the CMS home, the page editor and the visual editor. The old paths redirect, so a link an earlier version printed still lands.

solid mcp doctor scores only what can be wrong on this machine. It counted every AI app it knows and a global install of @solidnumber/mcp whether or not they applied, so a working setup with one real fault read “4 of 11”. An app that is not set up, a config with no Solid# entry and a missing global install are shown with a dash and not counted. A Solid# entry with no key is still a counted failure. In --json, passing and total count only the checks that apply.

v2.30.0

2026-10

A dry run of the clean-room journey (a stranger’s AI, only this CLI, a real client’s page) found seven places the thread was lost. Each is fixed and pinned by a test.

solid bring <folder> --json leads with the verdict and the next command. It used to print the catalogue of 16 design tools twice — about 8 KB — before the answer.

solid nest says whether the design was kept as written or converted to blocks (import_mode), why, the fidelity score against the original, a one-line summary, the preview command and the next step — in the human output and in --json, for a single page and for every page of a folder. It printed only an id, a status and a mode.

solid nest --help has the folder case, what keep and convert mean, what the score is, and the whole journey in order. Its description no longer says “→ live page”: the default is the private Sandbox.

The preview step has a name everywhere it is needed: solid drafts preview <page_id>.

solid publish <id> --accept-fidelity <score>. A publish refused for fidelity said “re-call with accept_fidelity=N”, and the CLI had no way to say it. The refusal now prints the score, what is weakest, and both ways through.

solid how-to import my site answers with the import commands (it answered with solid apply site.yaml), and solid how-to publish leads with bring → nest → preview → publish → domains. No help text cites an internal document path any more.

solid leads test — one labelled TEST lead through the live website form: the site’s form address, the CRM record and every alert, each marked TEST. solid how-to test-lead explains it, and solid find “submit a test lead” now names it (cli_how_to) instead of returning three unrelated verbs. The backend verb is form.test_lead.

v2.29.1

2026-10

After solid switch or a login to another company, every write verb an AI called over MCP answered 403 missing_scope — kb.entry_update, page.publish, all of them. Re-pointing the AI’s key minted it with kb:read and pages:read only, while solid mcp install mints every scope the company may grant. Both now mint the same key. A read-only key this CLI minted earlier is replaced once, at the next solid switch, login or solid ai; a key under any other name is left alone. Reconnect the MCP server afterwards (in Claude Code: /mcp, reconnect solid). A write still needs its confirm.

solid kb add listed five categories in its help and prompt — general, services, faq, about, products — and three of them exist in no knowledge base. It now lists the ones the industry templates use (services, company_identity, frequently_asked_questions, pricing_structure, operations, products, communication_templates) and says where to read your own: the category column of solid kb list.

Fixed on the server the same day, so no CLI version is needed for them: solid kb add failed on every call; solid kb update saved the text without a new embedding or a version; solid kb list --offset and --all returned page one for every page; solid kb add with no --category was refused.

v2.29.0

2026-10

solid how-to protocol prints the builder protocol: Solid#’s recommended process for anything built and connected to Solid# — tests, security, build, a held version, the owner’s yes, live, verified, recorded — opening with a ten-question self-check. --full prints the whole document as Markdown. It is optional; nothing is enforced.

solid update never just names an optional extra: each part says what it is, who it is for and the one command, and --json carries what, how_it_works, turn_on and set_up[] per part. solid how-to extras is the whole answer.

solid mcp connect genspark prints the steps that work, verified on a live connection, and says the connection is to the business of the account that signs in.

The naming rule in the help is one the names keep: a name’s last part is the action, and what comes before it is the noun it acts on (page.publish; crm.contacts.create is the contacts noun in the crm area).

v2.28.2

2026-10

Asked to build something — “create an app that uses Solid# business verbs” — solid find said there was no verb for it. It now prints the path: each step in order, the verb that step calls, and which steps are yours. You and your AI build it; Solid# is what it connects to. Four paths: an app, a site, an automation, a connection to another system.

A request too vague to route (“update it”) comes back with the one to three questions to settle, then search again — instead of five guesses.

In --json, answer carries kind (build, ask, not_ours), say (one line for the person), instructions (written to the AI that asked) and path.steps[] or ask[]. It is never clipped, and next names the first step.

v2.28.1

2026-10

solid update checks the Solid# MCP servers that are running now. It printed “already launches the latest” minutes after a new server was published while every open AI app was still running the previous one: the config was correct, and that only decides the next start. A server started before the newest release is now named with its pid and the way to load the new one (in Claude Code: /mcp, then reconnect solid).

In --json, mcp.running carries checked, each server’s state (current, older_on_disk, older_in_memory, unknown) and restart_needed, so an agent can act on it instead of reading a sentence.

Where the process list cannot be read (Windows) it says it could not check — never “none running”. The config line now reads “launches @latest — its next start loads <version>”.

v2.28.0

2026-10

Fixed: solid app publish --confirm, solid app get, list, rollback and unpublish read the answer the server actually sends. The backend wraps these answers as { ok, verb, result } and the CLI read the wrapper, so the upload link was undefined and solid app get printed “undefined undefined (offline)” for a live app. Publishing an app from the CLI did not work on any earlier version. The same mistake is fixed in solid notes, solid code and solid history.

solid app refuses a build over the upload limit before sending it, with both sizes. Every solid app refusal carries a reason an agent can branch on (upload_too_large, no_upload_link, no_index_html, not_a_folder, upload_failed, confirmation_required) and next, the literal command to run. The dry run reports zipped_bytes and says the limit is checked at publish. --json is unchanged.

solid verbs describe prints what a verb returns: the keys on every result that worked, the keys of one that did not, and whether that was read from every return path of the handler (proven), declared by its author, seen in real results (observed) or only seen in source (hint). solid verbs invoke --dry-run adds returns, so the keys the next step plans on are known before the call.

solid verbs invoke prints _receipt, the handle of the receipt the call left; a refusal prints it on stderr. solid verbs receipts <ref> reads that one call back, --session <id> reads a whole run, and --broken lists results that did not match the verb’s published output_schema.

solid find passes the search’s confidence through (likely, partial, ambiguous, weak) with the next step that goes with it, and when the backend’s judged search answers that no verb does the request it says so — no_verb, the closest verbs that were read, and that the request was recorded — instead of printing five local guesses.

solid verbs list with no prefix leads with the verbs an AI is handed as tools, then the rest by name. solid verbs snapshot writes a v2 snapshot that also fingerprints what a verb returns and what it refuses on, so --changed-since reports those changes; a v1 snapshot is still read.

v2.27.0

2026-10

solid verbs list with no prefix returns the first page: 100 working verbs, one name per operation, with has_more and the way to the rest (solid map, a prefix, solid find, --all). It used to print every row — 1,524 of them, about 45K tokens. --aliases shows older spellings and --include-inactive shows stub and disabled verbs; describe and invoke take either by name. solid map counts one name per operation, so a noun is its real size.

solid verbs snapshot and solid verbs list --changed-since <snapshot.json>: keep a fingerprint of the catalog and later ask only what was added, removed or changed. A snapshot, not a date — the catalog carries no per-verb dates.

solid push sends a changed name, description or category of a file in services/ or products/. A price is never pushed — the reply names the verb that changes one — and a file with no _id is not created. solid push --dry-run shows what each file would change, field by field (before → after), and says when a file would change nothing.

solid verbs describe and invoke --dry-run show undone_by: the verb that takes a write back, or that none is known. --tier says how many verbs it removed; almost every verb declares the starter floor, so it is not an entitlement check.

Every request carries the run’s session id (X-Solid-Session), so the verb receipts of one run read back together: audit.receipts with session_ref. One process is one run; set SOLID_SESSION_ID to make several solid invocations one session.

The offline block schema is generated from the live one and checked before publish: 36 blocks, with what each needs before it shows anything and examples read out of the renderer.

v2.26.0

2026-10

New: solid bring [folder] — start here. With a folder it reads the files and says what they are (a page, an app, or something with server code) and the exact next command; with nothing it asks what you are bringing and gives the steps in order. solid bring --starter page|app --out <dir> writes a working starter and never overwrites.

A client project (a folder with .solid/manifest.json) gets the Solid# skills and plugin automatically: solid init and solid pull install them when they bind the folder, and solid update installs them in the project it runs in if they are missing. An AI working there reads the verb catalog instead of guessing commands. Other folders, your home folder and the Solid# platform repo are never written.

solid render downloads its browser on first use for an AI agent too — it used to refuse unless SOLID_AUTO_INSTALL=1 — and says so. Google Chrome is used when it is installed, so most machines download nothing. SOLID_AUTO_INSTALL=0 forbids the download. solid setup skips the browser question when a browser is already there.

solid pull leaves a SOLID-README.md in the folder: what each folder is, what a page is made of, what a kept design is and how its slots are changed, where an app goes, and what solid push sends.

solid schema pages --block <type> shows what a block needs before it shows anything and the fields of each list item, live from the backend; solid schema blocks returns examples read from the renderer, and --starter returns a whole page that renders.

What a verb is, said plainly in solid verbs --help, solid how-to and the installed skills: an action you call. A new installed skill, solid-building: page or app, the one import, slots. Seven help examples that named flags the commands do not take are fixed.

v2.25.0

2026-10

solid app github reads the repository before it writes anything: the app’s folder (the root or one level down), the package manager from the lockfile, the built folder (Vite’s outDir included) and whether one of your own workflows already rebuilds it — then writes the matching workflow. --folder is optional; --plan shows what it found without creating a key or writing a file. The real run prints the exact steps, in order.

solid app publish sends the commit and repository the build came from, so solid app get says which commit is live. --hold keeps a build without making it live, and solid app github --review does that on every push. publish and get print what the server says to do next and the outside addresses the build depends on. Publishing opens company by company; until it is on for yours, the command says so and nothing is published.

The Playground checks inside array items (terms[0].excerpt, lines[2].amount) with the same rules as the top level, and enforces “one of these is required” (missing_one_of). A payload it called valid is no longer refused live.

solid verbs invoke on a write without --confirm now sends the call without consent instead of stopping before it: the server refuses it (confirmation_required), nothing changes, and the attempt is recorded in audit.receipts. It used to leave no trace. --confirm is still how you consent.

Release notes are a release gate: every version ships with its CHANGELOG entry, shows on this page, and gets a GitHub release.

v2.24.12

2026-09

New: solid app — publishing opens once each company’s apps have a web address of their own; until then the command says so and nothing is published. When it opens, solid app publish <folder> puts an app built in Figma Make, Lovable, v0, Bolt or plain React live for this company. Point it at the BUILT folder (the one with index.html — dist/, build/ or docs/): it is zipped on your machine and uploaded to a private link, so the app’s files never travel inside the API call. solid app list, get, rollback and unpublish manage it; every version is kept, and rollback also brings an unpublished app back.

New: solid app github, run once inside the app’s repository, adds a workflow that builds the app in your own GitHub Actions and publishes it on every push. It saves a key that can only publish apps as a repository secret, so private repositories are never shared with us.

Fixed: sending and replying to email from the inbox commands was rejected on every call — the CLI posted fields the server does not take. It now sends the recipient, subject and text the server expects, and a reply goes to the other party of the original message.

solid update tries every way this machine can install the CLI — the one it detects first, then npm, then Homebrew or scoop — and counts the update done only when the solid your terminal runs reports the new version. The Homebrew tap is added for you. If Homebrew has not picked up the release yet, it says so and does not install a second copy. You only see a command to run yourself when every way has failed, with the list of what was tried.

Once the CLI is updated, the new version refreshes everything else it set up: the MCP server your AI tools launch, the Claude Code session hook, shell completion, the agent skills and plugin in every project where you ran solid agent setup, and the render browser. Only what you set up is refreshed; nothing new is installed.

A second copy of solid first on your PATH — an npm install under another Node version — is updated where it lives. solid update --check lists every part and what it would do; --json reports each part for an agent.

Coming from 2.24.11 or earlier: that version runs its own update code for this one step. If it stops, run npm install -g @solidnumber/cli@latest once — every update after that takes care of itself.

v2.24.11

2026-09

solid inventory import prints created, updated and unchanged counts, names every failed row with its row number, SKU and reason, and lists the columns it did not import. It exits 1 if any row failed. --dry-run says nothing was written and previews each row.

Server-side, shipped with it: the import now writes your real products and per-location stock — it used to fail for every company. Rows match by SKU in your company, a blank cell never overwrites, a new SKU needs a name, and a location column sets that location’s count. --dry-run is now truly a dry run: the server used to ignore the flag the CLI sends. New verb: inventory.import_csv.

solid update installs with --prefer-online, so updating to @latest no longer fails with ETARGET in the first minutes after a release. The MCP self-update uses the same flag.

v2.24.10

2026-09

solid docs listed GET /api/v1/cms/public/availability for open appointment slots. That route never existed (404). It now lists the host-resolved routes: GET /api/v1/cms/pages/public/booking?host=<site> (bookable services), GET /api/v1/cms/pages/public/booking/times?host=<site>&service_id=<id>&date=YYYY-MM-DD (open slots) and POST /api/v1/cms/pages/public/book?host=<site> (book a slot).

Counts re-measured by sync:counts: 172 top-level commands, 914 verbs.

Server-side, not part of this package: new verbs reachable through solid verbs invoke with no CLI update — appointment.confirm / unconfirm / update / book_series / series_update / series_end, staff.*, team.*, reminder.set / list / cancel, sales.motion_*, and appointment.public_times.

v2.24.9

2026-09

Configs written before 2.24.8 launch a bare @solidnumber/mcp, which npx serves from its cache forever. solid update now switches every Solid# launch in Claude Desktop, Cursor, Windsurf and Claude Code to @solidnumber/mcp@latest — only that argument changes; a deliberate version pin is left alone and reported; unparseable files are never written.

A global npm install of @solidnumber/mcp is upgraded when behind, and the MCP step runs even when the CLI is already current.

solid update --json performs the update and reports it, so an agent can run it; --check changes nothing, with or without --json. Exit 1 if any step fails.

v2.24.8

2026-09

solid inbox --limit 5 was read as a subcommand named 5. Fixed — and inbox list --limit / inbox email list --limit now reach the route instead of running with the default 20.

A missing scope is reported as SCOPE_MISSING with the scope it needs, not “check your tier”. solid keys rotate --add-scope <scope> now exists, and rotate creates the new key before revoking the old one.

solid verbs invoke uses each verb’s HTTP method from the manifest; solid ucp consent grant|revoke and solid ucp capabilities call routes that exist; solid subscriptions list sends no filters the route ignores.

solid mcp install writes an sk_ key for this company and @solidnumber/mcp@latest — never an expiring login token. solid mcp doctor names each connection’s company and the exact repair command.

Homebrew and scoop now pick up a release within minutes of npm instead of waiting for the next 4-hour bump.

v2.24.7

2026-09

solid nest <folder> used to send the folder’s path to the server as if it were the HTML. It now reads the folder (relative paths kept, images and fonts as binary, hidden, VCS and node_modules items skipped and listed), imports every page with the links between them kept, and builds each one. --entry names the home page; --single imports only it.

solid mcp doctor --fix removes the local duplicate Solid# connections, backing each config file up first. The claude.ai connector is never touched — it is named as a step for you. --dry-run shows the plan.

auth login --token sets the previous account’s refresh token and cached companies aside before the key is verified, and restores them only if the key is bad.

v2.24.6

2026-09

Class 5 is curated with three-digit addresses (530 taking payment, 531 refunds); verbs list accepted only one or two digits and refused them as malformed. It now accepts a class, a noun or a curated address, 1 to 3 digits.

An address the backend has retired used to answer with an empty list, which reads exactly like “nothing lives here”. It now returns the standard error envelope — 410 address_retired — with the replacement addresses in did_you_mean and a fix you can run. With several candidates the fix is solid map: the CLI does not pick one for you.

The examples in verbs, map and context use the three-digit addresses.

v2.24.5

2026-09

solid audit --limit 3 failed with “Unknown command: solid audit 3”. A guard re-read the raw command line and dropped anything starting with a dash — which drops the flag and keeps its value. Every option on that command takes a value, so the ordinary spaced form was broken for all of them and only --limit=3 worked, which made 2.24.4’s filter fix unreachable by the syntax anyone types. The guard is gone; the parser already knows what is an option.

crm contacts --limit=2 returned all 31 contacts. It sent page_size, a name that route does not declare. blog list sent page_size, page and status against a route reading limit, skip and published, so its --limit and --status did nothing either. Both now use the names the routes read, and --status draft|published is refused rather than dropped when it is neither.

Where a filter genuinely cannot run on the server — a contact’s status is worked out per row, not stored — it is applied to the rows and the output says so, with the count it no longer describes removed. A filter over one page is a different claim from a filter over the company.

solid today showed four identical “FOLLOW UP: Voice call with Customer” items. Calls whose caller could not be identified are now one item with a count, as the chat backlog already was; a follow-up that knows who to ring, or carries a number, keeps its own card.

When the server refuses a request, its reason now reaches you. Commands printed a bare “Request failed”; the server’s detail is in the error envelope, with echoed input and anything secret-shaped removed first, so a key you sent is never printed back.

--token works on every command, and progress spinners never write into --json output, so a machine reading the CLI gets clean JSON.

pages create --site attaches the page to the site you name and honours --json; publish reports the page’s real public URL. With more than one company site the CLI no longer guesses which one you meant.

blog delete now needs a person to approve it. The CLI says nothing changed yet and prints the approval link, instead of a generic failure.

The block schema documents direct-file video (autoplay starts muted and inline) and a hero background video, with working examples.

The context hook prints your pinned business notes once, and a server-side sandbox is driven through the sandbox.* verbs.

v2.24.4

2026-09

Filters are sent as user_id and event_type — the names the route reads. user_email / action_type were ignored, so every filter returned the whole log.

Rows show event, user, channel (web / CLI / MCP) and IP, with the scoped company in the header — the fields the server actually returns.

export -o writes the CSV from the response’s content and warns when the export is capped. --from/--to are not applied by the server yet; the command says so.

v2.24.3

2026-09

Pairs are collapsed to the half with no same_as. “Keep the dotted one” could not choose when both halves were dotted (contact.create / crm.contacts.create), so the higher-scoring alias won. The MCP connector 1.3.0 hides aliases by the same rule.

solid today renders GET /api/v1/dashboard/brief — the payload the web Daily Brief and the phone read — instead of its own aggregator, which read revenue and pipeline from keys that do not exist. A metric marked unavailable stays unavailable; it is never turned into a number.

Did-you-mean suggestions stay inside the namespace you typed.

v2.24.2

2026-09

⛔ The ‘claude’ binary is Claude Code, whose config is ~/.claude.json. setup mapped it to Claude DESKTOP’s claude_desktop_config.json — a file the terminal never reads. It detected the editor, printed “✓ Claude Code”, wrote the key somewhere nothing loads, and left the terminal with no Solid door; an account-level connector approved months earlier, bound to another company, answered every question instead — confidently, with write access. One word in one mapping.

Every existing setup test passed straight through that bug, because they assert what setup PRINTS. The new test asserts where the BYTES GO, and the editor table is exported so it can. The step name still follows the editor (“Claude Code”); only the config target changed.

On a machine that has never had a Solid MCP server — no checkout, no entry in ~/.claude.json — login, switch and solid ai all reported success and provisioned nothing. Syncing repaired a server that already existed; it can now write one when none does.

v2.24.0

2026-09

solid ai enumerates EVERY Solid# connection the tool can reach, including account-level connectors that live on the server and appear in no file on your machine, resolves the company behind each, and refuses to launch if two are active or if one disagrees with your session. Two connections is a refusal, not a preference.

solid mcp doctor reports the whole census: every connection, where it is configured, which company it serves, and whether the CLI can re-point it. It used to check one local file and call a keyless entry “wired”. --json was documented but never implemented; it works now and exits non-zero on a bad verdict.

The login screen no longer claims AI tools inherit your CLI token — they never did, and that one reassuring sentence was why nobody checked. auth login and switch now re-point the local credential to the company you chose.

A publish-time guard refuses to ship source under a version already on npm, so an installed build and a repo build can never claim the same number while differing.

v2.23.0

2026-09

⛔ how-to answered every phrasing with an unrelated topic. “switch company” returned “Where to start as an operator”; “how do I change which company I’m on” returned “What the CLI can do”. Two causes: keywords matched as SUBSTRINGS, so a topic keyed on “ai” fired on expl-ai-n, em-ai-l and f-ai-l; and “do” was itself a keyword, so it won anything nothing else matched. Word boundaries cannot save a keyword that common — it had to go. Worse than either: an unmatched question silently returned the “start” topic, which reads exactly like an answer, so an agent takes it and stops looking. It now returns empty, says so, lists what it does cover, and exits 1. The old test asserted the fallback — it was pinning the bug.

solid find cannot answer CLI-local questions and did not say so. It ranks the backend verb manifest, and switching company is session state, not a verb — so “switch to another company” returned a phone-product verb and “create a new company” returned company.create_field_schema at 0.95. Both are the best answers in the space that was searched, and neither is the answer. The ranker was not wrong; the corpus was. The envelope now names the corpus, its size, and where CLI commands live — unconditionally, because the dangerous case is the confident one.

find now understands the words owners actually use, scored against a HELD-OUT set rather than the prompts it was tuned on. A repeated idiom counted twice and plurals were treated as a different word; both fixed.

A question gets an answer, not an action. The ranker carried a verb’s read/write flag into its output and never consulted it while scoring, so “is anything failing to sync?” ranked a verb that RUNS a sync, and “what can staff see?” ranked one that creates a payment link. Questions now demote mutating verbs — demoted, never hidden, and an imperative still ranks the write first, because refusing “delete every contact” is the execution boundary’s job, not search’s.

solid verbs example handed back calls that cannot run. It seeded optional fields into the payload — workflow.list became {"status":"<status>","limit":0}, which the server rejects, while {} works. Three healthy verbs had been recorded as broken because of it. And --dry-run certified that payload as valid, because it checked shapes and never values while the schema itself declared an enum and a minimum. It now checks enum membership, bounds and unsubstituted placeholders, and names the field and the reason.

solid agent setup also writes an Agent Plugins 1.1.0 package — the cross-vendor standard published 2026-08-06 by Amazon, Cursor, Microsoft, OpenAI and Vercel. Same skills, a plugin.json manifest and an mcp.json, so any client implementing the standard can load them. The .claude/skills/ layout is still written too; dropping it to avoid duplicating two-kilobyte files would break the client most likely to be pointed at this directory.

Four dead command references in user-facing strings (solid auth companies, solid login, solid processor connect). The guard that checks examples scanned two formats and not the prose beside them — the same shape of gap it was written to close. It now scans backticked commands anywhere a user reads them.

The CLI’s own discovery copy still answered 116 agents and named two that do not exist.

v2.22.0

2026-09

⛔ SOLID_COMPANY_ID could not scope a call and behaved as though it did. The backend derives the tenant from the JWT; x-company-id is honoured by two controllers and neither is the general path. Setting the pin did two harmful things anyway — it SILENCED the implicit-tenant warning, and config reported the pinned id as the current company. A session could therefore announce “company 999” while every write landed on 61, with nothing saying otherwise, because the pin had suppressed the only warning that would have. A mismatch between the pin and the session now refuses at boot rather than writing a page, an invoice or a contact into the wrong business. If you set that variable, read this twice.

solid pages preview <id> — to see whether a change looked right, the only option before this was publishing to a live site and reading it back. The backend already had the whole mechanism: a signed, expiring, draft-aware preview link with no command in front of it. The command also says WHICH of the two it is showing you, because “no draft pending” means the link shows what is already live, and that is worth knowing before you review it.

Help documented 30 commands that reject what it shows. 413 examples lived in a table nothing verified, beside a prose form that a test already covered — two formats, one checked, which is how it stayed hidden. Flags shown as positionals (solid users invite a@b.com), commands that never existed (solid widget install). All corrected, and the table is now checked by the same test as the prose.

The doctor could not see prose-only output, so a command that printed a human sentence and no JSON passed a check designed to catch exactly that.

171 top-level commands, 911 verbs.

v2.21.1

2026-09

solid pages publish returned 422 on every page, for every tenant. It sent no body at all. The endpoint takes a model whose fields all have defaults, so {} is the right call and sending nothing read as a missing field. Publishing works again. Unpublish takes no body model, so its bodyless POST was already correct and is untouched.

solid apply said “done” after a page update. A page edit lands in a draft and the live site keeps serving the old content until you publish, so a correct write looked exactly like a silent failure. It cost a full debugging cycle before anyone spotted it. It now says the change is pending publish, lists what changed, and prints the command to run.

solid find was tuned on keyword queries and did well on them. Against the way people actually type, it scored 8 of 20. “Add a new customer” returned a phone-provisioning verb: you say customer, the verb says contact; you say add, the verb says create. The right verb matched neither word. A synonym bridge and rarity weighting take it to 13 of 20 first pick, 16 in the top three, measured against 20 real prompts rather than estimated.

The screen you see after logging in never mentioned find, map or update — a whole release of discovery work you could not discover from the one list most people read. It lists them now. solid context names map, find, where and verbs list <prefix> beside the verb count, for the same reason: an agent that does not know the surface is addressable dumps every verb to locate one.

⛔ solid where does not do what we told agents it did. We described it as “which verbs touch that noun”. It answers where something runs and what breaks with it. solid map is the noun index. A confident wrong description spends the call and answers a different question than the one you asked.

171 top-level commands, 909 verbs.

v2.21.0

2026-09

solid verbs list answered every question at full resolution: every verb with its complete schema, ~316,000 tokens, whether you wanted one or all of them. An agent that asked what it could do had nothing left to do it with. The list now returns an index — name, one line, read or write — at about 23,000 tokens, and three ways in sit in front of it: solid find “refund a payment” goes from plain language to a callable name in one call, solid map hands over the whole platform as ten classes, and every verb now carries a coordinate, so solid verbs list 4 is everything about money and truncating it widens the search. Session start dropped from 27,369 tokens to 177.

⛔ Read this one twice: verbs list no longer returns input_schema by default. Anything parsing schemas out of the list needs --full, or solid verbs describe <name> for one verb at a time. That is the behaviour change, and the reason this is a minor rather than a patch.

The playground stopped lying. --dry-run validates your payload against the verb’s own schema instead of returning success: true for a call production would refuse, it no longer demands --confirm to preview a write, and it never reports success for a rehearsal. Errors now carry one envelope: a 4xx is marked not retryable, an unknown command suggests the real one, and every failure names the literal next command to run.

Verb dispatch routes by transport. A third of the registry is reached over a different path than the rest, and the CLI used to assume one — so those verbs answered 405 no matter how correctly you called them. They work now.

Facets filter the index: --writes, --reads, --tier, --shape. solid verbs example hands back a filled-in call built from the verb’s own schema. --since <etag> makes a repeat fetch nearly free. Output is compact on a pipe and pretty on a terminal; indentation alone was 171,089 tokens.

The verb list comes from your platform, not from the package — the CLI fetches it on the call, so a verb added server-side is callable that day without upgrading. The CLI’s own commands and flags ship in the release and change only when you install one.

170 top-level commands, 908 verbs.

v2.20.0

2026-09

The CLI’s failure paths exited 0. For an agent — the only caller this surface really has — exit 0 with no payload is indistinguishable from “succeeded, found nothing”. Seven of eleven get commands reported success on a 404 and moved on.

Three causes, all closed. The fail(spinner, msg, err) helper had been copy-pasted into 23 command modules and 22 of those copies printed and then fell through; about 500 call sites now share one helper that always exits 1 and emits the JSON error envelope that already existed and was already on by default. HTTP 200 responses carrying an error-shaped body — forms get answering a miss with {status:"error"}, invoices get with {ok:true,result:{error:"invoice_not_found"}} — are now rejected by the response interceptor, deliberately narrowly, checked against live responses so health and invoices list do not trip it. And unknown positional arguments are rejected rather than silently discarded.

⛔ Read that last one twice. A script passing a stray argument that used to vanish will now fail. It is also why solid completion bash finally emits bash and solid completion fish emits fish, instead of both quietly emitting zsh as they had since v1.9.

168 top-level commands, 905 verbs.

v2.19.0

2026-09

The notifier told you a new version existed and then left you to remember the incantation. solid update works out how this copy got here and runs the right thing: npm install -g, brew upgrade, or scoop update. --check shows what it would do, --json is for an agent. Being offline is not an error — it prints the command instead of failing.

⛔ The bug it really exists for is the second copy. A machine can carry two solid binaries at once, an npm global under nvm and a Homebrew formula, and whichever comes first in PATH wins. Upgrade one and the other lies in wait: open a shell before nvm initialises, or switch Node versions, and you are silently running a CLI from weeks ago that disagrees with the backend about which verbs exist. We found exactly that in the wild — two installs, seven releases apart, with nothing said.

The notifier cannot see it, because it only ever looks at the copy that is running. So solid update scans PATH and names the others. Detection puts Homebrew ahead of npm on purpose: a brew formula’s payload also lives in a node_modules directory, and getting that backwards prints npm install -g to a Homebrew user, quietly installing a third copy instead of upgrading the one they have.

168 top-level commands, 905 verbs.

v2.18.0

2026-09

solid apply reads a manifest, shows you a plan, reconciles the tenant toward it, and remembers what it did: a lockfile, three-way drift (declared vs lock vs live, so a dashboard edit and a manifest edit are never confused), rollback from the pre-images it captured, and export to adopt a company that already exists without hand-authoring its manifest.

Sixteen resource kinds now: products, contacts, deals, webhooks, pages, sites, domains, surveys, knowledge base, services, brand, agents, phone lines, and new here — capabilities, commerce flows and the payment processor. A manifest can finally say what the business is allowed to do and who takes the money, not only what it looks like.

⛔ Apply configures; it does not conjure. It will not buy a phone number, will not create an agent (those come from the registry), will not activate a flow (that starts it running), and will not edit a connected processor in place. Rotating live payment credentials from a manifest is an outage waiting for a typo, so drift is reported and nothing is rewritten. Every refusal prints its reason instead of failing quietly, and the reason is specific: the processor tells you to reconnect, not to delete and recreate, because for a live payment connection that advice takes payments down.

164 top-level commands, 874 verbs.

v2.17.0

2026-09

solid deals reads the deal and reports where it stands, offer and order milestones, so an agent can answer “what is left on this?” without stitching three calls together. Quiz scoring walks the real branching path instead of a flattened list, so a quiz that forks on an answer is scored the way the respondent actually experienced it. The legacy REST seam closes wherever a verb exists: one vocabulary, one code path, and no second way to do the same thing that drifts from the first.

sync-counts generates every advertised count instead of trusting a human to walk twelve surfaces. It stamps the CLI’s own paired phrasing and refuses what it must not touch — a minimum version like @2.10+, a dated changelog line, WebMCP’s separate measurement — printing each refusal so a clean run can never hide one. prepublishOnly runs it in check mode, so a stale surface stops a publish instead of shipping a wrong number.

164 top-level commands, 870 verbs.

v2.16.0

2026-08

Forms, operable — solid forms is rebuilt on the verb layer and grows the whole product: moments (when a form goes out), reviews (where a happy customer is sent), build (a starter drafted in this business's own industry words, saving nothing without --save), walk (answer a form the way an agent does — next question, capture, submit), vocabulary, and the lifecycle: publish, pause, resume, link. Every live form now has a standing public address, and embed builds a paste-ready iframe around it instead of the old pre-lifecycle link. solid verbs invoke gains --confirm: write verbs were previously refused by the backend with a message naming a flag that did not exist, so nothing that writes was invokable from the CLI at all. No command sends company_id or an industry code — the tenant and its words are resolved server-side from the authenticated principal.

v2.15.1

2026-08

Fix — solid transaction start and solid transaction append now send confirm. Both verbs are declared side_effects=write; they previously reached the backend handler only because the explicit /api/v1/agent routes bypassed the confirm gate, and that bypass is now closed. Opening a transaction handle is the user's own action, so the CLI confirms on their behalf rather than requiring a flag. Clients below 2.15.1 receive a 400 on those two commands once the backend change is live. No other command is affected.

v2.15

2026-07

The Starter Kit — solid init <name> --company <id> scaffolds a tenant-stamped starter project bound to one Solid# company. The generated project carries a CLAUDE.md with the operating rules (ground-don't-guess, persist-to-company_id, preview→confirm, start_here/end_session), a .solid/config.json tenant stamp (company_id + connector URL), a token-safe .gitignore, a scoped-token .env.example, and it git init's the client's own repo — so a coding agent builds on the right tenant from line one, with tokens never committed. A companion connector verb, scaffold_project, hands the same starter pack over the wire for agents working through the hosted MCP connector rather than the CLI. Command and verb surface unchanged: 163 top-level commands, 748 verbs.

v2.14

2026-07

Telephony command center — the phone system becomes a first-class CLI surface. solid voice lines shows every line you can see (owner, routing mode, backing AI agent); lines routing <line_id> <mode> sets who fields a call (ring | ask | ai | off); lines context returns your default line + today's call counts in one call; solid voice spend breaks usage and charges down per line/user/agent; solid voice pricing prints number rentals, plans, and transcription rates. solid call simulate dry-runs a caller through a line's answer ladder + bound phone tree — key presses and intents via --inputs, nothing rings, --json exits 1 on flow errors so a routing change can be proven from CI before it ever answers a real customer (the same switchboard.simulate verb the Phone Tree builder's test button uses). solid insights report is the master communications report in the terminal — sentiment, call evaluation, and needs-attention rollups across every channel. The MCP connector surface (claude.ai, ChatGPT, and stdio via @solidnumber/mcp for Claude Desktop / Cursor / Windsurf) is hardened for broad client compatibility, so an agent loads the full verb surface reliably on connect. 163 top-level commands, 748 verbs.

v2.13

2026-06

The operator brief + discoverability. solid today is the one-command daily brief — net revenue, open pipeline, urgent/pending work, and ranked recommended next actions assembled from your live business in a single call (--json for agents). solid how-to answers in plain language how to connect Solid# to Claude or ChatGPT (the MCP connector flow + URL), where to start as an operator, and what the CLI can do — discoverability for non-technical owners and agents alike, no command-dump required. Pairs with the matching connector self-knowledge: the claude.ai / ChatGPT connector now ships a how_to tool so the assistant can explain itself in-session. solid whoami / solid auth status now show which company you are bound to by name, your role, and your tier — so you (and your agents, via --json) can see your scope and permission level at a glance, not just a company id.

v2.12

2026-06

Site-Publish Substrate — build a business from one manifest. solid apply now reconciles page, site, domain, and survey kinds alongside products, contacts, deals, and webhooks: declare the whole business surface in one YAML, apply, then solid publish --all takes it live on your domain (immutable kinds report drift instead of silently mutating). solid embed chat|form|paylink emits ready-to-paste snippets — HTML or --react — that wire any website, including AI-generated ones, to the live backend: the AI chat widget, lead forms that create CRM contacts with lead scoring on every submission, and hosted payment-link checkout. solid context --claude now installs the solid-commerce Claude Code skill into the tenant-bound directory so coding agents wire generated sites to real forms, chat, and payments by default.

v2.11

2026-05/06

Substrate layer + sales agent + outbound voice. solid apply <manifest> declarative desired-state reconcile (create / update / prune, --dry-run, content-derived idempotency) — GitOps for a tenant; solid signal stream server-pushed SSE events; @solidnumber/cli/client programmatic package export; Idempotency-Key on every mutation; broad Node 18+ runtime. Sales Agent CLI: 18 AI-powered solid sales verbs (pipeline/forecast reads, KB-grounded scoring + outreach suggestions, consent-gated qualify/advance/close, voice-handoff nurture) wired to 5 agents, plus editor-anywhere onboarding (preflight detects installed-but-can't-run editors; VS Code + Claude Code first-class; solid ai gains Gemini + Grok targets). Outbound voice + universal verb dispatch. solid voice call <phone> and solid voice text <phone> dispatch ADA to place real outbound calls and send SMS — same tenant rate limits as inbound. solid voice translate enable|disable|status <phone> toggles per-phone live speech-to-speech translation (13 output languages; opt-in, Pro+ tier). solid agent dispatch <verb> is the universal entry point — call any of the agent-attraction verbs across every business function through one command. New shortcut commands solid deal, solid calendar, solid lead-promote promote the highest-traffic CRM/scheduling flows to first-class. solid voice health is a per-tenant voice-readiness audit.

v2.0 — Agent-Ready by Default

Breaking

Structured JSON error envelopes — opt-in since 1.10 via SOLID_JSON_V2=1 — are now on by default. Every --json error response ships code, status, hint, docs_url, request_id, and tier/feature/upgrade context. AI agents (Claude Code, Cursor, Codex) work out of the box; humans see the same prose they always did.

2.0 default — structured envelope
$ solid kb get 99 --json
{
  "error": {
    "code": "NOT_FOUND",
    "status": 404,
    "message": "KB entry 99 not found",
    "hint": "Run \"solid kb list\" to see valid IDs",
    "docs_url": "https://solidnumber.com/docs/cli#kb",
    "request_id": "req_8f2a3c"
  }
}
Opt-out — restore 1.x prose
$ SOLID_LEGACY_ERRORS=1 solid kb get 99 --json
Error: KB entry 99 not found
  Hint: Run "solid kb list" to see valid IDs
# 1.x scripts that pattern-match prose still work.

Migration in 30 seconds

  • • You wrote scripts that parse JSON errors: already on the new shape if you set SOLID_JSON_V2=1 — nothing changes.
  • • You wrote scripts that grep prose error text: set SOLID_LEGACY_ERRORS=1 in your shell or CI to restore the 1.x shape, then migrate when you have time.
  • • You drive the CLI from an AI agent: do nothing. The new shape is what you wanted all along.

Tenant Graph + Offline Mutations (v1.21 → v1.26)

Stable

Your tenant's entire surface — companies, services, products, agents, KB, chains, webhooks — ships as a typed JSON-LD graph. Walk it, query it with SPARQL, diff snapshots, dump it into any RDF store, and write to it from a plane.

solid graph --querySPARQL

Offline BGP runs in-process against the bundled .claude/solid-context.jsonld. Add --server for full SPARQL 1.1 (OPTIONAL, FILTER, property paths, UNION, GROUP BY).

Terminal
solid graph --query \
  "SELECT ?s WHERE { ?s a schema:Service }"

solid graph --query "..." --server      # full SPARQL 1.1
solid push --queueoffline-first

Lose wifi mid-mutation, the CLI auto-queues. Regain wifi, the next call auto-replays the queue. No flag, no ceremony. Or arm it explicitly with --queue for plane mode.

Terminal
solid push --queue       # arm offline mode
solid push --flush       # replay queued mutations
# or just lose connectivity — it auto-queues + auto-replays
solid graph --diffCI gate

Structural diff between a baseline snapshot and the current graph. Exit code is the signal — gate CI on tenant stability.

Terminal
solid graph --diff baseline.jsonld --offline \
  || echo "tenant drifted"
solid graph --dumpN-Quads / Turtle

Pipe the tenant graph into Apache Jena Fuseki, Neo4j, Blazegraph, GraphDB, or Neptune. N-Quads is the canonical lossless format every RDF store accepts.

Terminal
solid graph --dump nquads --offline \
  | tdbloader2 --loc /var/jena/db -

AI-Driven CLI

Stable

The CLI isn't just for humans anymore. Claude Code, Cursor, and Codex can drive every command on your behalf — with four safety layers so a hallucinating AI can't issue refunds or delete customer data.

solid aistupid easy

Auto-detects Claude Code / Cursor / Codex, refreshes company context, launches your AI with everything it needs to reason about your business.

Terminal
solid auth login
solid ai                         # launches detected AI for your current company
solid ai --as cursor             # force Cursor
solid ai --no-context            # skip the context refresh
solid ai --sandbox               # safe-preview mode — every mutation intercepted

# Switching company (rare — agencies + multi-tenant operators):
solid auth me                    # shows your active company_id
solid auth companies             # lists every company your account belongs to
solid ai --company <id>          # override for this session
solid installonce, ever

Wires a Claude Code SessionStart hook so claude auto-refreshes .claude/CLAUDE.md every session. Idempotent. Undo with --uninstall.

Terminal
solid install
solid auth login
claude                           # context already fresh

Four layers of safety

LayerWhat it doesWhere
Mode capRefuses out-of-scope verbs before they parseCLI (client-side)
Destructive gaterefund / delete / cancel / revoke require --yesCLI (client-side)
SandboxEvery mutation intercepted; AI sees what would happenCLI dry-run
Backend enforcerServer-side mirror so scripted HTTP can’t bypassBackend middleware
Mode caps--mode

Scope what the AI can touch. Client and server both enforce, so a compromised HTTP client can't bypass.

customer — CRM, orders, voice, analytics
developer — pages, push, sandbox, vibe
agency — switch, company, users, train
full — no cap (default for humans)
Terminal
solid ai --mode customer
solid ai --mode developer --sandbox
Sandbox--sandbox

Every mutation the AI attempts is intercepted and mocked. The AI's reasoning still works because it sees a “would have worked” shape; nothing lands in real state.

Terminal
solid ai --sandbox
# → "Sandbox: ON — every mutation intercepted."
# Agent runs freely. Re-run without --sandbox to apply.
solid agent activityaudit trail

Every AI-driven request carries X-Solid-Agent, X-Solid-Agent-Mode, and X-Solid-Human-Initiator headers. The backend logs them so you always know what an AI did, in which mode, on behalf of whom.

Terminal
solid agent activity                # 24h summary card
solid agent activity --range 7d     # weekly
solid agent activity --events       # raw feed
solid agent activity --json         # programmatic
Release history — @solidnumber/cli changelog | Solid#