Skip to content

Commit d15be9e

Browse files
Amram Englanderclaude
andcommitted
Add transaction management write commands (v0.4.0)
New commands: classify, rename, comment, exclude, include, merge, unclassified, set-budget-type, adjust. First write operations in the CLI — all verified against the live RiseUp API. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a9d9629 commit d15be9e

8 files changed

Lines changed: 477 additions & 2 deletions

File tree

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ RiseUp is an Israeli personal finance app with no public API. This CLI was built
3838
- **Spending breakdown** — by category, merchant, or payment source
3939
- **Income tracking** — salary, benefits, and all income sources
4040
- **Transaction search** — filter by merchant, category, amount, type
41+
- **Transaction management** — classify, rename, comment, exclude, merge
4142
- **Bank balances & investments** — balances, securities portfolio, savings, loans
4243
- **Credit card debt** — debt per card at a glance
4344
- **Trends** — month-over-month income vs. expenses, fixed vs. variable breakdown
@@ -116,6 +117,21 @@ riseup transactions --expenses --sort amount # Expenses sorted by amount
116117
riseup transactions --min 500 --max 2000 # Amount range
117118
```
118119

120+
### Transaction Management
121+
122+
```bash
123+
riseup unclassified # List unclassified transactions
124+
riseup classify <id> "מזון" # Classify a transaction
125+
riseup classify <id> "מזון" --apply-to all # Classify + teach future matching
126+
riseup rename <id> "Grocery Store" # Rename display name
127+
riseup comment <id> "monthly recurring" # Add a note
128+
riseup exclude <id> # Exclude from budget
129+
riseup include <id> # Re-include in budget
130+
riseup merge <id> # Approve CC billing merge
131+
riseup set-budget-type <id> fixed # Set as fixed expense
132+
riseup adjust <envId> 500 --sequence-id <seqId> # Adjust prediction
133+
```
134+
119135
### Balances
120136

121137
```bash

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "riseup-cli",
3-
"version": "0.3.0",
3+
"version": "0.4.0",
44
"description": "Unofficial CLI for RiseUp personal finance, query your spending, income and balances from the terminal",
55
"type": "module",
66
"bin": {

src/cli.ts

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,24 @@ import { insightsAction } from "./commands/insights.js";
1010
import { banksAction, subscriptionAction } from "./commands/account.js";
1111
import { progressAction } from "./commands/progress.js";
1212
import { skillInstallAction, skillStatusAction, skillUninstallAction, skillShowAction } from "./commands/skill.js";
13+
import {
14+
classifyAction,
15+
renameAction,
16+
commentAction,
17+
excludeAction,
18+
includeAction,
19+
mergeAction,
20+
unclassifiedAction,
21+
setBudgetTypeAction,
22+
adjustAction,
23+
} from "./commands/manage.js";
1324

1425
const program = new Command();
1526

1627
program
1728
.name("riseup")
1829
.description("Unofficial RiseUp Finance CLI")
19-
.version("0.1.0");
30+
.version("0.4.0");
2031

2132
// Global options
2233
program.option("--json", "Output as JSON");
@@ -96,6 +107,58 @@ program
96107
.description("Show financial health & savings progress")
97108
.action(progressAction);
98109

110+
// Transaction management (write) commands
111+
program
112+
.command("classify <transactionId> <category>")
113+
.description("Classify a transaction into a category")
114+
.option("--apply-to <scope>", "Apply to: single or all (future matching)", "all")
115+
.action(classifyAction);
116+
117+
program
118+
.command("rename <transactionId> <name>")
119+
.description("Rename a transaction display name")
120+
.option("--apply-to <scope>", "Apply to: single or all", "single")
121+
.action(renameAction);
122+
123+
program
124+
.command("comment <transactionId> <text>")
125+
.description("Add a comment/note to a transaction")
126+
.action(commentAction);
127+
128+
program
129+
.command("exclude <transactionId>")
130+
.description("Exclude a transaction from budget")
131+
.action(excludeAction);
132+
133+
program
134+
.command("include <transactionId>")
135+
.description("Re-include an excluded transaction in budget")
136+
.action(includeAction);
137+
138+
program
139+
.command("merge <transactionId>")
140+
.description("Approve a credit card billing merge")
141+
.option("--input <type>", "Merge type: approved, loan, clearing, addCreds, bug", "approved")
142+
.action(mergeAction);
143+
144+
program
145+
.command("unclassified [month]")
146+
.description("List unclassified transactions")
147+
.action(unclassifiedAction);
148+
149+
program
150+
.command("set-budget-type <transactionId> <type>")
151+
.description("Set transaction as fixed or variable expense")
152+
.action(setBudgetTypeAction);
153+
154+
program
155+
.command("adjust <envelopeId> <amount>")
156+
.description("Adjust a predicted transaction amount")
157+
.option("--sequence-id <id>", "Sequence ID (required)")
158+
.option("--budget-date <date>", "Budget month (YYYY-MM, default: current)")
159+
.option("--no-permanent", "Apply only for this month")
160+
.action(adjustAction);
161+
99162
const accountCmd = program
100163
.command("account")
101164
.description("Account settings");

src/client/RiseUpClient.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,44 @@ export class RiseUpClient {
9393
customerProgress: () => this.getCustomerProgress(),
9494
};
9595

96+
/** Transaction write operations. */
97+
transactions = {
98+
classify: (transactionId: string, expense: string, applyTo: "single" | "all" = "all") =>
99+
this.http.post("/api/enrichment-update/save-enrichment", { transactionId, expense, applyTo }),
100+
101+
rename: (transactionId: string, displayName: string, applyTo: "single" | "all" = "single") =>
102+
this.http.post("/api/enrichment-update/save-enrichment", { transactionId, displayName, applyTo }),
103+
104+
comment: (transactionId: string, comment: string) =>
105+
this.http.post("/api/enrichment-update/save-comments", { transactionId, comment }),
106+
107+
exclude: (transactionId: string) =>
108+
this.http.post("/api/investigator/answers/budget-category", { transactionId, budgetCategory: "excluded" }),
109+
110+
include: (transactionId: string) =>
111+
this.http.post("/api/investigator/answers/unexclude-transaction", { transactionId }),
112+
113+
setBudgetType: (transactionId: string, budgetCategory: "fixed" | "variable") =>
114+
this.http.post("/api/investigator/answers/budget-category", { transactionId, budgetCategory }),
115+
116+
merge: (transactionId: string, input: string = "approved") =>
117+
this.http.post("/api/investigator/answers/merge", { papasMergeInput: [{ transactionId, input }] }),
118+
119+
adjustPrediction: (payload: {
120+
envelopeId: string;
121+
amount: number;
122+
applyOnBudgetDate: string;
123+
sequenceId: string;
124+
isPermanent?: boolean;
125+
monthsAhead?: number;
126+
}) =>
127+
this.http.post("/api/prediction-update/update-amount", {
128+
...payload,
129+
isPermanent: payload.isPermanent ?? true,
130+
monthsAhead: payload.monthsAhead ?? 1,
131+
}),
132+
};
133+
96134
// ═══════════════════════════════════════════
97135
// Direct API methods
98136
// ═══════════════════════════════════════════

src/client/http.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,20 @@ export class HttpClient {
5050
return this.request<T>(path, "POST", body, "json");
5151
}
5252

53+
/**
54+
* Perform a POST request expecting a plain-text response.
55+
*/
56+
async postText(path: string, body?: unknown): Promise<string> {
57+
return this.request<string>(path, "POST", body, "text");
58+
}
59+
60+
/**
61+
* Perform a PUT request against the RiseUp API.
62+
*/
63+
async put<T = unknown>(path: string, body?: unknown): Promise<T> {
64+
return this.request<T>(path, "PUT", body, "json");
65+
}
66+
5367
// ── internal ────────────────────────────────
5468

5569
private async request<T>(

src/client/types.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,3 +433,31 @@ export interface StoredSession {
433433
savedAt?: string;
434434
expiresAt?: string;
435435
}
436+
437+
// ── Write Operation Payloads ────────────────
438+
439+
export interface SaveEnrichmentPayload {
440+
transactionId: string;
441+
expense?: string;
442+
displayName?: string;
443+
applyTo?: "single" | "all";
444+
}
445+
446+
export interface SaveCommentPayload {
447+
transactionId: string;
448+
comment: string;
449+
}
450+
451+
export interface BudgetCategoryPayload {
452+
transactionId: string;
453+
budgetCategory: "fixed" | "variable" | "excluded";
454+
monthsDiff?: number;
455+
expenseCategory?: string;
456+
}
457+
458+
export interface MergeAnswerPayload {
459+
papasMergeInput: Array<{
460+
transactionId: string;
461+
input: "approved" | "loan" | "clearing" | "addCreds" | "bug";
462+
}>;
463+
}

0 commit comments

Comments
 (0)