jaz-clio 4.23.0 → 4.24.0
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 +134 -27
- package/assets/skills/api/SKILL.md +1 -1
- package/assets/skills/conversion/SKILL.md +1 -1
- package/assets/skills/jobs/SKILL.md +1 -1
- package/assets/skills/transaction-recipes/SKILL.md +1 -1
- package/dist/commands/accounts.js +15 -29
- package/dist/commands/api-action.js +7 -5
- package/dist/commands/bank-rules.js +15 -22
- package/dist/commands/bank.js +6 -0
- package/dist/commands/bills.js +14 -34
- package/dist/commands/capsules.js +18 -29
- package/dist/commands/cash-entry.js +14 -30
- package/dist/commands/cash-transfer.js +15 -30
- package/dist/commands/cashflow.js +14 -22
- package/dist/commands/contact-groups.js +13 -22
- package/dist/commands/contacts.js +17 -38
- package/dist/commands/custom-fields.js +15 -31
- package/dist/commands/customer-credit-notes.js +14 -33
- package/dist/commands/fixed-assets.js +21 -24
- package/dist/commands/format-helpers.js +23 -0
- package/dist/commands/inventory.js +11 -13
- package/dist/commands/invoices.js +14 -34
- package/dist/commands/items.js +17 -33
- package/dist/commands/journals.js +14 -33
- package/dist/commands/output.js +120 -0
- package/dist/commands/pagination.js +2 -1
- package/dist/commands/payments.js +15 -36
- package/dist/commands/subscriptions.js +24 -29
- package/dist/commands/supplier-credit-notes.js +14 -33
- package/dist/commands/table-formatter.js +84 -0
- package/dist/commands/tags.js +14 -29
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -3,23 +3,40 @@
|
|
|
3
3
|
<p align="center">
|
|
4
4
|
<a href="https://www.npmjs.com/package/jaz-clio"><img src="https://img.shields.io/npm/v/jaz-clio?style=for-the-badge&logo=npm" alt="npm"></a>
|
|
5
5
|
<a href="https://www.npmjs.com/package/jaz-clio"><img src="https://img.shields.io/npm/dm/jaz-clio?style=for-the-badge&label=downloads" alt="npm downloads"></a>
|
|
6
|
+
<img src="https://img.shields.io/badge/tools-203-blue?style=for-the-badge" alt="203 Tools">
|
|
6
7
|
<img src="https://img.shields.io/badge/calculators-13-red?style=for-the-badge" alt="13 Calculators">
|
|
7
8
|
<img src="https://img.shields.io/badge/jobs-12-teal?style=for-the-badge" alt="12 Jobs">
|
|
8
9
|
<a href="https://github.com/teamtinvio/jaz-ai/blob/main/LICENSE"><img src="https://img.shields.io/github/license/teamtinvio/jaz-ai?style=for-the-badge&color=green" alt="License"></a>
|
|
9
10
|
</p>
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
**Complete agent stack for all of Jaz, built for AI agents and accountants.**
|
|
13
|
+
Create invoices, record bills, manage contacts, run financial calculators, execute accounting jobs, and install AI agent skills — all from your terminal.
|
|
12
14
|
|
|
13
15
|
> Also fully compatible with [Juan Accounting](https://juan.ac).
|
|
14
16
|
|
|
15
|
-
##
|
|
17
|
+
## Contents
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
- [Quickstart](#quickstart)
|
|
20
|
+
- [Install](#install)
|
|
21
|
+
- [Authenticate](#authenticate)
|
|
22
|
+
- [Commands](#commands)
|
|
23
|
+
- [MCP Server](#mcp-server)
|
|
24
|
+
- [Install AI Skills](#install-ai-skills)
|
|
25
|
+
- [Privacy & Security](#privacy--security)
|
|
26
|
+
- [Support](#support)
|
|
18
27
|
|
|
19
|
-
|
|
28
|
+
## Quickstart
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install -g jaz-clio
|
|
32
|
+
clio auth add <your-api-key> # Get key from Settings > API in Jaz app
|
|
33
|
+
clio invoices list # You're in
|
|
34
|
+
```
|
|
20
35
|
|
|
21
36
|
## Install
|
|
22
37
|
|
|
38
|
+
**Node.js 18+** required. If `node --version` works, you're set. Otherwise: [nodejs.org](https://nodejs.org) (LTS).
|
|
39
|
+
|
|
23
40
|
```bash
|
|
24
41
|
npm install -g jaz-clio
|
|
25
42
|
```
|
|
@@ -27,18 +44,43 @@ npm install -g jaz-clio
|
|
|
27
44
|
## Authenticate
|
|
28
45
|
|
|
29
46
|
```bash
|
|
30
|
-
# Add your Jaz API key
|
|
31
|
-
clio auth
|
|
47
|
+
clio auth add <your-api-key> # Add your Jaz API key
|
|
48
|
+
clio auth whoami # Verify it works
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
| I have... | Use |
|
|
52
|
+
|-----------|-----|
|
|
53
|
+
| API key from Jaz app | `clio auth add <key>` |
|
|
54
|
+
| Environment variable | `export JAZ_API_KEY=jk-...` |
|
|
55
|
+
| Multiple orgs | `clio auth add <key>` + `clio auth switch <label>` |
|
|
56
|
+
|
|
57
|
+
### Auth Precedence
|
|
58
|
+
|
|
59
|
+
When multiple credentials are available, Clio resolves them in this order:
|
|
60
|
+
|
|
61
|
+
| Priority | Source | Set via |
|
|
62
|
+
|----------|--------|---------|
|
|
63
|
+
| 1 | `--api-key` flag | Explicit per-command |
|
|
64
|
+
| 2 | `JAZ_API_KEY` env var | Shell or `.env` |
|
|
65
|
+
| 3 | `--org` flag / `JAZ_ORG` env | Named profile lookup |
|
|
66
|
+
| 4 | Active profile | `clio auth switch` |
|
|
32
67
|
|
|
33
|
-
|
|
34
|
-
clio auth whoami
|
|
68
|
+
> **Warning:** If `JAZ_API_KEY` is set in your shell, it overrides `--org` and the active profile. Unset it (`unset JAZ_API_KEY`) before switching tenants with `clio auth switch`, or use per-command `--api-key` instead.
|
|
35
69
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
70
|
+
<details>
|
|
71
|
+
<summary>All auth subcommands</summary>
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
clio auth add <key> # Add API key (validates against API)
|
|
75
|
+
clio auth list # List all saved profiles
|
|
76
|
+
clio auth switch <label> # Switch active org
|
|
77
|
+
clio auth remove <label> # Remove a profile
|
|
78
|
+
clio auth whoami # Show current org
|
|
79
|
+
clio auth clear # Remove all profiles
|
|
40
80
|
```
|
|
41
81
|
|
|
82
|
+
</details>
|
|
83
|
+
|
|
42
84
|
## Commands
|
|
43
85
|
|
|
44
86
|
### Transactions
|
|
@@ -55,6 +97,7 @@ clio journals list # List journal entries
|
|
|
55
97
|
clio cash-in list # List cash-in entries
|
|
56
98
|
clio cash-out list # List cash-out entries
|
|
57
99
|
clio cash-transfer list # List cash transfers
|
|
100
|
+
clio capsules list # List capsules (transaction groups)
|
|
58
101
|
```
|
|
59
102
|
|
|
60
103
|
### Contacts, Accounts & Items
|
|
@@ -65,11 +108,46 @@ clio contacts create --name "ACME Ltd" # Create a contact
|
|
|
65
108
|
clio accounts list # Chart of accounts
|
|
66
109
|
clio items list # Products and services
|
|
67
110
|
clio tags list # Tracking tags
|
|
111
|
+
clio contact-groups list # Contact groups
|
|
112
|
+
clio custom-fields list # Custom field definitions
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Bank & Reconciliation
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
clio bank import --file statement.csv # Import bank statement
|
|
119
|
+
clio bank accounts # List bank accounts
|
|
120
|
+
clio bank records # List bank records
|
|
121
|
+
clio bank add-records # Create bank records (JSON)
|
|
122
|
+
clio bank auto-recon # Auto-reconciliation
|
|
123
|
+
clio bank-rules list # List auto-tagging rules
|
|
124
|
+
clio bank-rules create # Create auto-tagging rule
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Fixed Assets
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
clio fixed-assets list # List fixed assets (alias: clio fa list)
|
|
131
|
+
clio fixed-assets get <id> # Get fixed asset details
|
|
132
|
+
clio fixed-assets create # Register a new asset
|
|
133
|
+
clio fixed-assets sell <id> # Record asset sale
|
|
134
|
+
clio fixed-assets discard <id> # Discard/scrap an asset
|
|
135
|
+
clio fixed-assets transfer <id> # Transfer between accounts
|
|
136
|
+
clio fixed-assets undo-disposal <id> # Reverse a disposal
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Subscriptions
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
clio subscriptions list # List recurring subscriptions (alias: clio subs)
|
|
143
|
+
clio subscriptions create # Create a subscription
|
|
144
|
+
clio subscriptions cancel <id> # Cancel a subscription
|
|
145
|
+
clio subscriptions search-scheduled # Search scheduled transactions
|
|
68
146
|
```
|
|
69
147
|
|
|
70
148
|
### Financial Calculators
|
|
71
149
|
|
|
72
|
-
|
|
150
|
+
13 IFRS-compliant calculators that output structured blueprints with journal entries, workings, and execution plans.
|
|
73
151
|
|
|
74
152
|
```bash
|
|
75
153
|
clio calc loan --principal 100000 --rate 6 --term 60 --json
|
|
@@ -80,8 +158,23 @@ clio calc provision --amount 100000 --rate 4 --periods 24 --json
|
|
|
80
158
|
clio calc fx-reval --account "USD Cash" --balance 10000 --old-rate 1.35 --new-rate 1.34 --json
|
|
81
159
|
clio calc fixed-deposit --principal 100000 --rate 3.5 --term 12 --json
|
|
82
160
|
clio calc disposal --cost 50000 --accum-dep 30000 --proceeds 15000 --json
|
|
83
|
-
clio calc
|
|
84
|
-
clio calc
|
|
161
|
+
clio calc prepaid-expense --amount 12000 --periods 12 --start 2025-01-01 --json
|
|
162
|
+
clio calc deferred-revenue --amount 24000 --periods 12 --start 2025-01-01 --json
|
|
163
|
+
clio calc accrued-expense --amount 5000 --periods 3 --json
|
|
164
|
+
clio calc leave-accrual --employees 50 --avg-daily-rate 200 --avg-days 15 --json
|
|
165
|
+
clio calc dividend --amount 100000 --json
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Transaction Recipes (Capsule Transactions)
|
|
169
|
+
|
|
170
|
+
13 recipe subcommands that compute, plan, and optionally execute multi-step transactions from calculator output.
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
clio capsule-transaction loan --principal 100000 --rate 6 --term 60 # alias: clio ct loan
|
|
174
|
+
clio ct lease --payment 5000 --term 36 --rate 5
|
|
175
|
+
clio ct depreciation --cost 50000 --salvage 5000 --life 5
|
|
176
|
+
clio ct prepaid-expense --amount 12000 --periods 12 --start 2025-01-01
|
|
177
|
+
clio ct fx-reval --account "USD Cash" --balance 10000 --old-rate 1.35 --new-rate 1.34
|
|
85
178
|
```
|
|
86
179
|
|
|
87
180
|
### Accounting Jobs
|
|
@@ -103,23 +196,37 @@ clio jobs fa-review # Fixed asset re
|
|
|
103
196
|
clio jobs statutory-filing sg-cs --ya 2026 --revenue 500000 --profit 120000 --json # SG Form C-S
|
|
104
197
|
```
|
|
105
198
|
|
|
106
|
-
###
|
|
199
|
+
### Reports
|
|
200
|
+
|
|
201
|
+
16 report types:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
clio reports generate <type> # Generate a report
|
|
205
|
+
clio reports pdf <type> # Download report as PDF
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Types: `trial-balance`, `balance-sheet`, `profit-loss`, `cashflow`, `aged-ar`, `aged-ap`, `cash-balance`, `general-ledger`, `vat-ledger`, `equity-movement`, `bank-balance-summary`, `bank-recon-summary`, `bank-recon-details`, `fa-summary`, `fa-recon-summary`, `ar-report`.
|
|
209
|
+
|
|
210
|
+
### Other Commands
|
|
107
211
|
|
|
108
212
|
```bash
|
|
109
213
|
clio org info # Current org details
|
|
214
|
+
clio org-users list # Organization members
|
|
110
215
|
clio currencies list # Enabled currencies
|
|
111
216
|
clio currency-rates list # Exchange rates
|
|
112
217
|
clio payments search # Search payments
|
|
113
|
-
clio
|
|
114
|
-
clio
|
|
115
|
-
clio
|
|
116
|
-
clio
|
|
117
|
-
clio
|
|
118
|
-
clio
|
|
119
|
-
clio
|
|
120
|
-
clio
|
|
121
|
-
clio
|
|
122
|
-
clio
|
|
218
|
+
clio tax-profiles list # Tax profiles
|
|
219
|
+
clio cashflow search # Search cashflow transactions
|
|
220
|
+
clio schedulers list-invoices # Scheduled (recurring) invoices
|
|
221
|
+
clio exports download --type INVOICES # Download data export
|
|
222
|
+
clio attachments list <id> # List attachments on a transaction
|
|
223
|
+
clio bookmarks list # Saved bookmarks
|
|
224
|
+
clio inventory items # Inventory items
|
|
225
|
+
clio inventory balance <item-id> # Inventory balance for an item
|
|
226
|
+
clio search "query" # Universal cross-entity search
|
|
227
|
+
clio magic create --file receipt.pdf # AI-extract from attachment
|
|
228
|
+
clio kb "topic" # Search help center (alias: clio hc)
|
|
229
|
+
clio context # Generate agent context summary
|
|
123
230
|
clio versions # Show version info
|
|
124
231
|
clio update # Update to latest
|
|
125
232
|
```
|
|
@@ -128,7 +235,7 @@ Every command supports `--json` for structured output — ideal for piping to ot
|
|
|
128
235
|
|
|
129
236
|
## MCP Server
|
|
130
237
|
|
|
131
|
-
Expose all 203 CLI tools to AI
|
|
238
|
+
Expose all 203 CLI tools to AI coding and coworking agents via the Model Context Protocol (MCP). The server runs locally on your machine — no cloud, no ports. API calls go directly from your machine to the Jaz API.
|
|
132
239
|
|
|
133
240
|
**Claude Code:**
|
|
134
241
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jaz-api
|
|
3
|
-
version: 4.
|
|
3
|
+
version: 4.24.0
|
|
4
4
|
description: Complete reference for the Jaz REST API — the accounting platform backend. Use this skill whenever building, modifying, debugging, or extending any code that calls the API — including API clients, integrations, data seeding, test data, or new endpoint work. Contains every field name, response shape, error, gotcha, and edge case discovered through live production testing.
|
|
5
5
|
license: MIT
|
|
6
6
|
compatibility: Requires Jaz API key (x-jk-api-key header). Works with Claude Code, Google Antigravity, OpenAI Codex, GitHub Copilot, Cursor, and any agent that reads markdown.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jaz-conversion
|
|
3
|
-
version: 4.
|
|
3
|
+
version: 4.24.0
|
|
4
4
|
description: Accounting data conversion skill — migrates customer data from Xero, QuickBooks, Sage, MYOB, and Excel exports to Jaz. Covers config, quick, and full conversion workflows, Excel parsing, CoA/contact/tax/items mapping, clearing accounts, TTB, and TB verification.
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jaz-jobs
|
|
3
|
-
version: 4.
|
|
3
|
+
version: 4.24.0
|
|
4
4
|
description: 12 accounting jobs for SMB bookkeepers and accountants — month-end, quarter-end, and year-end close playbooks plus 9 ad-hoc operational jobs (bank recon, document collection, GST/VAT filing, payment runs, credit control, supplier recon, audit prep, fixed asset review, statutory filing). Jobs can have paired tools as nested subcommands (e.g., `clio jobs bank-recon match`, `clio jobs document-collection ingest`, `clio jobs statutory-filing sg-cs`). Paired with an interactive CLI blueprint generator (clio jobs).
|
|
5
5
|
license: MIT
|
|
6
6
|
compatibility: Works with Claude Code, Claude Cowork, Claude.ai, and any agent that reads markdown. For API payloads, load the jaz-api skill. For individual transaction patterns, load the jaz-recipes skill.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jaz-recipes
|
|
3
|
-
version: 4.
|
|
3
|
+
version: 4.24.0
|
|
4
4
|
description: 16 IFRS-compliant recipes for complex multi-step accounting in Jaz — prepaid amortization, deferred revenue, loan schedules, IFRS 16 leases, hire purchase, fixed deposits, asset disposal, FX revaluation, ECL provisioning, IAS 37 provisions, dividends, intercompany, and capital WIP. Each recipe includes journal entries, capsule structure, and verification steps. Paired with 13 financial calculators that produce execution-ready blueprints with workings.
|
|
5
5
|
license: MIT
|
|
6
6
|
compatibility: Works with Claude Code, Claude Cowork, Claude.ai, and any agent that reads markdown. For API payloads, load the jaz-api skill alongside this one.
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { listAccounts, searchAccounts, createAccount, deleteAccount } from '../core/api/chart-of-accounts.js';
|
|
3
3
|
import { apiAction } from './api-action.js';
|
|
4
|
+
import { outputList } from './output.js';
|
|
4
5
|
import { parsePositiveInt, parseNonNegativeInt, readBodyInput, requireFields } from './parsers.js';
|
|
5
|
-
import { paginatedFetch
|
|
6
|
+
import { paginatedFetch } from './pagination.js';
|
|
7
|
+
import { formatId } from './format-helpers.js';
|
|
8
|
+
const ACCOUNTS_COLUMNS = [
|
|
9
|
+
{ key: 'resourceId', header: 'ID', format: formatId },
|
|
10
|
+
{ key: 'code', header: 'Code' },
|
|
11
|
+
{ key: 'name', header: 'Name' },
|
|
12
|
+
{ key: 'accountType', header: 'Type' },
|
|
13
|
+
];
|
|
6
14
|
export function registerAccountsCommand(program) {
|
|
7
15
|
const accounts = program
|
|
8
16
|
.command('accounts')
|
|
@@ -16,21 +24,11 @@ export function registerAccountsCommand(program) {
|
|
|
16
24
|
.option('--all', 'Fetch all pages')
|
|
17
25
|
.option('--max-rows <n>', 'Max rows for --all (default 10000)', parsePositiveInt)
|
|
18
26
|
.option('--api-key <key>', 'API key (overrides stored/env)')
|
|
27
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
19
28
|
.option('--json', 'Output as JSON')
|
|
20
29
|
.action(apiAction(async (client, opts) => {
|
|
21
30
|
const result = await paginatedFetch(opts, (p) => listAccounts(client, p), { label: 'Fetching accounts' });
|
|
22
|
-
|
|
23
|
-
console.log(paginatedJson(result, opts));
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
console.log(chalk.bold(`Accounts (${result.data.length} of ${result.totalElements}):\n`));
|
|
27
|
-
const { items, overflow } = displaySlice(result.data);
|
|
28
|
-
for (const a of items) {
|
|
29
|
-
console.log(` ${chalk.cyan(a.resourceId)} ${a.code ?? ''} ${a.name} ${chalk.dim(a.accountType)}`);
|
|
30
|
-
}
|
|
31
|
-
if (overflow > 0)
|
|
32
|
-
console.log(chalk.dim(` ... and ${overflow.toLocaleString()} more (use --json for full output)`));
|
|
33
|
-
}
|
|
31
|
+
outputList(result, ACCOUNTS_COLUMNS, opts, 'Accounts'); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
34
32
|
}));
|
|
35
33
|
// ── clio accounts search ────────────────────────────────────────
|
|
36
34
|
accounts
|
|
@@ -43,27 +41,13 @@ export function registerAccountsCommand(program) {
|
|
|
43
41
|
.option('--all', 'Fetch all pages')
|
|
44
42
|
.option('--max-rows <n>', 'Max rows for --all (default 10000)', parsePositiveInt)
|
|
45
43
|
.option('--api-key <key>', 'API key (overrides stored/env)')
|
|
44
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
46
45
|
.option('--json', 'Output as JSON')
|
|
47
46
|
.action((query, opts) => apiAction(async (client) => {
|
|
48
47
|
const filter = { or: { name: { contains: query }, code: { contains: query } } };
|
|
49
48
|
const sort = { sortBy: [opts.sort ?? 'code'], order: (opts.order ?? 'ASC') };
|
|
50
49
|
const result = await paginatedFetch(opts, ({ limit, offset }) => searchAccounts(client, { filter, limit, offset, sort }), { label: 'Searching accounts', defaultLimit: 20 });
|
|
51
|
-
|
|
52
|
-
console.log(paginatedJson(result, opts));
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
if (result.data.length === 0) {
|
|
56
|
-
console.log('No accounts found.');
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
console.log(chalk.bold(`Found ${result.data.length} account(s):\n`));
|
|
60
|
-
const { items, overflow } = displaySlice(result.data);
|
|
61
|
-
for (const a of items) {
|
|
62
|
-
console.log(` ${chalk.cyan(a.resourceId)} ${a.code ?? ''} ${a.name} ${chalk.dim(a.accountType)}`);
|
|
63
|
-
}
|
|
64
|
-
if (overflow > 0)
|
|
65
|
-
console.log(chalk.dim(` ... and ${overflow.toLocaleString()} more (use --json for full output)`));
|
|
66
|
-
}
|
|
50
|
+
outputList(result, ACCOUNTS_COLUMNS, opts, 'Accounts'); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
67
51
|
})(opts));
|
|
68
52
|
// ── clio accounts create ──────────────────────────────────────
|
|
69
53
|
accounts
|
|
@@ -76,6 +60,7 @@ export function registerAccountsCommand(program) {
|
|
|
76
60
|
.option('--status <status>', 'Account status (ACTIVE or INACTIVE)')
|
|
77
61
|
.option('--input <file>', 'Read full request body from JSON file (or pipe via stdin)')
|
|
78
62
|
.option('--api-key <key>', 'API key (overrides stored/env)')
|
|
63
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
79
64
|
.option('--json', 'Output as JSON')
|
|
80
65
|
.action(apiAction(async (client, opts) => {
|
|
81
66
|
const body = readBodyInput(opts);
|
|
@@ -113,6 +98,7 @@ export function registerAccountsCommand(program) {
|
|
|
113
98
|
.command('delete <resourceId>')
|
|
114
99
|
.description('Delete an account from the chart of accounts')
|
|
115
100
|
.option('--api-key <key>', 'API key (overrides stored/env)')
|
|
101
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
116
102
|
.option('--json', 'Output as JSON')
|
|
117
103
|
.action((resourceId, opts) => apiAction(async (client) => {
|
|
118
104
|
await deleteAccount(client, resourceId);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { JazClient, JazApiError } from '../core/api/client.js';
|
|
3
3
|
import { requireAuth, AuthError, resolvedProfileLabel, resolvedAuthSource, getProfile, listProfiles } from '../core/auth/index.js';
|
|
4
|
+
import { isMachineFormat } from './output.js';
|
|
4
5
|
/**
|
|
5
6
|
* Shared action wrapper for all online CLI commands.
|
|
6
7
|
* Handles auth resolution, client creation, org banner, and error formatting.
|
|
@@ -16,9 +17,9 @@ export function apiAction(fn) {
|
|
|
16
17
|
}
|
|
17
18
|
const auth = requireAuth(opts.apiKey);
|
|
18
19
|
const client = new JazClient(auth);
|
|
19
|
-
// Org banner — show which org we're hitting (suppressed in
|
|
20
|
+
// Org banner — show which org we're hitting (suppressed in machine formats)
|
|
20
21
|
// Visual guard: yellow warning when unpinned + multi-org, dim banner otherwise
|
|
21
|
-
if (!opts
|
|
22
|
+
if (!isMachineFormat(opts)) {
|
|
22
23
|
const label = resolvedProfileLabel();
|
|
23
24
|
if (label) {
|
|
24
25
|
const entry = getProfile(label);
|
|
@@ -46,22 +47,23 @@ export function apiAction(fn) {
|
|
|
46
47
|
await fn(client, opts, auth);
|
|
47
48
|
}
|
|
48
49
|
catch (err) {
|
|
50
|
+
const machine = isMachineFormat(opts);
|
|
49
51
|
if (err instanceof AuthError) {
|
|
50
|
-
if (
|
|
52
|
+
if (machine)
|
|
51
53
|
console.log(JSON.stringify({ error: { code: 'AUTH_ERROR', message: err.message } }));
|
|
52
54
|
else
|
|
53
55
|
console.error(chalk.red(`Error: ${err.message}`));
|
|
54
56
|
process.exit(3);
|
|
55
57
|
}
|
|
56
58
|
if (err instanceof JazApiError) {
|
|
57
|
-
if (
|
|
59
|
+
if (machine)
|
|
58
60
|
console.log(JSON.stringify({ error: { code: 'API_ERROR', status: err.status, message: err.message } }));
|
|
59
61
|
else
|
|
60
62
|
console.error(chalk.red(`API Error (${err.status}): ${err.message}`));
|
|
61
63
|
process.exit(2);
|
|
62
64
|
}
|
|
63
65
|
const message = err.message;
|
|
64
|
-
if (
|
|
66
|
+
if (machine)
|
|
65
67
|
console.log(JSON.stringify({ error: { code: 'UNKNOWN_ERROR', message } }));
|
|
66
68
|
else
|
|
67
69
|
console.error(chalk.red(`Error: ${message}`));
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { listBankRules, getBankRule, searchBankRules, createBankRule, updateBankRule, deleteBankRule, } from '../core/api/bank-rules.js';
|
|
3
3
|
import { apiAction } from './api-action.js';
|
|
4
|
+
import { outputList } from './output.js';
|
|
4
5
|
import { parsePositiveInt, parseNonNegativeInt, readBodyInput } from './parsers.js';
|
|
5
|
-
import { paginatedFetch
|
|
6
|
+
import { paginatedFetch } from './pagination.js';
|
|
7
|
+
import { formatId } from './format-helpers.js';
|
|
8
|
+
const BANK_RULES_COLUMNS = [
|
|
9
|
+
{ key: 'resourceId', header: 'ID', format: formatId },
|
|
10
|
+
{ key: 'name', header: 'Name' },
|
|
11
|
+
];
|
|
6
12
|
export function registerBankRulesCommand(program) {
|
|
7
13
|
const cmd = program
|
|
8
14
|
.command('bank-rules')
|
|
@@ -14,24 +20,17 @@ export function registerBankRulesCommand(program) {
|
|
|
14
20
|
.option('--offset <n>', 'Offset', parseNonNegativeInt)
|
|
15
21
|
.option('--all', 'Fetch all pages')
|
|
16
22
|
.option('--api-key <key>', 'API key')
|
|
23
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
17
24
|
.option('--json', 'JSON output')
|
|
18
25
|
.action(apiAction(async (client, opts) => {
|
|
19
26
|
const result = await paginatedFetch(opts, (p) => listBankRules(client, p), { label: 'Fetching bank rules' });
|
|
20
|
-
|
|
21
|
-
console.log(paginatedJson(result, opts));
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
console.log(chalk.bold(`Bank Rules (${result.data.length} of ${result.totalElements}):\n`));
|
|
25
|
-
const { items, overflow } = displaySlice(result.data);
|
|
26
|
-
for (const r of items)
|
|
27
|
-
console.log(` ${chalk.cyan(r.resourceId)} ${r.name} ${chalk.dim(r.actionType)}`);
|
|
28
|
-
if (overflow > 0)
|
|
29
|
-
console.log(chalk.dim(` ... and ${overflow} more`));
|
|
27
|
+
outputList(result, BANK_RULES_COLUMNS, opts, 'Bank Rules'); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
30
28
|
}));
|
|
31
29
|
cmd
|
|
32
30
|
.command('get <resourceId>')
|
|
33
31
|
.description('Get a bank rule')
|
|
34
32
|
.option('--api-key <key>', 'API key')
|
|
33
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
35
34
|
.option('--json', 'JSON output')
|
|
36
35
|
.action((resourceId, opts) => apiAction(async (client) => {
|
|
37
36
|
const res = await getBankRule(client, resourceId);
|
|
@@ -49,26 +48,18 @@ export function registerBankRulesCommand(program) {
|
|
|
49
48
|
.option('--limit <n>', 'Max results', parsePositiveInt)
|
|
50
49
|
.option('--offset <n>', 'Offset', parseNonNegativeInt)
|
|
51
50
|
.option('--api-key <key>', 'API key')
|
|
51
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
52
52
|
.option('--json', 'JSON output')
|
|
53
53
|
.action((query, opts) => apiAction(async (client) => {
|
|
54
54
|
const result = await paginatedFetch(opts, ({ limit, offset }) => searchBankRules(client, { filter: { name: { contains: query } }, limit, offset }), { label: 'Searching bank rules', defaultLimit: 20 });
|
|
55
|
-
|
|
56
|
-
console.log(paginatedJson(result, opts));
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
if (result.data.length === 0) {
|
|
60
|
-
console.log('No bank rules found.');
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
console.log(chalk.bold(`Found ${result.data.length} rule(s):\n`));
|
|
64
|
-
for (const r of result.data)
|
|
65
|
-
console.log(` ${chalk.cyan(r.resourceId)} ${r.name}`);
|
|
55
|
+
outputList(result, BANK_RULES_COLUMNS, opts, 'Bank Rules'); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
66
56
|
})(opts));
|
|
67
57
|
cmd
|
|
68
58
|
.command('create')
|
|
69
59
|
.description('Create a bank rule')
|
|
70
60
|
.option('--input <file>', 'Read request body from JSON file')
|
|
71
61
|
.option('--api-key <key>', 'API key')
|
|
62
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
72
63
|
.option('--json', 'JSON output')
|
|
73
64
|
.action(apiAction(async (client, opts) => {
|
|
74
65
|
const body = readBodyInput(opts);
|
|
@@ -91,6 +82,7 @@ export function registerBankRulesCommand(program) {
|
|
|
91
82
|
.option('--name <name>', 'New name')
|
|
92
83
|
.option('--input <file>', 'Read full update body from JSON file')
|
|
93
84
|
.option('--api-key <key>', 'API key')
|
|
85
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
94
86
|
.option('--json', 'JSON output')
|
|
95
87
|
.action((resourceId, opts) => apiAction(async (client) => {
|
|
96
88
|
const body = readBodyInput(opts);
|
|
@@ -114,6 +106,7 @@ export function registerBankRulesCommand(program) {
|
|
|
114
106
|
.command('delete <resourceId>')
|
|
115
107
|
.description('Delete a bank rule')
|
|
116
108
|
.option('--api-key <key>', 'API key')
|
|
109
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
117
110
|
.option('--json', 'JSON output')
|
|
118
111
|
.action((resourceId, opts) => apiAction(async (client) => {
|
|
119
112
|
await deleteBankRule(client, resourceId);
|
package/dist/commands/bank.js
CHANGED
|
@@ -20,6 +20,7 @@ export function registerBankCommand(program) {
|
|
|
20
20
|
.command('accounts')
|
|
21
21
|
.description('List bank accounts')
|
|
22
22
|
.option('--limit <n>', 'Max results', parsePositiveInt)
|
|
23
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
23
24
|
.option('--api-key <key>', 'API key (overrides stored/env)')
|
|
24
25
|
.option('--json', 'Output as JSON')
|
|
25
26
|
.action(apiAction(async (client, opts) => {
|
|
@@ -40,6 +41,7 @@ export function registerBankCommand(program) {
|
|
|
40
41
|
bank
|
|
41
42
|
.command('get <resourceId>')
|
|
42
43
|
.description('Get a bank account by resourceId')
|
|
44
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
43
45
|
.option('--api-key <key>', 'API key (overrides stored/env)')
|
|
44
46
|
.option('--json', 'Output as JSON')
|
|
45
47
|
.action((resourceId, opts) => apiAction(async (client) => {
|
|
@@ -69,6 +71,7 @@ export function registerBankCommand(program) {
|
|
|
69
71
|
.option('--amount-min <n>', 'Filter by minimum amount', parseFloat)
|
|
70
72
|
.option('--amount-max <n>', 'Filter by maximum amount', parseFloat)
|
|
71
73
|
.option('--limit <n>', 'Max results (default 50)', parsePositiveInt)
|
|
74
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
72
75
|
.option('--api-key <key>', 'API key (overrides stored/env)')
|
|
73
76
|
.option('--json', 'Output as JSON')
|
|
74
77
|
.action((accountResourceId, opts) => apiAction(async (client) => {
|
|
@@ -112,6 +115,7 @@ export function registerBankCommand(program) {
|
|
|
112
115
|
.command('add-records <accountResourceId>')
|
|
113
116
|
.description('Add bank records via JSON (1-100 records per call)')
|
|
114
117
|
.requiredOption('--records <json>', 'JSON array: [{amount, transactionDate, description?, payerOrPayee?, reference?}]')
|
|
118
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
115
119
|
.option('--api-key <key>', 'API key (overrides stored/env)')
|
|
116
120
|
.option('--json', 'Output as JSON')
|
|
117
121
|
.action((accountResourceId, opts) => apiAction(async (client) => {
|
|
@@ -151,6 +155,7 @@ export function registerBankCommand(program) {
|
|
|
151
155
|
.description('Get auto-reconciliation recommendations for a bank account')
|
|
152
156
|
.requiredOption('--type <type>', `Recommendation type (${RECON_TYPES.join(', ')})`)
|
|
153
157
|
.option('--account <resourceId>', 'Bank account resourceId (omit for all accounts)')
|
|
158
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
154
159
|
.option('--api-key <key>', 'API key (overrides stored/env)')
|
|
155
160
|
.option('--json', 'Output as JSON')
|
|
156
161
|
.action(apiAction(async (client, opts) => {
|
|
@@ -202,6 +207,7 @@ export function registerBankCommand(program) {
|
|
|
202
207
|
.description('Import a bank statement file (CSV, OFX, XLS, XLSX)')
|
|
203
208
|
.requiredOption('--file <path>', 'Bank statement file path')
|
|
204
209
|
.requiredOption('--account <resourceId>', 'Bank account resourceId')
|
|
210
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
205
211
|
.option('--api-key <key>', 'API key (overrides stored/env)')
|
|
206
212
|
.option('--json', 'Output as JSON')
|
|
207
213
|
.action(apiAction(async (client, opts) => {
|
package/dist/commands/bills.js
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import { formatStatus } from './format-helpers.js';
|
|
2
|
+
import { formatStatus, formatId, formatReference, formatCurrency } from './format-helpers.js';
|
|
3
3
|
import { listBills, getBill, searchBills, createBill, updateBill, deleteBill, createBillPayment, applyCreditsToBill, finalizeBill, } from '../core/api/bills.js';
|
|
4
4
|
import { listAttachments } from '../core/api/attachments.js';
|
|
5
5
|
import { apiAction } from './api-action.js';
|
|
6
6
|
import { resolveContactFlag, resolveAccountFlag, resolveTaxProfileFlag } from './resolve.js';
|
|
7
7
|
import { parsePositiveInt, parseNonNegativeInt, parseMoney, parseRate, parseLineItems, parseCustomFields, readBodyInput, requireFields } from './parsers.js';
|
|
8
|
-
import { paginatedFetch
|
|
8
|
+
import { paginatedFetch } from './pagination.js';
|
|
9
|
+
import { outputList } from './output.js';
|
|
9
10
|
import { BILL_REQUIRED_FIELDS, buildDraftReport, formatDraftTable, addDraftFinalizeOptions, mergeDraftFlags, validateDraft, buildValidation, normalizeDate, sanitizeLineItem, } from './draft-helpers.js';
|
|
11
|
+
const BILL_COLUMNS = [
|
|
12
|
+
{ key: 'resourceId', header: 'ID', format: formatId },
|
|
13
|
+
{ key: 'reference', header: 'Reference', format: formatReference },
|
|
14
|
+
{ key: 'status', header: 'Status', format: (v) => formatStatus(String(v)) },
|
|
15
|
+
{ key: 'totalAmount', header: 'Amount', align: 'right', format: formatCurrency },
|
|
16
|
+
{ key: 'valueDate', header: 'Date', format: (v) => normalizeDate(String(v)) ?? '-' },
|
|
17
|
+
];
|
|
10
18
|
export function registerBillsCommand(program) {
|
|
11
19
|
const bills = program
|
|
12
20
|
.command('bills')
|
|
@@ -19,24 +27,12 @@ export function registerBillsCommand(program) {
|
|
|
19
27
|
.option('--offset <n>', 'Page number offset (0-indexed)', parseNonNegativeInt)
|
|
20
28
|
.option('--all', 'Fetch all pages')
|
|
21
29
|
.option('--max-rows <n>', 'Max rows for --all (default 10000)', parsePositiveInt)
|
|
30
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
22
31
|
.option('--api-key <key>', 'API key (overrides stored/env)')
|
|
23
32
|
.option('--json', 'Output as JSON')
|
|
24
33
|
.action(apiAction(async (client, opts) => {
|
|
25
34
|
const result = await paginatedFetch(opts, (p) => listBills(client, p), { label: 'Fetching bills' });
|
|
26
|
-
|
|
27
|
-
console.log(paginatedJson(result, opts));
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
console.log(chalk.bold(`Bills (${result.data.length} of ${result.totalElements}):\n`));
|
|
31
|
-
const { items, overflow } = displaySlice(result.data);
|
|
32
|
-
for (const b of items) {
|
|
33
|
-
const amount = b.totalAmount !== undefined ? chalk.dim(` $${b.totalAmount.toFixed(2)}`) : '';
|
|
34
|
-
const status = formatStatus(b.status);
|
|
35
|
-
console.log(` ${chalk.cyan(b.resourceId)} ${b.reference || '(no ref)'} ${status}${amount} ${normalizeDate(b.valueDate)}`);
|
|
36
|
-
}
|
|
37
|
-
if (overflow > 0)
|
|
38
|
-
console.log(chalk.dim(` ... and ${overflow.toLocaleString()} more (use --json for full output)`));
|
|
39
|
-
}
|
|
35
|
+
outputList(result, BILL_COLUMNS, opts, 'Bills'); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
40
36
|
}));
|
|
41
37
|
// ── clio bills get ──────────────────────────────────────────────
|
|
42
38
|
bills
|
|
@@ -87,6 +83,7 @@ export function registerBillsCommand(program) {
|
|
|
87
83
|
.option('--offset <n>', 'Page number offset (0-indexed)', parseNonNegativeInt)
|
|
88
84
|
.option('--all', 'Fetch all pages')
|
|
89
85
|
.option('--max-rows <n>', 'Max rows for --all (default 10000)', parsePositiveInt)
|
|
86
|
+
.option('--format <type>', 'Output format: table, json, csv, yaml')
|
|
90
87
|
.option('--api-key <key>', 'API key (overrides stored/env)')
|
|
91
88
|
.option('--json', 'Output as JSON')
|
|
92
89
|
.action(apiAction(async (client, opts) => {
|
|
@@ -113,24 +110,7 @@ export function registerBillsCommand(program) {
|
|
|
113
110
|
const searchFilter = Object.keys(filter).length > 0 ? filter : undefined;
|
|
114
111
|
const sort = { sortBy: [opts.sort ?? 'valueDate'], order: (opts.order ?? 'DESC') };
|
|
115
112
|
const result = await paginatedFetch(opts, ({ limit, offset }) => searchBills(client, { filter: searchFilter, limit, offset, sort }), { label: 'Searching bills', defaultLimit: 20 });
|
|
116
|
-
|
|
117
|
-
console.log(paginatedJson(result, opts));
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
if (result.data.length === 0) {
|
|
121
|
-
console.log('No bills found.');
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
console.log(chalk.bold(`Found ${result.data.length} bill(s):\n`));
|
|
125
|
-
const { items, overflow } = displaySlice(result.data);
|
|
126
|
-
for (const b of items) {
|
|
127
|
-
const amount = b.totalAmount !== undefined ? chalk.dim(` $${b.totalAmount.toFixed(2)}`) : '';
|
|
128
|
-
const status = formatStatus(b.status);
|
|
129
|
-
console.log(` ${chalk.cyan(b.resourceId)} ${b.reference || '(no ref)'} ${status}${amount} ${normalizeDate(b.valueDate)}`);
|
|
130
|
-
}
|
|
131
|
-
if (overflow > 0)
|
|
132
|
-
console.log(chalk.dim(` ... and ${overflow.toLocaleString()} more (use --json for full output)`));
|
|
133
|
-
}
|
|
113
|
+
outputList(result, BILL_COLUMNS, opts, 'Bills'); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
134
114
|
}));
|
|
135
115
|
// ── clio bills create ───────────────────────────────────────────
|
|
136
116
|
bills
|