- Python 3.11+
- Poetry
- Your YNAB developer access token
- Your YNAB budget ID. You can get this from your browser URL while you have your budget open. For example, if the URL looks like
https://app.ynab.com/aaaaaaaa-1111-bbbb-2222-ddddddd
then the budget ID isaaaaaaaa-1111-bbbb-2222-ddddddd
.
$ git clone https://github.com/jeffsawatzky/ynab-cli.git
$ cd ynab-cli
$ poetry install --sync
You need to be in a Poetry shell first.
$ poetry shell
Warning
Developer access tokens are rate limited to 200 requests per hour. Some of the commands below will provide you an opportunity to enter a new developer access token when the current one has exceeded it's limit. It also seems like there is a limit to how many developer access tokens you can create from the developer settings UI.
Note
ynab-cli supports environment variables and dotenv files for specifying options. See the .env-sample
file for some examples.
Then you can run the individual commands. Note that for each command you will be asked you enter in your developer access token and the budget id.
$ ynab payees list-unused
Note
This will make 1 API call to get the list of payees, and then 1 API call for each payee to get the list of transactions. If you have more than 200 payees then you will hit your rate limit for the access token and will be asked to enter in a new one when this happens.
You can now go into YNAB and delete the ones you think you don't need.
$ ynab payees list-duplicates
Note
This will make 1 API call to get the list of payees, and then go through them all, comparing them to eachother with a fuzzy match to see which ones might be duplicates. You will probably get some false positives, but I prefer this over missing some.
You can now go into YNAB and combine the ones you think are duplicates.
$ ynab payees normalize-names
Warning
This will update the payees in place. You can also specify --dry-run
to see what changes would be made.
$ ynab --dry-run payees normalize-names
Note
This will make 1 API call to get the list of payees, and then 1 API call for each payee to update the name. If you have more than 200 payees then you will hit your rate limit for the access token and will be asked to enter in a new one when this happens.
To normalize a payee name, it converts the name to Title Case and applies some extra tweaks for possesive names and domain names.
$ ynab categories list-unused
Note
This will make 1 API call to get the list of categories, and then 1 API call for each category to get the list of transactions. If you have more than 200 categories then you will hit your rate limit for the access token and will be asked to enter in a new one when this happens.
You can now go into YNAB and delete the ones you think you don't need.
$ ynab categories list-all
You can use this to list the IDs for all your categories which you can then use in your transaction rules.
$ ynab transactions apply-rules rules.json
Warning
This will update the transactions in place. You can also specify --dry-run
to see what changes would be made.
$ ynab --dry-run transactions apply-rules rules.json
This assumes you have a rules.json
file with your rules to apply. It could look something like this:
{
"transaction_rules": [
{
"rules": [
"payee_name == 'My Payee' and amount == -213490"
],
"patch": {
"category_id": "insert the category id you want to assign it to here"
}
},
{
"rules": [
"payee_name == 'My Split Transaction Payee' and amount == -346500"
],
"patch": {
"category_id": null,
"subtransactions": [
{
"category_id": "insert the first category id you want to assign it to here",
"amount": -51980
},
{
"category_id": "insert the other category id you want to assign it to here",
"amount": -294520
}
]
}
}
]
}
Note
Amounts are in milliunits and can be either positive or negative depending on if they are inflow or outflow.
Note
To get the category IDs you can use the ynab categories list-all
command listed above.
The rules use the rule-engine library, so read that documentation to figure out how to write the rules. If ANY of the rules in the rules
list match a transaction then it will be updated with the patch
details.
The rules are supplied an instance of a TransactionDetail
, and the patch
needs to be an instance of a SaveTransactionWithIdOrImportId
. Read the YNAB API documention to see what properties are available to base your rules on and update.