jaz-clio 5.54.0 → 5.55.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  <p align="center"><b>Jaz accounting on the command line, and inside any AI agent.</b></p>
11
11
 
12
- 369 tools · 71 command groups · 7 skills · 13 calculators · 12 close playbooks · 159 field-tested API rules.
12
+ 369 tools · 72 command groups · 7 skills · 13 calculators · 12 close playbooks · 159 field-tested API rules.
13
13
 
14
14
  ```bash
15
15
  npm install -g jaz-clio
@@ -50,7 +50,7 @@ clio magic create --file receipt.pdf # AI extracts, drafts the
50
50
  clio invoices search --query 'status:unpaid AND $500+' # structured per-entity search
51
51
  ```
52
52
 
53
- 71 command groups, 16 report types, 13 calculators, 12 job playbooks. Every command takes `--json`. Run `clio --help` for the full list.
53
+ 72 command groups, 16 report types, 13 calculators, 12 job playbooks. Every command takes `--json`. Run `clio --help` for the full list.
54
54
 
55
55
  ### Foreign currency
56
56
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-api
3
- version: 5.54.0
3
+ version: 5.55.1
4
4
  description: >-
5
5
  Use this skill whenever you call, debug, or review code that touches the Jaz
6
6
  REST API. Covers field names, response shapes, 159 production gotchas, error
@@ -174,7 +174,7 @@ The rest of this skill — field names, gotchas, error catalog, dependency order
174
174
  46. **Known API bugs (500s)**: capsules POST (upstream returns nil), catalogs POST, inventory balances by status GET (`/inventory-balances/:status`, missing `c.Bind`). **Contact groups PUT and custom fields PUT are NO LONGER on this list** — both were re-probed live 2026-09-02 and returned 200 and applied the change. Do not route around them.
175
175
  47. **Non-existent endpoints**: `POST /inventory/adjustments` (and `/inventory-adjustments`, `/inventory-items/:id/adjustments`, `/items/:id/inventory-adjustments` — no stock-adjustment write path exists at any spelling), `GET /payments` (list), and `POST /payments/search` return 404 — these endpoints are not implemented. For payments, per-payment CRUD is `GET/PUT/DELETE /payments/:resourceId` and there ARE two payment-scoped searches — see Rule 64. `POST /deposits` also 404s, but for a different reason — see Rule 47a; do not read it as a missing feature.
176
176
  47a. **Deposits are not an entity — the 404 on `/deposits` is by design.** A deposit is a **flag on a Chart of Accounts account**, not a document: the account carries `depositContactType` = `CUSTOMER` (advance received, a liability) or `SUPPLIER` (advance paid, an asset). Once flagged, a deposit movement is an **ordinary transaction against that account** — top up with `POST /journals` / `POST /cash-in-entries` / `POST /cash-out-entries` (one leg on the flagged account), draw down with `POST /invoices/:id/payments` or `POST /bills/:id/payments` passing `accountResourceId` = the flagged account **and `paymentMethod` set to something other than BANK_TRANSFER / CASH / CHEQUE** (use `OTHER`) — those three force a bank/cash account and 422 here, see Rule 80, read with `POST /cashflow-transactions/search`. **Flagging the account is a web-app action**: `depositContactType` is on no chart-of-accounts request or response model here, and the platform-backend mutation that sets it (`configureDepositAccounts`) is not proxied — so `POST /chart-of-accounts` cannot create a deposit account. Over the API you can only read and post against an account someone already flagged. Full walkthrough: `references/endpoints.md` → Deposits.
177
- 48. **Attachments — full CRUD**: **Add**: `POST /:type/:id/attachments` (multipart, `file` field, `application/pdf` or `image/*` — NOT `text/plain`). **List**: `GET /:type/:id/attachments`. **Delete**: `DELETE /:type/:id/attachments/:attachmentResourceId` (HTTP 200). CLI: `clio attachments add --file <path>` or `--url <url>`, `clio attachments list`, `clio attachments delete <attachmentResourceId>`. **Response shape is non-standard**: `{ reference, resourceId, attachments: [{fileName, fileType, fileId, attachmentResourceId}] }` — NOT `{ data: [...] }`. The attachment ID field is `attachmentResourceId` (not `resourceId`).
177
+ 48. **Attachments — full CRUD**: **Add**: `POST /:type/:id/attachments` (multipart, `file` field, `application/pdf` or `image/*` — NOT `text/plain`). **List**: `GET /:type/:id/attachments`. **Delete**: `DELETE /:type/:id/attachments/:attachmentResourceId` (HTTP 200). CLI: `clio attachments add --file <path>` or `--url <url>`, `clio attachments list`, `clio attachments delete <attachmentResourceId>`. **The list response shape depends on the entity** — measured raw 2026-09-07: `/invoices/:id/attachments` returns `{ reference, resourceId, attachments: [{fileName, fileType, fileId, attachmentResourceId}] }`, while `/bills/:id/attachments` and `/journals/:id/attachments` return the conventional `{ data: [...] }`. Both credit-note types were unmeasured (every sampled record was void — see below). `listAttachments` in `core/api/attachments.ts` reads either key, so through the CLI or a tool you get `.data` in all cases; only a raw request sees the split. The attachment ID field is `attachmentResourceId` (not `resourceId`). **A VOIDED record 404s on three of the five types.** Measured 2026-09-07: a voided invoice, customer credit note and supplier credit note each answer `404 not_found` with `"<Entity> is voided"`, while a voided bill and a voided journal return 200 and list normally. The 404 is about the record's status, not its existence — `GET /invoices/:id` on the same id works — so never read this 404 as a bad resourceId. Anything fanning out to attachments alongside other calls must treat that leg as degradable, or one voided record destroys the whole response; `get_transaction_summary` did exactly that until 5.55.1.
178
178
  49. **Currency rate direction: `rate` = functionalToSource (1 base = X foreign)** — POST `rate: 0.74` for a SGD org means 1 SGD = 0.74 USD. **If your data stores rates as "1 USD = 1.35 SGD" (sourceToFunctional), you MUST invert: `rate = 1 / 1.35 = 0.74`.** GET confirms both: `rateFunctionalToSource` (what you POSTed) and `rateSourceToFunctional` (the inverse). **You do not have to do the arithmetic**: `add_currency_rate`, `update_currency_rate` and the `currency` object on the 8 FX create tools (invoice, bill, journal, both credit notes, both cash entries, TTB) accept an optional `rateDirection` (`FUNCTIONAL_TO_SOURCE` | `SOURCE_TO_FUNCTIONAL`) — declare how your figure reads and pass it verbatim. Omitting it always means `FUNCTIONAL_TO_SOURCE`. The two families differ only in where the label is applied: the rate-table tools (plus `bulk_upsert_currency_rates`) send it on the wire and the server applies it, while the 8 FX create tools have no such field, so the client inverts and strips it there. Prefer either to inverting by hand: a wrong inversion is silent and wrong by rate². `clio calc fx-reval` REQUIRES the direction — that calculator historically assumed the opposite convention to the API.
179
179
 
180
180
  ### Search & Filter
@@ -200,7 +200,7 @@ The rest of this skill — field names, gotchas, error catalog, dependency order
200
200
  63. **Workflow search tracks all magic uploads** — `POST /magic/workflows/search` searches across BT extractions AND bank statement imports. Filter by `resourceId` (eq), `documentType` (SALE, PURCHASE, SALE_CREDIT_NOTE, PURCHASE_CREDIT_NOTE, BANK_STATEMENT), `status` (SUBMITTED, PROCESSING, COMPLETED, FAILED), `fileName` (contains), `fileType`, `createdAt` (date range). Response: paginated `MagicWorkflowItem` with `businessTransactionDetails.businessTransactionResourceId` (the draft BT ID when COMPLETED) or `bankStatementDetails` (for bank imports). Standard search sort: `{ sortBy: ["createdAt"], order: "DESC" }`.
201
201
 
202
202
  ### Cashflow & Unified Ledger
203
- 64. **Three ways to read payments — pick by scope.** `GET /payments` (list) and `POST /payments/search` do NOT exist and never did. What does exist: (a) **per-payment CRUD** — `GET/PUT/DELETE /payments/:resourceId`; (b) **payment-scoped search** — `POST /sales/payments/search` and `POST /purchases/payments/search` (added 2026-08-13), one side of the ledger each, plus `POST /batch-payments/search` for batches; (c) **cross-entity ledger** — `POST /cashflow-transactions/search`, the unified transaction ledger spanning invoices, bills, credit notes, journals, cash entries and payments. Filter it by `businessTransactionType` (e.g. `SALE`, `PURCHASE`) and `direction` (`PAYIN`, `PAYOUT`). Response dates are epoch milliseconds. **Naming trap**: the `search_payments` tool is a wrapper over `/cashflow-transactions/search`, NOT over the sales/purchases payment searches — its name is narrower than what it calls. Reach the per-side searches with a raw request; they have no tool.
203
+ 64. **Four ways to read payments — pick by scope.** `GET /payments` (list) and `POST /payments/search` do NOT exist and never did. What does exist: (a) **per-payment CRUD** — `GET/PUT/DELETE /payments/:resourceId`; (b) **payment-scoped search** — `POST /sales/payments/search` and `POST /purchases/payments/search` (added 2026-08-13), one side of the ledger each, plus `POST /batch-payments/search` for batches; (c) **cross-entity ledger** — `POST /cashflow-transactions/search`, the unified transaction ledger spanning invoices, bills, credit notes, journals, cash entries and payments. Filter it by `businessTransactionType` (e.g. `SALE`, `PURCHASE`) and `direction` (`PAYIN`, `PAYOUT`). Response dates are epoch milliseconds. **Naming trap**: the `search_payments` tool is a wrapper over `/cashflow-transactions/search`, NOT over the sales/purchases payment searches — its name is narrower than what it calls. Reach the per-side searches with a raw request; they have no tool. (d) **Per-document settlements** — `GET /invoices/:id/payments` and `GET /bills/:id/payments`, and for credit notes `GET /customer-credit-notes/:id/refunds` / `GET /supplier-credit-notes/:id/refunds` (the domain distinguishes a refund from a payment; a journal has neither). This is the right call for **one known document's own settlements** and the one to reach for first — no filter to get wrong. All four answer `{ data: [...] }` (measured raw 2026-09-07). It is listed here because it was missing from this rule while (c) sat one line away, and `get_transaction_summary` consequently filtered the ledger by `businessTransactionResourceId` — a field `TransactionsFilter` does not declare — for its entire life, 400ing on every call behind a silent catch.
204
204
  65. **Contacts search uses `name`** — NOT `billingName`. The filter field for searching contacts by name is `name` (maps to `billingName` internally). Sort field is also `name`. Using `billingName` in a search filter returns zero results.
205
205
 
206
206
  ### Response Shape Gotchas
@@ -526,7 +526,7 @@ Supports `--json` for structured output. 186 articles across 20 sections. Automa
526
526
 
527
527
  ## Dashboard Deep Links (navigation tools)
528
528
 
529
- When the user wants to OPEN, SEE, or SHARE something in the Jaz dashboard ("open this invoice", "take me to the P&L"), hand them a real URL via ONE agent (MCP) tool — deliberately no CLI command: `navigate`. Called with no `destination` it discovers destination keys (filter by `query`/`resource`/`kind`; keys are named by product area, not task wording — on zero matches retry broader: "billing", not "card"); called with a `destination` it turns the key into `{ url, kind, label }`. Screens are dotted route paths (`reports.profit-and-loss`); record modals are `<resource>.modal.<type>` (`sales.modal.view-sale`). Record-specific modals (view/edit/duplicate one record) REQUIRE `resourceId` — the same Jaz resourceId from the search/get that found the record; screens and create/"new" modals take none (a resourceId on a screen is rejected). NEVER write a dashboard URL by hand and NEVER guess a destination key — routes are not guessable, and a wrong link is worse than no link; if `navigate` errors, follow its hint (near-matches + discovery pointer) and say the link could not be built rather than improvising one. The org query param is appended automatically when the surface knows the acting org; API-key surfaces open in the user's current org on the app.jaz.ai host. Examples: "open invoice INV-042" → `search_invoices` → `navigate("sales.modal.view-sale", resourceId)`; "take me to the P&L" → `navigate("reports.profit-and-loss")`; "where do I manage users?" → `navigate(query: "user")` → `navigate("settings.modal.user_management")`. (The pre-merge tool names `find_dashboard_destinations` / `get_dashboard_url` still resolve as aliases.)
529
+ When the user wants to OPEN, SEE, or SHARE something in the Jaz dashboard ("open this invoice", "take me to the P&L"), hand them a real URL via `navigate` — one operation, on both surfaces (`clio navigate` on the CLI, offline). Called with no `destination` it discovers destination keys (filter by `query`/`resource`/`kind`; keys are named by product area, not task wording — on zero matches retry broader: "billing", not "card"); called with a `destination` it turns the key into `{ url, kind, label }`. Screens are dotted route paths (`reports.profit-and-loss`); record modals are `<resource>.modal.<type>` (`sales.modal.view-sale`). Record-specific modals (view/edit/duplicate one record) REQUIRE `resourceId` — the same Jaz resourceId from the search/get that found the record; screens and create/"new" modals take none (a resourceId on a screen is rejected). NEVER write a dashboard URL by hand and NEVER guess a destination key — routes are not guessable, and a wrong link is worse than no link; if `navigate` errors, follow its hint (near-matches + discovery pointer) and say the link could not be built rather than improvising one. The org query param is appended automatically when the surface knows the acting org; API-key surfaces open in the user's current org on the app.jaz.ai host. Examples: "open invoice INV-042" → `search_invoices` → `navigate("sales.modal.view-sale", resourceId)`; "take me to the P&L" → `navigate("reports.profit-and-loss")`; "where do I manage users?" → `navigate(query: "user")` → `navigate("settings.modal.user_management")`. (The pre-merge tool names `find_dashboard_destinations` / `get_dashboard_url` still resolve as aliases.)
530
530
 
531
531
  ## Recommended Client Patterns
532
532
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-cli
3
- version: 5.54.0
3
+ version: 5.55.1
4
4
  description: >-
5
5
  Use this skill when running Clio CLI commands, building shell scripts with
6
6
  Clio, debugging auth issues, understanding --json output, paginating results,
@@ -8,7 +8,7 @@ description: >-
8
8
  precedence, output formats, entity resolution, and common workflow patterns.
9
9
  Also use when the user asks how to use clio, what commands are available, or
10
10
  how to automate accounting tasks from the command line. Covers all
11
- 71 command groups and 369 tools, including employee-expense claims.
11
+ 72 command groups and 369 tools, including employee-expense claims.
12
12
  license: MIT
13
13
  compatibility: Requires Node.js >= 18.0.0. Install via npm install -g jaz-clio.
14
14
  ---
@@ -17,7 +17,7 @@ compatibility: Requires Node.js >= 18.0.0. Install via npm install -g jaz-clio.
17
17
 
18
18
  > **Audience note:** for power users and CI/automation. Load this skill only when you're scripting from a terminal, building shell pipelines, or debugging from `clio --json` output. For day-to-day accounting inside Claude Desktop / Cowork, the MCP tools cover the common flows without dropping to the CLI.
19
19
 
20
- You are working with **Clio** (`jaz-clio`) — the CLI for the Jaz accounting platform. 71 command groups, 13 calculators, 12 job blueprints, 369 tools. Also fully compatible with Juan Accounting (same API, same endpoints).
20
+ You are working with **Clio** (`jaz-clio`) — the CLI for the Jaz accounting platform. 72 command groups, 13 calculators, 12 job blueprints, 369 tools. Also fully compatible with Juan Accounting (same API, same endpoints).
21
21
 
22
22
  ## When to Use This Skill
23
23
 
@@ -291,9 +291,19 @@ Offline commands (no auth needed): `calc`, `jobs` (blueprints only), `capsule-tr
291
291
 
292
292
  Everything else requires authentication (API key).
293
293
 
294
- ## Dashboard Deep Links (no CLI command — by design)
294
+ ## Dashboard Deep Links
295
295
 
296
- The navigation tool (`navigate` — no destination to discover keys, a destination to build the deep link) builds dashboard URLs for the user ("open this invoice", "take me to the P&L"). It is an agent/MCP tool only — this particular tool has no CLI twin — plenty of read-only tools do (`clio purchase-items`, `clio modules`, `clio report-templates`). Never hand-construct a dashboard URL in a script; if you need a link, call the MCP tool. Full usage rules live in the jaz-api skill under "Dashboard Deep Links".
296
+ `clio navigate` (alias `nav`) builds dashboard URLs for the user ("open this invoice", "take me to the P&L"). Offline — no API key, no request.
297
+
298
+ ```
299
+ clio navigate --query "profit" # discover the key
300
+ clio navigate reports.profit-and-loss # build the link
301
+ clio navigate sales.modal.view-sale --resource-id <id>
302
+ ```
303
+
304
+ Only the URL goes to stdout, so `clio nav <key> | pbcopy` copies a link and nothing else. **Never hand-construct a dashboard URL and never guess a key** — routes are not guessable and a wrong link is worse than no link. An unknown key comes back with near-matches; follow them rather than improvising.
305
+
306
+ The same operation is `navigate` on the MCP surface. Full usage rules live in the jaz-api skill under "Dashboard Deep Links"; the flag reference is in `references/command-catalog.md`.
297
307
 
298
308
  ## Error Handling
299
309
 
@@ -1,6 +1,6 @@
1
1
  # Clio Command Catalog
2
2
 
3
- Complete reference for all 71 command groups. Organized by domain.
3
+ Complete reference for all 72 command groups. Organized by domain.
4
4
 
5
5
  ---
6
6
 
@@ -399,6 +399,24 @@ What the organization can be billed for. No create/update/delete upstream; maint
399
399
 
400
400
  No free-text `--query`: the endpoint rejects it (`The query field is not supported for this entity`). Filters here are **plain strings, not expression objects** — `PurchaseItemFilter` declares them as bare `string`, so there is no `contains`. `purchaseResourceId` and `resourceId` also exist upstream and are reachable via `--filter`.
401
401
 
402
+ ### `clio navigate` (alias: `nav`) — Dashboard deep links (offline, 1 tool)
403
+ ```
404
+ clio navigate # discover: all destinations, capped
405
+ clio navigate --query invoice --kind modal # discover: narrow the search
406
+ clio navigate reports.profit-and-loss # build: a screen link
407
+ clio navigate sales.modal.view-sale --resource-id <id> # build: focus one record
408
+ clio navigate reports.profit-and-loss --org-id <orgResourceId>
409
+ ```
410
+ **Offline** — no API key, no request. The route manifest is generated in the dashboard and committed here.
411
+
412
+ Omit the destination to SEARCH; give one to BUILD a link. Discovery caps its output and reports the true total, so narrow with `--query`, `--resource` or `--kind` when it says it truncated.
413
+
414
+ The `--query` search bridges accounting vocabulary to dashboard vocabulary: `invoice` finds the `sale` destinations, `bill` finds `purchase`, `credit note` finds `credit`. Without that, the word an accountant would type returns nothing.
415
+
416
+ `--resource-id` attaches a record and is valid only on a record-modal destination (`<resource>.modal.view-*`); a screen rejects it rather than silently dropping it. An unknown key comes back with near-matches.
417
+
418
+ The URL is the only thing on stdout — the label goes to stderr — so `clio nav <key> | pbcopy` copies a link and nothing else. Links carry no `&org=` unless you pass `--org-id`; without it the link opens in whichever organization the reader is already viewing.
419
+
402
420
  ### `clio modules` — Which features are enabled for the organization (read-only, 2 tools)
403
421
  Provisioned upstream; no create/update/delete exists.
404
422
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-conversion
3
- version: 5.54.0
3
+ version: 5.55.1
4
4
  description: >-
5
5
  Use this skill when migrating accounting data into Jaz — importing from Xero,
6
6
  QuickBooks, Sage, MYOB, or Excel exports. Covers the full conversion pipeline:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-kit
3
- version: 5.54.0
3
+ version: 5.55.1
4
4
  description: >-
5
5
  Use this skill when an accountant, bookkeeper, or owner is running real books
6
6
  in Jaz across one or more organizations from the terminal — setting up a
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-pseudo-sql
3
- version: 5.54.0
3
+ version: 5.55.1
4
4
  description: >-
5
5
  Use this skill when answering ad-hoc data questions that aren't covered by
6
6
  download_export (canonical reports — anomaly, audit, aging, P&L, BS, GL,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-jobs
3
- version: 5.54.0
3
+ version: 5.55.1
4
4
  description: >-
5
5
  Use this skill for recurring accounting workflows — month/quarter/year-end
6
6
  close, bank reconciliation, GST/VAT filing, payment runs, credit control,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-recipes
3
- version: 5.54.0
3
+ version: 5.55.1
4
4
  description: >-
5
5
  Use this skill when modeling complex multi-step accounting transactions —
6
6
  anything that spans multiple periods, involves changing amounts, or requires