@buzzerboyinc/klaai-cli
v0.1.8
Published
Command-line client for Klaai — double-entry bookkeeping for Canadian small business.
Readme
Klaai CLI
Command-line client for Klaai — double-entry bookkeeping for Canadian
small business. Every command speaks to the same REST API the web app uses, and
every command supports --json, which is how the Claude skill drives it.
Install
cd cli
npm install
npm link # puts `klaai` on your PATHOr run it in place: node bin/klaai.js <command>.
Requires Node 18+ (uses the built-in fetch).
Sign in
The CLI points at production (https://www.klaai.co) by default, so you can sign
in straight away. Only set a URL if you're using a local or dev instance:
klaai config set-url http://localhost:8643 # local dev server (optional)klaai login url — browser flow (recommended)
$ klaai login url
Authorize the Klaai CLI https://www.klaai.co
Opening your browser. If it didn't open, use this URL:
https://www.klaai.co/cli-auth
Sign in if asked, click Authorize, then copy the code shown.
Enter the code: 35AE-D4A8
✓ Signed in as [email protected]
Company: Maple & Main Consulting Inc. (Owner)
Credentials saved to /Users/you/.klaai/config.json — 30 days remainingThe browser shows a one-time authorization code, not your token. The CLI exchanges it for the real credential, so the long-lived token never appears on screen or in your shell history. Codes are single-use and expire in 10 minutes.
Use --no-browser on a headless machine to just print the URL.
klaai login token — paste a token
Create one in the web app under Settings → CLI access, then:
klaai login token # prompts for the token
klaai login token dc4f…9a1 # or pass it directlyWhere credentials live
~/.klaai/config.json, mode 0600 — in your home directory, never in this
repo, so the source is safe to commit and a checkout carries no secrets.
{
"url": "https://www.klaai.co",
"token": "…",
"expires_at": "2026-08-17 16:40",
"company_id": "co_01",
"user": { "id": "usr_01", "email": "[email protected]" }
}Tokens are valid for 30 days (well beyond an 8-hour working session). The CLI tells you what's left:
klaai login status
klaai logout # clears locally AND revokes the token server-side
klaai revoke # the above, plus deletes the config file and the saved URLlogout signs you out but keeps pointing at the same server, so signing back in
is one command. revoke is for leaving nothing behind — handing a laptop back,
finishing up on someone else's machine, or resetting a config that has drifted to
a host you'd rather forget:
$ klaai revoke
✓ Token revoked and local config deleted.
Was signed in as [email protected]
Removed /Users/you/.klaai/config.json
Server URL forgotten — the CLI is back to its default. To restore it:
klaai config set-url http://localhost:8643
Sign in again with `klaai login url`.It never prompts, so it is safe to script, and it prints the URL back on the way out because that is the one thing signing in again won't restore. Running it while signed out, or twice, is a no-op. If the server can't be reached the local state is still wiped — a machine you're wiping shouldn't keep credentials just because the network was down — and the failed revoke is reported rather than swallowed.
Override the config location with KLAAI_CONFIG_DIR, the server with
KLAAI_URL, or the token with KLAAI_TOKEN (handy in CI). Note that revoke
kills a KLAAI_TOKEN server-side but cannot unset the variable in your shell —
it says so when it sees one.
Choosing company and fiscal year
The CLI is stateless — it sends the company and year on every request, so a session-based selection can't drift.
klaai companies list
klaai companies use co_01 # remembered in config
klaai reports trial-balance --fy 2025
klaai invoices list --company co_02Commands
klaai dashboard headline numbers
klaai companies list|use <id>
klaai accounts list [--group Cash] chart of accounts with balances
klaai accounts subtypes the account types you can create
klaai accounts create --code 1050 --name "Cash — USD" --type cash_chequing
klaai accounts ledger <accountId> transactions + running balance
klaai customers list
klaai customers create --name "Acme Ltd" --email [email protected] --industry Technology
klaai vendors list
klaai vendors create --name "Adobe" --category Software
klaai invoices list
klaai invoices show <invoiceId>
klaai invoices create --customer <id> --line "Work|acc_4000|1500" --tax 195 --terms net_30
klaai invoices pay <invoiceId> --amount 1695 --account acc_1000 --method e-transfer
klaai receipts list
klaai receipts create --description "AWS" --amount 200 --tax 26 \
--category acc_5000 --paid-from acc_1000 --vendor <id>
klaai receipts create --description "To savings" --amount 2500 --from acc_1000 --to acc_1010
klaai receipts approve <receiptId>
klaai inbox list
klaai inbox process <emailId> --description "Bell — July" --amount 92.50 \
--tax 12.03 --category acc_5000 --paid-from acc_1000
klaai journal list
klaai journal create --memo "Bank interest" \
--posting "acc_1000|12.40|0" --posting "acc_4000|0|12.40"
klaai reports balance-sheet|income-statement|cash-flow|trial-balance
klaai reports gst-hst [--from 2026-07-01 --to 2026-09-30]
klaai reports ar-aging|ap-aging
klaai config set-url <url>
klaai config show
klaai logout forget credentials, keep the server URL
klaai revoke forget everything, URL includedRepeatable arguments
Invoice lines and journal postings are pipe-delimited and repeatable:
--line "description|account_id|amount"
--posting "account_id|debit|credit"--json
Every command takes --json and prints the raw API response — no colour, no
truncation, stable shapes. This is the mode to use from scripts and from Claude:
klaai invoices list --json | jq '.[] | select(.balance > 0) | .number'
klaai customers create --name "Acme" --jsonNotes
- Money in, money out: an invoice is only paid when a payment is recorded
(
klaai invoices pay). Setting a status alone doesn't move cash. - Balancing:
journal createis rejected server-side if debits ≠ credits. - Locked years: writes to a closed fiscal year are refused; reads are fine.
- Attribution: pass
--by claudeonreceipts create/inbox processso the web app's review queue shows who recorded it.
