diff options
| author | Danilo M. <danix@danix.xyz> | 2026-07-01 10:40:32 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-07-01 10:40:32 +0200 |
| commit | 69647b1ca6f2e11429850b0782c65d04b86509cb (patch) | |
| tree | ab6b98c3595aaf04a9391f881357a73eb3d29c01 /firefly_cli | |
| parent | b078c5980facc0ebe4acd1f251f6ae3dad561292 (diff) | |
| download | firefly-cli-69647b1ca6f2e11429850b0782c65d04b86509cb.tar.gz firefly-cli-69647b1ca6f2e11429850b0782c65d04b86509cb.zip | |
feat: tx add --dry-run to validate before writing (v0.3.3)
An agent importing rows in a loop could fail mid-batch: a --to account that
didn't exist yet errored after earlier rows had already been written, leaving
a half-applied batch to clean up by hand.
--dry-run resolves --from/--to and infers the type but sends nothing, printing
{"dry_run": true, "would_send": {...}}. A missing account stays a hard error
(exit 1) so the agent can dry-run every row first, create the accounts the
errors name, then run the batch for real. No batch input mode: the agent
already owns the loop.
Verified live read-only: valid accounts emit would_send and write nothing
(search confirms []), missing account exits 1 with the candidate list.
PATCH: new optional flag, contract unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'firefly_cli')
| -rw-r--r-- | firefly_cli/__init__.py | 2 | ||||
| -rw-r--r-- | firefly_cli/commands/transaction.py | 6 |
2 files changed, 7 insertions, 1 deletions
diff --git a/firefly_cli/__init__.py b/firefly_cli/__init__.py index eb73e59..23ac8eb 100644 --- a/firefly_cli/__init__.py +++ b/firefly_cli/__init__.py @@ -2,4 +2,4 @@ # Copyright (C) 2026 Danilo M. <danix@danix.xyz> # Licensed under the GNU General Public License v2.0 only. -__version__ = "0.3.2" +__version__ = "0.3.3" diff --git a/firefly_cli/commands/transaction.py b/firefly_cli/commands/transaction.py index 1d6f219..72d2606 100644 --- a/firefly_cli/commands/transaction.py +++ b/firefly_cli/commands/transaction.py @@ -30,6 +30,8 @@ def _add_args(p): p.add_argument("--tags", default=None, help="comma-separated") p.add_argument("--type", default=None, help="withdrawal|deposit|transfer (overrides inference)") + p.add_argument("--dry-run", dest="dry_run", action="store_true", + help="resolve accounts and show what would be sent; write nothing") @registry.command("tx add", help="record a transaction; source/destination resolve to accounts, category/tags auto-create", args=_add_args) def cmd_add(args, ctx): @@ -50,6 +52,10 @@ def cmd_add(args, ctx): split["category_name"] = args.category if args.tags: split["tags"] = [t.strip() for t in args.tags.split(",") if t.strip()] + if args.dry_run: + # Accounts already resolved above (missing name = hard error). Write nothing. + output.emit({"dry_run": True, "would_send": split}, human=ctx.human) + return 0 resp = ctx.client.request("POST", "/api/v1/transactions", body={"transactions": [split]}) output.emit(output.unwrap(resp), human=ctx.human) |
