For the complete documentation index, see llms.txt. Every page is also served as Markdown at its URL followed by .md.

standards
How to use the CLICLI

How to use the CLI

Install the standards CLI, log in to the hosted API, and script your workspace with JSON, table or CSV output.


The standards CLI (@standards/cli) talks to the Standards API over HTTP. It is the shortest path from a terminal to your records, documents, schema and MCP servers.

Install and log in

npm i -g @standards/cli

Save an instance profile, then select it. Omit --key to be prompted for it.

standards login --url https://api.standards.new/v1 --name prod --key stndrds_your_api_key

Always pass --url for the hosted API

The compiled default URL is http://localhost:4100/v1. Without --url, login stores a profile that points at a local server and every command answers with a connection error.

login validates the key against the API before it saves anything. Confirm the profile is usable:

standards auth whoami

Profiles

Profiles live in ~/.standards/config.json, written with mode 0600. Set STANDARDS_CONFIG_DIR to move the whole directory, for example in CI.

standards instances
standards use prod
standards current
standards logout prod

logout without a name removes the active profile.

The environment profile

STANDARDS_API_URL and STANDARDS_API_KEY form a profile of their own. standards instances lists it as sandbox with source: "env". It is active only while no profile is selected in the config file.

STANDARDS_API_URL=https://api.standards.new/v1 STANDARDS_API_KEY=stndrds_ci_key standards records list contacts

Resolution order

  1. --api-url or --api-key on the command line. Either flag bypasses every profile; the other value falls back to the environment, then to the compiled default.
  2. --instance <name>, then the profile selected with use.
  3. STANDARDS_API_URL / STANDARDS_API_KEY.
  4. The compiled default URL, with no key.

Global flags

FlagDescription
--format <fmt>json (default), table or csv.
--api-url <url>API base URL. Bypasses the profile.
--api-key <key>API key. Bypasses the profile.
--instance <name>Use a named profile for this call.
--tenant <id>The tenant you are authenticated in. A confirmation of intent, not a selector: the API refuses any other value.

Output formats

json prints the response as-is. table and csv read the first row's keys as columns; a scalar or object response becomes a one-row table. Nested values are serialised as JSON. Table cells are truncated at 50 characters.

standards keys list --format table

records list and records search return { data, page }, so the table shows two columns. Pipe the JSON through jq instead:

standards records list contacts --limit 20 | jq .data

Record saves are acknowledged after the database write. Search indexing runs through durable batches, so a newly saved record can appear in records search shortly after the save response. The CLI has no job producer mode setting.

Exit codes

CodeMeaning
0Success. For diff, no differences.
1The API refused the request or the command failed. The message reads ✗ Error (status): message, for example ✗ Error (404): Record not found.
2No instance is configured: no profile, no --api-key, no STANDARDS_API_KEY. pull and diff also exit with code 2 on transport or schema errors.

diff uses exit code 1 to report differences, not a failure. See Schema and bundles.

Every command except login, use, instances, current, logout and help needs a key. Without one the CLI prints ✗ Error: No Standards instance configured and stops with exit code 2.

API keys

standards keys list
standards keys create --name laptop --yes                     # personal: acts with your access
standards keys create --name ci-bot --workspace --role ci --yes
standards keys detach <keyId> --yes
standards keys revoke <keyId> --yes

create, detach and revoke refuse to run without --yes. create makes a personal key (it acts for the person behind the key you run it with); --workspace makes an integration key that acts with its own roles; --role <name> binds that role instead of member. See Workspaces and API keys.

Tenant invitations

Manage the current tenant's explicit invitation lifecycle. Creating an invitation sends an email; the person becomes a member only after accepting it with their verified identity.

standards invitations list --format table
standards invitations create --email [email protected] --role <roleId> --yes
standards invitations resend <invitationId>
standards invitations revoke <invitationId> --yes

create requires --email and --role (an existing role ID). Both create and revoke require --yes: omitting it prints a message asking you to confirm and exits 1, before any API request. resend sends another email without a confirmation flag, and invalidates the link in the previous email. Use an invitation ID from list for resend and revoke: anything that is not an invitation ID is refused the same way, before any request, so the ID can only ever address its own route segment.

CommandRequired system permission
listpeople:read
createpeople:create
resendpeople:update
revokepeople:delete

The API refuses callers without the required permission (SCHEMA_FORBIDDEN). Creating an invitation for an address already in this tenant, including a deactivated member, fails with SCHEMA_DUPLICATE_OBJECT; an unknown role fails with SCHEMA_ROLE_NOT_FOUND. Resending the same invitation twice inside a minute fails with SCHEMA_STATE_GATE: the API allows one resend per minute per invitation. An address already invited and still pending returns its existing invitation unchanged. These commands require the server's tenant invitation capability to be configured. The people permission group is described in Workspaces and API keys.

There is deliberately no invitations accept command: an API key cannot accept on someone else's behalf. Acceptance requires the invitee's verified bearer identity and the invitation proof.

If record search misses records or shows outdated ones, rebuild the tenant's record search index:

standards search reindex --tenant <tenantId> --yes

The command requires workspace update permission and --yes: without it, it exits before any API request. It starts a background rebuild and returns when the API accepts it. The new index is built beside the current one, which keeps answering searches, and replaces it in one step once every record is in it. Records saved during the rebuild are included. Nothing is cleared first. If a rebuild is already running for the tenant, the API refuses a second one (HTTP 409).

If existing email messages are missing from search, hand the tenant's stored messages back to the email indexer:

standards search reindex --emails --tenant <tenantId>

The command requires workspace update permission. It starts a background job and returns when the API accepts it; follow the server logs for completion or failure. The job writes nothing to the email search index itself: it hands every stored message back to the email indexer, which a worker process runs and which delivers them in the background. Messages already waiting or in delivery keep their place. The job does not clear the index or alter the records search index.

The logs report how many messages were handed back and the last email ID processed. If the job fails, resume after that ID with --after-id:

standards search reindex --emails --tenant <tenantId> --after-id <last completed id>

Omit --after-id to start at the beginning. --after-id only applies to an email reindex: without --emails the command refuses it before any API request. The same resume is available directly as POST /admin/search/email-reindex with { "tenantId": "<tenantId>", "afterId": "<last completed id>" }. Use the tenant you are authenticated in; the API rejects a different tenant.

Messages reappear in email search as the indexer delivers them; until it has delivered them all, email search is incomplete.

To rebuild the email search index itself from the stored messages, add --rebuild and --yes:

standards search reindex --emails --rebuild --tenant <tenantId> --yes

The new index is built beside the current one, which keeps answering searches, and replaces it in one step once every stored message is in it. Messages received meanwhile appear a few minutes late. Without --yes the command exits before any API request, and --rebuild refuses --after-id. The same rebuild is POST /admin/search/email-reindex with { "tenantId": "<tenantId>", "rebuild": true }. The rebuild only recovers a mail index that is not built or whose indexer stopped on an uncertain write: on a healthy one the API refuses it (HTTP 409), as it does while a rebuild is running for the tenant.

Recompute meeting grants

Private meetings are shared with the members their calendar invite names. Each workspace recomputes these shares once, in the background, after the deploy that introduced them. To run the recompute again, as a retry or a repair:

standards --tenant <tenantId> meetings grants-recompute

The command requires the settings update permission and refuses to run without --tenant, before any request. It starts a background job and returns when the API accepts it (202); the job is idempotent and deletes nothing. Use the tenant you are authenticated in; the API rejects a different tenant. A server without a calendar service answers 404. A server with a calendar but without the meeting attendee tables answers 503 with CONFIGURATION_REQUIRED. The shares themselves are described in Record access.

Backfill agent memory

Agent memory is rebuilt from evidence. To feed it the workspace's last 30 days of conversations and meeting transcripts:

standards --tenant <tenantId> memory backfill --yes

The command requires the settings update permission, and refuses to run without --tenant or without --yes, before any request. It starts a background job and returns when the API accepts it (202); follow the server logs for progress. Sources are read oldest first and pass the same checks as live evidence: a one-message conversation that asks nothing to be remembered, or a meeting with no linked record, adds nothing. Memory records cannot be written through standards records; see Skills and memories. Each source is read once, however often the command runs. The job stops at 200 memory passes or 2,000,000 model tokens for the workspace; running it again resumes where it stopped. The same job is available directly as POST /admin/memory/backfill with { "tenantId": "<tenantId>" }. Use the tenant you are authenticated in; the API rejects a different tenant.

Shell pitfalls

  • Single-quote JSON so the shell keeps the double quotes: --data '{"name":"Alice"}'.
  • --filter takes the raw filter tree as JSON, exactly as the API expects it.
  • --sort takes one rule, attribute:direction. Pass it once.
  • --fields "" hydrates no reference attribute. Omit the flag to hydrate all of them.
  • Wrap --query in quotes when it contains spaces.

Next steps

Connectors

List configured providers and workspace connections:

standards connectors providers
standards connectors list

Start authorization with standards connectors connect --provider github and open the returned URL. Supported provider IDs are github, slack, gmail, outlook, google-calendar and outlook-calendar; availability depends on the instance configuration shown by connectors providers. A mailbox or calendar provider first prints what the connection allows and refuses to run, before any request, until you add --yes: see Connected mailboxes and calendars.

Disconnect a connection with --yes; the command refuses to run without it, before any request:

standards connectors disconnect <connectionId> --yes
standards connectors disconnect <connectionId> --yes --remove-imported

By default the mail and meetings a mailbox or calendar connection imported stay. With --remove-imported they are deleted too, for everyone, the owner included. Only the owner of a personal connection can ask it: on a connection made for the whole workspace, what it imported is the workspace's shared history, and the API refuses it (403, SCHEMA_WORKSPACE_INVARIANT) with nothing deleted. A GitHub or Slack connection imports neither, so the flag changes nothing there. What is kept and what goes is described in Record access.