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/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.