bukio-cli
Allows creation of SEPA payment batches from unpaid invoices or CSV and exports pain.001 files for upload to Dutch bank portals.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@bukio-cliRecord a €250 purchase of office supplies on the bank account."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Agent-first double-entry bookkeeping for Dutch SMEs.
VAT-optional · Peppol BIS 3.0-ready · Local-first (SQLite) · MCP-native
bukio-cli is a double-entry bookkeeping engine and CLI that runs natively on a VPS, stores everything in one local SQLite file, and is designed so AI agents — not just humans — can operate it safely and auditably. It is built for the Dutch B2B e-invoicing mandate: every invoice ends as a compliant PDF, a Peppol BIS 3.0 UBL document, and a sendable Peppol message.
Proven in production: bukio-cli currently runs a live Dutch company's books, operated end-to-end by Hermes Agent (Nous Research) running DeepSeek V4 Flash via OpenCode Go on a Linux VPS — the same stack every day: bank imports, invoice booking, month-end close checks and statutory reports, every action attributable in the audit log. The full stack disclosure is in AI Development Cost & Token Usage.
Features
Agent-native — every command emits deterministic
--json; every mutation supports--dry-run(plan mode); every action lands in an append-only audit log with named-actor attribution (--actor agent:bartholomeus/human:erik).VAT optional — the core ledger is VAT-agnostic. The optional VAT module adds codes, the OB readout (fields 1a–5d) and KOR support when you need them. Filing always stays manual — bukio never submits anything.
Peppol BIS 3.0 ready — the 2027 mandate both ways:
finalize → PDF → UBL → peppol-sendfor outgoing, andimport invoice(EN 16931/Peppol UBL) into the payables register for incoming.invoice emaildelivers the PDF by SMTP (BUKIO_SMTP_*env).Documents in the DB —
attachstores source documents (PDFs, scans) as BLOBs by default (metadata-only lists; 25 MB/file cap; sha256 dedupe) or content-addressed files, so the books carry their paper trail and backups stay one consistent file.backup --encrypt(AES-256-GCM) +--keep Nrotation protects it off-box.Cash management reports —
report aging(debtors/creditors 30/60/90+ buckets),contact statement(opgave with running balance),report sales --by contact|itemfor the agent's weekly briefings.FX built in — book foreign-currency purchase invoices in USD, GBP, …; rates resolve from your rate store or straight from the ECB.
Migration-ready —
import opening-balances,import journal(SnelStart/Exact-style CSV) andimport xaf(XML Auditfile Financieel 4.0) bring a whole administration in; every importer validates the entire file before writing a single cent.Runs itself —
month-endis the agent's close check (drafts, bank, VAT, invoices, recurring, fixed assets, profit);invoice remindersdrafts overdue payment reminders.Fixed assets — depreciation schemes (lineair / degressief with the standard switch-to-linear rule), an asset register with mid-life adoption (recognition date + cumulative depreciation at recognition — only the remaining depreciation is booked), monthly runs (idempotent per asset-month), disposal with winst/verlies booking, and the activastaat (CSV/XLSX export).
SEPA payment batches — a payables register (purchase invoices,
transfervsdirect_debit/incasso), batch creation from unpaid invoices or CSV, and pain.001 export (001.03/001.09) for upload in any Dutch bank portal. Direct debit adds an incassovolmacht register (payments mandate add, core/b2b) and pain.008.001.02 export (onePmtInfper scheme, FRST/RCUR auto-assigned). One export per batch (uniqueMsgId— re-uploading would double-pay); the ledger is untouched until the bank statement import books the payments.One company per database — a second company is a second SQLite file (
--dborBUKIO_DB).Local-first — no cloud, no lock-in. Your 7-year administration stays yours.
Related MCP server: billy-mcp
Quick start
Let your agent do it. Paste this prompt to any agentic assistant — the agent installs from source and stops before touching any financial data:
Install bukio-cli from github.com/erikvankempen/bukio-cli.
Verify Node.js 20+ and a Linux or macOS environment, then clone the repository, run npm install and npm link, and confirm with bukio --version.
Read the repository README.md and AGENTS.md files, configure `bukio mcp` as a local stdio MCP server, and explain the setup you made. Do not create a company or book real transactions yet. When we start, use named actors, preview every mutation with --dry-run, and ask for confirmation before writing.Screenshot
Table of Contents
Requirements & Install
Node.js >= 20
Linux/macOS (developed on a Linux VPS)
git clone https://github.com/erikvankempen/bukio-cli.git
cd bukio-cli
npm install # deps: better-sqlite3, commander
npm link # exposes `bukio` on PATH (or: npm install -g .)
bukio --versionUninstall: npm unlink -g bukio-cli (or npm uninstall -g bukio-cli).
Core Concepts
Double-entry bookkeeping
Every journal entry contains two or more postings (debits and credits) whose amounts sum to zero. Positive amounts are debits, negative amounts are credits. This invariant is enforced by the engine at creation time and by a database trigger when an entry is posted — an unbalanced posted entry is impossible.
Accounts and the chart of accounts
Accounts are organised in a chart of accounts with 4-digit codes and a type:
Type | Normal balance | Examples |
| debit | 1000 Kas, 1100 Bank, 1200 Debiteuren |
| credit | 2000 Crediteuren, 2100 Overige schulden |
| credit | 3000 Eigen vermogen |
| debit | 4000 Inkoopwaarde, 4100–4500 kosten |
| credit | 8000 Omzet, 8100 Overige opbrengsten |
bukio init seeds a minimal default chart (14 accounts, no VAT accounts — the core is VAT-agnostic). The full RGS (Referentie Grootboekschema) taxonomy import arrives in Phase 1; account codes are RGS-compatible in structure.
Entry lifecycle
draft ──post──▶ posted ──reverse──▶ (original stays posted)
│ + contra-entry posted (negated postings)
└──reverse── (not allowed) + audit traildraft — a work-in-progress entry. Postings can be added/changed/removed (via SQL or future commands). Drafts are excluded from reports.
posted — final. Postings are immutable (database trigger). Posted entries appear in the trial balance.
reverse — reversing a posted entry posts a linked contra-entry with negated postings. The original entry stays posted — the contra-entry cancels it, so the net effect on the books is zero. Linkage: the contra-entry's
reversed_from_idpoints at the original; the audit log records the action. Posted entries are never deleted — they are reversed.
Actors
Every mutation records an actor — every command requires a named identity in the form '<role>:<name>': human:erik when you act yourself, agent:bartholomeus when an agent acts. A bare human or agent is rejected. Actors appear on entries (created_by) and in the audit log, so a human can always see exactly what an agent did.
The audit log
An append-only log of every mutation: actor, action, command, JSON args, outcome, and affected entry IDs. Database triggers block UPDATE and DELETE — the log cannot be rewritten after the fact. Read it with bukio audit.
Amounts
All money is stored as integer cents (amount_cents). There are no floats anywhere in financial code paths. See Money Format.
Command Reference
Global flags (--json, --db, --actor) can appear before or after the subcommand. See Global Flags.
bukio init
Initialise a company database: creates the file, the company row, and seeds the default chart of accounts.
Option | Default | Description |
| (required) | Company name |
| — | KVK number |
|
|
|
| — | BTW identification number |
| — | Bank account (IBAN) |
|
| Enable the VAT module (Phase 2) |
| off | Small business scheme — implies |
|
| Fiscal year end |
| off | Show the plan without writing anything |
Fails with ALREADY_INITIALISED if the database already has a company.
bukio init --name "Demo BV" --kvk 12345678 --legal-form bv --vat on --dry-run
bukio init --name "Demo BV" --kvk 12345678 --legal-form bv --vat onbukio company
Company record — the supplier gegevens on your invoices (12-vereisten 1–3 must be complete before invoice finalize).
Command | Purpose |
| Current company record (name, kvk, btw-id, iban, address) |
| Update supplier data (audited; IBAN mod-97 validated) |
| Store/extract the invoice logo (PNG/JPEG/SVG ≤ 1 MB, ≤ 2048×2048 px, stored as a BLOB in the DB — travels with backups) |
bukio company update --address "Industrieweg 12" --postal-code "2712 CD" --city "Zoetermeer" --btw-id NL123456789B01
bukio company update --logo ~/logo.svg
bukio company showbukio entry add
Create a journal entry (draft by default; --post posts it immediately).
Option | Default | Description |
| today | Entry date (ISO) |
| (required) | Description |
| (required) | Posting spec — repeat the flag or comma-separate; positive = debit, negative = credit |
|
|
|
| — | Source reference (e.g. invoice number) |
| off | Post immediately (draft → posted) |
| off | Validate and show the plan without writing |
# two postings, comma-separated
bukio entry add --date 2026-08-04 --desc "Startkapitaal" \
--postings "1100:10000.00,3000:-10000.00" --post
# equivalent: repeated flag
bukio entry add --desc "Startkapitaal" \
--postings "1100:10000.00" --postings "3000:-10000.00"
# three postings (VAT-like split is a Phase 2 concern; 3-leg entries work today)
bukio entry add --desc "3-leg example" \
--postings "1100:121.00,8000:-100.00,2100:-21.00" --dry-runValidation errors (see Error Codes): INVALID_POSTING, INVALID_AMOUNT, INVALID_DATE, INVALID_DESCRIPTION, TOO_FEW_POSTINGS, UNBALANCED, ACCOUNT_NOT_FOUND, ACCOUNT_INACTIVE, INVALID_AMOUNT_CENTS, INVALID_SOURCE.
bukio entry post
Post a draft entry (draft → posted).
Option | Default | Description |
| (required) | Entry id |
| off | Show the plan without writing |
The database trigger backstops the invariant: an entry needs >= 2 postings summing to zero before it can be posted.
bukio entry reverse
Reverse a posted entry: posts a linked contra-entry with negated postings. The original stays posted; the contra-entry cancels it (net effect zero). See Core Concepts.
Option | Default | Description |
| (required) | Entry id |
| — | Reason, appended to the contra-entry description |
| off | Show the planned contra-entry without writing |
Fails with NOT_POSTED for drafts and ALREADY_REVERSED if a posted reversal already exists.
bukio entry reverse --id 2 --reason "verkeerde categorie" --dry-run
bukio entry reverse --id 2 --reason "verkeerde categorie"bukio entry list
List journal entries (newest first).
Option | Default | Description |
| all |
|
| — | Earliest date (inclusive) |
| — | Latest date (inclusive) |
|
| Max rows |
bukio entry show
Show one entry with its full postings.
Option | Default | Description |
| (required) | Entry id |
bukio report trial-balance
Per-account debit/credit/net totals from posted entries, with a final BALANCED/UNBALANCED verdict. Drafts and the mirror of reversed entries behave per the lifecycle rules (drafts excluded; contra-entries included — that's what makes reversals net to zero).
Option | Default | Description |
| all years | Filter by year |
| human (json with |
|
| stdout | Output file (required for xlsx) |
bukio report balans
Balance sheet as of a date, grouped by RGS hoofdgroep (Materiële vaste activa, Voorraden, Vorderingen, Liquide middelen / Eigen vermogen, Kortlopende schulden, …). Includes the computed Nog te verdelen resultaat (net result of income/expense accounts). Invariant: total assets = total liabilities + equity + result — the report says BALANCED or UNBALANCED!.
Option | Default | Description |
| today | Balance date (inclusive) |
| human (json with |
|
| stdout | Output file (required for xlsx) |
bukio report pnl
Winst- en verliesrekening for a period, grouped by RGS hoofdgroep (Omzet, Inkoopwaarde van de omzet, Personeelskosten, Afschrijvingen, Overige bedrijfskosten, Financiële baten en lasten, …). Reports revenue, costs and Netto resultaat.
Option | Default | Description |
| current year | Fiscal year (sets from/to) |
| year start | Period start (inclusive) |
| year end | Period end (inclusive) |
| human (json with |
|
| stdout | Output file (required for xlsx) |
bukio report journal
Journal export — one row per posting with account info, for a period. Ideal for handing to your boekhouder.
Option | Default | Description |
| current year | Fiscal year (sets from/to) |
| year start | Period start (inclusive) |
| year end | Period end (inclusive) |
| human (json with |
|
| stdout | Output file (required for xlsx) |
bukio report balans --as-of 2026-12-31
bukio report pnl --year 2026 --format xlsx --out ~/exports/pnl-2026.xlsx
bukio report journal --year 2026 --format csv --out ~/exports/journal-2026.csvbukio report aging / report sales / contact statement
Open-items and revenue analytics (v0.14) — all exportable with --format csv|xlsx [--out].
Command | Purpose |
| Open items per contact bucketed by days past due (current/30/60/90+); creditors show |
| Sales revenue: per contact (net/vat/gross via the totals engine) or per item (net after per-line discounts; invoice-level discounts are not allocated per line) |
| Opgave: the contact's invoices + payments + payables with a running balance (positive = they owe you) |
bukio report aging --kind debtors --format csv --out ~/exports/aging.csv
bukio report sales --year 2026 --by contact
bukio contact statement --id 3bukio account
Chart of accounts management.
Command | Purpose |
| Add an account |
| List accounts |
| Show one account |
| Deactivate (blocks new postings; history stays) |
| Reactivate |
| Import a chart from CSV: |
The bundled default chart lives at assets/chart-nl.csv — you can import it (or your own) into any database:
bukio account import --file assets/chart-nl.csv --dry-run # validate first
bukio account import --file assets/chart-nl.csvbukio bank
Bank accounts, import and matching.
Command | Purpose |
| Register a bank account (links to a ledger account) |
| Accounts with balance, transaction and unmatched counts |
| Import transactions — CAMT.053 XML or bank CSV (Rabo/ING/ABN column aliases, Dutch |
| List transactions |
| Auto-match unmatched transactions to posted entries (exact ≤ 2 days, fuzzy ≤ window) |
| Unmatched transactions with a proposed posting (income → 8000, expense → 4300) |
| Link a transaction to an existing posted entry |
| Post a new entry from an unmatched transaction (bank leg + counter leg), reconciled automatically |
| Ignore/re-open a transaction (e.g. transfers between own accounts) |
The bank balance vs ledger balance check is the reconciliation test: after matching everything, bank list balance should equal the ledger account balance in the trial balance.
bukio vat
Optional VAT module (per company; KOR companies cannot enable it).
Command | Purpose |
| Enable the module: accounts 1500 (te vorderen) + 2500 (te betalen), 8 VAT codes |
| List VAT codes (21, 9, 0, V vrijgesteld, R/RE verlegd, M marge, P privé) |
| Book a VAT-aware entry. |
| OB-aangifte manual-filing readout — fields 1a–5d for the period (quarter |
| Reclassify the outstanding VAT position to 'Af te dragen omzetbelasting' (default 2510, auto-created) at filing — clears 1500/2500, moves the exact-cents net. If the requested code is taken by another account (e.g. an imported chart), it auto-falls to the next free numeric code (2511, …) and reports it; pick any free code with |
| Book the bank payment that cancels the af-te-dragen balance (tx must be unmatched; outgoing for te betalen, incoming for a refund). |
# sale: 121.00 incl 21% -> omzet 100 + te betalen btw 21
bukio vat book --date 2026-06-01 --desc "Factuur 2026-001" \
--postings "1100:121.00,8000:-100.00@21" --post
# purchase: 60.50 incl 21% -> kosten 50 + te vorderen btw 10.50
bukio vat book --date 2026-06-05 --desc "Kantoorartikelen" \
--postings "4300:50.00@21,1100:-60.50" --post
# quarterly manual filing aid
bukio vat readout --period 2026-Q2OB field mapping: 1a/1b/1c omzet (21%/9%/0%/vrijgesteld), 1d privégebruik, 3a/3b/3c inkopen, 4a/4b verlegde btw (binnenland/EU, netted via 5b), 5a verschuldigde btw, 5b voorbelasting, 5d te betalen/te ontvangen. Fields 2a/2b (exports) and 5c are not tracked in Phase 2 (shown as 0).
bukio recurring / bukio depreciation
Recurring entries & period automation (FR3A) — deterministic, dry-run first, fully audited. Templates are validated at creation; generation just replays them. bukio never generates entries on its own: the agent or a cron job triggers run --due.
Command | Purpose |
| Create a recurring entry template (VAT-aware via |
| Create a subscription invoice template — each run generates a DRAFT invoice (never auto-finalizes; the agent finalizes) |
| Inspect templates |
| Control scheduling |
| What is due (read-only plan) |
| Generate all due entries/invoice drafts — backfills missed periods, idempotent, one transaction per template (a failing template is reported and skipped, others still run) |
| Linear monthly depreciation with a remainder-adjusted final run (cents-exact total over the asset life) |
Semantics:
Generated entries:
source='recurring',source_ref='tpl:<id>',created_by='recurring'(the trigger actor is in the audit log). Posted, immutable, reversible like any entry.--reverse-previousimplements the accrual pattern: each run first reverses the previous generated entry (contra-entry dated at the original), then books the new one — monthly estimates replace cleanly, each month carries its own amount.--runs/--endcomplete the template (statuscompleted); a completed template cannot be re-activated.First run is normalized to
--day(never backwards); days 29–31 are rejected to avoid month-end clamping.
# depreciation: 5370.00 over 36 months -> 149.17/mo, final 149.05 (total exactly 5370.00)
bukio depreciation add --name "Laptop Dell" --cost 5370.00 --life-months 36 --start 2026-08-01
# accrual with auto-reversal (nog te betalen kosten, monthly estimates)
bukio recurring add --name "Nog te betalen kosten admin" \
--postings "4310:250.00,2400:-250.00" --frequency monthly --start 2026-08-31 --day 28 --reverse-previous
# prepaid spreading: annual insurance over 12 months
bukio recurring add --name "Verzekering 12 mnd" \
--postings "4320:100.00,1700:-100.00" --frequency monthly --start 2026-08-01 --runs 12
# the agent's month-end: preview, then run
bukio recurring preview --as-of 2026-09-30
bukio recurring run --as-of 2026-09-30
# subscription invoices: run generates DRAFT invoices, then the agent finalizes
bukio recurring add --name "SaaS abonnement" --kind invoice --contact 1 \
--lines "2x Premium SaaS @ 99.00 @21" --frequency monthly --start 2026-08-01 --due-days 14
bukio recurring run --as-of 2026-10-31 # -> draft invoices 2026-08/09/10
bukio invoice finalize --id 1 # -> 2026-0001, booked
bukio invoice peppol-send --id 1 --dry-run # Peppol access-point (env creds)bukio contact / bukio invoice
Outgoing invoicing (FR3) — compliant with the 12 verplichte factuurvereisten, lifecycle draft → sent → paid (overdue derived), credit notes, PDF + UBL export, bank payment matching.
Command | Purpose |
| Add a customer (vat-id required when btw verlegd) |
| List contacts |
| Items catalog (v0.13): reusable products/services; invoice lines snapshot the price/VAT at creation, so later edits never rewrite existing invoices; |
| Create a draft invoice. Line spec: |
| Create from the catalog — item spec |
| Total discount (before VAT; allocated across VAT-rate groups to the cent so the OB readout reconciles) and invoice language (Dutch default, English optional — PDF labels and unit names) |
| Assign the sequential number (YYYY-NNNN) and book the entry (Debiteuren / Omzet / Te betalen btw) |
| Inspect invoices |
| Render a compliant PDF via headless Chromium — includes the company logo (set via |
| Export UBL 2.1 / Peppol BIS 3.0 (EN 16931) XML |
| Create a credit note (draft) from a finalized invoice (inherits language + discounts) |
| Record a payment (tracking; the posting comes from the bank flow) |
| Opgave (v0.14): the contact's invoices + payments + payables with a running balance |
| Email the finalized invoice PDF (v0.14) via SMTP ( |
| POST the UBL to a Peppol access-point provider ( |
Compliance (validated at finalize): supplier name/KvK/btw-id/address/postal/city (set at init), invoice date, sequential number, customer name+address+city, line descriptions/quantities/prices, VAT rate + amount per rate, totals, and the customer's btw-id when a line carries @R/@RE (btw verlegd). Missing data fails with SUPPLIER_INCOMPLETE / CUSTOMER_INCOMPLETE / CUSTOMER_VAT_REQUIRED.
Payment matching: bank match auto now recognizes incoming payments against unpaid sales invoices (exact outstanding amount, oldest due first) — it marks the invoice paid, posts Bank/Debiteuren, and reconciles the transaction. The OB readout picks up invoiced sales automatically.
bukio invoice create --contact 1 --date 2026-07-10 \
--lines "2x Consultancy @ 150.00 @21,1x Rapportage @ 400.00 @9" --reference "PO-2026-88"
bukio invoice finalize --id 1 --dry-run # plan: number + postings
bukio invoice finalize --id 1 # -> 2026-0001, entry posted
bukio invoice pdf --id 1 # 2026-0001.pdf
bukio invoice ubl --id 1 # 2026-0001.xml (Peppol BIS 3.0)
# payment arrives -> the bank import matches it automatically
bukio bank import --file stmt.xml --iban NL91ABNA0417164300
bukio bank match auto # tx -> invoice 2026-0001 (paid)bukio year-end / bukio jaarrekening / bukio icp
Annual close and statutory reporting (Phase 4).
Command | Purpose |
| Open/closed, the year's result, per-account nets |
| Close the fiscal year: reverse income/expense into 9900 (created on demand), then resultaatbestemming into 3000. Both entries |
| Statutory annual accounts in the Dutch layout (Titel 9 Boek 2 BW): balans (vaste activa / vlottende activa / eigen vermogen / voorzieningen / lang- en kortlopende schulden) + W&V (klein model). |
| ICP listing: EU btw-verlegde supplies per customer (from RE invoice lines), with their btw-ids. Fails |
bukio year-end status --year 2026
bukio year-end close --year 2026 --dry-run # plan: result 1254.15 + postings
bukio year-end close --year 2026 # entries #9 #10 posted
bukio jaarrekening report --year 2026 --model klein # JSON
bukio jaarrekening report --year 2026 --model klein --format pdf # jaarrekening-2026-klein.pdf (KVK)
bukio icp readout --period 2026-Q3 # EU customers + amountsOB readout fields (Phase 4): 1a/1b/1c omzet (21%/9%/0%-vrijgesteld), 1d privégebruik (21% auto-computed on @P), 2a verlegde EU leveringen (RE), 3a inkopen binnenland (incl. verlegd @R), 3b inkopen EU (RE), 3c buiten EU, 4a/4b verlegde btw, 5a verschuldigd, 5b voorbelasting, 5d te betalen/te ontvangen. 2b and 5c are not tracked.
bukio mcp / bukio fx / bukio compliance
The agent layer (Phase 5).
Command | Purpose |
| MCP server over stdio (JSON-RPC 2.0, newline-delimited): |
| Store a rate (1 EUR = N units of foreign currency, 4 decimals max). Upsert; audited |
| Fetch the ECB reference rate (free, no key) for a currency on/before a date and store it (source |
| Rate store inspection (all currencies, or one currency's history) |
| Foreign-currency purchase invoices: spec amounts are in the foreign currency, converted to EUR (round-half-up) at booking; the rate is auto-looked-up (exact date, else latest on/before) when |
| OB + ICP quarterly deadlines and the jaarrekening deposit (13 months after FY end, art. 2:394 BW) with filed/open/overdue status; |
bukio import / bukio month-end / bukio invoice reminders
Imports & period automation (Phase 6).
Every importer validates the ENTIRE file before writing anything — all
errors are collected and reported with line numbers (IMPORT_VALIDATION_FAILED
details), and the file is rejected as a whole when anything is wrong. Imports are idempotent: re-running skips already-imported boekstukken.
Command | Purpose |
| Import opening balances as ONE posted |
| Inbound e-invoice (v0.14): parse an EN 16931/Peppol BIS 3.0 UBL invoice (fast-xml-parser) into the payables register — whole-file validation, supplier auto-created with |
| Import a journal from SnelStart/Exact-style CSV: header |
| Import an XML Auditfile Financieel 4.0 — both the Belastingdienst layout ( |
| Read-only close check: draft entries, unmatched bank transactions, the OB readout for the containing quarter, draft + overdue invoices (with outstanding total), due recurring templates, period debit/credit totals ( |
| Import suppliers + customers from an audit file (either XAF layout) as invoice contacts: name, street, postal code, city, country, email, vat-id. Whole-file validation (every entry needs a name); idempotent by name |
| Overdue + due-soon sales invoices, sorted most-overdue first, with |
| Create a depreciation scheme. Default scheme (created lazily): 5 years lineair, monthly, 0% residual |
| Register an already-booked asset: only the remaining depreciation is booked from the recognition date (first run on the 1st). GL reconciliation warnings, never blockers |
| Book due depreciation runs — |
| The activastaat: cost, cumulative depreciation, book value per asset + totals |
| Dispose (sale or scrap): proposes the full entry (bank / cum-dep / asset / winst-verlies), status → |
| Register inspection + depreciation pause/resume |
| Register a purchase invoice (payable). |
| Open payables (unpaid / in_batch / paid); mark paid after the bank statement confirms |
| Incassovolmacht register (v0.14): SEPA mandates per contact. |
| Build a batch from unpaid payables matching the type and/or explicit lines; whole-set validation (IBAN mod-97, amounts, refs). Direct-debit lines auto-carry the contact's mandate snapshot + FRST/RCUR sequence |
| Export SEPA XML for bank-portal upload: pain.001 for transfer batches, pain.008.001.02 for direct-debit (one |
| Batch tracking; delete only allowed on drafts (releases payables back to unpaid) |
| Contact IBANs (mod-97 validated) — required to include a vendor in a batch |
| Export the fiscal year as an Auditfile Financieel 4.0 XML (Belastingdienst standard) — the file a boekhouder, tax advisor or auditor imports directly into SnelStart/Exact. One |
# switching from your old package in one morning:
bukio import opening-balances --file beginbalans.csv --date 2026-01-01
bukio import journal --file snelstart-export.csv --create-missing
bukio import xaf --file audit.xaf # the Belastingdienst format
# let an agent run the close every month:
bukio month-end --period 2026-08
bukio invoice reminders --within-days 7 --draft-emails
# hand the year to your boekhouder / tax advisor / auditor:
bukio export xaf --year 2026 --out ~/exports/bukio-2026.xaf
bukio audit --format xlsx --out ~/exports/bukio-audit-2026.xlsx --limit 1000Import validation notes: amounts accept the international form (1234.56)
and Dutch bookkeeping notation (1234,56, 1.234,56); ;-delimited files
split on ; (decimal commas stay intact), otherwise on ,. Journal lines
without a boekstuknummer, rows on different dates within one boekstuk, unknown
accounts (without --create-missing), and unbalanced opening balances all
reject the file with per-line details.
bukio fx set --currency USD --date 2026-07-03 --rate 1.0875
bukio fx fetch --currency GBP --date 2026-08-03 # ECB reference rate, stored
bukio vat book --date 2026-08-01 --desc "Stripe (USD)" --currency USD \
--postings "4300:895.00@21,1100:-1082.95" --post # 779.28 EUR — rate auto-fetched from the ECB
# koersverschil at payment: book the difference on 4700 (created on demand)
bukio account add --code 4700 --name "Koersverschillen" --type expense --normal-balance debit
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"entry_add","arguments":{"date":"2026-07-31","description":"Huur","postings":["4300:800.00","1100:-800.00"],"mode":"execute","actor":"agent:hermes"}}}' \
| bukio mcp # or wire it into an MCP client (Hermes, Claude Code, ...)
bukio compliance status --year 2026FX booking rules: amounts in posting specs are foreign currency; the rate
resolves as --rate → stored rate (exact, else latest on/before) → ECB
reference rate (fetched live, stored as source ECB for reuse). --rate
always wins; BUKIO_FX_NO_FETCH=1 keeps bukio fully offline. The description
should note the currency and the original invoice number. Outgoing invoices
stay EUR-only (the 12-vereisten and UBL are EUR-based).
bukio backup / bukio restore / bukio attach
Command | Purpose |
| Consistent SQLite backup (default |
| Restore from a backup file (validated first); encrypted backups are auto-detected by the |
| Self-update from the GitHub main branch: fetch |
| Source documents (v0.14): store the original PDF/scans against an invoice or entry. Default |
| Metadata-only listing (never reads the BLOB); |
restore refuses to overwrite an existing initialised database unless --force is given, and refuses --from/--to pointing at the same file. Wrong passphrase → BACKUP_PASSPHRASE_WRONG (tamper-proof via GCM auth tag).
bukio backup # ~/.bukio/backups/bukio-<ts>.db
BUKIO_BACKUP_PASSPHRASE='...' bukio backup --encrypt --keep 30
bukio restore --from ~/.bukio/backups/bukio-<ts>.db.enc --to ~/.bukio/restored.db
bukio attach add --invoice 1 --file ~/invoices/2026-08-01_acme_F2026-123.pdf
bukio attach list --invoice 1bukio audit
Read the append-only audit log (newest first).
Option | Default | Description |
| — | Only entries at/after this timestamp (ISO 8601) |
| all | Only entries by this actor (e.g. |
|
| Max rows |
|
|
|
| — | Output file for |
bukio audit --by agent:bartholomeus --json # what did the agent do?
bukio audit --since 2026-08-01 # everything this month
bukio audit --format xlsx --out ~/exports/audit-2026.xlsx --limit 1000 # for the boekhouderGlobal Flags
Flag | Env var | Default | Description |
| — | off | Machine-readable JSON output (see below) |
|
|
| Database file |
|
| (required) | Acting entity — |
JSON output contract
With --json, every command prints exactly one JSON document to stdout and exits 0 on success, 1 on failure:
// success
{ "ok": true, "data": { ... } }
// failure
{ "ok": false, "error": { "code": "UNBALANCED", "message": "postings do not sum to zero (sum = 1 cents)" } }All amounts appear both as integer cents (amount_cents) and formatted strings (amount: "1234.56"). The schema is stable and versioned with the tool — agents can rely on it.
Money Format
Strict international decimal:
1234.56, max 2 decimals, no thousands separators.1234= 123400 cents;0.5= 50 cents.Positive = debit, negative = credit. A balanced entry's signed amounts sum to zero.
Thousands separators are rejected on purpose (
1.234is an error, not 1234) — ambiguity is the enemy of agents.
Integrity & Safety Model
Guarantee | Enforced by |
Postings sum to zero | Engine (creation, in-transaction) + DB trigger (at post time) |
An entry needs >= 2 postings | Engine + DB trigger (at post time) |
No zero-amount postings | Engine + |
Account codes are 1–6 digits | Engine |
Account type ↔ normal balance consistency |
|
Postings of a non-draft entry are immutable | DB triggers (INSERT/UPDATE/DELETE) |
Posted entries are never deleted | Reversal-only workflow + triggers |
Audit log is append-only | DB triggers (UPDATE/DELETE abort) |
Money has no floats | Integer cents only, strict parser |
Single company per database |
|
Backup: the database is a single SQLite file (WAL mode). Copy it while the CLI is not writing, or use the .backup API / sqlite3 .backup:
sqlite3 ~/.bukio/bukio.db ".backup ~/backups/bukio-$(date +%F).db"A built-in bukio backup/restore lands in Phase 1.
The Database
Engine: SQLite (via better-sqlite3), WAL mode, foreign keys on.
Location:
~/.bukio/bukio.dbby default; override with--dborBUKIO_DB.Migrations: numbered
.sqlfiles inmigrations/, applied in order, tracked viaPRAGMA user_version.
Schema summary (see migrations/001_initial.sql for the authoritative DDL):
company — one row (id must be 1): name, kvk, legal_form, btw_id, iban,
vat_module, kor_flag, fiscal_year_end
accounts — chart of accounts: code, name, type, rgs_code, normal_balance, active
journal_entries — date, description, source, source_ref, state, reversed_from_id,
created_by, created_at, posted_at
postings — entry_id, account_id, amount_cents, document_id
audit_log — ts, actor, action, command, args_json, outcome, entry_idsUsing Agents
bukio-cli is built for agents. The companion file AGENTS.md in the repo root is the agent's manual: invariants, exact command/JSON contracts, error codes, and worked examples (opening the month, correcting mistakes). Agents should read AGENTS.md before driving the tool, and follow the house rules:
Always
--dry-runbefore mutating. Show the plan, then apply.Always pass
--actor '<role>:<name>'(e.g.agent:bartholomeus,human:erik) so the audit trail attributes your work — it is required.Prefer
--jsonfor parsing; keep human-readable output for humans.Never edit the SQLite file directly. Use the CLI/engine — the triggers and audit log exist for a reason.
Never delete a posted entry. Reverse it.
Verify after every mutation (e.g.
report trial-balance --jsonmust saybalanced: true).
Scheduling recurring actions (cron)
bukio never runs itself — the schedule engine, the asset module and the close check only act when someone calls them. That is exactly what makes them good cron jobs. Two flavours:
Read-only jobs (reminders, deadline calendar, close check, dry-run plans) — safe to run unattended; output lands in a log.
Mutating jobs (
recurring run,assets run) — they book entries, so always dry-run first. The recommended pattern is an agent-driven cron (e.g. Hermes Agent): produce the plan → verify → apply → re-verifytrial-balance→ backup. Never let a bare cron book blindly.
Recommended schedule
Cadence | Command | Kind |
Daily |
| read-only |
Weekly |
| read-only |
Weekly |
| backup |
Monthly (1st) |
| plan |
Monthly (1st) |
| plan |
Monthly (1st) |
| read-only |
Quarterly |
| read-only |
recurring run and assets run are idempotent and backfill missed periods —
if a cron tick was missed (server down), the next run simply catches up.
Plain system crontab (read-only + backup — safe unattended)
# ── daily 08:00 — overdue/due-soon invoices (draft emails only, never sends)
0 8 * * * BUKIO_DB=~/.bukio/bukio.db bukio invoice reminders --within-days 7 --draft-emails --json >> ~/.bukio/cron/invoices.log 2>&1
# ── weekly Mon 08:30 — filing-deadline calendar
30 8 * * 1 BUKIO_DB=~/.bukio/bukio.db bukio compliance status --year $(date +\%Y) --json >> ~/.bukio/cron/compliance.log 2>&1
# ── weekly Sun 07:00 — consistent DB snapshot + document archive
0 7 * * 0 BUKIO_DB=~/.bukio/bukio.db bukio backup --out ~/.bukio/backups/bukio-$(date +\%F).db >> ~/.bukio/cron/backup.log 2>&1
0 7 * * 0 tar -czf ~/.bukio/backups/invoices-$(date +\%F).tar.gz -C ~/.bukio invoices >> ~/.bukio/cron/backup.log 2>&1
# ── 1st of month 09:00 — the close check (read-only)
0 9 1 * * BUKIO_DB=~/.bukio/bukio.db bukio month-end --period $(date -d "1 month ago" +\%Y-\%m) --json >> ~/.bukio/cron/month-end.log 2>&1The mutating pair (recurring run, assets run) deliberately has no
unattended line here — their dry-run plans belong in the agent-driven loop
below, where a human or agent reviews before anything is posted.
Agent-driven month-end loop (mutating — plan, verify, apply)
With an agentic harness (e.g. Hermes Agent), the monthly close becomes one reviewed run instead of blind cron lines. Suggested job prompt:
Run the bukio month-end for <prev-month>:
1. bukio recurring run --as-of <1st> --dry-run --json → show the plan
2. bukio assets run --period <prev-month> --dry-run --json → show the plan
3. after approval: apply both without --dry-run (--actor agent:<name>)
4. bukio report trial-balance --json → must be balanced: true
5. bukio month-end --period <prev-month> --json → all clear?
6. bukio backup --out ~/.bukio/backups/bukio-<date>.db + tar the invoice archiveNever skip the dry-run step; the whole point of bukio's --dry-run is that a
machine can propose and a human (or a verifying agent) disposes.
Project Layout
bukio-cli/
├── bin/bukio.js # CLI entry point
├── src/
│ ├── cli/ # commander commands (init, entry, report, audit, util)
│ ├── core/ # db, accounts, chart, entries (posting engine), money
│ ├── audit/ # append-only audit log
│ └── report/ # trial balance
├── migrations/ # numbered SQL migrations (001_initial.sql)
├── test/ # node:test suites (unit + CLI end-to-end)
├── AGENTS.md # agent manual — read before driving the tool
└── README.mdDevelopment & Testing
npm test # node --test — discovers test/*.test.jsThe suite covers: money parsing, posting engine invariants, reversal semantics, DB triggers (balance, immutability, append-only audit), trial balance math, and end-to-end CLI flows against temporary databases.
Error Codes
Code | Meaning |
| No database at the path — run |
| The database already has a company |
| Unknown legal form for |
| Fiscal year end must be |
| RGS code does not match the expected format (e.g. |
| Chart CSV missing required columns or empty |
| Account already in that state |
| Amount string not parseable (see Money Format) |
| Posting amount is not a non-zero integer |
| Posting spec is not |
| Date is not |
| Description is empty |
| Unknown source ( |
| Actor is empty |
| Fewer than 2 postings |
| Postings do not sum to zero |
| Asset / scheme does not exist |
| Asset already disposed / wrong status for pause-resume |
| Company has no valid IBAN — set one with |
| Contact has no IBAN — |
| Batch lines failed validation (per-line |
| Batch already exported — exporting again could double-pay; create a new batch |
| Payable excluded from batches (incasso) / not in |
| Scheme validation (life 1-600 months, method lineair|degressief, unique name) |
| Cumulative depreciation at recognition exceeds cost minus residual |
| Asset purchase price / residual value invalid |
| The |
| Account code does not exist |
| Account exists but is inactive |
| Account code already exists (account creation, Phase 1) |
| Account validation (Phase 1 surface) |
| Entry id does not exist |
| Entry is already posted |
| Entry must be posted first (reversal) |
| A posted reversal already exists for this entry |
|
|
| Backup file does not exist |
| File is not a valid bukio database |
| Target already has a company — pass |
| Restore source and target are the same file |
| IBAN is malformed |
| CAMT.053 XML invalid or empty |
| Bank/chart CSV missing required columns or empty |
| Unknown |
| Bank transaction does not exist |
| Bank transaction already matched/ignored |
| VAT module not enabled for this company ( |
| KOR company cannot enable the VAT module |
|
|
| Margeregeling cannot be split automatically |
| Period must be |
| Recurring template schedule invalid |
| Depreciation parameters invalid |
| A completed recurring template cannot be re-activated |
| A template failed during |
| Invoice missing supplier/customer vereisten — set them at |
| btw verlegd line needs the customer's btw-id |
| Invoice line/contact validation |
| Invoice lifecycle violations |
| Payment validation |
| Playwright/Chromium could not render the invoice PDF |
| Peppol provider missing (env |
| Recurring template kind errors (reverse-previous is entry-only) |
| Year-end close guards |
| jaarrekening model must be micro or klein |
| EU customer without a btw-id — the ICP listing cannot be completed |
| FX booking errors (missing rate, malformed rate/currency/amount) |
| ECB unreachable, or no reference rate for the currency/date (unknown currency, pre-1999) |
| A mutation was attempted on a read-only MCP server (BUKIO_MCP_READONLY=1) |
| compliance mark errors |
| A database trigger aborted the operation (e.g. editing a posted entry, rewriting the audit log) |
Common Tasks
Open a company's books
bukio init --name "Demo BV" --kvk 12345678 --legal-form bv --vat on
bukio entry add --desc "Startkapitaal" --postings "1100:10000.00,3000:-10000.00" --postBook an expense (paid from the bank account)
bukio entry add --desc "Kantoorartikelen" --postings "4300:250.00,1100:-250.00" --postBook sales (money received, income)
bukio entry add --desc "Factuur 2026-001" --postings "1100:1210.00,8000:-1210.00" --postCorrect a mistake — reverse, then book correctly:
bukio entry reverse --id 2 --reason "verkeerde categorie"
bukio entry add --desc "Kantoorartikelen (gecorrigeerd)" --postings "4200:250.00,1100:-250.00" --postMonth-end sanity check
bukio report trial-balance --year 2026 --json # must be balanced: true
bukio report balans --as-of 2026-12-31 # must say BALANCED
bukio report pnl --year 2026 # result = revenue - costs
bukio audit --since 2026-08-01 --by agent:bartholomeusHand the year to your boekhouder
bukio report journal --year 2026 --format xlsx --out ~/exports/journal-2026.xlsx
bukio report balans --as-of 2026-12-31 --format csv --out ~/exports/balans-2026.csv
bukio report pnl --year 2026 --format xlsx --out ~/exports/pnl-2026.xlsxMonth-end close with bank + VAT (the real workflow)
# 1. import the bank statement (idempotent — safe to re-run)
bukio bank import --file ~/exports/rabo-2026-06.camt.xml --iban NL91ABNA0417164300
# 2. dry-run the auto-match, then apply
bukio bank match auto --dry-run
bukio bank match auto
# 3. handle the leftovers: suggest -> post or link
bukio bank match suggest
bukio bank match post --tx 17 --account 4300
# 4. the balance check: bank balance must equal the ledger balance
bukio bank list
bukio report trial-balance --json # must be balanced: true
# 5. VAT quarter: read the OB fields, file manually in Mijn Belastingdienst
bukio vat readout --period 2026-Q2
bukio vat readout --period 2026-Q2 --mark-filedProtect the books
bukio backup # ~/.bukio/backups/bukio-<ts>.db
bukio restore --from ~/.bukio/backups/bukio-....db --to ~/.bukio/test-restore.dbExtend the chart of accounts
bukio account add --code 4350 --name "Reiskosten" --type expense --normal-balance debit --rgs-code WBED.42
bukio account import --file assets/chart-nl.csv --dry-runRun two companies — separate databases:
bukio --db ~/.bukio/bv-a.db init --name "BV A" --legal-form bv
bukio --db ~/.bukio/bv-b.db init --name "BV B" --legal-form bvKOR / non-VAT entity — simply omit the VAT module; the ledger never exposes VAT concepts:
bukio init --name "Mijn ZZP" --korEU AI Act Transparency
Regulation (EU) 2024/1689 — the EU Artificial Intelligence Act.
This software is not an AI system. bukio-cli is deterministic, rule-based accounting software: every booking, VAT calculation and report follows fixed double-entry rules over integer cents. It performs no inference, no machine learning, no autonomous decision-making, and no profiling — so the obligations the AI Act places on providers/deployers of AI systems (high-risk requirements, conformity assessment, risk management, Article 50 interaction transparency) do not apply to the product itself.
The code, however, was written with AI assistance. This section is the project's transparency disclosure, in the spirit of the Act's transparency principle for AI-generated content:
Aspect | Disclosure |
Development method | All source, tests and documentation were generated with an AI coding assistant (Hermes Agent, running |
Human oversight | Every commit is reviewed by the owner before it lands; the automated test suite (495 tests, |
Synthetic content | Code, tests and docs are AI-generated output; this README section and the commit history serve as the disclosure that the content is machine-generated. |
Model provider obligations | The underlying general-purpose AI model is provided by DeepSeek; its obligations under the AI Act (e.g. Article 53 documentation, copyright policy, training-data summary) sit with the provider, not with this repository. |
No prohibited practices | The project involves none of the Article 5 prohibited practices (no social scoring, no biometric identification, no manipulation). |
No high-risk use | Bookkeeping is not a high-risk use case under Annex III; no fundamental-rights decisions are made by this software. |
AI literacy | The developer maintains AI literacy (Article 4) and exercises it: every AI output is verified against accounting invariants before use. |
Status for the record: the AI Act entered into force on 1 August 2024; prohibitions and AI-literacy obligations applied from 2 February 2025; GPAI and governance provisions from 2 August 2025; the remainder of the Act applies from 2 August 2026. This disclosure is provided as a matter of transparency and good faith; it is not legal advice.
AI Development Cost & Token Usage
The entire project was built with AI assistance. For full transparency, here
is the measured token consumption and its cost at official list prices
(per 1M tokens; OpenCode Go / DeepSeek API, Aug 2026): DeepSeek V4 Flash
$0.14 input (cache miss), $0.0028 cached input, $0.28 output;
MiMo-V2.5-Pro $0.435 input, $0.003625 cached input, $0.87
output. Reasoning tokens are billed at the output rate. Data is captured by
the bukio-token-track tool from the agent's session telemetry — including
delegation subagent sessions (snapshot 2026-08-09, 10:07).
Proven stack: bukio-cli is developed and operated end-to-end with Hermes Agent (Nous Research) via OpenCode Go. The main development sessions ran DeepSeek V4 Flash (a small number of calls via the DeepSeek API directly); the parallel code-review subagents (delegation batches) ran MiMo-V2.5-Pro, also via OpenCode Go. The live day-to-day operations (bank imports, invoice booking, month-end checks) run on the same stack against this same codebase.
Token usage — per model
Model | API calls | Input | Cached input | Output | Reasoning | Est. cost |
DeepSeek V4 Flash | 5,682 | 16.35M | 1,385.95M | 4.15M | 1.98M | $7.89 |
MiMo-V2.5-Pro (review subagents) | 574 | 6.82M | 42.12M | 1.06M | — | $4.05 |
Total | 6,264 | 23.17M | 1,428.07M | 5.22M | 1.98M | $11.93 |
$11.93 total at official list prices for the entire project (6,264 API calls across all development sessions, ≈ 1.46B tokens). An additional 8 API calls (≈ 9K tokens) ran on MiMo-V2.5 at ≈ $0.00.
Developer Time (contributed, unpaid)
Beyond API spend, this project took my review-and-direction time: five evenings after work (Aug 4–7, 2026), ≈ 1 hour of effective time per evening — plus Saturday (Aug 8, 2026) and Sunday (Aug 9, 2026), ≈ 2.5 clock hours of review and direction each — i.e. roughly 10 hours total, all contributed unpaid.
At a senior Dutch software-developer rate of ≈ €45/hour (Amsterdam senior average, 2026: €45/h Glassdoor, €45.50/h SalaryExpert; the national average is lower), my time is worth ≈ €450.
Stated plainly, so nothing is hidden:
Compliance: all of this work happened in my free time, outside working hours — no employer time, equipment, or other resources were used.
Deliberately conservative: I am an amateur developer, and a senior professional rate overstates the market value of my review time by a wide margin. I include it high on purpose: every cost of this project is quantified rather than tucked away as unmeasured "effort and work".
It was free: the ≈ €450 is an imputed opportunity cost, not money paid. My out-of-pocket spend remains $11.93 in API costs.
Not a full review: these hours do not come close to the effort a conventional code review of a 23.3 KLOC codebase would take; treat them as my direction-and-check time, not a substitute for professional review.
COCOMO benchmark
For a frame of reference, the same codebase priced by the classic COCOMO
model (Boehm, 1981): 23,389 non-blank, non-comment lines of JavaScript
across 105 files (13,429 in src/, 9,960 in test/), i.e. 23.39 KLOC
(measured with scc v3.7.0).
COCOMO mode | Effort (person-months) | Duration | Team size | Cost @ €9,000/PM* |
Organic | 65.7 PM | 12.3 months | ~5 developers | ≈ €591K |
Semi-detached | 102.5 PM | 12.6 months | ~8 developers | ≈ €923K |
Embedded | 158.2 PM | 12.6 months | ~12 developers | ≈ €1,424K |
*Fully-loaded senior developer rate in the Netherlands (2026).
Comparison: a conventional team building this would estimate ≈ 66–158 person-months (≈ €591K–€1,424K); the AI-assisted build consumed $11.93 in API costs plus ≈ €450 of my review-and-direction time (contributed, unpaid — see above) over five evenings, a Saturday and a Sunday — still a tiny fraction of the conventional estimate. COCOMO is a rough 1981-era estimate (organic/semi-detached/embedded are the three standard modes); treat the ratios, not the decimals, as the point.
Troubleshooting
Ran into a question, bug, or anything else you need to know? Ask your agent first — it has the full agent manual (AGENTS.md) and this README in context. If your agent is unable to help, shoot me a message at erik@posthumanresources.nl and I'll try to answer it when I'm able.
Roadmap
Phase | Scope | Status |
0 | Foundation: ledger, posting engine, audit, trial balance, | ✅ done |
1 | Accounts CRUD + CSV import, RGS-mapped chart, balans + W&V, CSV/XLSX export, backup/restore | ✅ done |
2 | Bank import (CAMT.053/CSV), matching; optional VAT module (codes, OB readout, KOR) | ✅ done |
3 | Invoicing: factuurvereisten, PDF (Playwright), UBL/Peppol BIS 3.0, credit notes, payment matching, recurring entries + recurring invoices + Peppol send | Compliant invoice PDF + UBL per invoice; due entries generated & posted on time |
4 | Jaarrekening micro/klein models, closing entries, KVK package, ICP readout | Jaarrekening package for a micro BV — ✅ done (v0.7.0, 178 tests green) |
5 | Agent layer: MCP server, permissions/approval gates, NL query, AI categorization suggestions, compliance calendar, FX translation | Agent closes a month end-to-end with zero unsupervised mutations — ✅ done (v0.8.0, 199 tests green) |
6 | Migration & automation: | Switch from an old package in one morning; the agent runs the close check monthly — ✅ done (v0.9.0, 229 tests green) |
7 | Fixed assets: depreciation schemes (lineair/degressief), asset register with mid-life adoption, monthly runs, disposal, activastaat | Recognise mid-life assets and book only the remaining depreciation — ✅ done (v0.10.0, 271 tests green) |
8 | SEPA payment batches: payables register (transfer vs direct-debit), pain.001 export for bank-portal upload | Prepare vendor payments in bukio, upload the file in the bank, close the loop via the CAMT import — ✅ done (v0.11.0, 295 tests green) |
9 | External handover: | The year as a file your boekhouder/tax advisor/auditor imports directly — ✅ done (v0.12.0, 342 tests green) |
10 | Optional: Ponto live feeds, Peppol send/receive, OCR, SQLCipher | optional |
11 | Items catalog + discounts + invoice languages: | Invoice from a reusable catalog with discounts, in Dutch or English, with the company logo — ✅ done (v0.13.0, 433 tests green) |
12 | Inbound e-invoicing + delivery + cash management: attachments in-DB ( | The 2027 e-invoice mandate both ways: receive UBL invoices, email the PDF, collect by incasso — ✅ done (v0.14.1, 603 tests green) |
Design principles persist across phases: agent-native from day one, VAT optional, no automated tax filing, single company per database, local-first.
Part of the Bukio product line — separate from the Bukio web platform: shared brand and philosophy, no shared code.
bukio-cli is provided completely open source and free by Posthuman Resources. No license fees, no account, no cloud dependency — clone it, audit it, run it yourself.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityAmaintenanceA Model Context Protocol (MCP) server that keeps the books for your personal and business finances using double-entry accounting — driven entirely from an LLM.378MIT
- AlicenseBqualityCmaintenanceAn MCP server for Danish accounting via Billy.dk API, enabling natural-language control over invoices, bank lines, reports, and more, with a write-guard for safety.65MIT
- Alicense-qualityAmaintenanceDouble-entry accounting ledger MCP server for autonomous agents that enables creating accounts, posting journal entries, and generating financial reports.MIT
- AlicenseAqualityAmaintenanceMCP server for Spanish accounting for freelancers and SMEs, enabling AI agents to issue invoices, OCR expense PDFs, reconcile bank transactions, and prepare quarterly VAT (Modelo 303).23MIT
Related MCP Connectors
Hosted MCP server for Mini Accountant: invoices, expenses, customers, analytics, tax estimates.
AI-native ERP MCP: ES/EU fiscal compliance (VeriFactu/TicketBAI/Facturae), invoicing, tax, banking
Hosted AgentLux MCP server for marketplace, identity, creator, services, and social flows.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/erikvankempen/bukio-cli'
If you have feedback or need assistance with the MCP directory API, please join our Discord server