CLI for working with Actual Budget.
Install globally with npm:
npm install -g abctlOr run it without installing:
npx abctl --helpUsage: abctl [options] [command]
Actual budget helper commands.
Options:
-h, --help display help for command
Commands:
budgets List budgets and their sync ids.
accounts List accounts and their current balances.
uncategorized List uncategorized transactions across all accounts.
make-transfer|transfer [options]
Find uncategorized transfer pairs and link them.
find <payee> <txn-date> Find transactions by exact payee name and ISO date (YYYY-MM-DD).
split [options] <entries...> Split a transaction into sub-transactions.
report [options] <name> Render a custom report by name.
qif-import [options] <account> <qif-path>
Import a QIF file into an Actual account.
st-george-import [options] <account> <csv-path>
Import a St.George CSV into an Actual account.
help [command] display help for command
Environment:
ACTUAL_PASSWORD Required.
ACTUAL_SYNC_ID Optional. Budget name, groupId, or cloudFileId. Defaults to the first available budget.
ACTUAL_SERVER_URL Optional. Defaults to http://localhost:5007
ACTUAL_DATA_DIR Optional. Defaults to /tmp/actualFor split, express <entries...> as repeated triplets:
<notes> <category> <amount> [<notes> <category> <amount> ...]Example:
abctl split --transaction-id abc123 "Groceries run" "Food" -45.60 "Petrol" "Transport" -30If the split amounts do not add up, you can append the exact remainder as one extra split using the parent transaction category:
abctl split --add-remainder-split --transaction-id abc123 "Agent fees" "Expenses" -90Preview uncategorized transfer candidates without writing:
abctl make-transfer --dry-runLink all unambiguous uncategorized transfer pairs:
abctl make-transferThe command only links pairs when there is exactly one uncategorized inflow and one uncategorized outflow with the same date and absolute amount in two different accounts. Ambiguous groups are reported and skipped.
Split by transaction id:
abctl split --transaction-id abc123 "Groceries run" "Food" -45.60 "Petrol" "Transport" -30Split by exact payee and ISO date:
abctl split --payee "Example Store" --txn-date 2026-04-05 "Groceries run" "Food" -45.60Each split entry is a repeated <notes> <category> <amount> triplet. Quote notes or category names when they contain spaces.
Use --add-remainder-split to append one extra split for any remaining difference. The extra split uses the parent transaction category, so it only works when the original transaction is already categorized.
Preview the mapped ImportTransactionEntity objects:
abctl st-george-import <account> path/to/st-george.csv --jsonPreview Actual's reconciliation result without writing:
abctl st-george-import <account> path/to/st-george.csv --dry-runImport the CSV into an account:
abctl st-george-import <account> path/to/st-george.csv<account> may be either the Actual account id or account name. Matching prefers exact id, then exact name, then unique case-insensitive name, then a unique case-insensitive substring match. If the match is ambiguous, the command fails and asks you to use the id.
Preview the parsed transactions returned by Actual:
abctl qif-import <account> path/to/file.qif --jsonPreview reconciliation without writing:
abctl qif-import <account> path/to/file.qif --dry-runImport the QIF into an account:
abctl qif-import <account> path/to/file.qifOptional flags:
--import-noteskeeps the QIF memo field as Actual notes.--swap-payee-and-memouses the QIF memo field as the payee before optional note import.
<account> may be either the Actual account id or account name. Matching prefers exact id, then exact name, then unique case-insensitive name, then a unique case-insensitive substring match. If the match is ambiguous, the command fails and asks you to use the id.