Changing your budget
Writes sync into your live budget as soon as the command finishes, including for anyone you share the budget with.
Every write takes --dry-run, which shows what would change without changing anything. Every destructive action needs --yes. For anything scripted, try it on a copy of your budget first: in Actual, export the budget and import it as a new one.
Transactions#
fob-actual transactions add --account Checking --date 2026-09-20 \
--amount -42.50 --payee "Coffee Shop" --dry-run
[dry-run] Would add 1 transaction(s) to 'Checking':
DATE PAYEE AMOUNT NOTES
--------------------------------------
2026-09-20 Coffee Shop -42.50 —
Drop --dry-run to add it. Negative amounts are money out. --category takes a category ID (from categories list), --cleared marks it cleared, and a new payee name is created for you.
Import from a file#
transactions import runs the same logic as importing a bank file in the Actual app: it skips duplicates and applies your rules.
fob-actual transactions import --account Checking --file september.json --dry-run
[dry-run] Would import: 1 added, 0 updated (2 submitted to 'Checking').
The file is a JSON array (or { "transactions": [...] }). Amounts are in minor units:
[
{ "date": "2026-09-21", "amount": -1999, "payee_name": "Streaming Co", "imported_id": "bank-88213" },
{ "date": "2026-09-20", "amount": -4250, "payee_name": "Coffee Shop", "notes": "team coffee" }
]
Give each row a stable imported_id from your bank's export where you have one; it makes duplicate detection exact. transactions add --file adds rows as they are, without duplicate detection or rules.
Edit and delete#
fob-actual transactions edit <id> --category <category-id> --notes "reimbursable"
fob-actual transactions delete <id> --yes
edit changes only the options you pass. Transaction IDs are in transactions list --json.
The monthly budget#
fob-actual budgets set-amount 2026-10 <category-id> --amount 450.00
fob-actual budgets carryover 2026-10 <category-id> # --off to stop rolling over
fob-actual budgets hold 2026-10 --amount 500.00 # keep funds for next month
fob-actual budgets reset-hold 2026-10
Accounts#
fob-actual accounts create --name "Savings" --balance 1000.00
fob-actual accounts edit Savings --name "Emergency fund"
fob-actual accounts close "Old Card" --transfer-account Checking
fob-actual accounts reopen "Old Card"
fob-actual accounts delete "Old Card" --yes # deletes its transactions too
Closing keeps the account's history. Deleting removes it and every transaction in it.
Categories, payees and tags#
fob-actual category-groups create --name "Subscriptions"
fob-actual categories create --name "Streaming" --group <group-id>
fob-actual payees merge <keep-id> --from <other-id> --yes # fold duplicates into one payee (--from repeats)
fob-actual tags create --tag reimbursable
Run a command with --help to see its options. All of them are in the command reference.
Rules and schedules#
Rules and schedules have nested conditions and actions, so create and edit take JSON, in the same shape show --json prints:
fob-actual rules show <id> --json | jq 'del(.id)' > rule.json # copy an existing rule
# edit rule.json, then:
fob-actual rules create --file rule.json --dry-run
fob-actual rules edit <id> --file rule.json # or change the original
fob-actual schedules edit <id> --amount -1200.00 --reset-next-date
{
"stage": null,
"conditionsOp": "and",
"conditions": [{ "op": "is", "field": "payee", "value": "<payee-id>" }],
"actions": [{ "op": "set", "field": "category", "value": "<category-id>" }]
}
Copying a rule you made in the Actual app is the easiest way to get the format right. Remove its id before create: with the id kept, create overwrites that rule instead of making a new one. Schedules also take simple flags such as --name, --amount and --completed.