- Rust 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Filtering on the expense value date drops back-dated expenses: one entered into Spliit today for a value date weeks ago looks old to --after, even though it is new to the user. --created-after filters on the createdAt timestamp instead, so those expenses still make it into the file. Every run reports the newest createdAt in the input as the cutoff for the next run. The cutoff is exclusive, so feeding that value back never re-exports the expense it came from. createdAt stays a String internally and is parsed on demand - it feeds the transaction ID and the rounding hash, so changing its representation would break GnuCash deduplication against already-imported data. Spliit records no updatedAt, so edits to pre-cutoff expenses are missed and deletions are invisible; both are documented in the README. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
| src | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CLAUDE.md | ||
| config.example.toml | ||
| README.md | ||
spliit2gnucash
A command-line tool for converting Spliit expense tracking data into GnuCash-compatible CSV format.
Overview
Spliit is a web-based expense sharing app that allows groups to track shared expenses. This tool converts Spliit's JSON export into a CSV format that can be imported into GnuCash for personal finance tracking.
The key feature is that all transactions are converted from the perspective of a single person ("P"), making it easy to track personal expenses and money owed/owing within a Spliit group.
How It Works
Transaction Types
From person P's perspective, there are three types of transactions. Note: These are the splits generated by spliit2gnucash - you must then reconcile them with your bank accounts in GnuCash.
1. Two-legged (someone else paid)
- When another person pays for a shared expense
- spliit2gnucash creates:
- Expense account (debit): Your share of the expense
- AR:Payer (credit): Amount you owe them
- You later reconcile: When you reimburse them, match your bank transfer to AR:Payer
2. Three-legged (P paid)
- When P pays for a shared expense
- spliit2gnucash creates:
- Expense account (debit): Your share of consumption
- AR:OtherParticipant(s) (debit): Amount they owe you
- AR:Self (credit): Total amount you paid out
- You later reconcile: Match your bank payment to AR:Self to complete the double-entry
3. Reimbursement
- When money is transferred between participants to settle debts
- spliit2gnucash creates:
- AR:Receiver (credit): They owe you less / You owe them more
- AR:Payer or AR:Self (depends on direction): The offsetting entry
- You later reconcile: Match your bank transfer to AR:Self to complete the double-entry
Account Mapping
The tool uses a TOML configuration file to map:
- Spliit participants to GnuCash Accounts Receivable accounts
Expense categories are taken directly from Spliit (combining grouping and name fields). For example, a Spliit expense with grouping="Food" and name="Groceries" becomes the GnuCash account "Food:Groceries". You can optionally add a prefix to all expense accounts.
Each participant (including yourself) has their own AR account:
-
AR:Self - Acts as a reconciliation account between Spliit transactions and your actual bank payments. This account temporarily tracks payments you made through the group until you reconcile them with your bank transactions in GnuCash.
-
AR:OtherPerson - Tracks what you owe to (or are owed by) other participants, AND serves as the reconciliation account when you actually pay/receive reimbursements.
Note: The tool does NOT create cash/bank account entries. Those must be added by you when reconciling with your actual bank transactions in GnuCash (see "GnuCash Integration Workflow" below).
Usage
The tool provides two subcommands:
1. Initialize Configuration
First, create a configuration file from your Spliit data:
spliit2gnucash init-config --input example.json --output config.toml
This will:
- Create a new config file with all participants from your Spliit data
- Generate sensible default account mappings for participants
- Set the first participant as the default person (you should change this)
You can also extend an existing config with new participants:
spliit2gnucash init-config --input example.json --config old-config.toml --output updated-config.toml
2. Convert Transactions
After setting up your configuration, convert Spliit expenses to GnuCash CSV:
spliit2gnucash transactions --input example.json --config config.toml --output transactions.csv
You can filter transactions to only include those after a specific value date:
spliit2gnucash transactions --input example.json --config config.toml --output transactions.csv --after 2024-01-01
This is useful for:
- Ignoring old transactions already imported
- Only importing recent transactions
Incremental Exports (--created-after)
For recurring imports, filtering by value date is the wrong tool: a shared expense
entered into Spliit today may carry a value date from weeks ago, and --after
would silently drop it. --created-after instead filters on the createdAt
timestamp - when the expense was entered into Spliit - so back-dated expenses
still land in the file as long as they are new to you:
spliit2gnucash transactions --input example.json --config config.toml --output transactions.csv --created-after 2025-11-16T18:30:00.123Z
Every run prints the newest createdAt in the export and the exact flag to use
next time:
Successfully converted 4 expenses to transactions.csv
Newest expense in this export was created at 2025-11-21T09:14:02.371Z
For the next incremental export, use: --created-after 2025-11-21T09:14:02.371Z
Note that timestamp down after each import, and the next run picks up exactly the expenses added since. The cutoff is exclusive, so feeding back the reported timestamp never re-exports the expense it came from.
Accepted formats:
- A full timestamp as printed above, e.g.
2025-11-16T18:30:00.123Z(recommended - this is what Spliit stores) - A timestamp without a zone, e.g.
2025-11-16T18:30:00(interpreted as UTC) - A bare date, e.g.
2025-11-16, which means midnight UTC at the start of that day, i.e. everything created on that day or later
Caveats
Spliit records no "updated at" timestamp, so this scheme keys off creation time only:
- Edits to existing expenses are missed. If someone corrects the amount of an
expense created before your cutoff, it will not reappear in the export. Re-run
without
--created-after(or with an older cutoff) if you suspect edits; GnuCash deduplicates on Transaction ID, so re-importing overlapping ranges is safe. - Deletions are invisible. An expense removed in Spliit simply stops appearing in exports; the already-imported GnuCash transaction stays and must be removed by hand.
--after and --created-after can be combined - both filters are applied.
Spliit Export
- Go to your Spliit group:
https://spliit.app/groups/YOUR_GROUP_ID - Navigate to
https://spliit.app/groups/YOUR_GROUP_ID/expenses/export/jsonin your browser. Due to bot protection, this tool cannot do the download for you directly. - Use this saved file as input to the tool
Configuration File
Create a config.toml file:
# Which person's perspective to use
person = "Alice"
# Optional: Prefix for all expense accounts
# If set, expense accounts will be prefixed with this value
# For example, "Food:Groceries" becomes "Expenses:Food:Groceries"
expense_account_prefix = "Expenses"
# Participant-specific Accounts Receivable
# Find participant IDs in your Spliit JSON export
# IMPORTANT: Include ALL participants, including yourself!
[participant_accounts]
"participant-id-1" = "Accounts Receivable:GroupName:Alice"
"participant-id-2" = "Accounts Receivable:GroupName:Bob"
Output Format
The tool generates a CSV file compatible with GnuCash import:
Transaction ID,Date,Description,Account,Deposit,Withdrawal,Notes
2024-11-02T10:30:00Z,2024-11-02,Grocery Shopping,Expenses:Food:Groceries,25.00,,
2024-11-02T10:30:00Z,2024-11-02,Grocery Shopping,Accounts Receivable:Group,,25.00,
Each transaction includes:
- Transaction ID: Timestamp from Spliit (used by GnuCash for deduplication)
- Date: Transaction date
- Description: Expense title
- Account: GnuCash account name
- Deposit/Withdrawal: Amount in decimal format
- Notes: Additional metadata (payer, etc.)
Importing into GnuCash
When importing the generated CSV file into GnuCash, use the following import settings:
- File → Import → Import Transactions from CSV
- Select your generated CSV file
- Configure the import settings:
- Multi-split: Check this checkbox (required for multi-split transactions)
- Date format:
y-m-d - Currency format:
period(decimal point as separator) - Leading lines to skip:
1(skips the header row)
- Column mapping (in order):
- Transaction ID
- Date
- Description
- Account
- Amount
- Amount (negated)
- Memo
After configuring these settings, proceed with the import. GnuCash will use the Transaction ID to prevent duplicate imports, so you can safely re-import updated exports from Spliit.
GnuCash Integration Workflow
The transactions generated by this tool are incomplete - they need to be reconciled with your actual bank transactions in GnuCash. Here's how the complete double-entry bookkeeping works:
Understanding AR:Self (Your Reconciliation Account)
AR:Self acts as a temporary holding account. When you pay for a group expense:
-
spliit2gnucash generates:
- Expense account: +€30.00 (debit - what you consumed)
- AR:Self: -€30.00 (credit - you paid this amount)
-
You manually reconcile in GnuCash by linking to your bank transaction:
- Checking Account: -€30.00 (credit - money left your account)
- AR:Self: +€30.00 (debit - balances the -€30.00 from step 1)
-
Result: AR:Self returns to zero, and the complete entry is:
- Expense account: +€30.00 (what you consumed)
- Checking Account: -€30.00 (where the money came from)
Example: Complete Three-Legged Transaction
Scenario: You pay €60 for dinner, split equally between you, Alice, and Bob (€20 each).
Step 1: Import spliit2gnucash CSV into GnuCash
The CSV contains these splits:
Transaction ID,Date,Description,Account,Deposit,Withdrawal,Notes
2024-11-15T19:30:00Z,2024-11-15,Dinner,Expenses:Food:Restaurant,20.00,,Paid by: You
2024-11-15T19:30:00Z,2024-11-15,Dinner,AR:Group:Alice,20.00,,Paid by: You
2024-11-15T19:30:00Z,2024-11-15,Dinner,AR:Group:Bob,20.00,,Paid by: You
2024-11-15T19:30:00Z,2024-11-15,Dinner,AR:Self,,60.00,Paid by: You
After import, your AR:Self balance is -€60.00 (you paid out this amount).
Step 2: Reconcile with your bank transaction
Find the corresponding €60 charge in your checking account. Edit that transaction in GnuCash to add the other side:
- Checking Account: -€60.00 (credit - the actual payment)
- AR:Self: +€60.00 (debit - balances the import)
Step 3: Final account balances
- Expenses:Food:Restaurant: +€20.00 (your share of consumption)
- AR:Group:Alice: +€20.00 (Alice owes you)
- AR:Group:Bob: +€20.00 (Bob owes you)
- AR:Self: €0.00 (balanced after reconciliation)
- Checking Account: -€60.00 (the actual payment)
Example: Two-Legged Transaction + Reimbursement
Scenario: Alice pays €45 for groceries, split equally between you, Alice, and Bob (€15 each). Later, you reimburse Alice €15.
Step 1: Import spliit2gnucash CSV for the expense
Transaction ID,Date,Description,Account,Deposit,Withdrawal,Notes
2024-11-16T10:00:00Z,2024-11-16,Groceries,Expenses:Food:Groceries,15.00,,Paid by: Alice
2024-11-16T10:00:00Z,2024-11-16,Groceries,AR:Group:Alice,,15.00,Paid by: Alice
After import, your AR:Group:Alice balance is -€15.00 (you owe Alice).
Step 2: Import spliit2gnucash CSV for the reimbursement
When you mark the reimbursement in Spliit and re-export, you get:
Transaction ID,Date,Description,Account,Deposit,Withdrawal,Notes
2024-11-17T14:00:00Z,2024-11-17,Reimbursement to Alice,AR:Group:Alice,15.00,,
2024-11-17T14:00:00Z,2024-11-17,Reimbursement to Alice,AR:Self,,15.00,
After import:
- AR:Group:Alice: €0.00 (debt cleared)
- AR:Self: -€15.00 (you paid out this amount)
Step 3: Reconcile the reimbursement with your bank transfer
Find the €15 transfer to Alice in your checking account:
- Checking Account: -€15.00 (credit - the actual transfer)
- AR:Self: +€15.00 (debit - balances the import)
Step 4: Final account balances
- Expenses:Food:Groceries: +€15.00 (your consumption)
- AR:Group:Alice: €0.00 (debt settled)
- AR:Self: €0.00 (balanced after reconciliation)
- Checking Account: -€15.00 (the actual reimbursement payment)
Reconciliation Checklist
After importing transactions and reconciling with bank accounts:
- AR:Self should be zero (or close to zero if some payments are still pending reconciliation)
- AR:OtherPerson balances show outstanding debts (positive = they owe you, negative = you owe them)
- Expense accounts accurately reflect your consumption
- Bank accounts match your actual bank statements
If AR:Self has a balance, it means you have unreconciled payments - you need to match them with bank transactions.
Workflow
Initial Setup
- Export data from Spliit (save as
spliit-data.json) - Generate initial config:
spliit2gnucash init-config --input spliit-data.json --output config.toml - Edit
config.tomlto set your name as thepersonfield - Review and adjust account mappings as needed
- Convert transactions:
spliit2gnucash transactions --input spliit-data.json --config config.toml --output transactions.csv - Import
transactions.csvinto GnuCash - Reconcile imported transactions with your bank accounts (see "GnuCash Integration Workflow" above)
Regular Updates
- Export fresh data from Spliit (overwrites previous export)
- Optionally extend config with new participants:
spliit2gnucash init-config --input spliit-data.json --config config.toml --output config.toml - Run converter with the timestamp noted after the previous run:
spliit2gnucash transactions --input spliit-data.json --config config.toml --output transactions.csv --created-after 2025-11-16T18:30:00.123Z - Note down the new timestamp the converter prints - that is the cutoff for your next run
- Import the CSV into GnuCash (GnuCash handles deduplication based on Transaction ID)
- Reconcile new transactions with your bank accounts to balance AR:Self and AR:OtherPerson accounts
Building
cargo build --release
The binary will be available at target/release/spliit2gnucash.
Development
See CLAUDE.md for development guidelines and commands.
License
TBD