CLI
The deliverd command-line tool: connect your AI tools, publish from a terminal or CI, ask a person from a build step, and push actions and policy.
deliverd is Deliverd's command-line tool, published on npm. It sets up your AI tools, publishes reports from a terminal or a CI job, puts a person in the loop of a shell script, and pushes the actions and policy your organisation's gate reads.
Install
npm install -g deliverd
Or run any command without installing, with npx deliverd ….
Set up your AI tools
npx deliverd setup
setup finds Claude Code, Codex, Claude Desktop and Cursor on this machine and adds the Deliverd MCP server to each one it finds. It writes no credential — each tool asks you to approve the connection in a browser the first time — merges into existing configuration rather than replacing it, keeps a backup of anything it changes, and refuses a file it cannot parse. --print shows the configuration without writing it, --agent <id> limits it to one tool, and --url points it at your own Deliverd address.
Sign in
deliverd login deliverd login --url https://your-deliverd-address
login opens your browser at /cli/authorize; you approve, and the CLI receives an API token for you and keeps it in ~/.config/deliverd/config.json. --token takes a token from Settings → API tokens instead, with no browser.
In CI there is no browser and nothing keeps that file between steps, so set DELIVERD_URL and DELIVERD_TOKEN instead. They take precedence over the configuration file.
export DELIVERD_URL=https://your-deliverd-address export DELIVERD_TOKEN=dlv_… # from Settings → API tokens, stored as a CI secret npx deliverd publish ./dist/report --slug finance/weekly --living --json
Commands
| Command | What it does |
|---|---|
deliverd setup | Find the AI tools on this machine and connect them to the MCP server. |
deliverd login | Approve once in a browser; keeps a token for you. |
deliverd publish ./report.html | Publish an HTML file, a ZIP or a folder as a report. |
deliverd update <report> ./report.html | A new version at the same URL. |
deliverd share <report> --audience … | Give people, teams or groups access. |
deliverd rollback <report> --version 3 | Serve an earlier version again. |
deliverd data set <report> figures today.json | New numbers for a living report, no new version. |
deliverd comments open | Every open comment thread, across all reports. |
deliverd ask "Ship v4?" --wait | Block a build until a person decides. |
deliverd policy simulate --action … | What your gate policy would say, recording nothing. |
…and the rest: renaming, archiving, versions, copies and templates, datasets, comments, analytics, reviews, requests for information, flows, schedules and evidence packs. deliverd --help lists them all, and deliverd <command> --help explains one.
Publishing
deliverd publish ./report.html --audience "Finance team" --title "Q3 Review" deliverd publish ./report-folder --slug finance/weekly --living # A new version at the same URL, refused if somebody else published first deliverd update finance/weekly ./report-folder \ --change-summary "October figures" --expected-version 4 deliverd who "Finance team" sarah@acme.com # check a name before you share deliverd share finance/weekly --audience "Finance team" deliverd unshare finance/weekly --audience sarah@acme.com deliverd send finance/weekly --to sarah@client.com -m "Final numbers." deliverd rollback finance/weekly --version 3 deliverd archive finance/weekly # stops the URL serving; nothing is deleted
deliverd versions <report> prints latestVersion, which is what --expected-version compares against. A living report's numbers can change with no new version: deliverd data set <report> <name> <file>, or - to read standard input. See Publishing reports.
Putting a person in the loop
A build step that opens an approval, exits zero and carries on has done worse than not asking. --wait blocks — for an hour, or the number of seconds you give it — and exits non-zero on anything but an approval, so set -e is the whole integration.
# Blocks until somebody decides, then exits 0 only if they approved.
deliverd ask "Ship the Q3 pack to Acme?" \
--why "Final numbers, partner-reviewed" \
--approver partner@firm.com --wait
# With arguments the approver may correct, and the decision as JSON
deliverd ask "Refund Acme for invoice 4821" \
--input '{"customer": "acme", "amount": 1240}' --editable amount \
--risk high --approver finance@firm.com --wait --json > decision.json
deliverd approvals get <id> --wait
deliverd approvals answer <id> --question <question-id> --answer "Yes, signed off Friday"
deliverd reviews ask "Check the Q3 commentary" --reviewer "Finance team" --report finance/weekly
deliverd collect ask "Renewal details" --question "Which quarter?" --respondent ops@firm.com
deliverd flows start "Q3 close" # then pass --flow <id> to the above--inputtakes inline JSON,@file.json, or@-for standard input, and must be an object.--editablemust name fields--inputhas. Both are checked before anything is sent.- Run with
approvedInputfrom the JSON, never with what you proposed. - A wait stops when the approver asks an unanswered question, rather than timing out silently: the request is waiting on you.
--callback <url>has the outcome posted to you instead; the signing secret is printed once. See Callbacks.
Actions and policy
deliverd actions push --file deliverd.actions.json
deliverd policy push --file deliverd.policy.json --activate
deliverd policy simulate --action finance.refund \
--input '{"amount":1240}'actions push registers every action in deliverd.actions.json and is meant to run on deploy. policy push stores deliverd.policy.json as a new version and puts it in force only with --activate. Both need a key belonging to a person; policy also needs an owner or administrator. See Agent policy for the file formats.
Conventions
- Errors
- Every failure prints
Error (code): messageon standard error and exits 1. The code is the API's own — branch on it in a script, not on the message. See Errors and limits. --json- Every command that returns something takes
--jsonand prints exactly what the API said. The human output is meant to be read, and will be reworded. - Lists
- No
--limitmeans all of them: a list follows the cursor to the end.--limit Ngives one page and prints the cursor to continue from. - Agent tokens
- If
DELIVERD_TOKENbelongs to an agent that has been deleted, every command fails withagent_not_found. The token still authenticates; the identity it acts as is gone.