$npx -y skills add ya5huk/findash --skill findash-doctorUse when the user says "doctor", "finance doctor", "check finance setup", "what's missing", or any "is everything set up?" equivalent. Audits binaries, configs, secrets, npm deps, vendor assets, DB, live Drive connectivity, and Chromium profiles. Auto-fixes safe local gaps and pr
| 1 | # findash-doctor |
| 2 | |
| 3 | You audit setup, fix what's safe, print a short scannable report. **Diagnose → auto-fix → report.** Anything needing the user goes into the report, not into a shell call. |
| 4 | |
| 5 | ## Where things live |
| 6 | |
| 7 | - Run from the project root (the dir holding `CLAUDE.md`, `scripts/`, `templates/`, `docs/`). Paths below are relative. |
| 8 | - Drive root ID: `root_folder_id=…` in `.secrets/findash` under `[drive]` (chmod 600, gitignored). |
| 9 | - Seed script: `scripts/init-db.sql`. Vendor script: `scripts/bundle-assets.py`. npm manifest: `scripts/package.json`. |
| 10 | |
| 11 | ## Checks |
| 12 | |
| 13 | | # | Category | What | Auto-fix? | |
| 14 | |---|---|---|---| |
| 15 | | 1 | Binaries | `qpdf`, `rclone`, `node ≥22.13.0`, `python3`, `sqlite3` on PATH | No | |
| 16 | | 2 | Dirs | `data/`, `inbox/staging/fetched/`, `inbox/staging/drive/`, `output/`, `.secrets/` exist | `mkdir -p` | |
| 17 | | 3 | rclone.conf | `./rclone.conf` exists + mode 600 | Perms; OR move `~/.config/rclone/rclone.conf` → `./rclone.conf` if local is absent | |
| 18 | | 4 | Drive root ID | `.secrets/findash` `[drive]` has a non-placeholder `root_folder_id=` | Perms only | |
| 19 | | 5 | Secrets | `.secrets/findash` exists + mode 600; note which `[sections]` are filled | Perms only | |
| 20 | | 6 | npm deps | `scripts/node_modules/` populated | `cd scripts && npm install` | |
| 21 | | 7 | Vendor | 3 files under `templates/vendor/` | `python3 scripts/bundle-assets.py` | |
| 22 | | 8 | DB | `data/finance.db` + has tables (incl. `positions`, `meta`) | `sqlite3 data/finance.db < scripts/init-db.sql` (fresh DB only) | |
| 23 | | 9 | Chromium profiles | `~/.cache/findash/chromium-profile/{hapoalim,visaCal}/` (only when matching secrets exist) | No | |
| 24 | | 10 | Drive live | `rclone lsf` against vault root succeeds in 5 s | No | |
| 25 | | 11 | IBKR connector | optional — the official Interactive Brokers connector is added in Claude (claude.ai), not findash config; interactive auth (unattended daily runs skip it) | No | |
| 26 | |
| 27 | Node: parse `node --version`; major ≥ 23, or major = 22 with patch ≥ 22.13.0. Perms: anything with non-zero group/others digit is wrong → `chmod 600`. For Drive live: read `root_folder_id=…` from `.secrets/findash` `[drive]`; if it's missing or the value is empty/placeholder/<20 chars, skip the live call and let check #4 own it. |
| 28 | |
| 29 | Positions + meta tables (#8): if `data/finance.db` exists but lacks the `positions` or `meta` table (an older install), **don't** re-run `init-db.sql` against a populated DB — its plain `CREATE TABLE`s will error. `positions` is added idempotently on the next `/findash:fetch-investments`, `meta` on the next `/findash:sync-finance-data` (or apply the matching `init-db.sql` block by hand); note under ⚠️ Optional, not a blocker. If `meta.last_db_backup_at` exists and is older than 14 days, add one ⚠️ line — the weekly Drive backup hasn't succeeded lately. Same idea for the run journal: for each configured source, one ⚠️ staleness line when its journal key is missing or >5 days old — `last_ingest_hapoalim_at`/`last_ingest_cal_at` (when the matching `[section]` exists in `.secrets/findash`), `last_ibkr_at` (when an `accounts.live_source='ibkr'` row exists), and `last_sync_at` >3 days regardless. IBKR connector (#11): purely informational and **optional** — the official Interactive Brokers connector is added by the user via Claude's connector directory, not by findash, and is interactive-only, so never treat its absence as an install error. If it's visible in this session (`/mcp` shows `Interactive Brokers (IBKR) · connected`), note ✓ OK; otherwise a one-line ⚠️ Optional pointer ("add it via Claude → Connectors if you want portfolio snapshots"). If `data/finance.db` exists and has the `live_source` column, also sanity-check the marker: `SELECT COUNT(*) FROM accounts WHERE live_source='ibkr'` should be 0 or 1, and a marked account must not have `closed_on` set — more than one marked row, or a closed marked row, is a ⚠️ with a one-line explanation (`fetch-investments` refuses to run until it's resolved); zero rows just means `fetch-investments` hasn't run yet. Never print balances, account ids, or positions (principle #1). |
| 30 | |
| 31 | ## Auto-fix order |
| 32 | |
| 33 | 1. `mkdir -p data inbox/staging/fetched inbox/staging/drive output .secrets` |
| 34 | 2. If `./rclone.conf` is missing but `~/.config/rclone/rclone.conf` exists (rclone's default XDG path — what plain `rclone config` writes to), move it: `mv ~/.config/rclone/rclone.conf ./rclone.conf`. Then re-check perms in step 3. (Not a symlink — the project owns this file.) |
| 35 | 3. `chmod 600` `rclone.conf` and `.secrets/findash` if either exists and is looser than 600 |
| 36 | 4. Init DB if missing/empty (needs `sqlite3`) |
| 37 | 5. `(cd scripts && npm install)` if `node_modules/` empty ( |