The plain text accounting tool of the future.
Keep track of your
For help please come visit us on one of the following sites:
- List of Features / TODOs
- Journal File Format
- Import from Ledger CLI
- Comparison with Hledger
List of Features / TODOs
- Modeled on transactions instead of debiting / crediting accounts => Support for complex transactions made up of several transfers
- Dedicated payer (from) and payee (to) fields (ledger only supports payee)
- No misuse of accounts as categories / tags => direct support for them
- No hard-coded asset / liability connotation as it is viewpoint dependent => Choose viewpoint when printing the balance
- Easily editable & processable file format based on YAML
- Clear separation between
- Physical account (e.g. wallet, bank account)
- Entities (e.g. my mum, a company)
- Purpose of transaction (food, travel)
- Initial balances
- High precision timestamps
- Including nanoseconds
- BigInt rational numbers to eliminate rounding errors
- Support for all states of transaction life cycle
- Request - Request to exchange a commodity
- Offer - Specification of commodity & expected trade item
- Acceptance - Affirmation of interest in offered exchange
- Certification - Acknowledgment that exchange was performed
- Support for any type of commodity (e.g. even time and messages)
- Differentiation between transfers, transactions & exchanges
- Special syntax for exchanges
- Meta data for all entities (transactions, accounts, entities, …)
- Verifies sole use of predefined entities
- Checks match with verification balances
- Duplicate detection
- Syntax checking in addition to syntax highlighting
- CSV import
- Link to receipt file
- Budgets (including progress visualization)
- Export to various formats for post-processing
- Additional features for crypto currencies
- TODO: Think about what features exactly
- Multi file support
- Cache-files to speed up processing of large data sets
- Support for time limited commodities (e.g. subscription for a month)
- Treat as scientific units (e.g 1 k€ == 1000 €)
- Hard vs Soft vs Fungible vs …
- Define which are allowed / prohibited for each account
- Generate EPC QR Codes for transfers
npm install --global transity
While Transity is licensed under the AGPL-3.0-or-later and can therefore be used free of charge, I hope you will acknowledge the work and effort it takes to maintain and improve this software and make a donation via my GitHub Support page.
If you find Transity valuable and/or use it regularly this should be a small nuisance for you, but it would mean the world for me! It would mean that I can spend more time on this project and bring it to the next level!
Thanks a lot for your support!
For including Transity in proprietary closed source products, please contact me!
$ transity balance examples/journal.yaml anna 1 evil-machine -49978.02 € ben -50 $ -1.432592 BTC -100 € evil-corp -1 evil-machine 50015 € good-inc -100 € grocery-shop 11.97 € john 371.04 € 50 $ 1.432592 BTC :default 219.99 € giro 50 $ 1.432592 BTC 85 € wallet 66.05 €
If linked modules aren't exposed in your path you can also run
cli/main.js balance examples/journal.yaml
List complete usage manual by simply calling
transity without any arguments.
$ transity Usage: transity <command> <path/to/journal.yaml> Command Description ------------------ ------------------------------------------------------------ balance Simple balance of all accounts transactions All transactions and their transfers transfers All transfers with one transfer per line entries All individual deposits & withdrawals entries-by-account All individual deposits & withdrawals grouped by account gplot Code and data for gnuplot impulse diagram to visualize transfers of all accounts gplot-cumul Code and data for cumuluative gnuplot step chart to visualize balance of all accounts
Check Order of Entries
Check if all entries are in a chronological order
ag --nonumbers "^ utc:" journals/main.yaml | tr -d "\'" | sort -c
Retrieving Data from Banks
Transity includes a few scripts located at ./scripts to automate a Chrome browser to download data. It supports downloading CSV files of all transactions and converting them to journal files and retrieving the current account balance:
Currently supported accounts for transactions:
Currently supported accounts for balances:
Contributions are very welcome!
node scripts/transactions/hypovereinsbank.js > transactions.yaml
This will prompt you for your credentials and afterwards automate a headless Chrome instance to download and convert the data.
Journal File Format
A minimal journal file is a YAML file with following format:
owner: anna commodities: - id: € name: Euro alias: - EUR note: Currency used in the European Union utc: '2017-04-02 19:33:53' entities: - id: anna name: Anna Smith utc: '2017-04-02 19:33:28' tags: - person accounts: - id: wallet name: Wallet note: Anna's black wallet utc: '2017-04-02 19:33:28' tags: - wallet - id: evil-corp name: Evil Corporation utc: '2017-04-02 19:33:28' note: The Evil Corporation in the United States of Evil tags: - company transactions: - title: Purchase of evil machine transfers: - utc: '2017-02-17' from: anna to: evil-corp amount: 50000 € - utc: '2017-02-17' from: evil-corp to: anna amount: 1 evil-machine
By default all accounts are plotted.
To limit it to only a subsection use
awk to filter the output.
For example all transactions of Euro accounts:
transity gplot examples/journal.yaml \ | awk '/^$/ || /(EOD|^set terminal)/ || /€/' \ | gnuplot \ | imgcat
Or all account balances of Euro accounts over time:
transity gplot-cumul examples/journal.yaml \ | awk '/^$/ || /(EOD|^set terminal)/ || /€/' \ | gnuplot \ | imgcat
Import from Ledger CLI
Execute the included ledger2transity script:
./ledger2transity.sh examples/hledger.journal > transactions.csv
transactions.csv to YAML with e.g. browserling.com/tools/csv-to-yaml
- Merge adjacent entries as each entry only debits / credits an account.
A transaction always involves 2 accounts (
to). (For expenses basically copy the ledger-account from the second entry into the
fromfield of the first entry)
tomight be reversed for income (depending on how the
payeefield was used)
- Account names of Ledger-CLI are interpreted as tags Transity understands accounts as physical accounts
- The note is duplicated in the
tagsfield. There is no way to get only the tags in Ledger-CLI
Why another plain text accounting tool?
Existing accounting tools are historically based on the notion of an account. You add money (debit) and you remove money (credit). (If this sounds backwards to you, read this explanation)
For example you get 50 € from your mum and buy some food for 20 €.
Account | Debit | Credit --------|---------|-------- Wallet | 50.00 € | Wallet | | 20.00 € ---------------------------
Simple, but also incomplete. Where did the money come from, where did it go? This led to double entry bookkeeping. Whenever you add some money to an account, you have to remove the same amount from another.
Account | Debit | Credit --------|---------|-------- Wallet | 50.00 € | Mum | | 50.00 € Wallet | | 20.00 € Food | 20.00 € | ---------------------------
But you must never forget a posting, because otherwise your account won't balance.
Account | Debit | Credit --------|---------|-------- Wallet | 50.00 € | Mum | | 50.00 € Wallet | | 20.00 € ---------------------------
Oops, where did the money go? 🤷
If this looks (and sounds) confusing or too complicated, you're not alone! It made sense in former times as this layout makes it easier to add up the amounts by hand, but not in times of computers.
So how can we simplify it? It's actually quite easy: We just have to model it in terms of transactions, and not accounts.
Amount | From | To -------|--------|-------- 50 € | Mum | Wallet 20 € | Wallet | Food -------------------------
- Simple - No more confusing debit / credit / asset / liability mumbo jumbo
- Intuitive - Just like you would talk about it
- Safe - It's obvious if you forget to fill out a field
Together with some further changes it yields an easier to understand, more robust and more complete representation of accounting!
Why is it written in PureScript?
You wouldn't want your money to get lost in rounding errors or
be turned to
undefined, would you?
Why is it not written in Haskell?
Comparison with Hledger
(H)ledger's transactions are a (balanced) group of account postings. Transity's transactions are a group of transfers between two accounts.
There is a lot of ambiguity in the ledger journal format. Are you able to tell the difference between the 2 options?
2019-01-17 Bought food expenses:food $10 assets:cash ; vs 2019-01-17 Bought food assets:cash expenses:food $10
Also, it lacks some fields for more precise recording of which parties where involved.
- What food?
- Where did you buy it?
- Which supermarket?
2019-01-17 Bought food expenses:food $10 assets:cash
hledger --file examples/hledger.journal balance # vs transity balance examples/journal.yaml
hledger --file examples/hledger.journal register # vs transity transactions examples/journal.yaml
hledger --file examples/hledger.journal register --output-format=csv # vs transity entries examples/journal.yaml
- No support for precise timestamps (transactions only have an associated date)
- No first class support for Gnuplot (Check out Report Scripts for Ledger CLI with Gnuplot for some scripts)
Measured with hyperfine including 3 warmups on an early 2015 MacBook Pro.
For a journal file with around 2000 entries:
Benchmark #1: transity balance journals/main.yaml Time (mean ± σ): 1.287 s ± 0.021 s [User: 1.790 s, System: 0.140 s] Range (min … max): 1.250 s … 1.324 s 10 runs
Benchmark #1: hledger -f test.ledger balance Time (mean ± σ): 409.6 ms ± 6.1 ms [User: 366.6 ms, System: 28.5 ms] Range (min … max): 398.8 ms … 417.6 ms 10 runs
Benchmark #1: ledger -f test.ledger balance Time (mean ± σ): 76.3 ms ± 9.1 ms [User: 62.7 ms, System: 9.4 ms] Range (min … max): 65.1 ms … 101.8 ms 28 runs
Entry / Value Date
There are no separate fields for entry or value dates necessary. Simply use ISO 8601 time intervals to specify the duration of a transfer.
transactions: - id: '123456789' note: Deposit of savings transfers: - utc: 2018-01-04T12:00--05T22:10 from: john to: bank amount: 100 €
This is a first concept for an alternative syntax for the YAML journal file:
2016-04-16 18:50:28 #20135604 1 year registration of domain "example.org" john -> paypal : 9.95 € paypal -> namecheap : 10.69 $ paypal -> icann : 0.18 $ namecheap -> john : 1 Domain
- plaintextaccounting.org - Best of plain text accounting.
- cs007.blog - Personal finance for engineers.
- principlesofaccounting.com - Online tutorial on accounting.
- npoacct.sfconservancy.org - Effort to create accounting software for non-profit organizations.
- github.com/nuex/t - sh script for working with ledger timelog files.
- github.com/bankscrap/bankscrap - Ruby gem to extract balance and transactions from multiple banks.
- github.com/prashants/webzash - Easy to use web based double entry accounting software.