Getting Started with BananaSplit CLI: Automate expense tracking and splitting with AI Agents
Install the CLI, add the skill, and ask your agent to split last night's dinner. Then go further: let it turn the receipts in your inbox into BananaSplit expenses every week.

Most expenses don't need a decision. They need someone to type them in. A dinner with the team, the monthly hosting bill, the Amazon order you split with your flatmate: you already know who paid and how to split it. The typing is the annoying part.
The BananaSplit CLI hands that part to your AI agent. You say what happened in plain words, and the agent records it in BananaSplit. Push it one step further and the agent doesn't even need you to ask: it reads the receipts in your inbox and adds them on a schedule.
This guide goes from zero to both.
1. Install the BananaSplit CLI
On macOS or Linux:
curl -fsSL https://github.com/teotti/banana-cli/releases/latest/download/install.sh | shOn Windows (PowerShell):
irm https://github.com/teotti/banana-cli/releases/latest/download/install.ps1 | iexPrefer a package manager? npm install -g @bananasplitapp/cli or bun install -g @bananasplitapp/cli work too.
Then sign in. This opens your browser, and the CLI stores the login securely on your machine:
banana loginCheck that everything is in place:
banana doctor
banana balanceIf banana balance prints your balance, the CLI is ready.
2. Launch your agent
Any agent that can run terminal commands works: Claude Code, Codex, Cursor, Gemini CLI, OpenCode. In this guide we use Claude Code.
claude3. Ask your agent to install the banana skill
The skill teaches your agent how the CLI works: which commands exist, how splits add up, how to name groups and friends, and when to ask before changing something. You don't need to look any of that up. Just ask:
Install the BananaSplit skill for Claude Code with banana skill install --agent claude.
Once it's done, start a new session (quit and run claude again) so the agent picks up the skill.
Prefer to do it yourself? Run this in your terminal:
banana skill installWithout --agent, it finds every agent you have installed and writes the skill for each one. You can also install it with npx skills add teotti/banana-cli --skill banana --global.
4. Add your first expense by asking
Now just say what happened:
Add last night's dinner at Wendy's with Leo, $40
That's it. The agent records it, splits it, and tells you what it did. Leo sees it in BananaSplit right away.
Some more things to ask:
- "Who owes me money, and how much?"
- "Show the last 10 expenses in Lisbon trip."
- "Leo paid me back $20, record it."
- "Add rent, $1,800, every 1st of the month, split with Leo."
What happens behind the scenes
The agent looks up Leo in your friends, works out the split, and runs one command:
banana expenses add --title "Dinner at Wendy's" --amount 40 --currency USD \
--date 2026-10-27 --split me=20 --split Leo=20For a group dinner, it uses --group instead. With --group and no split, the expense is split equally across everyone in the group:
banana expenses add --title "Team dinner at Rosetta" --amount 239 --currency USD \
--date 2026-10-27 --group "Team"You never have to write these commands, but you can. They're the same commands you'd type yourself, so you can always read what the agent did, or skip the agent and run them directly. banana expenses add --help lists every option.
5. Let your inbox feed BananaSplit
Asking is fast. Not having to ask is faster.
A lot of expenses already arrive as email: Amazon orders, hosting invoices, utility bills, toll statements. Give your agent access to your inbox and it can turn those emails into expenses for you.
We use HEY, which has its own CLI, so the agent can search mail and read receipts from the terminal. Gmail and Outlook work the same way through their MCP servers or APIs.
In a session that has both the HEY and BananaSplit skills, try:
Look for Amazon order emails from the last week and add each one to BananaSplit as a personal expense. Use --notify-me.
The --notify-me flag is the important bit. Normally you don't get a notification for an expense you added yourself. With --notify-me, BananaSplit sends you the "expense created" push notification anyway, so every automated expense taps you on the shoulder and you can glance at it on your phone:
banana expenses add --title "Amazon: USB-C hub" --amount 34.99 --currency USD \
--date 2026-10-24 --split me=34.99 --notify-me6. Turn it into a job that runs every week
Doing this by hand once a week is still a chore. So the next step is to ask the agent to write it as a small script and schedule it. Something like:
Write a script that searches HEY for receipts from Amazon and our hosting provider from the last 10 days and adds each one to BananaSplit with --notify-me. Never add the same receipt twice. Log what it does. Then schedule it to run every Monday at 10:00.
This is how my own importer was built. It runs every Monday, and its log reads like this:
2026-10-19 10:00:01 signed in to HEY as [email protected]
2026-10-19 10:00:07 signed in to BananaSplit as Diogo ([email protected])
2026-10-19 10:00:08 [amazon] 1 email(s) in HEY from the last 10 days, 0 new
2026-10-19 10:00:08 [amazon] Your Amazon.com order of "USB-C hub": already handled in an earlier run
2026-10-19 10:00:08 [hosting] no emails in HEY from the last 10 days
2026-10-19 10:00:08 done: 0 added, 1 already in BananaSplit
2026-10-26 10:00:01 signed in to HEY as [email protected]
2026-10-26 10:00:07 signed in to BananaSplit as Diogo ([email protected])
2026-10-26 10:00:07 [amazon] no emails in HEY from the last 10 days
2026-10-26 10:00:08 [hosting] 1 email(s) in HEY from the last 10 days, 1 new
2026-10-26 10:00:12 [hosting] ADDED Hosting 29.00 USD 2026-10-25 [Side project] (receipt #2291-4410)
2026-10-26 10:00:12 done: 1 added, 0 already in BananaSplitThe script
Here is a trimmed version you can copy and adapt. It does three things: search the inbox, read the amount out of each receipt, and add it to BananaSplit. Both CLIs print JSON with --json, which makes them easy to script.
#!/usr/bin/env python3
"""Weekly job: receipts in HEY -> expenses in BananaSplit."""
import json, os, re, subprocess
from datetime import datetime
STATE = os.path.expanduser("~/.local/state/receipts-to-banana.json")
FOOTER = "\n\n🤖 automated" # marks expenses this job created
def cli(*args):
out = subprocess.run([*args, "--json"], capture_output=True, text=True).stdout
return json.loads(out)
def log(msg):
print(f"{datetime.now():%Y-%m-%d %H:%M:%S} {msg}", flush=True)
# One entry per kind of receipt: what to search for and where it goes.
SOURCES = [
dict(name="amazon", query="Your Amazon.com order",
amount_re=r"Order Total:\s*\$([\d,]+\.\d{2})", group=None),
dict(name="hosting", query="Your receipt from",
amount_re=r"Amount paid\s*\$([\d,]+\.\d{2})", group="Side project"),
]
def main():
handled = set(json.load(open(STATE))) if os.path.exists(STATE) else set()
for src in SOURCES:
emails = cli("hey", "search", src["query"], "--date", "last_7_days").get("data", [])
log(f"[{src['name']}] {len(emails)} email(s) in HEY")
for email in emails:
topic = str(email["topic_id"])
if topic in handled:
continue
thread = cli("hey", "thread", "read", topic).get("data", [])
body = "\n".join(entry.get("body") or "" for entry in thread)
match = re.search(src["amount_re"], body)
if not match:
log(f"[{src['name']}] could not read an amount from {email['subject']}")
continue
amount = match.group(1).replace(",", "")
args = ["banana", "expenses", "add",
"--title", email["subject"][:80],
"--amount", amount, "--currency", "USD",
"--date", email["updated_at"][:10],
"--description", f"From: {email['subject']}{FOOTER}",
"--notify-me"]
args += ["--group", src["group"]] if src["group"] else ["--split", f"me={amount}"]
cli(*args)
handled.add(topic)
log(f"[{src['name']}] ADDED {email['subject']} {amount} USD")
os.makedirs(os.path.dirname(STATE), exist_ok=True)
json.dump(sorted(handled), open(STATE, "w"))
if __name__ == "__main__":
main()A few things worth keeping, whatever your sources are:
- Never add twice. Remember which emails you already handled. My real importer also checks BananaSplit for a matching expense before adding, in case a receipt arrived twice.
- Mark what's automated. Every description ends with
🤖 automated, so you can tell these expenses apart from the ones you typed. - Use --notify-me. You get a push for each new expense, which is your chance to catch a wrong amount.
- Try it before it's real. Ask the agent for a
--dry-runflag that prints what would be added and changes nothing. - Respect the rate limit. The BananaSplit API allows 20 requests per minute, so pause a few seconds between calls when a run adds many expenses.
Schedule it
On macOS, a launchd job runs the script every Monday at 10:00, and catches up if your Mac was asleep. Save this as ~/Library/LaunchAgents/net.bananasplit.receipts.plist, with your own paths:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key><string>net.bananasplit.receipts</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/python3</string>
<string>/Users/you/jobs/receipts-to-banana.py</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key><string>/Users/you/.local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
</dict>
<key>StartCalendarInterval</key>
<dict>
<key>Weekday</key><integer>1</integer>
<key>Hour</key><integer>10</integer>
<key>Minute</key><integer>0</integer>
</dict>
<key>StandardOutPath</key><string>/Users/you/Library/Logs/receipts-to-banana.log</string>
<key>StandardErrorPath</key><string>/Users/you/Library/Logs/receipts-to-banana.log</string>
</dict>
</plist>Load it once:
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/net.bananasplit.receipts.plistOn Linux, one line in crontab -e does the same:
0 10 * * 1 /usr/bin/python3 $HOME/jobs/receipts-to-banana.py >> $HOME/receipts-to-banana.log 2>&1To add a new kind of receipt later, you don't edit the script yourself. Open your agent in the job's folder and say "also import my electricity bill". It adds one entry to SOURCES, runs a dry run, and shows you the result.
Give the log some color
A plain log does the job, but you'll read it more often if it's easy to scan. Ask your agent:
Write a small awk script that colors the log: timestamps gray, sign-ins blue, errors red, "done" green, added expenses bold, skipped receipts gray, HEY in purple and BananaSplit in yellow.
It writes something like this colorize.awk:
# Colors importer log lines: awk -f colorize.awk
BEGIN {
e = "\033["; reset = e "0m"; bold = e "1m"; gray = e "90m"
red = e "31m"; green = e "32m"; yellow = e "33m"; blue = e "34m"; purple = e "35m"
}
{
if ($0 !~ /^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] /) { print; fflush(); next }
ts = substr($0, 1, 19); rest = substr($0, 21)
if (rest ~ /ERROR|FATAL|not logged in|^done with/) c = red
else if (rest ~ /^signed in/) c = blue
else if (rest ~ /^done/) c = green
else if (rest ~ /ADDED/) c = bold
else if (rest ~ /already|nothing to add|dry run|no emails/) c = gray
else c = ""
gsub(/HEY/, purple "HEY" reset c, rest)
gsub(/BananaSplit/, yellow "BananaSplit" reset c, rest)
printf "%s%s%s %s%s%s\n", gray, ts, reset, c, rest, reset
fflush()
}The log file itself stays plain text. The colors are added only when you read it:
tail -f ~/Library/Logs/receipts-to-banana.log | awk -f colorize.awkNow a failed run jumps out in red, and a new expense stands out in bold among the gray "nothing new" lines.
What you get back
Count the expenses you typed last month. For most people it's somewhere between 15 and 40, at about a minute each once you include opening the app, finding the group and checking the split. That's half an hour to an hour a month, every month, for work that needs no thinking.
With the CLI and a skill, the one-off expenses become a sentence to your agent. With a weekly job, the recurring ones stop needing you at all: they show up in BananaSplit, already split, with a notification on your phone. You still see everything. You just don't type it.
Install the CLI, ask your agent to install the skill, and ask it to add the last thing you paid for. Everything else is on the BananaSplit for AI agents page and in the docs.