A terminal-first CLI for Splitwise with readable tables, structured JSON/YAML output, and built-in skill files for coding assistants.
- npm package: splitwise-cli on npm
- Code repository: michaelschnyder/splitwise-cli
- Splitwise library: keriwarr/splitwise
- Splitwise API docs: dev.splitwise.com
npm install -g splitwise-cli
# or
npx splitwise-cli --help# save login credentials
splitwise-cli login token YOUR_TOKEN
# splitwise-cli login oauth YOUR_KEY YOUR_SECRET
# verify current login
splitwise-cli login whoami
# common commands
splitwise-cli friends list
splitwise-cli groups list
splitwise-cli expenses list --from -30d --all
splitwise-cli cache add all
splitwise-cli cache statusConfiguration is stored under ~/.splitwise-cli/.
| Area | Summary | Commands | Jump |
|---|---|---|---|
| Login | Manage multiple login credentials and inspect current user | token, oauth, list, status, select, default, remove, validate, whoami |
Login |
| Friends | List friends and balances | list |
Friends |
| Groups | List groups and fetch group details | list, get |
Groups |
| Expenses | Query, create, delete, and import expenses | list, get, add, delete, import |
Expenses |
| Profiles | Manage profile restrictions, active profile, and lock state | list, show, create, edit, select, remove, validate, lock |
Profiles |
| Cache | Export immutable snapshots and inspect offline cache state | add, list, refresh, status, delete |
Cache & Offline |
| Skills | List/install/create assistant skill files | list, path, install, create |
Skills |
For global log flags, output streams, and debug behavior, see Console Logging.
Global profile selection:
-p, --profile <name>selects a profile for the current command.- If the active profile is locked, switching profiles is blocked until the profile file is edited manually.
Global credential selection:
-c, --credential <name>selects a credential for the current command.- Resolution order: explicit
--credential-> profile credential -> active login credential -> default login credential.
Global offline selection:
--offlineforces cache-only reads and prevents network access.- Resolution order: explicit
--offline-> profileofflineEnabled-> online by default.
Use -o / --output when available.
| Format | Use case |
|---|---|
table |
default terminal view |
json |
scripts, pipes, automation |
yaml |
readable structured output |
When --output is omitted, commands run in TUI mode by default (readable table layout with an intro line, title-cased headers, and a single summary footer line with items/time/source).
splitwise-cli friends list -o yaml
splitwise-cli expenses list --from -7d -o jsonCreate login credentials at splitwise.com/apps/register.
splitwise-cli login token YOUR_TOKEN
splitwise-cli login oauth YOUR_KEY YOUR_SECRET
splitwise-cli login list
splitwise-cli login status
splitwise-cli login select work
splitwise-cli login default personal
splitwise-cli login validate work
splitwise-cli login whoami
splitwise-cli login whoami -o json{
"id": 12345678,
"name": "Alex Example",
"email": "alex@example.com"
}splitwise-cli friends list
splitwise-cli friends list -o jsonShowing friends and balances
Id Name Balance
──────── ───────────── ─────────────
11111111 Alice Example -12.40 USD
22222222 Bob Example settled up
• 2 item(s) | 43 ms | source: Splitwise API
[
{
"id": 11111111,
"name": "Alice Example",
"balance": "-12.40 USD"
},
{
"id": 22222222,
"name": "Bob Example",
"balance": "settled up"
}
]splitwise-cli groups list
splitwise-cli groups get <groupId>splitwise-cli groups list
splitwise-cli groups get <groupId>splitwise-cli expenses list [options]
splitwise-cli expenses get <expenseId>
splitwise-cli expenses add [options]
splitwise-cli expenses delete <expenseId>
splitwise-cli expenses import <file> [options]splitwise-cli expenses list --from -30d --all
splitwise-cli expenses get <expenseId>
splitwise-cli expenses add -d "Groceries" -a 48.90 -C USD -g Flatmates
splitwise-cli expenses delete <expenseId>
splitwise-cli expenses import monthly.yaml| Flag | Short | Description |
|---|---|---|
| `--group <id | name>` | -g |
| `--friend <id | name>` | -u |
--from <date> |
-f |
include expenses on or after date |
--to <date> |
include expenses on or before date | |
--max <n> |
-m |
max rows unless --all is used |
--all |
walk all API pages | |
--mine |
shorthand for --payer @me |
|
| `--involved <@me | id | name>` |
| `--payer <@me | id | name>` |
--query <string> |
shorthand key:value query | |
--output <format> |
-o |
table, json, or yaml |
Date values support ISO (2026-01-01) and relative values (-10d, -2w, -1month, -1y).
| Flag | Short | Description |
|---|---|---|
--description <text> |
-d |
Expense description (required) |
--cost <amount> |
-a |
Total cost (required) |
--date <date> |
Expense date (YYYY-MM-DD or relative) |
|
--currency <code> |
-C |
Currency code |
| `--group <id | name>` | -g |
| `--friend <id | name>` | -u |
--notes <text> |
Additional notes | |
| `--category <id | name>` | |
| `--payer <@me | id | name>` |
--split-equally |
Split equally (default) | |
--user-share <id:paid:owed> |
Custom share — repeat per participant |
| Flag | Description |
|---|---|
--yes |
Skip the confirmation prompt |
| Flag | Description |
|---|---|
--dry-run |
Preview changes without writing |
--matcher <type> |
Duplicate detection: exact (default) or intelligent |
--on-duplicate <action> |
Action on match: skip (default) or update |
--no-cache |
Disable cache update after import |
Import files are YAML or JSON lists. Two record shapes are supported:
Simplified — group/friend resolved by name:
- description: Dinner
cost: "30.00"
date: "2024-01-15"
currency: USD
group: FlatmatesFull — explicit per-user splits (requires userId):
- description: Dinner
cost: "30.00"
date: "2024-01-15"
currency: USD
splits:
- userId: 123
paidShare: "30"
owedShare: "15"
- userId: 456
owedShare: "15"Both shapes can be mixed in the same file. The intelligent matcher tolerates date differences of ±5 days, a single adjacent-key digit typo per date component or in the cost digits, with exact currency match required.
splitwise-cli expenses list --from -30d --all -o json
splitwise-cli expenses list --group Flatmates --mine --from -1month
splitwise-cli expenses list --involved Alice --from -14d
splitwise-cli expenses get 99999 -o yaml
splitwise-cli expenses add -d "Coffee" -a 4.50 --friend Alice
splitwise-cli expenses add -d "Rent" -a 1200 -g Flatmates --user-share 123:1200:600 --user-share 456:0:600
splitwise-cli expenses delete 99999 --yes
splitwise-cli expenses import monthly.yaml --dry-run
splitwise-cli expenses import monthly.yaml --matcher intelligent --on-duplicate updateShowing expenses from 2026-06-01 to 2026-06-13
ID Date Group/Friend Paid By Description Costs Category Share
──────── ────────── ──────────── ─────────── ─────────────────────── ───────── ──────── ───────────
99999 6/10/2026 Flatmates Alex Example Groceries 48.90 USD Food 24.45 USD
99998 6/09/2026 Flatmates Alex Example Rent transfer -> Jo 650.00 USD Payment 325.00 USD
• 2 item(s) | 71 ms | source: Splitwise API
[
{
"id": 99999,
"date": "2026-06-10T10:25:00Z",
"description": "Groceries",
"cost": "48.90",
"currency": "USD",
"category": "Food",
"isPayment": false,
"paidBy": "Alex Example",
"group": "Flatmates",
"splits": [
{ "userId": 12345678, "name": "Alex Example", "paid": "48.90", "owes": "24.45" },
{ "userId": 87654321, "name": "Jo Example", "paid": "0.00", "owes": "24.45" }
],
"createdAt": "2026-06-10T10:25:10Z",
"createdByName": "Alex Example",
"updatedByName": "Alex Example",
"deletedByName": ""
}
]Profiles control what the CLI is allowed to do and can optionally bind a credential name.
Restriction semantics:
limitExpensesToGroupIds/limitExpensesToFriendIdsomitted ornull: unrestricted[]: nobody allowed[id1, id2, ...]: only listed ids are allowed
Lock behavior:
profiles lockis one-way from the CLI (no unlock command)- lock confirmation is interactive in default TUI mode
- in explicit output mode, pass
--yesto confirm lock - when locked, login updates and profile/credential switching are blocked
splitwise-cli profiles list
splitwise-cli profiles show <name>
splitwise-cli profiles create <name>
splitwise-cli profiles edit <name>
splitwise-cli profiles select <name>
splitwise-cli profiles validate [name]
splitwise-cli profiles lock [name]splitwise-cli profiles list
splitwise-cli profiles show default
splitwise-cli profiles create work
splitwise-cli profiles select worksplitwise-cli profiles edit work --limit-expenses-to-groups Flatmates,12345 --limit-expenses-to-friends Alice,67890| Flag | Description |
|---|---|
| `--create-expenses <yes | no>` |
| `--update-expenses <yes | no>` |
| `--delete-expenses <yes | no>` |
--limit-expenses-to-groups <items> |
comma-separated ids/names, none for empty list, null for unrestricted |
--limit-expenses-to-friends <items> |
comma-separated ids/names, none for empty list, null for unrestricted |
--clear-expense-group-limit |
set expense group limit to unrestricted (null) |
--clear-expense-friend-limit |
set expense friend limit to unrestricted (null) |
--profile-credential <name> |
bind a profile to a credential |
--clear-profile-credential |
remove profile credential binding |
| `--offline-enabled <yes | no>` |
--preferred-cache-target <target> |
preferred cache target: local, user, global |
--clear-preferred-cache-target |
clear profile cache target preference |
--api-endpoint <url> |
override the Splitwise API base URL |
--clear-api-endpoint |
clear the API endpoint override |
When a profile is locked and an operation is blocked, the CLI prints the exact profile file path.
To recover, edit that file and set "locked": false, or remove the file manually.
Use the cache command group to export immutable local snapshots and query data offline.
local: workspace-local cache under the current working directoryuser: cache under~/.splitwise-cli/cache(default)global: appdata-based cache area
splitwise-cli cache add expenses --from -30d
splitwise-cli cache add lookup
splitwise-cli cache add lookup --target user
splitwise-cli cache refresh expenses
splitwise-cli cache delete 01hzzzzzzzzzzzzzzzzzzzzzzz
splitwise-cli cache delete --all
splitwise-cli cache list
splitwise-cli cache statuscache add and cache refresh create immutable cache directories. Writes are staged into temporary cache folders and finalized by rename, so incomplete exports are not exposed as valid cache snapshots.
# add while online
splitwise-cli cache add all
# read from cache only
splitwise-cli --offline expenses list --from -30d --all
splitwise-cli --offline friends list
splitwise-cli --offline groups listOffline behavior:
- no HTTP requests are made when
--offlineis effective - partial expense coverage returns available rows plus warnings for uncovered date ranges
- missing expense cache produces an actionable error with an example
cache addcommand
cache listincludes expense coverage windows and a derived coverage statuscache refresh expensesreuses the latest compatible scope for the same account/profile- refresh prefers both
created_atandupdated_atcursors when available and falls back to a bounded overlap window when they are not
lookupis stored as separatecategoriesandcurrenciesentities- expense exports also persist comments and a lightweight groups snapshot for offline name resolution
Built-in skills are copied into the package and can be installed for supported assistants.
splitwise-clisplitwise-loginsplitwise-expensessplitwise-groupssplitwise-friendssplitwise-profilessplitwise-cache
splitwise-cli skills list
splitwise-cli skills path [platform]
splitwise-cli skills install [platform]
splitwise-cli skills createSupported platform values: claude, cursor, codex, opencode, windsurf, gemini, pi, all.
- name: splitwise-cli
type: skill
description: Top-level splitwise-cli command reference and workflow.
- name: splitwise-expenses
type: skill
description: Expense listing filters, date parsing, and output behavior.Logging and progress output are powered by consola.
Global logging controls:
| Flag | Description |
|---|---|
--log <level> |
explicit level: error, warn, info, debug, trace |
-v |
increase verbosity (-v, -vv, -vvv, -vvvv) |
Environment override:
SW_DEBUG=1|yes|trueforces trace-level logging in all modes.
Stream contract:
- Structured payloads (
-o json,-o yaml) are printed tostdout. - Logs, warnings, errors, and progress/status text are printed to
stderr.
HTTP client logging:
- Request/response lifecycle logs include method, URL, status code, duration, and attempt.
- Error logs include method, URL, duration, and error message.
- Headers and response/request content are intentionally not logged.
Cache/offline diagnostics:
- add and refresh operations emit cache diagnostics under the
cachetag - debug/trace logging includes refresh strategy and staged batch lifecycle details
- offline expense warnings are emitted to
stderrso structured output remains machine-readable
Color behavior:
- Colored logs are shown only in table/TUI mode.
- JSON and YAML modes keep logs uncolored to stay script-friendly.
Icons and progress indicators:
- In TUI/table mode, status lines are icon-first (for example info/success) without the
INFOtext label. - TUI progress uses an animated spinner on supported terminals.
- Progress completion uses a success icon when done and an error icon when failed.
- On minimal terminals, icon/spinner output falls back to ASCII-safe symbols.
Examples:
splitwise-cli friends list --log info
splitwise-cli expenses list -vv --from -30d
SW_DEBUG=true splitwise-cli groups get 12345 -o jsonnpm install
npm run build
npm run dev -- expenses list --from -7dPackaging workflow:
npm run buildcompiles TypeScript only (fast local validation, no skill copy).npm run build:packagecompiles, copies skills todist/skills, and syncs skill metadata version topackage.json.npm packandnpm publishrunprepackautomatically, so published tarballs always contain versioned skills.npm run releaseis a convenience wrapper fornpm publish.