legdgerEncrypted local-first ledger
Obsidian for bookkeeping: local-first, an on-device AI finance copilot, and a plugin system open to any AI. All ledger data is encrypted on the machine and AI analysis never leaves the device. Only sync requires an account and a fee; local capability is free forever.
01$ ledger-cli doctor02{ "ok": true, "store": "ledger-mac.store", "readonly": true }0304$ ledger-cli stats --month 2026-0905{ "monthExpense": 12483.20, "monthIncome": 32000.00,06 "netWorth": 486210.55, "wallets": 7 }The data is yours; the AI is just a finance copilot living on your device.
Design decisions
Why this tool is built the way it is, and what that buys.
iOS is the quick-entry bookkeeper; macOS is the full data terminal hosting the plugin system, AI access and batch consolidation.
One unified bag model, legs summing to zero per currency, and a three-verb validation gate on opening entries — once settled, the data model is never overturned.
UUIDv7 primary keys + HLC versioning + entity-state mirror sync; the server keeps only the latest ciphertext and accumulates no history.
ledger-cli opens the local store read-only; tokens are issued and revoked by the Mac app, with an audit log attached.
Capabilities at a glance
- Local-first with on-device AI: statistics, Q&A and chat all run on the device
- Double-entry kernel: an entry is a set of legs summing to zero, and balances are always derived, never stored
- Eleven wallet bag types: assets, liabilities, securities, crypto holdings, reconciliation and split accounts
- On-device receipt OCR: Vision parsing → rules engine → confirmation card
- Native App Intents and Shortcuts: log an entry in one sentence
- ledger-cli: a read-only CLI with token authorization for external AI agents to analyse safely
Design metrics
Each one maps to a concrete decision in the implementation.
Entries are encrypted on the machine; the cloud only keeps the latest ciphertext
Assets, liabilities, securities, crypto holdings, pending reconciliation, split intermediates and more
LedgerCore is a standalone Swift package with full kernel test coverage
Balances are always derived from legs; no cached value can drift out of sync
Entity-state mirror sync; the server accumulates no history
Statistics, Q&A and chat all complete on the device
Platform support
With kernel and shell separated, support levels can advance independently per platform.
The full data terminal: plugin system, AI access and batch consolidation
Quick-entry bookkeeping with App Intents, Shortcuts and widgets
Read-only commands with JSON output, built for agents
The kernel is designed cross-platform; the shell is not yet scheduled
Same kernel; on-device AI depends on platform capability adaptation
How it differs from the common approach
The difference usually is not in the feature table — it is in where the boundary is drawn.
Commands at a glance
For the full manual, see the CLI reference page. All commands output structured results by default.
ledger-cli doctorSelf-check: store location, read-only state, kernel version and encryption status
--jsonledger-cli statsMonthly income and expense, net worth and wallet distribution
--month YYYY-MM--wallet <id>ledger-cli walletsList wallets and their bag types (assets / liabilities / securities / crypto holdings, etc.)
ledger-cli querySearch entries by tag, time range and amount range
--tag <tag>--from--to--minActual output
01$ ledger-cli doctor02{ "ok": true, "store": "ledger-mac.store", "readonly": true }0304$ ledger-cli stats --month 2026-0905{ "monthExpense": 12483.20, "monthIncome": 32000.00,06 "netWorth": 486210.55, "wallets": 7 }Modules
3 groups, 10 modules — all from the repository’s real directory structure.
SwiftUI · SwiftData · Swift 6 · FoundationModels · Vision · GRDB (V1) · CLILedgerCore is a standalone Swift package; the app and the CLI share one implementation.
LedgerCoreThe double-entry kernel: legs sum to zero, balances derived, a three-verb validation gate on opening entries
LedgerCore/Sources/LedgerCoreLedgerCoreStorageStorage: SwiftData models and local-store reads; the CLI opens read-only
LedgerCore/Sources/LedgerCoreStorageLedgerCoreCryptoEncryption: storage encrypted on the machine; only ciphertext reaches the cloud
LedgerCore/Sources/LedgerCoreCryptoLedgerCoreSyncSync: UUIDv7 primary keys + HLC versions + entity-state mirror sync
LedgerCore/Sources/LedgerCoreSynciOS for quick capture; macOS is the full data terminal.
ledger-iosiOS: the main bookkeeping entry, App Intents and Shortcuts, widgets
ledger-ios/ledger-macmacOS: the full data terminal, plugin system and batch consolidation
ledger-mac/IntelligenceOn-device intelligence: FoundationModels inference + rules-engine fallback + Vision OCR receipt recognition
ledger/IntelligenceImport / LANData import (standard formats) and a LAN sync channel
ledger/{Import,LAN}Let external agents read your ledger safely — read-only.
ledger-cliRead-only CLI: doctor / stats and friends, with JSON output for AI agents
ledger-cli/Sources/ledger-cliToken authorizationTokens are issued and revoked by the Mac app, with an audit log attached
ledger-mac/Usage
4 typical scenarios, each broken into steps you can follow.
Record an entry through App Intents and Shortcuts, without opening the app.
- 1Tell Siri or a Shortcut: “log an entry — lunch, 38”
- 2The on-device rules engine parses amount, category and time
- 3The matching wallet and bag type are resolved, producing a set of legs that sums to zero
- 4A confirmation card shows the parsed result; confirming commits it
On-device OCR reads the receipt; nothing ever leaves the device.
- 1Take a photo or pick a receipt image from the library
- 2The Vision framework performs on-device text recognition
- 3The rules engine extracts merchant, amount and date
- 4A confirmation card is generated; after a human check it is committed
Ask “how much did dining cost this month” — the answer is computed on the device.
- 1FoundationModels inference on-device understands the natural-language question
- 2The kernel translates the question into a read-only query over the local ledger
- 3Statistics are computed on the device, with no network requests
- 4When the model falls short it degrades to the rules engine, so the feature stays available
Read-only authorization plus an audit log: AI can look, never modify.
- 1Generate an access token in the Mac app
- 2The agent opens the local store read-only through ledger-cli
- 3Structured JSON output is handed to the agent for analysis
- 4Every call is written to the audit log, and the token can be revoked at any time
Data boundary and security
Much of the value of this kind of tool is in what it does not do. Every item below notes where it is implemented.
Entries are encrypted on the machine; the cloud keeps only the latest ciphertext, and the server never sees plaintext.
LedgerCoreCryptoledger-cli opens the local store read-only; any write is rejected at the storage layer.
ledger-cli doctor → readonly: trueAccess tokens are issued and revoked by the Mac app, with an audit log attached — cut off at any time.
ledger-cli token revokeStatistics and Q&A complete on the device; AI analysis never sends data out.
FoundationModels · IntelligenceThe opening-entry transaction passes a three-verb validation gate; once settled, the data model is never overturned.
LedgerCore validation gateEntity-state mirror overwrite sync; the server accumulates no history, shrinking the exposure surface.
LedgerCoreSyncRelease cadence
Shipped items state what was delivered; in-progress items state what is being built.
v0.6ReleasedKernel- Double-entry kernel with legs summing to zero
- Eleven wallet bag types
- SwiftData local storage and the encryption layer
- iOS bookkeeping app with App Intents
v0.9ReleasedIntelligence & access- On-device AI statistics and Q&A
- Vision OCR receipt recognition
- ledger-cli read-only access and tokens
- The macOS full data terminal
v1.0In developmentSync & plugins- UUIDv7 + HLC entity-mirror sync ships
- The plugin system opens to third-party AI
- Batch consolidation and reconciliation workflows
- Multi-currency rates and conversion
v1.2PlannedExpansion- Windows / Android apps
- Shared ledgers and family collaboration
- Portfolio analysis views
- A standard-format import/export ecosystem
FAQ
No. Entries are stored encrypted on the machine; only when sync is switched on does the latest ciphertext get uploaded — the server keeps no plaintext and accumulates no history. AI statistics and Q&A complete entirely on the device.
Modules
3 groups, 10 modules. Paths map directly to repository directories, so engineers can locate code fast.
LedgerCore is a standalone Swift package; the app and the CLI share one implementation.
LedgerCoreThe double-entry kernel: legs sum to zero, balances derived, a three-verb validation gate on opening entries
LedgerCore/Sources/LedgerCoreLedgerCoreStorageStorage: SwiftData models and local-store reads; the CLI opens read-only
LedgerCore/Sources/LedgerCoreStorageLedgerCoreCryptoEncryption: storage encrypted on the machine; only ciphertext reaches the cloud
LedgerCore/Sources/LedgerCoreCryptoLedgerCoreSyncSync: UUIDv7 primary keys + HLC versions + entity-state mirror sync
LedgerCore/Sources/LedgerCoreSynciOS for quick capture; macOS is the full data terminal.
ledger-iosiOS: the main bookkeeping entry, App Intents and Shortcuts, widgets
ledger-ios/ledger-macmacOS: the full data terminal, plugin system and batch consolidation
ledger-mac/IntelligenceOn-device intelligence: FoundationModels inference + rules-engine fallback + Vision OCR receipt recognition
ledger/IntelligenceImport / LANData import (standard formats) and a LAN sync channel
ledger/{Import,LAN}Let external agents read your ledger safely — read-only.
ledger-cliRead-only CLI: doctor / stats and friends, with JSON output for AI agents
ledger-cli/Sources/ledger-cliToken authorizationTokens are issued and revoked by the Mac app, with an audit log attached
ledger-mac/Tech stack
Layered design
From kernel to shell — what each layer owns and what it is built with. The core design of these tools is separating kernel from shell.
Four entities — Ledger / Wallet / Transaction / Term — plus the Leg value object
Double-entry legs sum to zero; balance = opening + Σ bag legs, derived on the spot
FoundationModels on-device inference + rules-engine fallback + Vision OCR
UUIDv7 identity + HLC versions + entity-mirror overwrite sync (V1)
The ledger-cli read-only CLI, token authorization and JSON output for AI agents
SwiftUI · SwiftData · Swift 6 · iOS 17.6+ · macOS
Multi-platform support
One kernel; a different platform is just a different shell. Support levels can advance per platform.
The full data terminal: plugin system, AI access and batch consolidation
Quick-entry bookkeeping with App Intents, Shortcuts and widgets
Read-only commands with JSON output, built for agents
The kernel is designed cross-platform; the shell is not yet scheduled
Same kernel; on-device AI depends on platform capability adaptation
Tech stack
Command reference
6 commands. Design premises: structured output and semantic exit codes, so both scripts and AI agents can consume them reliably.
ledger-cli doctorSelf-check: store location, read-only state, kernel version and encryption status
--jsonledger-cli statsMonthly income and expense, net worth and wallet distribution
--month YYYY-MM--wallet <id>ledger-cli walletsList wallets and their bag types (assets / liabilities / securities / crypto holdings, etc.)
ledger-cli querySearch entries by tag, time range and amount range
--tag <tag>--from--to--minledger-cli exportStructured export for external AI agents to consume
--format json|csv--monthledger-cli tokenInspect or revoke access tokens (revocation requires confirmation in the Mac app)
listrevoke <id>Output conventions
The CLI is an interface for programs; humans being able to read it is a side effect.
JSON by default, with stable field names. Human-readable formatting is the caller’s decision, not something the CLI guesses.
Success, failure and usage errors return distinct exit codes, so scripts and agents branch on the code instead of parsing text.
Local token files are discovered automatically, avoiding plaintext credentials on the command line (which would land in shell history and process lists).
One real invocation
01$ ledger-cli doctor02{ "ok": true, "store": "ledger-mac.store", "readonly": true }0304$ ledger-cli stats --month 2026-0905{ "monthExpense": 12483.20, "monthIncome": 32000.00,06 "netWorth": 486210.55, "wallets": 7 }Hand the complexity of identity, agents and private domain to one governable kernel
Whether you are replacing an existing IAM, building an agent platform, or trying to make private-domain operations actually work — start with a 30-minute architecture call. We will first judge whether this is the kind of problem we are good at, and say so plainly if it is not.