financy 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +190 -0
- package/README.md +139 -0
- package/dist/bin.js +750 -0
- package/dist/chunk-JZO2ARNB.js +492 -0
- package/dist/server-SIRWJMXP.js +199 -0
- package/package.json +65 -0
- package/skills/financy-setup/SKILL.md +177 -0
- package/skills/freshness-check/SKILL.md +139 -0
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "financy",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Your Open-Finance accounts, balances and transactions in the terminal — with an embedded MCP server and agent skills",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"financy": "dist/bin.js"
|
|
8
|
+
},
|
|
9
|
+
"license": "Apache-2.0",
|
|
10
|
+
"author": "Open Finance AI <hello@open-finance.ai>",
|
|
11
|
+
"homepage": "https://github.com/open-finance-ai/financy#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/open-finance-ai/financy/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"financy",
|
|
17
|
+
"open-finance",
|
|
18
|
+
"open-banking",
|
|
19
|
+
"cli",
|
|
20
|
+
"mcp",
|
|
21
|
+
"claude-code",
|
|
22
|
+
"agent-skills",
|
|
23
|
+
"fintech",
|
|
24
|
+
"israel"
|
|
25
|
+
],
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/open-finance-ai/financy.git"
|
|
29
|
+
},
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public",
|
|
32
|
+
"provenance": true
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"skills"
|
|
37
|
+
],
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=20"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsup",
|
|
43
|
+
"test": "vitest run",
|
|
44
|
+
"test:watch": "vitest",
|
|
45
|
+
"typecheck": "tsc --noEmit",
|
|
46
|
+
"lint": "eslint .",
|
|
47
|
+
"smoke": "node scripts/smoke.mjs",
|
|
48
|
+
"prepublishOnly": "npm run build"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
52
|
+
"commander": "^12.1.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@eslint/js": "^10.0.1",
|
|
56
|
+
"@types/node": "^20.14.0",
|
|
57
|
+
"eslint": "^10.7.0",
|
|
58
|
+
"globals": "^17.7.0",
|
|
59
|
+
"tsup": "^8.2.4",
|
|
60
|
+
"typescript": "^5.5.4",
|
|
61
|
+
"typescript-eslint": "^8.65.0",
|
|
62
|
+
"undici": "^6.19.8",
|
|
63
|
+
"vitest": "^2.0.5"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: financy-setup
|
|
3
|
+
description: >
|
|
4
|
+
Onboard a user onto the financy CLI so their Open-Finance banking data is
|
|
5
|
+
available to you. Use when the user asks to "set up financy", "connect my
|
|
6
|
+
bank data", "configure the financy CLI", when any financy command fails with
|
|
7
|
+
a NOT_CONFIGURED or AUTH error, or when you need account/transaction data and
|
|
8
|
+
no working financy credentials exist yet. Covers installing the CLI, locating
|
|
9
|
+
clientId/clientSecret/userId in the Financy app, saving them without ever
|
|
10
|
+
reading the secret, verifying the result, and explaining the paid-plan
|
|
11
|
+
requirement when the account is not eligible.
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# financy setup
|
|
15
|
+
|
|
16
|
+
Get the `financy` CLI configured and verified for this user. When you are done,
|
|
17
|
+
`financy status` exits `0` and every other financy command works.
|
|
18
|
+
|
|
19
|
+
**Minimum CLI version:** 0.1.0
|
|
20
|
+
|
|
21
|
+
## Guardrails
|
|
22
|
+
|
|
23
|
+
These are not optional and they apply to every step below.
|
|
24
|
+
|
|
25
|
+
- **Never handle the client secret at all.** Do not ask the user to paste it into
|
|
26
|
+
the conversation, and never place it in a command you run — a command you run
|
|
27
|
+
is recorded in the transcript, and it is visible in shell history and to
|
|
28
|
+
anything that can list processes. The user types the secret into
|
|
29
|
+
`financy setup`, which masks it at the prompt; you never see it. If the user
|
|
30
|
+
pastes it anyway, do not repeat it, do not use it in a command, and tell them
|
|
31
|
+
to rotate it in Financy → Settings → API. Never print it, read it back for
|
|
32
|
+
confirmation, or include it in a summary, and never `cat` the config file.
|
|
33
|
+
- **Confirm before spending credits.** `financy refresh` costs 20 credits per
|
|
34
|
+
run. Never run it without the user explicitly agreeing to that cost in this
|
|
35
|
+
conversation.
|
|
36
|
+
- **Exit code 4 means the plan, not the credentials.** The credentials are
|
|
37
|
+
valid but the account is not on a paid plan. Do not retry, do not suggest
|
|
38
|
+
re-entering the credentials — point the user at the upgrade path and stop.
|
|
39
|
+
|
|
40
|
+
## What the user needs before you start
|
|
41
|
+
|
|
42
|
+
The financy data API is a paid feature. To finish this skill the user must have:
|
|
43
|
+
|
|
44
|
+
1. A registered Financy account at <https://open-finance.ai>.
|
|
45
|
+
2. A **paid plan** — Starter or Pro. The data API is not available on the free
|
|
46
|
+
plan.
|
|
47
|
+
3. Three values from the Financy app → **Settings → API**: `clientId`,
|
|
48
|
+
`clientSecret`, and `userId`.
|
|
49
|
+
|
|
50
|
+
If the user does not have a paid plan yet, say so up front rather than letting
|
|
51
|
+
them collect credentials that will fail at the last step.
|
|
52
|
+
|
|
53
|
+
## Method
|
|
54
|
+
|
|
55
|
+
### 1. Check whether it is already configured
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
financy status --json
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Branch on the exit code:
|
|
62
|
+
|
|
63
|
+
- `0` — already configured and working. Report the connection summary and stop;
|
|
64
|
+
there is nothing to set up.
|
|
65
|
+
- `3` with `"code":"NOT_CONFIGURED"` — no credentials yet. Continue to step 2.
|
|
66
|
+
- `3` with any other code — credentials exist but are rejected. Continue to
|
|
67
|
+
step 2 to replace them.
|
|
68
|
+
- `4` — credentials are fine, the plan is not. Jump to *Handling exit 4*.
|
|
69
|
+
- `127` / command-not-found — the CLI is not installed. Continue to step 2.
|
|
70
|
+
|
|
71
|
+
### 2. Make the CLI available
|
|
72
|
+
|
|
73
|
+
Prefer a global install so later sessions do not re-download it:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npm install -g financy
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
If the user cannot or does not want to install globally, every command in this
|
|
80
|
+
skill also works as `npx financy <command>`.
|
|
81
|
+
|
|
82
|
+
### 3. Have the user run setup themselves
|
|
83
|
+
|
|
84
|
+
**Do not collect the credentials and run setup for them.** Ask the user to run
|
|
85
|
+
this in their own terminal:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
financy setup
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
It prompts for `clientId`, `clientSecret` and `userId` in turn, and **masks the
|
|
92
|
+
secret as they type it** — so the secret goes straight from the user to the CLI
|
|
93
|
+
and never passes through you, this conversation, or a command line. Tell them
|
|
94
|
+
where to find the three values: the Financy app → **Settings → API**.
|
|
95
|
+
|
|
96
|
+
`setup` validates the credentials against the live API before saving, so a wrong
|
|
97
|
+
value fails immediately rather than on their first real command. On success it
|
|
98
|
+
writes `~/.config/financy/config.json` with permissions `600` and prints the path.
|
|
99
|
+
|
|
100
|
+
Ask the user to tell you the exit code or what it printed — that is all you need.
|
|
101
|
+
Do not ask them to paste any of the three values.
|
|
102
|
+
|
|
103
|
+
Exit codes from `setup`:
|
|
104
|
+
|
|
105
|
+
- `0` — saved and verified.
|
|
106
|
+
- `3` — the credentials were rejected. Ask them to run `financy setup` again and
|
|
107
|
+
re-copy the values; a partial paste or a stray space is the usual cause.
|
|
108
|
+
- `4` — the credentials are valid but the plan is not eligible. The CLI still
|
|
109
|
+
saves them so a later upgrade works immediately. Go to *Handling exit 4*.
|
|
110
|
+
- `7` — the API could not be reached. This is a network or endpoint problem, not
|
|
111
|
+
a credential problem; retry once, then report it.
|
|
112
|
+
|
|
113
|
+
### 5. Verify
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
financy status
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Exit `0` with a connection table means setup is done. Report what you see:
|
|
120
|
+
how many connections there are, and whether any are stale or in error. If the
|
|
121
|
+
user has no connections yet, tell them to connect a bank in the Financy app —
|
|
122
|
+
the CLI reads data, it does not create connections.
|
|
123
|
+
|
|
124
|
+
If anything looks stale, do not refresh on your own initiative. Hand off to the
|
|
125
|
+
`freshness-check` skill, which knows how to weigh staleness against the 20-credit
|
|
126
|
+
cost.
|
|
127
|
+
|
|
128
|
+
## Handling exit 4
|
|
129
|
+
|
|
130
|
+
Exit `4` (`NOT_AVAILABLE_ON_PLAN`) means the account is registered and the
|
|
131
|
+
credentials are correct, but the plan does not include the data API.
|
|
132
|
+
|
|
133
|
+
Tell the user, in plain terms:
|
|
134
|
+
|
|
135
|
+
> Your credentials are valid, but the data API needs a paid plan (Starter or
|
|
136
|
+
> Pro). You can upgrade at <https://open-finance.ai> — the credentials are
|
|
137
|
+
> already saved, so `financy status` will work as soon as the plan is active.
|
|
138
|
+
|
|
139
|
+
Then stop. Do not retry the command, do not ask for different credentials, and
|
|
140
|
+
do not look for a workaround.
|
|
141
|
+
|
|
142
|
+
## Non-interactive and CI environments
|
|
143
|
+
|
|
144
|
+
If `FINANCY_CLIENT_ID`, `FINANCY_CLIENT_SECRET` and `FINANCY_USER_ID` are
|
|
145
|
+
**already present in the environment** — put there by CI, a secret manager, or
|
|
146
|
+
the user's own shell profile — the CLI reads them directly and no config file is
|
|
147
|
+
needed. There is nothing for you to do; just run `financy status` and continue.
|
|
148
|
+
|
|
149
|
+
`financy setup --no-input` reads those same variables and persists them for
|
|
150
|
+
future sessions. Use it only when the environment already carries them. Never
|
|
151
|
+
set them yourself as a prefix to the command in order to pass along a secret the
|
|
152
|
+
user gave you — `FINANCY_CLIENT_SECRET=… financy setup --no-input` puts the
|
|
153
|
+
secret in the command line, which defeats the whole point. In that situation the
|
|
154
|
+
answer is always step 3: let the user run `financy setup` and type it.
|
|
155
|
+
|
|
156
|
+
To see which endpoints and credential sources are in effect without exposing
|
|
157
|
+
the secret:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
financy config
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
It prints the resolved endpoints and marks each credential as coming from the
|
|
164
|
+
environment or the config file, with the secret masked.
|
|
165
|
+
|
|
166
|
+
## MCP alternative
|
|
167
|
+
|
|
168
|
+
If the user runs agents against the financy MCP server instead of the CLI, the
|
|
169
|
+
same surface is available as tools. Register it once:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
claude mcp add financy -- npx financy mcp
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The server resolves credentials exactly as the CLI does. Until setup is
|
|
176
|
+
complete, every tool returns a structured `NOT_CONFIGURED` error — which is your
|
|
177
|
+
signal to run this skill.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: freshness-check
|
|
3
|
+
description: >
|
|
4
|
+
Decide whether the user's Open-Finance banking data is current enough to
|
|
5
|
+
answer with, and offer a refresh when it is not. Use before any analysis that
|
|
6
|
+
depends on recent transactions or balances ("what did I spend this week",
|
|
7
|
+
"what is my balance", "did the card charge clear"), and whenever the user asks
|
|
8
|
+
"is my data up to date", "why is this missing", "refresh my accounts", or a
|
|
9
|
+
recent transaction they expect is absent. Interprets financy status --json,
|
|
10
|
+
applies the staleness threshold, and confirms the 20-credit cost with the user
|
|
11
|
+
before ever triggering financy refresh.
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# freshness check
|
|
15
|
+
|
|
16
|
+
Answer one question — *is this data current enough to use?* — and act on the
|
|
17
|
+
answer. Every analysis skill that reads financy data should start here.
|
|
18
|
+
|
|
19
|
+
**Minimum CLI version:** 0.1.0
|
|
20
|
+
|
|
21
|
+
## Guardrails
|
|
22
|
+
|
|
23
|
+
- **Confirm before spending credits.** `financy refresh` costs **20 credits**
|
|
24
|
+
every time it is called. Never run it without stating the cost and getting an
|
|
25
|
+
explicit yes from the user in this conversation. "The data is stale, want me
|
|
26
|
+
to refresh?" is not enough — say the number.
|
|
27
|
+
- **Never echo the client secret** or the contents of the config file. If you
|
|
28
|
+
need to show what is configured, use `financy config`, which masks the secret.
|
|
29
|
+
- **Exit code 4 means the plan, not the credentials.** Point the user at the
|
|
30
|
+
upgrade path at <https://open-finance.ai> and stop; do not retry and do not
|
|
31
|
+
ask for new credentials.
|
|
32
|
+
|
|
33
|
+
## Method
|
|
34
|
+
|
|
35
|
+
### 1. Read the status
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
financy status --json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The envelope:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"data": [
|
|
46
|
+
{
|
|
47
|
+
"provider": "hapoalim",
|
|
48
|
+
"status": "ACTIVE",
|
|
49
|
+
"fresh": "2026-08-01",
|
|
50
|
+
"expires": "2026-11-14",
|
|
51
|
+
"accounts": 3
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
"staleThresholdDays": 2
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Per row:
|
|
59
|
+
|
|
60
|
+
- `provider` — the bank or card issuer. `null` while a connection is still
|
|
61
|
+
being established.
|
|
62
|
+
- `status` — `ACTIVE` means the connection itself is healthy. Anything else is
|
|
63
|
+
a broken connection, not a staleness problem.
|
|
64
|
+
- `fresh` — the date the data runs through, as `YYYY-MM-DD`. `null` means the
|
|
65
|
+
connection has never fetched anything.
|
|
66
|
+
- `expires` — when the user's bank consent lapses. Not a freshness signal, but
|
|
67
|
+
worth surfacing when it is close.
|
|
68
|
+
- `accounts` — how many accounts, cards, savings, loans and securities this
|
|
69
|
+
connection covers.
|
|
70
|
+
|
|
71
|
+
`staleThresholdDays` is the CLI's own threshold (2 days). Read it from the
|
|
72
|
+
response rather than hard-coding it.
|
|
73
|
+
|
|
74
|
+
Handle the exit code before the body: `3` → the CLI is not configured or the
|
|
75
|
+
credentials are rejected, so run the `financy-setup` skill instead; `4` → see
|
|
76
|
+
the guardrail above; `7` → the API is unreachable, retry once then report.
|
|
77
|
+
|
|
78
|
+
### 2. Classify each connection
|
|
79
|
+
|
|
80
|
+
Compare `fresh` to today, in whole calendar days:
|
|
81
|
+
|
|
82
|
+
| Condition | Meaning | What to do |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| `status` is not `ACTIVE` | The connection is broken | A refresh will not fix it — the user must reconnect the bank in the Financy app |
|
|
85
|
+
| `fresh` is `null` | Never fetched | A refresh is worth offering; if it has been pending a long time, reconnecting is more likely to help |
|
|
86
|
+
| days since `fresh` ≤ `staleThresholdDays` | Fresh | Proceed with the analysis |
|
|
87
|
+
| days since `fresh` > `staleThresholdDays` | Stale | Offer a refresh (step 3) |
|
|
88
|
+
|
|
89
|
+
Weigh this against what the user actually asked. Banks post transactions with a
|
|
90
|
+
lag, so a one-day-old feed is normal and a weekend gap is expected. Two facts
|
|
91
|
+
matter more than the raw number:
|
|
92
|
+
|
|
93
|
+
- **How stale relative to the question.** "What did I spend last month" is fine
|
|
94
|
+
on three-day-old data. "Did this morning's transfer land" is not.
|
|
95
|
+
- **Which connection is stale.** If only an unrelated card is behind, say so and
|
|
96
|
+
carry on rather than refreshing everything.
|
|
97
|
+
|
|
98
|
+
### 3. Offer the refresh
|
|
99
|
+
|
|
100
|
+
When a refresh would genuinely help, ask — with the cost stated:
|
|
101
|
+
|
|
102
|
+
> Your Hapoalim data runs through 2026-07-28, which is 6 days old. I can trigger
|
|
103
|
+
> a refresh, which costs **20 credits** and takes a few minutes. Want me to?
|
|
104
|
+
|
|
105
|
+
Only after an explicit yes:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
financy refresh --json
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Notes on the behaviour:
|
|
112
|
+
|
|
113
|
+
- Refresh is **org-wide** — it refreshes every connection, not the one you named.
|
|
114
|
+
Say that when you ask, so 20 credits does not read as a per-bank price.
|
|
115
|
+
- `{"data":{"status":"already_running"}}` means a refresh was already in flight.
|
|
116
|
+
No new charge; just wait.
|
|
117
|
+
- It is asynchronous. Data lands in a few minutes; `financy refresh` returning
|
|
118
|
+
does not mean the data is there. Poll `financy status --json` and watch `fresh`
|
|
119
|
+
advance.
|
|
120
|
+
- Exit `5` (`INSUFFICIENT_CREDITS`) — the account is out of credits. Tell the
|
|
121
|
+
user and stop.
|
|
122
|
+
|
|
123
|
+
### 4. Report and proceed
|
|
124
|
+
|
|
125
|
+
Say what you found before you answer the actual question, in one line — for
|
|
126
|
+
example *"Data is current through yesterday across all 3 banks"* or *"Leumi is
|
|
127
|
+
4 days behind; the rest are current, so the card analysis below is complete but
|
|
128
|
+
the checking-account view may be missing a few days."*
|
|
129
|
+
|
|
130
|
+
If the user declines the refresh, proceed with the stale data and state the
|
|
131
|
+
as-of date in your answer. Do not silently analyse stale data as if it were
|
|
132
|
+
current.
|
|
133
|
+
|
|
134
|
+
## MCP alternative
|
|
135
|
+
|
|
136
|
+
Against the financy MCP server the same flow is `get_status` followed, only
|
|
137
|
+
after confirmation, by `refresh_connections`. The envelopes are identical to the
|
|
138
|
+
CLI's `--json` output. `refresh_connections` carries the 20-credit warning in its
|
|
139
|
+
tool description — treat that as binding, not advisory.
|