bkper 4.12.14 → 4.12.16

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.
@@ -0,0 +1,469 @@
1
+ # Data Management
2
+
3
+ Interact with books, accounts, transactions, and balances using the `bkper` CLI.
4
+
5
+ All commands that operate within a book use `-b, --book <bookId>` to specify the book context.
6
+
7
+ ---
8
+
9
+ ## Books
10
+
11
+ Create and manage financial books with locale-specific settings.
12
+
13
+ ```bash
14
+ # List all books
15
+ bkper book list
16
+
17
+ # Get book details
18
+ bkper book get abc123
19
+
20
+ # Create a book with Brazilian settings
21
+ bkper book create --name "My Company" --fraction-digits 2 \
22
+ --date-pattern "dd/MM/yyyy" --decimal-separator COMMA \
23
+ --time-zone "America/Sao_Paulo"
24
+
25
+ # Create a book with custom properties
26
+ bkper book create --name "Project X" -p "code=PX001" -p "department=Engineering"
27
+
28
+ # Update a book
29
+ bkper book update abc123 --lock-date 2024-12-31
30
+ ```
31
+
32
+ <details>
33
+ <summary>Command reference</summary>
34
+
35
+ - `book list` - List all books
36
+ - `-q, --query <query>` - Search query
37
+ - `book get <bookId>` - Get a book's details
38
+ - `book create` - Create a new book
39
+ - `--name <name>` - Book name (required)
40
+ - `--fraction-digits <digits>` - Number of decimal places (`0`-`8`)
41
+ - `--date-pattern <pattern>` - Date format pattern (`dd/MM/yyyy`, `MM/dd/yyyy`, or `yyyy/MM/dd`)
42
+ - `--decimal-separator <separator>` - Decimal separator (`DOT` or `COMMA`)
43
+ - `--time-zone <timezone>` - IANA time zone (e.g. `America/New_York`, `UTC`)
44
+ - `--period <period>` - Period (`MONTH`, `QUARTER`, or `YEAR`)
45
+ - `-p, --property <key=value>` - Set a property (repeatable)
46
+ - `book update <bookId>` - Update a book
47
+ - `--name <name>` - Book name
48
+ - `--fraction-digits <digits>` - Number of decimal places (`0`-`8`)
49
+ - `--date-pattern <pattern>` - Date format pattern (`dd/MM/yyyy`, `MM/dd/yyyy`, or `yyyy/MM/dd`)
50
+ - `--decimal-separator <separator>` - Decimal separator (`DOT` or `COMMA`)
51
+ - `--time-zone <timezone>` - IANA time zone identifier (e.g. `America/New_York`, `Europe/London`, `UTC`)
52
+ - `--lock-date <date>` - Lock date in ISO format (`yyyy-MM-dd`, e.g. `2024-01-31`)
53
+ - `--closing-date <date>` - Closing date in ISO format (`yyyy-MM-dd`)
54
+ - `--period <period>` - Period (`MONTH`, `QUARTER`, or `YEAR`)
55
+ - `-p, --property <key=value>` - Set a property (repeatable, e.g. `-p code=1010 -p branch=NYC`; empty value deletes the property)
56
+
57
+ </details>
58
+
59
+ ---
60
+
61
+ ## Accounts
62
+
63
+ Manage your chart of accounts within a book.
64
+
65
+ ```bash
66
+ # List all accounts
67
+ bkper account list -b abc123
68
+
69
+ # Get an account by name
70
+ bkper account get "Bank Account" -b abc123
71
+
72
+ # Create an asset account
73
+ bkper account create -b abc123 --name "Bank Account" --type ASSET --groups "Current Assets"
74
+
75
+ # Update an account
76
+ bkper account update "Bank Account" -b abc123 --type LIABILITY
77
+
78
+ # Archive an account
79
+ bkper account update "Old Account" -b abc123 --archived true
80
+
81
+ # Delete an account
82
+ bkper account delete "Old Account" -b abc123
83
+ ```
84
+
85
+ <details>
86
+ <summary>Command reference</summary>
87
+
88
+ - `account list -b <bookId>` - List accounts in a book
89
+ - `account get <nameOrId> -b <bookId>` - Get an account
90
+ - `account create -b <bookId>` - Create a new account
91
+ - `--name <name>` - Account name (required)
92
+ - `--type <type>` - Account type (`ASSET`, `LIABILITY`, `INCOMING`, `OUTGOING`)
93
+ - `--description <description>` - Account description
94
+ - `--groups <groups>` - Comma-separated group names
95
+ - `-p, --property <key=value>` - Set a property (repeatable)
96
+ - `account update <nameOrId> -b <bookId>` - Update an account
97
+ - `--name <name>` - Account name
98
+ - `--type <type>` - Account type (`ASSET`, `LIABILITY`, `INCOMING`, `OUTGOING`)
99
+ - `--archived <true|false>` - Archive status
100
+ - `-p, --property <key=value>` - Set a property (repeatable, merges with existing)
101
+ - `account delete <nameOrId> -b <bookId>` - Delete an account
102
+
103
+ </details>
104
+
105
+ ---
106
+
107
+ ## Groups
108
+
109
+ Organize accounts into hierarchical groups for structured reporting.
110
+
111
+ ```bash
112
+ # List all groups (shows hierarchy)
113
+ bkper group list -b abc123
114
+
115
+ # Create a group
116
+ bkper group create -b abc123 --name "Current Assets"
117
+
118
+ # Create a child group
119
+ bkper group create -b abc123 --name "Cash" --parent "Current Assets"
120
+
121
+ # Update a group
122
+ bkper group update "Cash" -b abc123 --hidden true
123
+
124
+ # Delete a group
125
+ bkper group delete "Cash" -b abc123
126
+ ```
127
+
128
+ ### Book setup guidance (important)
129
+
130
+ When setting up a full Book or starter chart of accounts, prefer a hierarchical group structure by default.
131
+
132
+ Create top-level groups first, then child groups with `--parent`, then accounts with `--groups`.
133
+
134
+ Verify the resulting group hierarchy and account memberships before reporting success.
135
+
136
+ Avoid using the same name for a Group and an Account in the same Book.
137
+
138
+ <details>
139
+ <summary>Command reference</summary>
140
+
141
+ - `group list -b <bookId>` - List groups in a book
142
+ - `group get <nameOrId> -b <bookId>` - Get a group
143
+ - `group create -b <bookId>` - Create a new group
144
+ - `--name <name>` - Group name (required)
145
+ - `--parent <parent>` - Parent group name or ID
146
+ - `--hidden` - Hide the group
147
+ - `-p, --property <key=value>` - Set a property (repeatable)
148
+ - `group update <nameOrId> -b <bookId>` - Update a group
149
+ - `--name <name>` - Group name
150
+ - `--hidden <true|false>` - Hide status
151
+ - `-p, --property <key=value>` - Set a property (repeatable, merges with existing)
152
+ - `group delete <nameOrId> -b <bookId>` - Delete a group
153
+
154
+ </details>
155
+
156
+ ---
157
+
158
+ ## Transactions
159
+
160
+ Record, query, and manage financial transactions.
161
+
162
+ ```bash
163
+ # Create a draft transaction
164
+ bkper transaction create -b abc123 --description "Office supplies"
165
+
166
+ # Create a complete transaction
167
+ bkper transaction create -b abc123 --date 2025-01-15 --amount 100.50 \
168
+ --from "Bank Account" --to "Office Supplies" --description "Printer paper"
169
+
170
+ # List transactions for a full year (on:YYYY)
171
+ bkper transaction list -b abc123 -q 'on:2025'
172
+
173
+ # List transactions for a month (on:YYYY-MM)
174
+ bkper transaction list -b abc123 -q 'on:2025-01'
175
+
176
+ # List with custom properties included
177
+ bkper transaction list -b abc123 -q 'account:Sales' -p
178
+
179
+ # Update a transaction
180
+ bkper transaction update tx_456 -b abc123 --amount 120.00 --description "Printer paper (corrected)"
181
+
182
+ # Post a draft transaction
183
+ bkper transaction post tx_456 -b abc123
184
+
185
+ # Check (reconcile) a transaction
186
+ bkper transaction check tx_456 -b abc123
187
+
188
+ # Trash a transaction
189
+ bkper transaction trash tx_456 -b abc123
190
+
191
+ # Merge two duplicate transactions
192
+ bkper transaction merge tx_123 tx_456 -b abc123
193
+ ```
194
+
195
+ <details>
196
+ <summary>Command reference</summary>
197
+
198
+ - `transaction list -b <bookId> -q <query>` - List transactions matching a query (auto-paginates through all results)
199
+ - `-p, --properties` - Include custom properties in the output
200
+ - `transaction create -b <bookId>` - Create a transaction
201
+ - `--date <date>` - Transaction date
202
+ - `--amount <amount>` - Transaction amount
203
+ - `--description <description>` - Transaction description
204
+ - `--from <from>` - Credit account (source)
205
+ - `--to <to>` - Debit account (destination)
206
+ - `--url <url>` - URL (repeatable)
207
+ - `--remote-id <remoteId>` - Remote ID (repeatable)
208
+ - `-p, --property <key=value>` - Set a property (repeatable, empty value deletes)
209
+ - `transaction update [transactionId] -b <bookId>` - Update a transaction (or batch update via stdin)
210
+ - `--date <date>` - Transaction date
211
+ - `--amount <amount>` - Transaction amount
212
+ - `--description <description>` - Transaction description
213
+ - `--from <from>` - Credit account (source)
214
+ - `--to <to>` - Debit account (destination)
215
+ - `--url <url>` - URL (repeatable, replaces all)
216
+ - `--update-checked` - Also update checked transactions
217
+ - `-p, --property <key=value>` - Set a property (repeatable, empty value deletes)
218
+ - `transaction post <id> -b <bookId>` - Post a draft transaction
219
+ - `transaction check <id> -b <bookId>` - Check a transaction
220
+ - `transaction trash <id> -b <bookId>` - Trash a transaction
221
+ - `transaction merge <id1> <id2> -b <bookId>` - Merge two transactions
222
+
223
+ </details>
224
+
225
+ ---
226
+
227
+ ## Balances
228
+
229
+ Query account balances and group totals.
230
+
231
+ ```bash
232
+ # List balances for a specific date (point-in-time)
233
+ bkper balance list -b abc123 -q 'on:2025-12-31'
234
+
235
+ # Monthly balance evolution of one account during 2025
236
+ bkper balance list -b abc123 -q "account:'<accountName>' after:2025-01-01 before:2026-01-01 by:m" --expanded 2
237
+ ```
238
+
239
+ <details>
240
+ <summary>Command reference</summary>
241
+
242
+ - `balance list -b <bookId> -q <query>` - List balances
243
+ - `--expanded <level>` - Expand groups to specified depth (`0`+)
244
+
245
+ </details>
246
+
247
+ ---
248
+
249
+ ## Query Semantics
250
+
251
+ Use the same query language across Bkper web app, CLI, and Google Sheets integrations.
252
+
253
+ - `on:` supports different granularities:
254
+ - `on:2025` → full year
255
+ - `on:2025-01` → full month
256
+ - `on:2025-01-31` → specific day
257
+ - `after:` is **inclusive** and `before:` is **exclusive**.
258
+ - Full year 2025: `after:2025-01-01 before:2026-01-01`
259
+ - In shell commands, wrap queries with Bkper date variables (`$d`, `$m`, `$y`) in single quotes to avoid shell expansion.
260
+ - Example: `bkper transaction list -b abc123 -q 'after:$m-3 before:$m+1'`
261
+ - If the query already needs single quotes inside (for example, `account:'Brex Cash'`), keep double quotes and escape `$`: `-q "account:'Brex Cash' after:\$m-3 before:\$m+1"`
262
+ - For point-in-time statements (typically permanent accounts `ASSET`/`LIABILITY`), prefer `on:` or `before:`.
263
+ - For activity statements over a period (typically non-permanent accounts `INCOMING`/`OUTGOING`), prefer `after:` + `before:`.
264
+ - For statement-level analysis, prefer filtering by the report root group. Root names vary by book — run `bkper group list -b <bookId>` first to discover them: top-level groups containing `ASSET`/`LIABILITY` accounts are Balance Sheet roots; those containing `INCOMING`/`OUTGOING` accounts are P&L roots.
265
+
266
+ ```bash
267
+ # Discover root groups
268
+ bkper group list -b abc123
269
+
270
+ # Balance Sheet snapshot (point-in-time)
271
+ bkper balance list -b abc123 -q "group:'<balanceSheetRootGroup>' before:2026-01-01"
272
+
273
+ # P&L activity over 2025
274
+ bkper balance list -b abc123 -q "group:'<profitAndLossRootGroup>' after:2025-01-01 before:2026-01-01"
275
+ ```
276
+
277
+ For the full balance sheet and P&L workflow, see the [Financial Statements guide](https://github.com/bkper/bkper-cli/blob/main/docs/financial-statements.md).
278
+
279
+ ---
280
+
281
+ ## Collections
282
+
283
+ Organize books into collections.
284
+
285
+ ```bash
286
+ # Create a collection
287
+ bkper collection create --name "My Collection"
288
+
289
+ # Add books to a collection
290
+ bkper collection add-book col_789 -b abc123 -b def456
291
+
292
+ # List all collections
293
+ bkper collection list
294
+
295
+ # Remove a book from a collection
296
+ bkper collection remove-book col_789 -b abc123
297
+
298
+ # Delete a collection
299
+ bkper collection delete col_789
300
+ ```
301
+
302
+ <details>
303
+ <summary>Command reference</summary>
304
+
305
+ - `collection list` - List all collections
306
+ - `collection get <collectionId>` - Get a collection
307
+ - `collection create` - Create a new collection
308
+ - `--name <name>` - Collection name (required)
309
+ - `collection update <collectionId>` - Update a collection
310
+ - `--name <name>` - Collection name
311
+ - `collection delete <collectionId>` - Delete a collection
312
+ - `collection add-book <collectionId>` - Add books to a collection
313
+ - `-b, --book <bookId>` - Book ID (repeatable)
314
+ - `collection remove-book <collectionId>` - Remove books from a collection
315
+ - `-b, --book <bookId>` - Book ID (repeatable)
316
+
317
+ </details>
318
+
319
+ ---
320
+
321
+ ## Output Format
322
+
323
+ All commands support three output formats via the `--format` global flag:
324
+
325
+ | Format | Flag | Best for |
326
+ | ------ | -------------------------- | ------------------------------------------- |
327
+ | Table | `--format table` (default) | Human reading in the terminal |
328
+ | JSON | `--format json` | Programmatic access, single-item detail |
329
+ | CSV | `--format csv` | LLM consumption, spreadsheets, list reports |
330
+
331
+ ```bash
332
+ # Table output (default)
333
+ bkper account list -b abc123
334
+
335
+ # JSON output
336
+ bkper account list -b abc123 --format json
337
+
338
+ # CSV output -- raw data, no truncation, RFC 4180
339
+ bkper account list -b abc123 --format csv
340
+ ```
341
+
342
+ **CSV output details:**
343
+
344
+ - **RFC 4180 compliant** -- proper quoting, CRLF line endings, no truncation
345
+ - **All metadata included** -- IDs, properties, hidden properties, URLs, and timestamps are enabled
346
+ - **Raw values** -- dates stay in ISO format, numbers are unformatted (no locale formatting)
347
+ - **Single-item commands** (e.g. `account get`, `transaction create`) fall back to JSON since CSV adds no value for non-tabular data
348
+
349
+ **LLM-first output guidance (important):**
350
+
351
+ When command output will be loaded into an LLM context (chat, prompt, memory, or agent reasoning), prefer:
352
+
353
+ - **`--format csv` for list commands** (`balance list`, `transaction list`, `account list`, etc.).
354
+ - **`--format json` for single-item commands** (`get`, `create`, `update`) and CLI-to-CLI pipelines.
355
+
356
+ CSV is significantly more token-efficient than JSON for tabular data, and for wide balance outputs it can reduce token usage by up to **95%**.
357
+
358
+ **Quick rule:**
359
+
360
+ - **LLM consumption of lists/reports** → CSV
361
+ - **Programmatic processing / pipelines** → JSON
362
+ - **Human terminal reading** → Table
363
+
364
+ ---
365
+
366
+ ## Batch Operations & Piping
367
+
368
+ Write commands (`account create`, `transaction create`) accept JSON data piped via stdin for batch operations. The `transaction update` command also accepts stdin for batch updates. The input format follows the [Bkper API Types](https://raw.githubusercontent.com/bkper/bkper-api-types/refs/heads/master/index.d.ts) exactly -- a single JSON object or an array of objects.
369
+
370
+ ```bash
371
+ # Create transactions
372
+ echo '[{
373
+ "date": "2025-01-15",
374
+ "amount": "100.50",
375
+ "creditAccount": {"name": "Bank Account"},
376
+ "debitAccount": {"name": "Office Supplies"},
377
+ "description": "Printer paper",
378
+ "properties": {"invoice": "INV-001"}
379
+ }]' | bkper transaction create -b abc123
380
+
381
+ # Create accounts
382
+ echo '[{"name":"Cash","type":"ASSET"},{"name":"Revenue","type":"INCOMING"}]' | \
383
+ bkper account create -b abc123
384
+
385
+ # Pipe from a script
386
+ python export_bank.py | bkper transaction create -b abc123
387
+ ```
388
+
389
+ The input follows the exact `bkper.Transaction` or `bkper.Account` type from the [Bkper API Types](https://raw.githubusercontent.com/bkper/bkper-api-types/refs/heads/master/index.d.ts). Custom properties go inside the `properties` object.
390
+
391
+ Groups are created explicitly with `bkper group create --name` and optional `--parent` so hierarchy stays deterministic during setup.
392
+
393
+ The `--property` CLI flag can override or delete properties from the stdin payload:
394
+
395
+ ```bash
396
+ echo '[{"name":"Cash","type":"ASSET"}]' | \
397
+ bkper account create -b abc123 -p "region=LATAM"
398
+ ```
399
+
400
+ **Batch output:** results are output as a flat JSON array, matching the same format as list commands:
401
+
402
+ ```bash
403
+ bkper account create -b abc123 < accounts.json
404
+ # Output: [{"id":"acc-abc","name":"Cash",...}, {"id":"acc-def","name":"Revenue",...}]
405
+ ```
406
+
407
+ **Piping between commands:**
408
+
409
+ For resources that support stdin creation, JSON output can be piped directly into create or update commands:
410
+
411
+ ```bash
412
+ # Copy all accounts from one book to another
413
+ bkper account list -b $BOOK_A --format json | bkper account create -b $BOOK_B
414
+
415
+ # Copy transactions matching a query
416
+ bkper transaction list -b $BOOK_A -q 'after:2025-01-01' --format json | \
417
+ bkper transaction create -b $BOOK_B
418
+
419
+ # Clone accounts, then transactions
420
+ bkper account list -b $SOURCE --format json | bkper account create -b $DEST
421
+ bkper transaction list -b $SOURCE -q 'after:2025-01-01' --format json | \
422
+ bkper transaction create -b $DEST
423
+
424
+ # Batch update: list transactions, modify, and pipe back to update
425
+ bkper transaction list -b $BOOK -q 'after:2025-01-01' --format json | \
426
+ jq '[.[] | .description = "Updated: " + .description]' | \
427
+ bkper transaction update -b $BOOK
428
+
429
+ # Batch update: add a property to all matching transactions
430
+ bkper transaction list -b $BOOK -q 'account:Expenses' --format json | \
431
+ bkper transaction update -b $BOOK -p "reviewed=true"
432
+
433
+ # Batch update checked transactions
434
+ bkper transaction list -b $BOOK -q 'is:checked after:2025-01-01' --format json | \
435
+ bkper transaction update -b $BOOK --update-checked -p "migrated=true"
436
+ ```
437
+
438
+ <details>
439
+ <summary>Writable fields reference</summary>
440
+
441
+ Only the fields below are meaningful when creating or updating resources via stdin. For batch updates, items must include an `id` field. Other read-only fields (`createdAt`, `updatedAt`, etc.) are ignored.
442
+
443
+ **Transaction** (`bkper.Transaction`)
444
+
445
+ | Field | Type | Notes |
446
+ | --------------- | ---------------------------------- | --------------------------------------------- |
447
+ | `id` | `string` | Required for batch updates, ignored on create |
448
+ | `date` | `string` | ISO format `yyyy-MM-dd` |
449
+ | `amount` | `string` | Decimal format `####.##` (string, not number) |
450
+ | `creditAccount` | `{"name":"..."}` or `{"id":"..."}` | Reference to an existing account |
451
+ | `debitAccount` | `{"name":"..."}` or `{"id":"..."}` | Reference to an existing account |
452
+ | `description` | `string` | Free-text description |
453
+ | `urls` | `string[]` | Attached URLs (e.g. receipts) |
454
+ | `remoteIds` | `string[]` | External IDs to prevent duplicates |
455
+ | `properties` | `{"key": "value", ...}` | Custom key/value properties |
456
+
457
+ **Account** (`bkper.Account`)
458
+
459
+ | Field | Type | Notes |
460
+ | ------------ | ----------------------- | -------------------------------------------------- |
461
+ | `name` | `string` | Account name (required) |
462
+ | `type` | `string` | `ASSET`, `LIABILITY`, `INCOMING`, or `OUTGOING` |
463
+ | `credit` | `boolean` | Credit nature (`true`) or debit (`false`) |
464
+ | `archived` | `boolean` | Archive the account on creation |
465
+ | `permanent` | `boolean` | Permanent accounts (e.g. bank accounts, customers) |
466
+ | `groups` | `[{"name":"..."}, ...]` | Groups to assign by name or id |
467
+ | `properties` | `{"key": "value", ...}` | Custom key/value properties |
468
+
469
+ </details>
@@ -0,0 +1,225 @@
1
+ # Financial Statements — Deterministic Workflow
2
+
3
+ Use this guide when a user asks for a balance sheet, P&L, income statement, profit and loss, or any other ledger-derived financial report from a Bkper book.
4
+
5
+ ## Deterministic first
6
+
7
+ Financial statements are **deterministic accounting tasks**.
8
+
9
+ For the same book snapshot, statement type, period, and report settings, the agent should be able to run the same local code/config and obtain the same result every time. Use non-deterministic reasoning only for tasks whose nature is interpretive — such as suspicious transaction analysis, commentary, or general insights — not for deciding how the statement itself is computed.
10
+
11
+ Treat the reporting route as something that should be **persisted locally** and reused.
12
+
13
+ ---
14
+
15
+ ## Step 0 — Reuse an existing local statement runner
16
+
17
+ Before running ad-hoc balance queries, inspect the local project for a canonical deterministic route for financial statements.
18
+
19
+ Look for artifacts such as:
20
+
21
+ - `reports/`
22
+ - `scripts/`
23
+ - `package.json` scripts
24
+ - local config/spec files
25
+ - `AGENTS.md`
26
+
27
+ If a local statement runner already exists:
28
+
29
+ - Use it as the default route
30
+ - Pass explicit parameters for book, statement type, and dates/period
31
+ - Return the result produced by that runner
32
+ - Do **not** rediscover groups or rebuild fresh balance queries unless the user explicitly asks to update or rebuild the reporting logic
33
+
34
+ Once a deterministic route exists, prefer it over live ad-hoc querying.
35
+
36
+ ---
37
+
38
+ ## Step 1 — If none exists, bootstrap one
39
+
40
+ If no deterministic runner exists yet, do **not** treat a live one-off balance query as the canonical solution.
41
+
42
+ Instead:
43
+
44
+ 1. Explain briefly that financial statements should be generated by repeatable local code/config
45
+ 2. Offer to create that local statement runner for the project
46
+ 3. Ask approval before writing files
47
+ 4. Use live Bkper queries only as **bootstrap/discovery steps** to build the deterministic route correctly
48
+
49
+ If the request is ambiguous (for example, “run a financial statement”), clarify whether the user wants:
50
+
51
+ - Balance Sheet
52
+ - Profit & Loss / Income Statement
53
+ - Both
54
+
55
+ During bootstrap, it is acceptable to create either:
56
+
57
+ - a small shell script that runs fixed CLI queries and formats the output, or
58
+ - a `bkper-js` script that resolves dates, loads groups, and renders the statement in a stable format
59
+
60
+ Prefer the smallest boring solution that is easy to rerun and inspect.
61
+
62
+ ---
63
+
64
+ ## Step 2 — Discover the correct root groups
65
+
66
+ Use these commands during bootstrap to identify the correct statement roots.
67
+
68
+ ```bash
69
+ bkper group list -b <bookId> --format csv
70
+ ```
71
+
72
+ Inspect the output and identify **top-level groups** (no parent). Root group names vary by book — common examples: `Total Equity`, `Balance Sheet`, `Profit & Loss`, `Results`, `Net Worth`.
73
+
74
+ Identify each root group by the account types it contains:
75
+
76
+ | Root group contains | Statement |
77
+ | ---------------------------------- | ---------------------------- |
78
+ | ASSET and/or LIABILITY accounts | Balance Sheet |
79
+ | INCOMING and/or OUTGOING accounts | Profit & Loss / Income Statement |
80
+
81
+ When you discover the correct roots, persist them for future runs.
82
+
83
+ Prefer storing the **group ID** in the local report config/script. If the execution route also needs the group name for a query string, persist the name as well.
84
+
85
+ ### If the book has no usable statement hierarchy
86
+
87
+ If Step 2 does **not** reveal clear statement roots, treat that as a modeling gap, not as permission to improvise one silently.
88
+
89
+ In that case:
90
+
91
+ - explain that the book is **not yet statement-ready** for deterministic reporting
92
+ - do **not** invent arbitrary roots from subgroup names or partial account matches
93
+ - inspect the existing account names, language, and reporting style already present in the book
94
+ - propose the **smallest** hierarchy that fits the user's actual use case and local standards
95
+ - ask approval before creating groups, moving accounts, or persisting the proposed roots
96
+ - once approved, validate the hierarchy with live balance queries and then persist it in the local runner/config
97
+
98
+ When relevant, clarify whether the user wants:
99
+
100
+ - internal management reporting
101
+ - local/statutory reporting
102
+ - a simplified starter structure to evolve later
103
+
104
+ If the user only wants a quick answer for now, you may still provide an **exploratory / provisional** result, but state clearly that the book still needs an approved reporting hierarchy for future deterministic statements.
105
+
106
+ ---
107
+
108
+ ## Step 3 — Fetch balances to validate and implement the runner
109
+
110
+ Use these commands during bootstrap to validate the accounting logic and to implement the deterministic runner.
111
+
112
+ **Balance Sheet** — permanent accounts, cumulative position at a point in time:
113
+
114
+ ```bash
115
+ bkper balance list -b <bookId> \
116
+ -q "group:'<rootGroup>' before:<date>" \
117
+ --format csv --expanded 2
118
+ ```
119
+
120
+ **Profit & Loss / Income Statement** — non-permanent accounts, activity within a period:
121
+
122
+ ```bash
123
+ bkper balance list -b <bookId> \
124
+ -q "group:'<rootGroup>' after:<start> before:<end>" \
125
+ --format csv --expanded 2
126
+ ```
127
+
128
+ Use the output to confirm the correct hierarchy, totals, and period semantics before persisting the script/spec.
129
+
130
+ ---
131
+
132
+ ## Step 4 — Persist the deterministic route locally
133
+
134
+ After discovery and validation, create or update local artifacts so future requests reuse the same route.
135
+
136
+ Typical artifacts:
137
+
138
+ - `reports/balance-sheet.sh`
139
+ - `reports/profit-and-loss.sh`
140
+ - `scripts/financial-statements.ts`
141
+ - `reports/financial-statements.json`
142
+ - `package.json` scripts such as `report:balance-sheet` and `report:pl`
143
+
144
+ Persist the decisions that make the report repeatable:
145
+
146
+ - `bookId`
147
+ - statement type
148
+ - root group ID
149
+ - root group name if needed by the chosen execution path
150
+ - timezone, if relevant to date boundaries
151
+ - expanded depth / output detail level
152
+ - exact date semantics for each statement type
153
+ - output format
154
+
155
+ The canonical runner should produce a stable output shape, such as structured JSON, Markdown, or CSV with clear sections, totals, and period labels.
156
+
157
+ If helpful, also create or update a local `AGENTS.md` note telling future agent sessions to use the canonical financial statement script. `AGENTS.md` is **optional persistence**, not a prerequisite for the first request.
158
+
159
+ ---
160
+
161
+ ## Step 5 — Use the script for future requests
162
+
163
+ Once the local statement runner exists:
164
+
165
+ - Use it as the default route for balance sheet and P&L requests
166
+ - Resolve relative periods like “last year” into explicit date boundaries in code/config
167
+ - Keep deterministic statement generation separate from optional AI commentary
168
+ - If the reporting logic must change, update the script/config instead of improvising a fresh one-off route
169
+
170
+ Do not re-decide the accounting method on every request.
171
+
172
+ ---
173
+
174
+ ## One-off exploratory fallback
175
+
176
+ If the user explicitly does **not** want to create the script now and only wants a quick one-off answer, you may run live balance queries directly.
177
+
178
+ In that case:
179
+
180
+ - Clearly label the result as **exploratory / provisional**
181
+ - State that it is **not yet** the canonical deterministic reporting route for the project
182
+ - Recommend persisting a local script/config if the user wants repeatable accounting output in future requests
183
+
184
+ ---
185
+
186
+ ## Date patterns
187
+
188
+ Use these patterns when validating or implementing the deterministic runner.
189
+
190
+ | Request | Balance Sheet | Profit & Loss |
191
+ | -------------- | -------------------------- | ------------------------------ |
192
+ | Current month | `before:$m` | `after:$m-1 before:$m` |
193
+ | Current year | `before:$y` | `after:$y-1 before:$y` |
194
+ | Full year 2024 | `before:2025-01-01` | `after:2024-01-01 before:2025-01-01` |
195
+
196
+ - `after:` is **inclusive**, `before:` is **exclusive**
197
+ - `$d` = today, `$m` = current month-end, `$y` = current year-end
198
+ - In shell, wrap queries containing `$` variables in **single quotes** to prevent shell expansion
199
+
200
+ ---
201
+
202
+ ## Key rules
203
+
204
+ - **Always use the ROOT group** — never subgroups like `Assets`, `Liabilities`, `Revenue`, `Expenses`
205
+ - **Balance Sheet** uses `before:` only — permanent accounts accumulate continuously
206
+ - **P&L** uses `after:` + `before:` — non-permanent accounts track period activity
207
+ - **Use `--format csv`** for token efficiency when loading bootstrap results into an LLM context
208
+ - **Use `--expanded 2`** to see meaningful sub-totals in the hierarchy
209
+ - Once a canonical local report route exists, **reuse it instead of rediscovering the logic**
210
+ - Prefer persisting reporting decisions in code/config rather than relying on session memory
211
+
212
+ ---
213
+
214
+ ## Common mistakes
215
+
216
+ | Wrong | Right |
217
+ | --- | --- |
218
+ | Immediately running ad-hoc balance queries as the default response to a first statement request | First look for a local runner; if none exists, propose creating one and use queries only for bootstrap |
219
+ | Assuming `AGENTS.md` must already exist | `AGENTS.md` can be created or updated during bootstrap to route future requests |
220
+ | `group:'Assets' before:2025-01-01` | `group:'Total Equity' before:2025-01-01` — use root group, not subgroup |
221
+ | Inventing a new statement hierarchy silently because no roots were found | Explain that the book is not yet statement-ready, propose a minimal hierarchy aligned with the user's language and local standards, and ask approval before changing structure |
222
+ | `before:$m` for P&L | `after:$m-1 before:$m` — P&L needs a period, not just an end date |
223
+ | `after:$y-1 before:$d` | `after:$y-1 before:$y` — use consistent date basis on both ends |
224
+ | `-q 'before:2025-01-01'` without group filter | `-q "group:'<rootGroup>' before:2025-01-01"` — always filter by group |
225
+ | Re-interpreting “last year” differently each time | Resolve relative periods into explicit dates inside the canonical script/config |