A friendly walkthrough from zero to clean payees. Follow along step by step — you'll be done in five minutes.
Before you start, make sure you have a few things in place. Nothing exotic — just the basics.
Head over to YNAB Developer Settings and click "New Personal Access Token". Give it a name you'll recognize (something like "payee splitter"), copy the token, and keep it somewhere safe. You'll need it every time you run the tool.
YNAB only shows your token once when you create it. If you lose it, you'll need to create a new one.
The YNAB API has a rate limit per access token to prevent misuse. Normal usage of this tool is well within limits, but keep it in mind if you're running it very frequently. See the YNAB API docs for details.
Let's get those payees cleaned up. We'll start with a dry run so you can see what the tool would do, without actually changing anything.
Always use --dry-run the first time. It lets you preview the changes
before committing them to your budget. Add --verbose for detailed
output showing exactly which transactions will be split and how — really helpful
to understand what the tool is doing. No surprises.
Try a dry run first
docker run --rm \
ghcr.io/zzave/ynab-split-payee-and-memo \
--token YOUR_TOKEN \
--dry-run --verboseHere's what happens when you run that command:
--dry-run, it logs what it would change — but doesn't touch anything.
Happy with what you see? Run it for real by dropping the --dry-run flag:
Run it for real
docker run --rm \
ghcr.io/zzave/ynab-split-payee-and-memo \
--token YOUR_TOKENThat's it. Your transactions are now clean. Payees are payees, memos are memos. The way it should have been from the start.
By default, the tool uses your last-used budget and processes all accounts. That's great for most people. But if you have multiple budgets or only want to clean up a specific account, you can be more precise.
Pass --budget-id to target a specific budget. You can find your budget ID
in the YNAB web app URL — it's the long string after /budget/.
docker run --rm \
ghcr.io/zzave/ynab-split-payee-and-memo \
--token YOUR_TOKEN \
--budget-id abc123-your-budget-id
Similarly, use --account-id to only process a specific account within your budget:
docker run --rm \
ghcr.io/zzave/ynab-split-payee-and-memo \
--token YOUR_TOKEN \
--budget-id BUDGET_ID \
--account-id ACCOUNT_ID
The tool looks back 30 days by default. Want to process older transactions?
Use --days-back:
docker run --rm \
ghcr.io/zzave/ynab-split-payee-and-memo \
--token YOUR_TOKEN \
--days-back 90Tired of typing long flags? Use environment variables instead. This is especially handy for automated setups (more on that in Section 5).
docker run --rm \
-e YNAB_TOKEN=YOUR_TOKEN \
-e YNAB_BUDGET_ID=BUDGET_ID \
-e YNAB_ACCOUNT_ID=ACCOUNT_ID \
ghcr.io/zzave/ynab-split-payee-and-memoBy default, the tool only processes unapproved transactions. These are the ones that just came in from your bank and haven't been reviewed yet.
This is intentional: if you've already approved a transaction, you've probably looked at it and are happy with how it looks. The tool respects that and leaves it alone.
The tool also skips any transaction where you've manually changed the payee name
(it checks whether payee_name still matches import_payee_name).
Transfers (payees starting with "Transfer : ") are always skipped too.
Want to go back and clean up older, already-approved transactions? Use the --all flag:
docker run --rm \
ghcr.io/zzave/ynab-split-payee-and-memo \
--token YOUR_TOKEN \
--all
This processes every eligible transaction in the lookback window, regardless of approval status.
Pair it with --dry-run and a larger --days-back
to preview the full blast radius before committing:
docker run --rm \
ghcr.io/zzave/ynab-split-payee-and-memo \
--token YOUR_TOKEN \
--all --days-back 365 --dry-runThe real magic is running this automatically. Set up a cron job and never think about messy payees again. Every morning, your transactions are clean before you even open YNAB.
Create a small shell script that runs the Docker container with your token. Use environment variables to keep things tidy:
~/scripts/run-ynab-splitter.sh
#!/bin/bash
DOCKER=/usr/local/bin/docker
YNAB_TOKEN=YOUR_TOKEN
$DOCKER run --rm \
-e YNAB_TOKEN=$YNAB_TOKEN \
ghcr.io/zzave/ynab-split-payee-and-memo \
--days-back 7Make it executable and add it to your crontab:
Make the script executable
chmod +x ~/scripts/run-ynab-splitter.shAdd to crontab (crontab -e)
# Run every day at 8 AM
0 8 * * * ~/scripts/run-ynab-splitter.sh >> ~/ynab-splitter.log 2>&1
Use --days-back 7 for cron jobs instead of the default 30.
Since you're running it regularly, a week's lookback is plenty — and it's faster.
Skip the local cron setup and run this as a managed job instead. See the Scaleway Serverless Jobs guide for a hands-off setup that runs whether your laptop is on or not.
For detailed platform-specific instructions (including macOS-specific tips and how to disable the job later), see the full cron setup guide in the README.
Every flag and option at a glance. All flags can also be set via the corresponding environment variable where noted.
--budget-id.--only-unapproved.