Convert QIF (Quicken Interchange Format) or CSV files to Ledger-CLI format. Zero dependencies—runs on Bun with no external npm packages.
Several entry points are provided, each of which can be compiled to a standalone binary:
| Entry Point | Description | Default Format |
|---|---|---|
| qif-to-ledger | For converting QIF files | QIF |
| csv-to-ledger | For converting CSV files | CSV |
| ledger-converter | Generic converter with explicit format options | (requires -i) |
| ledger-converter-tui | Interactive terminal UI (no arguments needed) | (interactive) |
Conversion logic ported from chrisnatali/ledger-tools.
ledger-converter/
├── qif-to-ledger.ts # Entry point: QIF converter (compilable to binary)
├── csv-to-ledger.ts # Entry point: CSV converter (compilable to binary)
├── ledger-converter.ts # Entry point: Generic converter (compilable to binary)
├── ledger-converter-tui.ts # Entry point: Interactive TUI (compilable to binary)
├── cli/
│ ├── arg_parser.ts # Shared argument parsing for CLI entry points
│ ├── help.ts # Shared help text for CLI entry points
│ ├── tui.ts # TUI utilities (prompts, colors, selection)
│ └── types.ts # Shared types
├── utils/
│ ├── qif_parser.ts # QIF file parsing
│ ├── qif_parser.test.ts # QIF parser tests
│ ├── csv_parser.ts # CSV file parsing
│ ├── csv_parser.test.ts # CSV parser tests
│ └── ledger_converter.ts # Ledger format conversion
├── examples/
│ ├── sample.qif # Sample QIF file for testing
│ └── sample.csv # Sample CSV file for testing
└── README.md
- Bun runtime
Sample files are included in examples/ to test each entry point:
# Test qif-to-ledger with sample QIF file
bun qif-to-ledger.ts -a "Assets:Checking" examples/sample.qif
# Test csv-to-ledger with sample CSV file
bun csv-to-ledger.ts -a "Assets:Checking" examples/sample.csv
# Test ledger-converter with either format
bun ledger-converter.ts -a "Assets:Checking" -i qif examples/sample.qif
bun ledger-converter.ts -a "Assets:Checking" -i csv examples/sample.csv
# Test the interactive TUI
bun ledger-converter-tui.ts
# Then select QIF or CSV and enter: examples/sample.qif or examples/sample.csvRun the test suite with Bun's built-in test runner:
bun testTests cover the QIF and CSV parsers, including edge cases for date formats, quoted fields, split transactions, and amount parsing.
Each entry point can be compiled to a standalone executable that runs without Bun installed:
# Build all binaries
bun build --compile --outfile=qif-to-ledger qif-to-ledger.ts
bun build --compile --outfile=csv-to-ledger csv-to-ledger.ts
bun build --compile --outfile=ledger-converter ledger-converter.ts
bun build --compile --outfile=ledger-converter-tui ledger-converter-tui.tsBuild for other platforms:
# Linux x64
bun build --compile --target=bun-linux-x64 --outfile=qif-to-ledger-linux-x64 qif-to-ledger.ts
# Linux ARM64
bun build --compile --target=bun-linux-arm64 --outfile=qif-to-ledger-linux-arm64 qif-to-ledger.ts
# macOS x64 (Intel)
bun build --compile --target=bun-darwin-x64 --outfile=qif-to-ledger-darwin-x64 qif-to-ledger.ts
# macOS ARM64 (Apple Silicon)
bun build --compile --target=bun-darwin-arm64 --outfile=qif-to-ledger-darwin-arm64 qif-to-ledger.ts
# Windows x64
bun build --compile --target=bun-windows-x64 --outfile=qif-to-ledger.exe qif-to-ledger.tsAfter compilation, run directly without bun:
./qif-to-ledger -a "Assets:Checking" bank_export.qif
./csv-to-ledger -a "Assets:Checking" bank_export.csv
./ledger-converter -a "Assets:Checking" -i qif bank_export.qif
./ledger-converter-tui # Interactive mode - no arguments neededInstall system-wide (optional):
# Copy to a directory in your PATH
sudo cp qif-to-ledger csv-to-ledger ledger-converter ledger-converter-tui /usr/local/bin/
# Then run from anywhere
qif-to-ledger -a "Assets:Checking" bank_export.qif
ledger-converter-tui # Launch interactive modebun qif-to-ledger.ts -a <asset-account> <input-file>
bun qif-to-ledger.ts -a <asset-account> -f csv <input-file> # Override formatbun csv-to-ledger.ts -a <asset-account> <input-file>
bun csv-to-ledger.ts -a <asset-account> -f qif <input-file> # Override formatbun ledger-converter.ts -a <asset-account> -i qif <input-file>
bun ledger-converter.ts -a <asset-account> -i csv <input-file>
bun ledger-converter.ts -a <asset-account> -i csv -o ledger <input-file>bun ledger-converter-tui.tsThe TUI provides an interactive experience with:
- Arrow key navigation for option selection
- Sample files as default input (press Enter to accept)
- Transaction preview before output
- Back navigation (press 'b' or Escape at any prompt)
- Choice of stdout or file output
Flow:
- Select input format (QIF or CSV)
- Enter input file path (default:
examples/sample.qiforexamples/sample.csv) - Enter asset account name (default:
Assets:Checking) - Preview first 3 transactions
- Confirm conversion
- Choose output destination (terminal or file)
| Option | Short | Description |
|---|---|---|
--asset-account |
-a |
The asset account transactions apply to (required) |
--format |
-f |
Input file format: qif or csv (default depends on entry point) |
--help |
-h |
Show help message |
| Option | Short | Description |
|---|---|---|
--asset-account |
-a |
The asset account transactions apply to (required) |
--input-format |
-i |
Input file format: qif or csv (required) |
--output-format |
-o |
Output file format: ledger (default: ledger) |
--help |
-h |
Show help message |
Ledger is a plain text accounting tool that uses double-entry accounting, where every transaction must balance between two or more accounts. When you spend $50 on groceries, the money flows from your checking account into an expense category:
2024/01/15 Grocery Store
Expenses:Food $50.00 <- Category (from your QIF/CSV file)
Assets:Checking <- Asset account (you specify this)
Why is the asset account required?
When you export transactions from your bank, the file contains:
- Date, payee, amount
- Category (where the money went)
But it doesn't specify which account the money came from—your bank assumes you know. You must provide this via the -a flag so Ledger can create balanced transactions.
Common asset account names:
| Account | Use For |
|---|---|
Assets:Checking |
Bank checking account |
Assets:Savings |
Savings account |
Assets:Cash |
Physical cash transactions |
Liabilities:Credit Card |
Credit card (technically a liability) |
Liabilities:Credit Card:Visa |
Specific credit card |
Convert QIF file (using qif-to-ledger):
bun qif-to-ledger.ts -a "Assets:Checking" bank_export.qifConvert CSV file (using csv-to-ledger):
bun csv-to-ledger.ts -a "Assets:Checking" bank_export.csvConvert QIF file (using ledger-converter):
bun ledger-converter.ts -a "Assets:Checking" -i qif bank_export.qifOverride input format with -f flag:
bun qif-to-ledger.ts -a "Assets:Checking" -f csv bank_export.csv
bun csv-to-ledger.ts -a "Assets:Checking" -f qif bank_export.qifSave output to file:
bun qif-to-ledger.ts -a "Assets:Checking" bank_export.qif > transactions.ledgerCredit card account:
bun csv-to-ledger.ts -a "Liabilities:Credit Card:Visa" visa_export.csvAppend to existing ledger:
bun qif-to-ledger.ts -a "Assets:Savings" savings.qif >> master.ledgerCSV files must have a header row. The following columns are supported:
| Column | Required | Description |
|---|---|---|
date |
Yes | Transaction date |
payee |
Yes | Payee/merchant name |
category |
Yes | Ledger account (e.g., Expenses:Food) |
amount |
Yes* | Transaction amount (negative = expense) |
debit |
Yes* | Debit amount (alternative to amount) |
credit |
Yes* | Credit amount (alternative to amount) |
memo |
No | Optional memo/note |
*Either amount OR debit/credit columns are required.
YYYY-MM-DD→2024-01-15MM/DD/YYYY→01/15/2024MM-DD-YYYY→01-15-2024
date,payee,category,amount,memo
2024-01-15,Grocery Store,Expenses:Food,-50.00,Weekly groceries
2024-01-16,Acme Electric,Expenses:Utilities,-120.00,Monthly bill
2024-01-18,Employer,Income:Salary,2500.00,Paycheckdate,payee,category,debit,credit,memo
2024-01-15,Grocery Store,Expenses:Food,50.00,,Weekly groceries
2024-01-18,Employer,Income:Salary,,2500.00,PaycheckThe tool supports standard QIF bank transaction records:
| Code | Description | Example |
|---|---|---|
!Type:Bank |
Header (bank account type) | !Type:Bank |
D |
Date (MM/DD/YYYY or MM/DD'YY) | D01/15/2024 or D01/15'24 |
T |
Transaction amount | T-50.00 |
U |
Transaction amount (alternate) | U-50.00 |
P |
Payee | PGrocery Store |
L |
Category/Account | LExpenses:Food |
M |
Memo | MWeekly groceries |
C |
Cleared status | C* |
N |
Check number | N1234 |
A |
Address line | A123 Main St |
S |
Split category | SExpenses:Food |
E |
Split memo | EGroceries |
$ |
Split amount | $-25.00 |
^ |
End of transaction | ^ |
!Type:Bank
D01/15/2024
T-50.00
PGrocery Store
LExpenses:Food:Groceries
^
D01/16/2024
T-120.00
PAcme Electric
LExpenses:Utilities:Electric
MMonthly bill
^
Each transaction is converted to Ledger format:
YYYY/MM/DD Payee
;Memo (if present)
Category $Amount
Asset:Account
Simple transaction:
2024/01/15 Grocery Store
Expenses:Food:Groceries $50.00
Assets:Checking
Transaction with memo:
2024/01/16 Acme Electric
;Monthly bill
Expenses:Utilities:Electric $120.00
Assets:Checking
Split transaction:
2024/01/17 Costco
Expenses:Food:Groceries $75.00
Expenses:Household $125.00
Assets:Checking
Income (negative in Ledger expenses):
2024/01/18 Employer
Income:Salary $-2500.00
Assets:Checking
QIF amounts are from the asset account's perspective:
- Negative = money leaving the account (expenses)
- Positive = money entering the account (income)
The tool negates amounts for the category posting so Ledger balances correctly:
- Expenses become positive (money flows into expense accounts)
- Income becomes negative (money flows out of income accounts)
The asset account posting has no amount—Ledger infers it to balance the transaction.
QIF input formats:
MM/DD/YYYY→D01/15/2024MM/DD'YY→D01/15'24(years 00-50 = 2000s, 51-99 = 1900s)M/DD/YYYY→D 1/15/2024(space-padded month)
CSV input formats:
YYYY-MM-DD→2024-01-15MM/DD/YYYY→01/15/2024MM-DD-YYYY→01-15-2024
Output format is always YYYY/MM/DD.
QIF split transactions use multiple S/E/$ record groups:
D01/17/2024
T-200.00
PCostco
SExpenses:Food:Groceries
EFood items
$-75.00
SExpenses:Household
EHousehold supplies
$-125.00
^
Converts to:
2024/01/17 Costco
Expenses:Food:Groceries $75.00 ;Food items
Expenses:Household $125.00 ;Household supplies
Assets:Checking
Contributions are welcome! See CONTRIBUTING.md for guidelines, including how to pair with AI assistants like Claude for development.
MIT