Use the Economico CLI

The Economico CLI is a REST client for a terminal or an agent without an MCP host. It discovers operations and their flags from the server’s authorized OpenAPI document. It uses the same business permissions and command path as HTTP and MCP.

Install and sign in

Use Node.js 24 or newer:

npm install -g @economico/cli
economico --version
economico login --server https://economi.co --local

Login opens the browser for OAuth approval with PKCE and a loopback callback. --local stores the connection in the current project’s .economico/config.json and adds .economico/ to that directory’s .gitignore. Keep credentials out of chat, shared files and version control. Approve the business and access yourself.

For your own agent identity, choose Continue with AgentID and follow the AgentID sign-in and signup procedure. Use your AgentMail inbox to authorize the pending sign-in, then return to the same browser. Existing books require a membership grant; creating a Solo business requires a separate human-owner signup approval and gives the agent bookkeeper access. Complete the original OAuth flow before running CLI commands.

Use login --no-browser to print the authorization URL instead of opening it. login --port <port> selects the callback port. A new user can create a business in the browser during login; signup flags only prefill the form for review. economico login --help lists those flags. economico logout removes stored tokens from the selected configuration file; it does not delete the business.

Without a permanent installation, npx -y @economico/cli@latest runs the same CLI:

npx -y @economico/cli@latest login --server https://economi.co --local
npx -y @economico/cli@latest businesses list

Select a business and discover operations

economico businesses list
economico --business example-sandbox tools
economico --business example-sandbox catalog list
economico --business example-sandbox catalog describe --name parties.create

Replace example-sandbox with a business slug returned by businesses list. Every business invocation sends its own --business; there is no mutable current business. The flag becomes X-Economico-Business on the HTTP request. A slug is an identifier, not a grant of access. Use a disposable sandbox or isolated demo for practice writes; never use the Economico production business, slug economico.

tools lists the operations this connection can discover for the selected business. An operation ID becomes a tool and verb: reports.run becomes reports run. Availability can change with permissions and the server catalog; use discovery rather than assuming a fixed command tree.

economico --business example-sandbox reports run --help
economico --business example-sandbox commands execute --help --json

The first prints the operation’s flags. --help --json prints its complete schema. For commands, describe the named command separately: generic commands execute help summarizes the envelope, not every command’s input variant.

Read a report

economico --business example-sandbox reports list
economico --business example-sandbox reports run \
  --kind balance_sheet --currency USD --as_of 2026-07-31
economico --business example-sandbox reports run \
  --kind balance_sheet --currency USD --as_of 2026-07-31 --human

JSON is the default and preserves the report contract. --human formats supported financial statements and summarizes other results. Reports and previews do not create entries. Their descriptions distinguish recorded books from calculations based on supplied assumptions. Keep native currencies and date windows explicit. The report reference explains each report’s parameters and how to interpret its result.

Submit a command and check what changed

Read the command reference and the live description before sending a write. This example creates a fictional counterparty in a disposable sandbox; it does not post money:

economico --business example-sandbox catalog describe --name parties.create
economico --business example-sandbox commands execute \
  --name parties.create \
  --idempotency_key cli-example-vendor-1 \
  --effective_at 2026-07-01T00:00:00Z \
  --input '{"partyId":"pty_cli_example_vendor","name":"CLI Example Vendor","categories":["vendor"]}'

--input is the command-specific input object. --name, --idempotency_key and --effective_at belong to the outer envelope. Use a stable source identity and real evidence for actual bookkeeping, and keep exact minor-unit amounts as strings. Creating a party is different from receiving a document, recording an invoice, recording a completed payment or recognizing revenue.

On acceptance, inspect result and the returned event IDs and CIDs. Retain the commandId and any domain identifiers returned by the command. To recover the receipt, substitute the actual returned command ID:

economico --business example-sandbox commands get --id COMMAND_ID

Replay the same intent with the same key to recover its original receipt; replayed identifies a replay. Changing the command or input under an accepted key is an idempotency conflict. A domain no_change outcome has no persisted receipt. Some commands also succeed with events: [] and return a transient commandId and result without storing a receipt. Looking up that ID can return null; retain the result and verify the affected record. Retrying such a command can re-evaluate current state instead of replaying a stored receipt. Check the affected records or reports before moving to the next action.

JSON files, stdin and field types

Field flags use the schema’s exact spelling, including underscores. String fields stay strings; booleans use true or false; numeric fields use JSON numbers; objects and arrays take JSON. Money remains an integer string in a named unit, even if it looks like a number.

Use --args for an entire JSON request object:

{
  "name": "parties.create",
  "idempotency_key": "cli-example-vendor-1",
  "effective_at": "2026-07-01T00:00:00Z",
  "input": {
    "partyId": "pty_cli_example_vendor",
    "name": "CLI Example Vendor",
    "categories": ["vendor"]
  }
}

Save this as command.json, or pass equivalent JSON on stdin:

economico --business example-sandbox commands execute --args @command.json
cat command.json | economico --business example-sandbox commands execute --args -

These are alternative ways to send the same intent, with the same key. Do not invent a fresh key just to retry a failed response. Flags can supplement --args, but duplicate fields are refused. Unknown fields are refused too.

Upload a source document

When the operation advertises multipart upload, --file sends exact local bytes:

economico --business example-sandbox documents submit \
  --file invoice.pdf \
  --input '{"kind":"source_document","title":"Vendor invoice"}' \
  --idempotency_key vendor-invoice-123 \
  --effective_at 2026-07-01T00:00:00Z

Omit input.contentBase64 when using --file. The upload limit is up to 10 MiB; a document kind may allow less. The client allows two minutes for an upload and 30 seconds for other calls; the server separately requires upload transfer to finish within 30 seconds. Receiving the source preserves evidence; it does not classify an expense or post its economics by itself.

Errors and retries

Errors go to stderr and the process exits nonzero. A command is not automatically replayed after a network failure. The client can refresh once after a 401 and retry a 503 busy with Retry-After, because the server did not start that request. Other refusals require the caller to inspect the error and fix its cause.

After a lost response, recover the receipt or retry the same intent and key. Never switch business, widen permissions or choose a new key merely to get past a refusal. Browser-only actions require the signed-in human rather than a CLI workaround. See request and recovery rules for HTTP errors.

Configuration and agent use

The configuration file is selected in this order:

  1. ECONOMICO_CONFIG_FILE, when explicitly set.
  2. The nearest trusted ancestor’s .economico/config.json.
  3. $XDG_CONFIG_HOME/economico/config.json, normally ~/.config/economico/config.json.

Config files use mode 0600. Ancestor discovery does not walk above the user’s home directory and, on Unix, ignores files the current user does not own. ECONOMICO_API_URL overrides the stored server URL. Credentials belong to the server that issued them; sign in again when changing servers.

Agents should parse JSON stdout, inspect stderr and exit status, discover the authorized catalog, and name the business on every invocation. Ask the user to complete interactive login; never ask for tokens in a prompt. This guide’s Markdown mirror and the agent execution map provide the same workflow without requiring HTML rendering.

Navigate documentation