clawbooks 0.1.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.
@@ -0,0 +1,60 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFileSync, appendFileSync, existsSync, writeFileSync } from "node:fs";
3
+ export function computeId(data, meta) {
4
+ const sortedData = JSON.stringify(data, Object.keys(data).sort());
5
+ const envelope = { data: sortedData, source: meta.source, ts: meta.ts, type: meta.type };
6
+ const canonical = JSON.stringify(envelope);
7
+ return createHash("sha256").update(canonical).digest("hex").slice(0, 16);
8
+ }
9
+ export function readAll(path) {
10
+ if (!existsSync(path))
11
+ return [];
12
+ return readFileSync(path, "utf-8")
13
+ .split("\n")
14
+ .filter(Boolean)
15
+ .map((l) => JSON.parse(l));
16
+ }
17
+ export function filter(events, opts) {
18
+ let out = events;
19
+ if (opts?.after)
20
+ out = out.filter((e) => e.ts >= opts.after);
21
+ if (opts?.before)
22
+ out = out.filter((e) => e.ts <= opts.before);
23
+ if (opts?.source)
24
+ out = out.filter((e) => e.source === opts.source);
25
+ if (opts?.type)
26
+ out = out.filter((e) => e.type === opts.type);
27
+ if (opts?.last)
28
+ out = out.slice(-opts.last);
29
+ return out;
30
+ }
31
+ export function hashLine(line) {
32
+ return createHash("sha256").update(line).digest("hex").slice(0, 16);
33
+ }
34
+ const CURRENCY_EXEMPT_TYPES = new Set(["snapshot", "reclassify", "opening_balance"]);
35
+ export function append(path, event) {
36
+ if (!CURRENCY_EXEMPT_TYPES.has(event.type) && event.data.currency === undefined) {
37
+ throw new Error(`Event missing data.currency (type: ${event.type}, id: ${event.id})`);
38
+ }
39
+ if (!existsSync(path))
40
+ writeFileSync(path, "", "utf-8");
41
+ const existing = readAll(path);
42
+ if (existing.some((e) => e.id === event.id))
43
+ return false;
44
+ // Compute prev hash from last line in file
45
+ if (existing.length === 0) {
46
+ event.prev = "genesis";
47
+ }
48
+ else {
49
+ const lines = readFileSync(path, "utf-8").split("\n").filter(Boolean);
50
+ event.prev = hashLine(lines[lines.length - 1]);
51
+ }
52
+ appendFileSync(path, JSON.stringify(event) + "\n", "utf-8");
53
+ return true;
54
+ }
55
+ export function latestSnapshot(events, before) {
56
+ let snapshots = events.filter((e) => e.type === "snapshot");
57
+ if (before)
58
+ snapshots = snapshots.filter((e) => e.ts <= before);
59
+ return snapshots.at(-1) ?? null;
60
+ }
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "clawbooks",
3
+ "version": "0.1.0",
4
+ "description": "Accounting by inference, not by engine. Zero dependencies.",
5
+ "type": "module",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/rev1ck/clawbooks.git"
9
+ },
10
+ "homepage": "https://github.com/rev1ck/clawbooks#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/rev1ck/clawbooks/issues"
13
+ },
14
+ "keywords": [
15
+ "accounting",
16
+ "ledger",
17
+ "cli",
18
+ "bookkeeping",
19
+ "finance",
20
+ "llm"
21
+ ],
22
+ "bin": {
23
+ "clawbooks": "./build/cli.js"
24
+ },
25
+ "scripts": {
26
+ "build": "tsc && chmod 755 build/cli.js",
27
+ "prepare": "npm run build",
28
+ "prepack": "npm run build"
29
+ },
30
+ "files": [
31
+ "build",
32
+ "program.md",
33
+ "policy.md.example",
34
+ "policy-simple.md.example",
35
+ "policy-complex.md.example"
36
+ ],
37
+ "engines": {
38
+ "node": ">=20"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "dependencies": {},
44
+ "devDependencies": {
45
+ "@types/node": "^22.0.0",
46
+ "typescript": "^5.8.0"
47
+ },
48
+ "license": "MIT"
49
+ }
@@ -0,0 +1,149 @@
1
+ # Accounting policy
2
+
3
+ ## Entity
4
+
5
+ Solo quantitative trader operating across centralized exchanges, DeFi protocols, and prediction markets. US tax resident. Not registered as a company — individual trader.
6
+
7
+ Base currency: USD for all P&L tracking.
8
+ Fiscal year: January 1 to December 31.
9
+
10
+ ## Jurisdiction notes
11
+
12
+ The IRS treats crypto as property (Notice 2014-21, Rev. Rul. 2019-24). For a frequent trader:
13
+ - Short-term gains (held < 1 year) are taxed as ordinary income
14
+ - Long-term gains (held > 1 year) are taxed at capital gains rates (0%, 15%, or 20%)
15
+
16
+ This operation is frequent trading. **All crypto gains and losses are short-term unless a specific lot has been held over 1 year.**
17
+
18
+ ## Cost basis
19
+
20
+ FIFO (First In, First Out) for all assets across all venues.
21
+
22
+ Track cost basis per asset in USD.
23
+
24
+ Lot tracking: each acquisition event creates a lot. Each disposal event consumes lots in FIFO order. The LLM must maintain a running lot schedule when generating reports.
25
+
26
+ ## Source: Hyperliquid
27
+
28
+ Hyperliquid is a perpetual futures DEX. Events from this source include:
29
+
30
+ - **Trades** (type: `trade`): opening or closing perpetual positions. The `side` field indicates buy/sell. These are leveraged positions, not spot purchases. Track the notional value and the margin used.
31
+ - **Funding payments** (type: `funding`): periodic funding rate payments. If rate is positive and you're long, you pay. If rate is positive and you're short, you receive. Classify as **interest expense** (paid) or **interest income** (received).
32
+ - **Liquidations** (type: `liquidation`): forced closure of a position. Classify the loss as a **realized trading loss**. Flag for review — liquidations indicate risk management failure.
33
+ - **Deposits/Withdrawals** (type: `transfer`): movement of USDC to/from the Hyperliquid bridge contract on Arbitrum. These are not income or expense — they are transfers between own accounts. Match the on-chain transfer with the Hyperliquid balance change.
34
+
35
+ ### Hyperliquid P&L
36
+
37
+ Realized P&L on each trade = (exit price - entry price) x quantity x direction.
38
+ Include all fees (taker/maker) as a deduction from the P&L, not as a separate expense line.
39
+ Unrealized P&L on open positions should be reported separately and NOT included in taxable income until the position is closed.
40
+
41
+ ## Source: Polymarket
42
+
43
+ Polymarket is a binary prediction market on Polygon. Events include:
44
+
45
+ - **Position entry** (type: `trade`): buying YES or NO shares on a market. Cost basis = price paid per share x quantity. These are **speculative derivative contracts**, not purchases of an underlying asset.
46
+ - **Settlement** (type: `settlement`): market resolves. If the position wins, payout = number of shares x $1.00. If it loses, payout = $0. Realize the gain or loss as: payout - cost basis.
47
+ - **Redemption** (type: `trade`, side: `sell`): selling a position before settlement. Realize gain/loss as: sale proceeds - cost basis (FIFO).
48
+
49
+ ### Polymarket classification
50
+
51
+ Classify all Polymarket activity as **speculative derivative income/loss**. This is distinct from the trading income on Hyperliquid — keep them as separate line items in reports.
52
+
53
+ ## Source: Ethereum / Arbitrum / Polygon (on-chain)
54
+
55
+ Chain watchers emit transfer events. Classification rules:
56
+
57
+ - **Transfers between own wallets**: not income/expense. Internal transfer. Match by amount and token across the two addresses. Maintain a list of own addresses (see Known Addresses below).
58
+ - **Bridge transactions**: transfers to/from bridge contracts. These are internal transfers that may take time to complete. Match the source chain debit with the destination chain credit. If the amounts don't match after 1 hour, flag as a potential bridge failure.
59
+ - **Gas fees**: classify as **operating expense: gas**. Always denominated in the chain's native token (ETH, MATIC). Convert to USD at the block timestamp.
60
+ - **Token approvals**: zero economic impact, but record the gas fee.
61
+ - **Failed transactions**: the transaction reverted but gas was still consumed. Classify the gas as **operating expense: failed transaction gas**. This is deductible.
62
+ - **Unknown contract interactions**: flag for manual review. Do not auto-classify interactions with unrecognized contracts.
63
+
64
+ ## Source: Agent (autonomous agents, bots, etc.)
65
+
66
+ Agent-generated events are annotations, not primary financial events. They provide context for the LLM but do not create new economic activity.
67
+
68
+ - **Notes** (type: `note`): agent's commentary on a trade, strategy, or observation. Use these for context when generating reports but do not create journal entries from them.
69
+ - **Signals** (type: `signal`): agent's trading signals. These are informational only — the actual trade event from the exchange is the authoritative record.
70
+
71
+ Exception: if an agent records a type: `adjustment`, treat it as a legitimate correction (same as a human adjustment). The adjustment must include a `reason` field.
72
+
73
+ ## Reconciliation rules
74
+
75
+ ### Trade booking vs on-chain settlement
76
+
77
+ When a trade is executed on Hyperliquid/Polymarket, the exchange event and the on-chain settlement may not match exactly. Rules:
78
+
79
+ | Delta | Classification | Action |
80
+ |-------|---------------|--------|
81
+ | < 0.1% | Slippage | Auto-classify, no flag |
82
+ | 0.1% - 1.0% | Fee variance | Log as operating expense: execution variance |
83
+ | > 1.0% | Discrepancy | Flag for manual review, do not auto-classify |
84
+
85
+ ### Cross-source matching
86
+
87
+ When the same economic event appears from multiple sources (e.g., a Hyperliquid trade appears both in the exchange feed and in the Arbitrum chain watcher), deduplicate:
88
+
89
+ 1. Check `id` (content hash) — if identical, skip the duplicate
90
+ 2. If hashes differ (different raw payloads), match by: timestamp (+/-30 seconds) + amount (+/-0.5%) + token
91
+ 3. If matched, keep the exchange source as primary (more detailed), link the on-chain source as confirmation
92
+ 4. If not matched, flag both events for review
93
+
94
+ ## Known addresses
95
+
96
+ These are all my addresses. Transfers between them are internal.
97
+
98
+ - `0x_eth_main` — Ethereum mainnet primary
99
+ - `0x_arb` — Arbitrum primary
100
+ - `0x_polygon` — Polygon primary
101
+ - `0x_hl_deposit` — Hyperliquid deposit address
102
+
103
+ (Replace with actual addresses)
104
+
105
+ ## Reporting
106
+
107
+ ### Monthly
108
+ - P&L by source (Hyperliquid, Polymarket, other)
109
+ - Realized vs unrealized breakdown
110
+ - Funding income/expense
111
+ - Gas costs
112
+ - Open positions with unrealized P&L
113
+ - Cash/stablecoin balances across all venues
114
+
115
+ ### Quarterly
116
+ - Tax estimate (quarterly estimated payments due: April 15, June 15, September 15, January 15)
117
+ - Strategy performance: arb P&L (HL long + PM short combined)
118
+ - Win rate by market type
119
+ - Risk metrics: max drawdown, largest single loss
120
+ - Reconciliation status: any unresolved discrepancies
121
+
122
+ ### Annual (tax filing)
123
+ - Total income from trading (all sources)
124
+ - Total deductible expenses (gas, fees, execution variance, home office if applicable)
125
+ - Net taxable income
126
+ - Supporting schedule: every realized gain/loss with dates, amounts, cost basis
127
+ - Schedule D / Form 8949 preparation notes
128
+
129
+ ## Special rules
130
+
131
+ ### The arb strategy
132
+
133
+ The primary strategy is microstructure arbitrage between Hyperliquid and Polymarket on short-term BTC price windows. This means:
134
+
135
+ - A Hyperliquid long/short AND a Polymarket YES/NO position are opened together as a single economic unit
136
+ - When reporting arb P&L, combine the HL leg and PM leg into a single arb trade with net P&L
137
+ - For tax purposes, each leg is still reported individually (IRS doesn't recognize synthetic positions)
138
+ - For management accounting, report both: individual leg P&L AND combined arb P&L
139
+
140
+ ### Stablecoin treatment
141
+
142
+ USDC, USDT, and DAI are treated as cash equivalents. Do not track cost basis on stablecoins — treat them as USD at 1:1. If a stablecoin depegs more than 2%, flag and begin tracking cost basis from that point.
143
+
144
+ ### Airdrops and rewards
145
+
146
+ Any tokens received as airdrops, staking rewards, or protocol incentives:
147
+ - Recognize as income at fair market value at time of receipt
148
+ - Cost basis = fair market value at receipt
149
+ - If no reliable price feed exists, flag for manual valuation
@@ -0,0 +1,48 @@
1
+ # Accounting policy
2
+
3
+ ## Entity
4
+
5
+ Small web design studio. US-based, single member LLC.
6
+ Cash basis accounting. Fiscal year: January to December.
7
+ Base currency: USD.
8
+
9
+ ## Revenue recognition
10
+
11
+ Income is recognized when payment is received, not when invoiced.
12
+ All client payments are service revenue.
13
+ Crypto payments are converted to USD at the spot price at time of receipt and recognized as service revenue at that USD amount. The crypto itself is not held as an investment — convert or record the USD equivalent immediately.
14
+
15
+ ## Expense classification
16
+
17
+ - **Software subscriptions** (Figma, hosting, domains): operating expenses
18
+ - **Contractor payments**: cost of goods sold
19
+ - **Hardware** (laptops, monitors): capitalize if over $2,500, otherwise operating expense. Depreciate capitalized assets over 3 years straight-line.
20
+ - **Home office**: allocate 15% of rent and utilities as business expense
21
+ - **Meals with clients**: 50% deductible business expense
22
+ - **Conference travel**: fully deductible if business purpose documented
23
+
24
+ ## Tax
25
+
26
+ Quarterly estimated tax payments due: April 15, June 15, September 15, January 15.
27
+ Self-employment tax rate: 15.3% on net earnings.
28
+ Set aside 30% of net income for combined federal + state + SE tax.
29
+ State: California.
30
+
31
+ ## Bank accounts
32
+
33
+ - Chase Business Checking: primary operating account
34
+ - Mercury: secondary / savings
35
+ - Stripe: payment processing (settlement to Chase, 2-day rolling)
36
+
37
+ When Stripe settles to Chase, do not double-count. The Stripe payout and the Chase deposit are the same money. Match them by amount and date (±2 days).
38
+
39
+ ## Invoicing
40
+
41
+ Net 30 terms. Invoices over 45 days past due should be flagged.
42
+ Deposits (typically 50% upfront) are recognized as revenue when received, not deferred.
43
+
44
+ ## Reports
45
+
46
+ - Monthly: P&L summary, outstanding invoices, cash position
47
+ - Quarterly: tax estimate, P&L by client, expense breakdown by category
48
+ - Annual: full P&L, balance sheet, Schedule C preparation
@@ -0,0 +1,80 @@
1
+ # Accounting policy
2
+
3
+ ## Entity
4
+
5
+ Describe your business here.
6
+
7
+ ## Currencies
8
+
9
+ Base currency: USD.
10
+ The CLI aggregates per-currency; the agent handles cross-currency reporting and conversions when needed.
11
+
12
+ ## Revenue recognition
13
+
14
+ Cash basis. Income is recognized when payment is received.
15
+
16
+ ## Expense classification
17
+
18
+ ### Operating expenses (OpEx)
19
+ - **Software subscriptions** (Figma, hosting, domains, SaaS tools)
20
+ - **Home office**: allocate 15% of rent and utilities as business expense
21
+ - **Meals with clients**: 50% deductible business expense
22
+ - **Conference travel**: fully deductible if business purpose documented
23
+ - **Office supplies**: consumables, stationery, minor accessories
24
+ - **Professional services**: legal, accounting, consulting
25
+ - **Insurance**: business-related insurance premiums
26
+ - **Bank fees**: monthly fees, transaction charges, card fees
27
+
28
+ ### Cost of goods sold (COGS)
29
+ - **Contractor payments**: direct labor for client deliverables
30
+ - **Platform fees**: marketplace commissions, payment processing fees tied to revenue
31
+
32
+ ### Capital expenditure (CapEx)
33
+ See capitalization policy below. Hardware, equipment, and other tangible assets above the threshold are capitalized, not expensed.
34
+
35
+ ## Capitalization policy
36
+
37
+ - **Threshold**: $2,500 — items below this are expensed immediately
38
+ - **Method**: straight-line depreciation
39
+ - **Default useful life**: 36 months (per-asset override via `data.useful_life_months`)
40
+ - **Selection**: events with `data.capitalize: true` appear in the asset register
41
+ - **Disposal**: record a `disposal` event with `data.asset_id` and `data.proceeds`. Gain/loss = proceeds - net book value
42
+ - **Write-off**: record a `write_off` event with `data.asset_id`. Remaining NBV is a loss
43
+ - **Impairment**: record an `impairment` event with `data.asset_id` and `data.impairment_amount`. Reduces carrying value
44
+
45
+ ## Tax jurisdiction
46
+
47
+ Your jurisdiction and relevant rules.
48
+
49
+ ## Reconciliation
50
+
51
+ ### Post-import checklist
52
+ 1. **Count**: verify event count matches source row count
53
+ 2. **Debits/credits**: verify totals match source statement totals
54
+ 3. **Closing balance**: `clawbooks verify --balance <closing> --currency USD`
55
+ 4. **Duplicates**: review `potential_duplicates` in verify output
56
+ 5. **Gaps**: `clawbooks reconcile --source S --gaps` to find date gaps >7 days
57
+
58
+ ### Cross-source checks
59
+ When importing from multiple sources (bank, Stripe, manual), verify:
60
+ - No double-counting of the same transaction across sources
61
+ - Transfers between accounts net to zero
62
+ - Opening balances + net transactions = closing balances per source
63
+
64
+ ## Reporting
65
+
66
+ ### Monthly
67
+ - **P&L**: revenue, operating expenses, COGS, tax, net income
68
+ - **Cash flow**: inflows vs outflows by category
69
+ - **Reconciliation**: verify + reconcile for each source imported that month
70
+
71
+ ### Quarterly
72
+ - **Balance sheet**: assets (cash + capitalized), liabilities, equity
73
+ - **Asset register**: `clawbooks assets --as-of <quarter-end>` — active, disposed, written-off
74
+ - **Tax estimate**: projected tax based on year-to-date income
75
+
76
+ ### Annual
77
+ - **Full P&L**: 12-month income statement with monthly breakdown
78
+ - **Balance sheet**: year-end position
79
+ - **Asset register**: full depreciation schedule, disposals, write-offs
80
+ - **Tax preparation**: categorized expenses, income by source, deductions summary
package/program.md ADDED
@@ -0,0 +1,186 @@
1
+ # Clawbooks
2
+
3
+ You have access to `clawbooks`, a CLI tool for financial record-keeping.
4
+ The ledger is an append-only JSONL file. The accounting policy is a markdown file.
5
+ You are the accountant. The CLI is just data storage.
6
+
7
+ ## Reading the books
8
+
9
+ To answer any financial question, first load context:
10
+
11
+ ```bash
12
+ clawbooks context 2026-03 # specific month
13
+ clawbooks context --after 2026-01-01 # everything since a date
14
+ clawbooks context # everything (small ledgers)
15
+ ```
16
+
17
+ This prints the accounting policy, the latest snapshot, and all events
18
+ in the period. Read the output, apply the policy, answer the question.
19
+
20
+ ## Writing events
21
+
22
+ To record a financial event:
23
+
24
+ ```bash
25
+ clawbooks record '{"source":"stripe","type":"income","data":{"amount":500,"currency":"USD","customer":"acme"}}'
26
+ ```
27
+
28
+ Required fields: `source`, `type`, `data` (any object). `ts` is optional (defaults to now).
29
+ `data.currency` is **required** — the ledger rejects events without it (except snapshots, reclassify, opening_balance).
30
+
31
+ The CLI enforces sign convention automatically for known types:
32
+ - **Outflow** (stored negative): `expense`, `tax_payment`, `owner_draw`, `fee`, `dividend`, `loan_repayment`, `refund`, `transfer_out`, `withdrawal`
33
+ - **Inflow** (stored positive): `income`, `deposit`, `equity_injection`, `loan_received`, `transfer_in`, `refund_received`, `grant`
34
+ - **Meta types** (sign not enforced): `snapshot`, `reclassify`, `opening_balance`
35
+ - **Asset events** (sign not enforced): `disposal`, `write_off`, `impairment`
36
+ - **Unknown types**: the CLI warns and preserves the sign you provide. Use critical thinking — if a new type represents money leaving the business, pass a negative amount. `verify` will flag sign inconsistencies.
37
+
38
+ The ledger is hash-chained — each event's `prev` field links to the previous event.
39
+
40
+ For bulk data, output JSONL and pipe it:
41
+
42
+ ```bash
43
+ echo '{"source":"bank","type":"income","data":{"amount":1000,"currency":"USD"}}
44
+ {"source":"bank","type":"fee","data":{"amount":25,"currency":"USD","desc":"Monthly fee"}}' | clawbooks batch
45
+ ```
46
+
47
+ ## Opening balances
48
+
49
+ Before importing transaction data, record opening balances for each account/currency. One event per account/currency:
50
+
51
+ ```bash
52
+ clawbooks record '{"source":"manual","type":"opening_balance","ts":"2025-01-01T00:00:00.000Z","data":{"amount":50000,"currency":"USD","account":"checking","category":"cash"}}'
53
+ clawbooks record '{"source":"manual","type":"opening_balance","ts":"2025-01-01T00:00:00.000Z","data":{"amount":-12000,"currency":"USD","account":"credit_card","category":"liability"}}'
54
+ ```
55
+
56
+ Convention:
57
+ - Positive amount = asset (cash, receivables, equipment)
58
+ - Negative amount = liability (credit cards, loans)
59
+ - `data.category`: `cash`, `asset`, `liability`, or `equity`
60
+ - `data.account`: identifies which account (e.g., `checking`, `credit_card`)
61
+ - One event per account/currency pair
62
+ - `opening_balance` is exempt from currency requirement and sign enforcement
63
+
64
+ ## Importing messy data (CSVs, statements, etc.)
65
+
66
+ When the user gives you a CSV or other raw financial data:
67
+
68
+ 1. Record opening balances first (if not already present)
69
+ 2. Read the raw data and the policy (`clawbooks policy`)
70
+ 3. Parse each row into a ledger event, classifying per the policy
71
+ 4. For hardware/equipment purchases that meet the capitalization threshold, set `data.capitalize: true` and optionally `data.useful_life_months`
72
+ 5. Output as JSONL and pipe to `clawbooks batch`
73
+ 6. Run `clawbooks verify --balance <closing_balance>` to cross-check against the statement's closing balance
74
+
75
+ You are the parser. There is no import tool. You read the data and write the events.
76
+
77
+ ## Capitalizing assets
78
+
79
+ When an expense meets the capitalization threshold (see policy), set `data.capitalize: true` on the event:
80
+
81
+ ```bash
82
+ clawbooks record '{"source":"bank","type":"expense","ts":"2025-09-15T00:00:00.000Z","data":{"amount":15000,"currency":"USD","description":"MacBook Pro","category":"hardware","capitalize":true,"useful_life_months":36}}'
83
+ ```
84
+
85
+ - `data.capitalize: true` — marks the event for the asset register
86
+ - `data.useful_life_months` — overrides the default useful life (default: 36 months)
87
+ - The `assets` command finds all events with `capitalize: true` and computes depreciation
88
+ - `--category` on the `assets` command is an optional filter, not the selection mechanism
89
+
90
+ ## Asset lifecycle
91
+
92
+ After capitalizing an asset, you can record disposal, write-off, or impairment events. These reference the original asset by its event ID via `data.asset_id`:
93
+
94
+ **Disposal** (sold or traded in):
95
+ ```bash
96
+ clawbooks record '{"source":"manual","type":"disposal","data":{"asset_id":"abc123","proceeds":5000,"currency":"USD"}}'
97
+ ```
98
+ Gain/loss = proceeds - net book value at time of disposal.
99
+
100
+ **Write-off** (destroyed, stolen, obsolete):
101
+ ```bash
102
+ clawbooks record '{"source":"manual","type":"write_off","data":{"asset_id":"abc123","currency":"USD"}}'
103
+ ```
104
+ Remaining NBV becomes a loss.
105
+
106
+ **Impairment** (value reduced but still in use):
107
+ ```bash
108
+ clawbooks record '{"source":"manual","type":"impairment","data":{"asset_id":"abc123","impairment_amount":3000,"currency":"USD"}}'
109
+ ```
110
+ Reduces carrying value by the impairment amount. Multiple impairments can accumulate.
111
+
112
+ ## Generating reports
113
+
114
+ When asked for a P&L, tax summary, balance, etc.:
115
+
116
+ 1. Run `clawbooks summary <period>` for pre-computed aggregates
117
+ 2. Map the output to the requested report:
118
+ - **P&L**: `by_type` + `by_category` → Revenue - OpEx = Gross Profit - Tax = Net
119
+ - **Balance Sheet**: `cash_flow.net` + opening balance (from snapshot or opening_balance events) → Assets. Capitalized assets from `clawbooks assets`. Equity = Assets - Liabilities
120
+ - **Cash Flow Statement**: Map categories to Operating/Investing/Financing per policy
121
+ 3. For details or edge cases, also run `clawbooks context <period>` and reason over raw events
122
+
123
+ ## Reconciliation workflow
124
+
125
+ After importing data from any source:
126
+
127
+ 1. During import, compute expected totals (count, debits, credits) from the source data
128
+ 2. Run `clawbooks verify <period> --source S` to check integrity (totals, hash, issues)
129
+ 3. Run `clawbooks verify --balance <closing_balance> --currency USD` to cross-check the statement's closing balance
130
+ 4. Run `clawbooks reconcile <period> --source S --count N --debits N --credits N --gaps` to compare and detect date gaps
131
+ 5. Review `potential_duplicates` in verify output — same source/date/amount/description
132
+ 6. If `RECONCILED`, proceed. If `MISMATCH`, investigate and fix before generating reports
133
+ 7. Include the verify hash in report footers for audit trail
134
+
135
+ ## Classification review
136
+
137
+ When importing events, set a `confidence` field in each event's data:
138
+ - `"clear"` — unambiguous classification (e.g., payroll labeled by bank)
139
+ - `"inferred"` — reasonable but uncertain (e.g., "AMZN" → office supplies)
140
+ - `"unclear"` — couldn't classify confidently
141
+
142
+ After import, run `clawbooks review <period> --source S` to see items needing review.
143
+
144
+ To reclassify an event, record an append-only correction:
145
+ ```bash
146
+ clawbooks record '{"source":"manual","type":"reclassify","data":{"original_id":"abc123","new_category":"contractor"}}'
147
+ ```
148
+
149
+ The `summary` command automatically applies reclassifications. The `review` command excludes already-reclassified events.
150
+
151
+ ## Generating snapshots
152
+
153
+ When the ledger is large, generate a snapshot to keep future context bounded:
154
+
155
+ ```bash
156
+ clawbooks snapshot 2026-03 --save # compute and save to ledger
157
+ clawbooks snapshot 2026-03 # compute and print (no save)
158
+ ```
159
+
160
+ The snapshot includes balances by currency, totals by category, and P&L by currency.
161
+
162
+ ## Quick reference
163
+
164
+ ```
165
+ clawbooks record <json> # append one event
166
+ clawbooks batch # append JSONL from stdin
167
+ clawbooks log [--last N] # view recent events
168
+ clawbooks context [period] # load policy + events for reasoning
169
+ clawbooks policy # print policy.md
170
+ clawbooks stats # ledger overview
171
+ clawbooks verify [period] # integrity + chain + balance check + duplicates
172
+ clawbooks verify --balance N # cross-check closing balance
173
+ clawbooks reconcile [period] -S # compare expected vs actual totals
174
+ clawbooks reconcile -S --gaps # also detect date gaps >7 days
175
+ clawbooks review [period] # show items needing classification review
176
+ clawbooks summary [period] # pre-computed aggregates for reports
177
+ clawbooks snapshot [period] [--save] # compute period snapshot (balances, P&L)
178
+ clawbooks assets [--category C] [--life N] [--as-of DATE]
179
+ # asset register (capitalize-flag based)
180
+ ```
181
+
182
+ ## Idempotent imports
183
+
184
+ When importing from a source (CSV, statement), include a stable `data.ref` field derived
185
+ from the source row (e.g. hash of date + description + amount + running balance). This
186
+ ensures re-importing the same source file produces identical event IDs and gets deduplicated.