CLI Scripting & Piping
Use the Bkper CLI as a scripting tool — pipe JSON between commands for batch creates and updates, reshape output with jq for data pipelines and AI agents, and chain operations to migrate, transform, or sync book data without writing code.
The Bkper CLI is designed for scripting. Every data command outputs JSON, and selected write commands accept piped JSON input — making it easy to build data pipelines, batch operations, and automated workflows.
Output format
All data commands output JSON only. Results go to stdout. Hints (such as the next-page command), warnings, and notices go to stderr, so stdout is always parseable.
| Output | Shape |
|---|---|
Lists (book list, transaction list, batch writes, …) | {"items":[...]}, plus "cursor" only when another page exists |
Single items (get, create, update, …) | One JSON object |
Balances (balance list) | A 2D matrix: header row first, then one row per account or group |
# List output: one record per line inside the envelopebkper account list -b abc123# {"items":[# {"id":"acc-abc","name":"Cash","type":"ASSET",...},# {"id":"acc-def","name":"Revenue","type":"INCOMING",...}# ]}Output details:
- Lists and balance matrices put one record or row per line, so
head,grep, andwc -lwork on records. - Single items are pretty-printed on an interactive terminal and compact (one line) otherwise.
- Transactions include
creditAccount.nameanddebitAccount.name, so the from/to flow is readable without an account lookup. Custom properties are always included. - Transaction
amountvalues are exact decimal strings. - Balance values are unformatted JSON numbers, dates are ISO
yyyy-MM-dd, and account and group properties are extra columns. Group hierarchy is shown by indenting names 4 spaces per level.
--json and --format json are accepted for compatibility and have no effect. Table and CSV output formats were removed in CLI v5; reshape JSON with jq instead.
Reshape with jq
# Iterate list itemsbkper transaction list -b abc123 -q "on:2025-01" | jq '.items[]'
# Pick columnsbkper transaction list -b abc123 -q "on:2025-01" | \ jq '.items[] | {date, amount, from: .creditAccount.name, to: .debitAccount.name, description}'
# Export transactions to CSVbkper transaction list -b abc123 -q "on:2025-01" | \ jq -r '.items[] | [.date, .amount, .creditAccount.name, .debitAccount.name, .description] | @csv'
# Export a balance matrix to CSVbkper balance list -b abc123 -q "on:2025-12-31" | jq -r '.[] | @csv'
# Read the next-page cursorbkper transaction list -b abc123 -q "on:2025" --limit 100 | jq -r '.cursor // empty'Query semantics quick reference
Use these rules in scripts to avoid ambiguous or empty results:
on:supports year, month, and day (on:2025,on:2025-01,on:2025-01-31).after:is inclusive andbefore:is exclusive.- A full-year range uses next-year boundary:
after:2025-01-01 before:2026-01-01
# Full year with on:bkper transaction list -b $BOOK_ID -q "on:2025"
# Same full year with explicit boundariesbkper transaction list -b $BOOK_ID -q "after:2025-01-01 before:2026-01-01"Batch operations
Write commands (account create, transaction create, transaction update) accept JSON piped via stdin. The input format follows the Bkper API Types — a single JSON object or an array of objects.
Groups are created explicitly with bkper group create --name and optional --parent, so hierarchy stays deterministic.
Creating in batch
# Create transactions from JSONecho '[{ "date": "2025-01-15", "amount": "100.50", "creditAccount": {"name": "Bank Account"}, "debitAccount": {"name": "Office Supplies"}, "description": "Printer paper", "properties": {"invoice": "INV-001"}}]' | bkper transaction create -b abc123
# Create accountsecho '[{"name":"Cash","type":"ASSET"},{"name":"Revenue","type":"INCOMING"}]' | \ bkper account create -b abc123
# Create a group explicitlybkper group create -b abc123 --name "Fixed Costs" --hidden
# Pipe from any script that outputs JSONpython export_bank.py | bkper transaction create -b abc123Batch results use the same {"items":[...]} envelope as lists:
bkper account create -b abc123 < accounts.json# {"items":[# {"id":"acc-abc","name":"Cash",...},# {"id":"acc-def","name":"Revenue",...}# ]}Stdin accepts a single object, an array, or the {"items":[...]} envelope, so list and batch output can be piped directly into another command.
Adding properties via CLI flag
The --property flag can add or override properties from the stdin payload:
echo '[{"name":"Cash","type":"ASSET"}]' | \ bkper account create -b abc123 -p "region=LATAM"Piping between commands
All JSON output is designed to feed directly into other commands. This is the most powerful pattern — combining commands into pipelines:
Copy data between books
# Copy all accounts from one book to anotherbkper account list -b $BOOK_A | bkper account create -b $BOOK_B
# Copy transactions matching a querybkper transaction list -b $BOOK_A -q "after:2025-01-01" | \ bkper transaction create -b $BOOK_BRecreate groups explicitly with bkper group create --name ... --parent ... before copying accounts that reference them.
Clone a full chart of accounts
# Recreate the group hierarchy explicitlybkper group create -b $DEST --name "Assets"bkper group create -b $DEST --name "Current Assets" --parent "Assets"
# Then copy accounts and transactionsbkper account list -b $SOURCE | bkper account create -b $DESTbkper transaction list -b $SOURCE -q "after:2025-01-01" | \ bkper transaction create -b $DESTBatch updates with jq
Use jq to transform data between commands:
# List transactions, modify descriptions, pipe back to updatebkper transaction list -b $BOOK -q "after:2025-01-01" | \ jq '[.items[] | .description = "Updated: " + .description]' | \ bkper transaction update -b $BOOK
# Add a property to all matching transactionsbkper transaction list -b $BOOK -q "account:Expenses" | \ bkper transaction update -b $BOOK -p "reviewed=true"
# Batch update checked transactionsbkper transaction list -b $BOOK -q "is:checked after:2025-01-01" | \ bkper transaction update -b $BOOK --update-checked -p "migrated=true"Shell script examples
Daily export
#!/bin/bash# Export yesterday's transactions to CSVDATE=$(date -d "yesterday" +%Y-%m-%d)bkper transaction list -b $BOOK_ID -q "on:$DATE" | \ jq -r '.items[] | [.date, .amount, .creditAccount.name, .debitAccount.name, .description] | @csv' \ > "export-$DATE.csv"Bulk categorization
#!/bin/bash# Add a property to all uncategorized transactionsbkper transaction list -b $BOOK_ID \ -q "account:Uncategorized" | \ bkper transaction update -b $BOOK_ID -p "needs_review=true"Combining with other tools
The CLI works with standard Unix tools:
# Count transactions matching a querybkper transaction list -b $BOOK_ID -q "after:2025-01-01" | jq '.items | length'
# Extract specific fields with jqbkper account list -b $BOOK_ID | \ jq '[.items[] | {name, type}]'
# Sort by amountbkper transaction list -b $BOOK_ID -q "after:1900-01-01" | \ jq '.items | sort_by(.amount | tonumber) | reverse'Full CLI reference
For the complete command reference including all options, see the bkper-cli app page or run bkper --help.