Releases: erikvankempen/bukio-cli
Release list
v0.17.0 — Cost Centers
[0.17.0] — 2026-09-01
Added
- Cost centers — an optional analytical dimension for management reporting.
Define cost centers (bukio cost-center add/list/show/deactivate/reactivate),
tag expense/revenue postings at booking time (4700:-100.00@SALES), and run
bukio report cost-centerto see revenue, costs and result per center for any
period (year, quarter, month, or date range). Cost centers are purely analytical
— they never block a posting and are invisible to statutory reporting.
Schema migration 026; nullablecost_center_idon postings; entry-level@CC
suffix in posting specs; cost center carried through reversals; period filtering
via--period YYYY-Qn|YYYY-MM,--from/--to,--year; single-center drill-down
with--cost-center CODE. - Authz gate for cost centers —
cost-center add/deactivate/reactivatemapped
toadmin.chart(owner + bookkeeper);cost-center list/showand
report cost-centermapped toreport.read. Cost-center commands now
participate in the Tier 0.5 RBAC system like every other command. - Flexible period filtering on cost-center reports —
--period 2026-Q2or
--period 2026-08(quarter/month),--from/--to(arbitrary date range),
--year(full fiscal year).
Changed
- Code cleanup — ponytail audit cut deprecated CLI aliases, empty PLANNED
sections, and duplicated CSV parsers. - README/AGENTS.md — cost-center commands added to command quick reference;
posting spec documentation updated with@CCsuffix; token usage snapshot
refreshed ($22.05 total, 149 sessions, 37.25 KLOC).
Internal
- Migration 026:
cost_centerstable + nullablecost_center_idcolumn on
postingswith index. - 12 new cost-center tests; 941/944 tests passing (3 pre-existing).
v0.16.3 — Code-simplification pass
v0.16.3 — Code-simplification pass
Pure refactoring release: net −851 lines of source (+2,200/−3,051 across 191 files) with zero capability changes. The full CLI surface, MCP schemas, document outputs, and error-code contract are unchanged. Suite: 946/946 green. Two consecutive independent review passes, both clean.
Changed
- New shared core modules:
src/core/dates.js(date validation, today, month math) andsrc/core/errors.js(makeError) replace per-module copies across ~15 modules - CLI: command registry loop;
withDbaction-shell wrapper (67 handlers converted);cliErrortyped-error factory (46 throw sites); stale program description fixed - Compliance:
quarterDeadlineOnOffsetcollapses nine quarterly deadline rules to one-liners; FYE deadline helpers delegate tomonthsAfterFyEnd; byte-identicalisBooksClosedclone removed - Invoice: NL/EU/LU party-field validators share one
validateVereistenCorewith per-locale config; UBL VAT-category logic unified in exportedvatCategory(code);invoice createsingle engine call for dry-run and real paths (JSON shapes unchanged) - Reports: duplicated date-validation and
todayIsocopies replaced by the core dates module - i18n: parity-guard FULL list derived from the table registry; UNITS built from UNIT_CODES
- Housekeeping: ~180 stale license-header jurisdiction counts corrected to thirty-one; XK profile shape anomalies fixed; dead code deleted
Full changelog: https://github.com/erikvankempen/bukio-cli/blob/main/CHANGELOG.md
v0.16.2 — 31 markets, 28 i18n tables
Added
-
**Phase E: BG Bulgaria + HR Croatia + SI Slovenia + EE Estonia + LV Latvia
- LT Lithuania + MT Malta + CY Cyprus** — eight more EUR-market profiles
(twenty-four live): research briefs at
docs-research/{bg,hr,si,ee,lv,lt,mt,cy}-profile.md(EAS codes verified
against the official OpenPEPPOL codelist release 8 Dec 2025 — BG 9926,
HR 9934, SI 9949, EE 9931, LV 9939, LT 9937, MT 9943, CY 9928);
monthly VAT returns (BG 14th, HR/SI/EE/LV 20th, LT 25th; MT/CY
quarterly 15th/10th of the second month), annual-accounts + CIT
deadlines per market (BG 30 Jun, HR 30 Apr, SI 31 Aug/31 Mar, EE 30 Jun
(CIT on distributions), LV 31 Jul (CIT on distributions), LT 30 Apr/1
Oct, MT 10/9 months, CY 10 months/31 Jan+2y). New markets keep
English-document defaults (no i18n tables yet — same treatment as
GB/IE/US) and inherit the art. 226 EU baseline + cross-border Peppol
BIS; domestic e-invoicing mandates (e-Sąskaita LT, PVN LV 2025
framework) and return layouts stay documented B-milestones.
- LT Lithuania + MT Malta + CY Cyprus** — eight more EUR-market profiles
-
**Phase F: CZ Czechia + SK Slovakia + GR Greece + PL Poland + HU Hungary
- RO Romania** — the final six EU members (thirty live markets; 27/27 EU
- GB/NO/US): research briefs at
docs-research/{cz,sk,gr,pl,hu,ro}-profile.md(EAS codes verified
against the official OpenPEPPOL codelist release 8 Dec 2025 — CZ 9929,
SK 9950, GR 9933, PL 9945, HU 9910, RO 9947); monthly VAT returns
(CZ/SK/PL/RO 25th, GR 26th, HU 20th), annual-accounts + CIT deadlines
per market (CZ 6mo/31 Mar, SK 6mo/31 Mar, GR 10mo/30 Jun, PL 6mo/31
Mar, HU 31 May/31 May, RO ~150d/25 Jun); CZK/PLN/HUF/RON base
currencies via per-profile baseCurrency; GR uses the EL VIES prefix;
RO is the only non-Peppol market (e-Factura national, cross-border UBL
only); domestic mandates (KSeF PL — live 2026, RTIR HU, myDATA GR,
e-Factura RO, SK 2027) stay documented B-milestones. English-document
defaults; art. 226 EU baseline + cross-border Peppol BIS inherited.
-
i18n refactor: per-language table modules —
src/i18n/index.js's
singleTABLESliteral split intosrc/i18n/locales/<lang>.js(one
module per language: en/nl/nl-be/de/fr/fr-lu/da/fi/nb/sv/it/es/pt);
index.jskeeps the machinery (t/label/unitLabel/resolveLocale,
LABELS/UNITS backwards-compat exports) and re-assemblesTABLESfrom
imports. Public API unchanged; keys/values byte-identical; the parity
guard still pins 89 keys across all 11 full tables. Behavior-neutral —
944/944 green. -
i18n: 14 national-language PDF tables — full 89-key tables for
pl/cs/hu/ro/sk/sl/hr/bg/el/et/lv/lt/mt/cy undersrc/i18n/locales/
(25 full tables + 2 regional overrides; parity guard extended). The
Phase E/F profiles now render documents in their national language by
default (PLpl, CZcs, SKsk, GRel, HUhu, ROro, BGbg,
HRhr, SIsl, EEet, LVlv, LTlt, MTmt, CYcy) — the
invoice PDF/email pipeline is fully localized for all 30 markets;
--languageaccepts any of the 27 table codes.meta.localealigned
to ISO language codes (si->sl, ee->et, cz->cs, gr->el). -
Phase G: Kosovo (XK) — 31st market. Non-EU EUR jurisdiction
(unilateral euro adoption), SKRFI convention chart in Albanian, VAT
18%/8% (monthly returns by the 20th), CIT + annual accounts by 31 March
(10% flat CIT), Sh.p.k./Sh.a./O.P./K.P./B.I. legal forms, NBR
(8-digit) + K-prefixed VAT identifiers. Not a Peppol participant —
cross-border EN 16931 UBL emission only. Full Albanian (sq) i18n table
(26 full + 2 regional overrides); documents render in Albanian by default.
Full changelog: CHANGELOG.md
v0.16.1
[0.16.1] — 2026-08-16
Added
- Phase C: AT Austria + IE Ireland — two more jurisdiction profiles
(thirteen live):- AT — Einheitskontenrahmen (EKR) chart (BMF SAF-T verified, 3-digit
codes zero-padded), USt 20/13/10, Kleinunternehmer ≤ €55K, UID
(ATU + 8 digits) / Peppol 9914, UVA quarterly (15th of the second
following month; monthly above €100K) + annual USt-Erklärung 30 Jun. - IE — UK-style chart (no statutory chart), VAT 23/13.5/9/4.8/0,
registration thresholds €85K goods / €42.5K services, CRO + IE-format
VAT number / Peppol 9935, VAT3 bi-monthly returns (23rd of the month
after the period; theYYYY-Pnshape) + annual accounts/CT1 in 9 months. - Research briefs at
docs-research/{at,ie}-profile.md; strict dispatch
keeps the B-milestones loud (UVA/VAT3 return engines, UGB/CA 2014
accounts, SAF-T AT (OECD-style ≠ Auditfile), § 11 UStG / s. 108B VATCA
invoice rule sets).
- AT — Einheitskontenrahmen (EKR) chart (BMF SAF-T verified, 3-digit
- PLANNED now holds Phase D (
IT,ES,PT) —init --country
answersCOUNTRY_NOT_SUPPORTEDfor them (CH remains parked). - Profile-aware init output — the
vat: module enabledline shows the
profile's clearing accounts (NL 1500/2500, AT 2500/3500, IE 2110/2100, …)
instead of a hardcoded NL pair. - Clearer B-milestone errors —
FORMAT_NOT_SUPPORTEDnow names the
country and the milestone ("no invoice compliance rule set for AT yet…",
"no VAT-return layout for IE yet…") instead of'undefined'. - Phase D: IT Italy + ES Spain + PT Portugal — three more jurisdiction
profiles (sixteen live):- IT — commercialisti convention chart (no statutory chart; standard
Italian account names), IVA 22/10/5/4, regime forfettario ≤ €85K,
Partita IVA (IT + 11 digits) / Peppol 0211, liquidazione IVA quarterly
(16th of the second month after the quarter) + Dichiarazione IVA 30 Apr- bilancio ~5 months.
- ES — official PGC chart (R.D. 1514/2007), IVA 21/10/4, recargo de
equivalencia, NIF / Peppol 9920, Modelo 303 quarterly (20th; Q4 30 Jan)- 390 (30 Jan) + 200 (25 Jul) + cuentas anuales (7 months).
- PT — official SNC chart (DL 158/2009; 2-digit bases zero-padded),
IVA 23/13/6, isenção art. 53 CIVA, NIPC / Peppol 9946, Declaração
Periódica quarterly (20th of the second month) + IRC (31 May) + IES
(15 Jul). - Research briefs at
docs-research/{it,es,pt}-profile.md; strict
dispatch keeps the B-milestones loud (liquidazione/303/DP return
engines, bilancio/cuentas/demonstrações financeiras, SAF-T PT,
FatturaPA/SdI (IT), Verifactu (ES), ATCUD (PT) — domestic
e-invoicing formats; Peppol BIS registered for cross-border).
- IT — commercialisti convention chart (no statutory chart; standard
- Fully localised invoice PDFs — the rendered invoice is now localised
in every market language. New full i18n tables it/es/pt (88 keys each,
key-identical to the pivot — parity guard now covers 11 full tables);
the document language follows the company profile (de-AT→ de,it→
it,nl-be→ nl, …) with--languageaccepting any i18n table;
migration 025 rebuildsinvoicesto drop the staleCHECK (language IN ('nl','en'))that rejectedde/itat INSERT. - EU invoice-compliance baseline — the harmonized art. 226 VAT Directive
party requirements ('eu-invoice-vereisten') are registered for the twelve
EU markets without a national rule set (AT/BE/DE/DK/ES/FI/FR/IE/IT/NO/PT/
SE), so invoice finalization — and thus the localised PDF — works for
every EU market; NL/LU keep their national rule sets; GB/US stay
B-milestone (no EU baseline).
v0.16.0 — Eleven jurisdictions, localization, English-first sweep
[0.16.0] — 2026-08-15
Added
- Eleven jurisdictions —
bukio init --country <cc>now seeds the country
profile's chart convention, VAT codes/rates (2026), identifiers, Peppol
scheme and compliance calendar for NL, LU, GB, FR, US, BE, DE, DK, FI, NO
and SE (Phase B; profiles atsrc/jurisdictions/, roadmap rows 14–15):- NL: 29-account RGS-mapped chart (unchanged baseline, byte-identical),
KvK/btw-id, Peppol 9944. - LU: PCN 2020 chart, RCS, Peppol 0195; LU e-invoicing rules.
- GB: QuickBooks/Xero-style chart, Companies House number, Peppol 0208,
MTD-compatible stance, 03-31 fiscal year. - FR: PCG chart, SIREN, Peppol 0002, franchise small-business scheme.
- US: no-federal-VAT tracking model (track + export).
- BE: PCN-BE AR 12-09-1983 chart, KBO, Peppol 0208, BTW readout.
- DE/DK/FI/NO/SE: SKR 03 / standard charts, USt-IdNr. / CVR / Y-tunnus /
Org.nr., Peppol 9930 / 0184 / 0037 / 0192 / 0007, per-market VAT bands
(incl. DK 25 % only, NO no-reduced band, DE 0 % solar, FI 25.5 %). - Strict dispatch: unregistered formats fail loudly (
PROFILE_NOT_FOUND),
never a silent NL fallback — NL is one of eleven equal citizens.
- NL: 29-account RGS-mapped chart (unchanged baseline, byte-identical),
- Localization (i18n) — optional, opt-in
--locale <code>(global flag)
orBUKIO_LOCALEenv switches human-facing output; English stays the
default and the JSON contract, error codes and MCP tool names never
localize:- Locale tables for en, nl, nl-be, de, fr, fr-lu, da, fi, nb, sv
(8 full tables × 88 keys, parity-guarded by tests; nl-be/fr-lu as
regional overrides). - Wired: invoice PDF labels/units, invoice + reminder emails, CLI tables
and renders (invoice list/reminders, balance sheet, P&L, month-end,
year-end, company show), VAT file/settle descriptions.--descstill
wins over localized defaults. - Invoice document language follows the company profile (Dutch for NL/BE
companies, English for every other market;--language nl|enoverrides)
— no market is the de facto base.
- Locale tables for en, nl, nl-be, de, fr, fr-lu, da, fi, nb, sv
- English-first terminology sweep — generic all-market runtime strings
(labels, plans, help, MCP descriptions) are English by default; statutory
artifacts keep their legal language per market (OB readout labels,
'Winst en verlies' statutory XLSX sheet, RGS group names, command aliases,
import CSV header aliases). financial-statementscommand (year-end close) with the deprecated
jaarrekeningalias;init --kvk/--btw-iddeprecated in favour of
--registration-id/--tax-id.
Changed
-
Positioning — repository, README and CLI description now state the
eleven-jurisdiction scope (the "Dutch SMEs" tagline is gone); the invoice
document-language default is documented as profile-derived (Dutch for NL/BE
companies, English otherwise). The README presents the Netherlands as one of
eleven equal citizens:init/company/account/contactoptions use the
profile-neutral names (--country,--registration-id,--tax-id,
--taxonomy-code), chart and report examples are marked as the NL profile's,
and the OB readout is framed as the NL statutory VAT-return shape. The
command reference was re-verified against the live CLI (init/company/
account/contact option names, invoice create + bank import + fx set options,
per-profile VAT codes and statutory models). -
Migrations 021–024: company gains
country,base_currency,locale,
profile_version;legal_formCHECK removed;taxonomybackfill for RGS;
vat_returns/filingstype CHECK widened — lossless, verified. -
Code comments remain Dutch where they explain statutory/fiscal mechanics;
the public surface is English.
Fixed
invoice showno longer throwsReferenceErroron invoices with payments
or outstanding amounts in human mode (locale was undeclared in the render
path; JSON mode had masked it).- i18n table parity repair (the 14 balance-sheet/company keys now exist in
all 8 full tables; a parity-guard test prevents silent regressions). - Residual Dutch literals on generic paths (assets list/schemes, fx, item
list, ICP readout, import/export summaries, MCP tool descriptions).
Verified
- 891/891 tests green (was 876 at Phase B start; +15 market/i18n
coverage). Two consecutive clean full-review passes (rounds 8+9) plus the
round-10 fresh pass and the i18n 3-review chain — all fail-closed,
static-only subagent reviews with file:line verdicts.
v0.15.1 — Remote access
Remote access — drive the books from any device
Host the books on one machine (an in-house server, a VPS) and drive them from a phone, a laptop, or an agent on another VPS — while the private signing keys stay on the devices that own them.
What's new
bukio server start— serve ONE company DB over HTTP(S). Clients POST signed command envelopes; the server verifies each against the company registry (Ed25519 signature, ±5 min window, nonce replay refusal, authz) and executes it. Output is byte-identical to local mode; audit rows carry the real signature (audit verifyworks server-side).bukio server token <actor>— mint a one-time enrolment token (single-use, TTL, actor-bound, stored sha256-hashed at rest).bukio actor register --server <url> --token <t>— remote enrolment: the client's public key is enrolled; the private key never leaves the client.- Global
--server <url>/BUKIO_SERVER— run ANY command remotely, e.g.bukio --server https://bukio.intranet vat book .... - Transport guidance — SSH tunnel (recommended for humans, zero new listening ports), Tailscale/WireGuard for agents & always-on clients, native TLS for direct exposure. Plain HTTP on a public interface is discouraged.
- Same-device mode —
--server http://127.0.0.1:PORTon the same host works too.
Security model
The private key never leaves the client; the server verifies signatures against enrolled public keys only. Enrolment is capability-gated (one-time, short-lived tokens). Every command is tamper- and replay-proof (canonical digest + nonce + time window); the authz gate and actor enforce on apply server-side. Full rationale in issue #2.
Also in this release
- SSH/Tailscale transport options documented (README + AGENTS.md)
- README screenshot regenerated (v0.15.1) showing the remote-access flow
- Fix: test suite no longer leaks
bukio-*temp dirs into/tmp(RAM-starved SQLite on tmpfs hosts) - Cost-section refresh: 28.25 KLOC, token spend $13.59, owner time ≈8.8 h / €396
Stats
- 773/773 tests passing (20 new e2e tests for remote access)
- 3 new files:
src/cli/server.js,src/cli/remote.js,test/remote.test.js - Resolves #2 — issue auto-closed by this release
Built with an AI agent (Hermes) and reviewed by a human owner who is not a professional developer. All code Apache-2.0.
bukio-cli v0.15.0 — Verifiable actor attribution
Verifiable actor attribution — resolves #1
The audit trail now records proofs, not claims. Every command is cryptographically signed by its declared actor (Ed25519) and verified against the per-company key registry before dispatch; audit verify re-checks the whole trail and detects tampering, replay, and revoked keys.
Added — actor identity (Tier 0)
bukio actorCLI:keygen(Ed25519; human keys passphrase-encrypted),register,list,revoke,enforce --on|--off,unlock/lock(12 h sessions),verify- Sign-and-verify gate: every CLI command is auto-signed (canonical digest + ±5 min window + 24 h nonce cache; replay refused in every mode)
bukio audit verify: per-rowok | unsigned | revoked | tampered | invalid-signature | unknown-key, exit 1 on anomalies; a copied DB file verifies standalone- MCP signed execution: every mutating tool call signed with the same gate, same guarantees across CLI + MCP
- Migration 018/019: per-company
actor_keysregistry + audit signature columns (legacy rows read backunsigned— backwards compatible)
Added — per-actor authorizations (Tier 0.5)
bukio actor authz --on|--off: deny-by-default capability model (20 families, 6 roles) with segregation-of-duties warningsbukio actor roles/roles grant/roles revoke(owner-only; LAST owner never revoked)
Fixed
- Aging report: creditors leg now honours
--as-of - Invoice finalize: sequential number allocated inside the transaction with a UNIQUE-collision retry
markPaid: payment insert + status transition commit atomically- Recurring
createTemplate: object postings kept in VAT-tagged lists - MCP server:
params: nullanswered cleanly (-32602, not -32603) audit verify: negative--limitrejected withINVALID_LIMIT
753/753 tests green. Full details in CHANGELOG.md.
bukio-cli v0.14.1: Initial Release
bukio-cli v0.14.1: Initial Release
We are excited to announce the initial release of bukio-cli (v0.14.1), an open-source, local-first double-entry bookkeeping engine designed specifically for Dutch SMEs and AI agents.
While built for human operators, bukio-cli is architected from the ground up to be safely driven by AI agents via the Model Context Protocol (MCP). Everything runs natively on your machine or VPS against a single SQLite database file—giving you complete ownership of your financial data without vendor lock-in.
Key Features
-
Agent-Native Architecture:
- Native MCP server integration over stdio.
- Deterministic
--jsonmachine outputs for every command. - Forced
--dry-run(plan mode) support for safe agent execution. - Append-only audit logging with required actor identity attribution (
--actor human:erikoragent:bartholomeus).
-
Built for the Dutch Business Ecosystem:
- Bidirectional E-Invoicing (Peppol BIS 3.0): Complete outgoing pipeline (
finalize→ compliant PDF → UBL → Peppol send) and inbound UBL import (import invoice) directly into the payables register. - Tax Compliance: Optional VAT module with Dutch OB-aangifte readout (fields 1a–5d),
vat filebalance reclassification,vat settlepayment booking, KOR support, and ICP listing. - Statutory Reporting: Generate Jaarrekening reports (micro/klein models for Title 9 Book 2 BW) and KVK deposit packages.
- Auditfile Compatibility: Full import and export for XML Auditfile Financieel 4.0 (
XAF).
- Bidirectional E-Invoicing (Peppol BIS 3.0): Complete outgoing pipeline (
-
Core Bookkeeping & Cash Management:
- Immutable Ledger: Double-entry engine backstopped by SQLite database triggers. Reversals create linked contra-entries; posted entries are never altered or deleted.
- Reconciliation & Payments: CAMT.053 / CSV bank statement imports, auto-matching, payables management, and SEPA payment exports (
pain.001credit transfers andpain.008direct debits with mandate tracking). - In-Database Attachments (
attach): Store source PDFs or scans directly in the SQLite file as BLOBs (up to 25 MB per file, SHA-256 deduplicated). - Encrypted Backups: AES-256-GCM database backup encryption (
backup --encrypt) with automated rotation (--keep N). - Fixed Assets & FX: Asset register with mid-life adoption support, lineair/degressief schemes, and live European Central Bank (ECB) rate integration for foreign currency transactions.
- Items Catalog & Multi-Language: Product/service catalog with fractional quantities, total and line-item discounts, custom logo support, and Dutch/English invoice rendering.
Quick Start
Ensure you have Node.js >= 20 installed:
# Install globally or clone
git clone https://github.com/erikvankempen/bukio-cli.git
cd bukio-cli && npm install && npm link
# Initialize a new company database
bukio init --name "Demo BV" --kvk 12345678 --legal-form bv --vat on
# Post an initial capital entry
bukio entry add --date 2026-08-04 --desc "Startkapitaal" \
--postings "1100:10000.00,3000:-10000.00" --post
# Check trial balance
bukio report trial-balanceRunning as an MCP Server for AI Agents
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"trial_balance","arguments":{}}}' \
| bukio mcpDocumentation & Agent Guide
- Check out
AGENTS.mdin the repository root for the agent integration manual, command syntax, and strict execution guardrails. - View the full
README.mdfor comprehensive command references, database schema details, and cron scheduling recipes.
Feedback & Contributions
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, or if you want to contribute, shoot me a message at erik@posthumanresources.nl and I'll try to answer it when I'm able.
License: Apache-2.0