CLI
work is a single binary with no runtime dependency. It uses the same API as the web app.
Install
curl -fsSL https://work.betterthangood.xyz/install-cli | bash
The script verifies a checksum, then installs into /usr/local/bin, or ~/.local/bin if that is not writable. macOS, Linux and Windows are supported.
| Variable | Effect |
|---|---|
WORK_INSTALL_DIR | Install location |
WORK_VERSION | Pin a version, for example 1.0.0 |
Sign in
Create a token at Settings → API tokens (details), then:
work auth login
The command prompts for the token, verifies it against the API and saves it to ~/.config/work/config.json with owner-only permissions. The token can also be piped in:
pass work/token | work auth login
There is no --token flag, because arguments appear in shell history and in the process list.
WORK_TOKEN in the environment takes precedence over the saved token. WORK_CONFIG selects a different config file, for using two accounts from one machine.
Command structure
work <resource> <verb> [id] [--flags]
Verbs are list, show, create, update and delete, matching the API. Invoices have no update or delete, and payments are read-only. Requesting one of those fails before a request is sent.
work contacts list [--page N] [--per-page N]
work contacts show 12
work contacts create --first-name Ada --last-name Lovelace --email ada@example.com --company-id 7
work contacts update 12 --title "CTO"
work contacts delete 12
work deals update 412 --stage won
work projects create --name "Website redesign" --company-id 13
work tasks create --title "Draft the sitemap" --project-id 4
Only the flags given are sent, so update leaves unmentioned fields unchanged.
Invoices
work invoices create --company-id 7 --contact-id 12 \
--issue-on 2026-08-27 --due-on 2026-09-26 \
--lines '[{"description": "Design retainer", "quantity": "1", "unit_price": "1200.50"}]'
work invoices send 88
work invoices pay 88 --amount 1200.50 --paid-on 2026-08-27 --reference wire-442
send emails the client and freezes the invoice. pay records a payment against it.
Money in flags
- Flags ending in
-centstake cents.--value-cents 500000is $5,000. - Invoice amounts take dollar strings:
--amount 1200.50andunit_pricewithin--lines.
Responses return cents. Table output renders them as decimal amounts.
Output
When output is piped or redirected, work writes the API's data payload as JSON. In a terminal it writes a table. --format json and --format table override the default.
work deals list --format json | jq '.[] | select(.stage == "proposal") | .name'
Exit codes
| Code | Meaning |
|---|---|
0 | Success. Deletes produce no output |
1 | The server refused the request. code: message on stderr, with one line per field on a validation error |
2 | The command was invalid. No request was sent |
Help
work help
work help invoices
work contacts create -h
Help does not require a token.
Pagination
Request pages until one returns fewer rows than --per-page:
work contacts list --per-page 100 --page 1
Use from an AI agent
An agent skill ships with the binary. It documents the command grammar, the money conventions, pagination and which operations are safe to run without confirmation.
The skill classifies operations as follows:
- Safe unattended:
listandshowon any resource;createandupdateon contacts, companies, deals, projects and tasks; creating an invoice, which is a draft. - Confirm first:
invoices send, which emails the client and freezes the figures;invoices pay, which records a payment; anydelete, which cannot be undone; and large write loops, which consume rate limit.
Writes are recorded in the audit log against the token's owner.
Command table generation
The CLI's command table is generated from the API specification, which is generated from the server's routes and contract-tested. The CLI cannot offer a command the server does not have.