#!/usr/bin/env node // Note: mostly generated by ChatGPT, I am not a Javascript developer const actual = require('@actual-app/api'); const yargs = require('yargs/yargs'); const { hideBin } = require('yargs/helpers'); (async () => { const argv = yargs(hideBin(process.argv)) .option('account', { alias: 'a', type: 'string', demandOption: true, describe: 'The UUID of the account', }) .option('payee', { alias: 'p', type: 'string', demandOption: false, describe: 'The name of the payee', }) .option('amount', { alias: 'm', type: 'number', demandOption: true, describe: 'The amount in dollars (positive or negative)', }) .option('date', { alias: 'd', type: 'string', demandOption: true, describe: 'The date in ISO format' }) .option('notes', { alias: 'n', type: 'string', demandOption: false, describe: 'Notes' }) .option('server', { alias: 's', type: 'string', describe: 'Actual server URL (fallback if ACTUAL_SERVER is not set)', }) .option('password', { alias: 'w', type: 'string', describe: 'Password (fallback if ACTUAL_PASSWORD is not set)', }) .option('sync-id', { alias: 'b', type: 'string', describe: 'UUID of the budget to connect to' }) .help() .argv; const serverURL = process.env.ACTUAL_SERVER || argv.server; const password = process.env.ACTUAL_PASSWORD || argv.password; const syncId = process.env.ACTUAL_SYNC_ID || argv.sync_id; if (!serverURL || !password || !syncId) { console.error('❌ Error: server URL, budget ID, and password must be provided (via CLI or environment)'); process.exit(1); } try { await actual.init({ dataDir: './cache', serverURL: serverURL, password: password, }); await actual.downloadBudget(syncId) const amount = Math.round(argv.amount * 100); // Convert to milli-units await actual.importTransactions(argv.account, [{ imported_payee: argv.payee, payee_name: argv.payee ?? '', amount, date: argv.date, // today's date notes: argv.notes ?? '' }]); console.log('✅ Transaction added successfully.'); await actual.shutdown(); } catch (err) { console.error('❌ Error:', err.message || err); process.exit(1); } })();