Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). We use
[SemVer](https://semver.org/) for versioning — `0.x` releases batch
related changes, breaking changes can land in `0.x → 0.y`.

## [Unreleased]

### Changed

- SQLite is now documented and treated as FinSight's authoritative local data
store during normal CLI and web operation.
- The legacy plain-text ledger is explicit interoperability only; it is not
automatically synchronized and is not the canonical recovery format.
- `doctor` checks SQLite integrity and reads the database without migrations or
writes. `init` refuses to load demo data into a populated portfolio database.

### Added

- `finsight backup create` creates an integrity-checked native SQLite backup
with SHA-256 metadata and restrictive local file permissions.
- `finsight backup verify <file>` verifies an existing native SQLite backup.

## [0.1.0] — 2026-06-02 — Initial public release

The first public version of FinSight. A local-first, AI-friendly personal
Expand Down
74 changes: 39 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
**See your money. Know where it sits. Decide what's next.**

A personal portfolio tracker that runs on your laptop, plays well with AI tools,
and keeps your data in plain text files you can read and edit yourself.
and keeps your data in a local SQLite database you can back up and inspect.

[![CI](https://github.com/ApeCodeAI/finsight/actions/workflows/ci.yml/badge.svg)](https://github.com/ApeCodeAI/finsight/actions/workflows/ci.yml)
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](./LICENSE)
Expand Down Expand Up @@ -38,9 +38,10 @@ rebalance?", you're stuck taking screenshots.

FinSight takes the other path:

- 🗂 **Your files are the truth.** Holdings live in plain text on your disk
(YAML — readable by humans). Back them up with `git`, edit them in any editor,
open them on any machine. The app's database is just a working copy.
- 🗂 **SQLite is the truth.** Holdings, transactions, snapshots, and decisions
are stored locally in `~/.finsight/data/finsight.db`. Create a native,
integrity-checked backup with `finsight backup create` whenever you want a
recovery point.
- 🌍 **You pick the base currency.** USD, CNY, JPY, EUR — pick one, everything
else gets converted automatically. No region-locked product here.
- 🤖 **AI is a first-class user.** Every command can output structured JSON, and
Expand All @@ -49,14 +50,14 @@ FinSight takes the other path:
- 🔒 **Stays on your machine.** No cloud account, no signup, no telemetry. The
dashboard runs at `localhost`.

> A good portfolio tracker should be a file format first, a command-line tool
> second, and a dashboard third — in that order.
> A good portfolio tracker should be local-first, command-line friendly, and
> easy for an AI agent to inspect and operate.

## ⚡ Install

```bash
npm install -g finsight
finsight init # asks for base currency, locale, where to store your files
finsight init # asks for base currency and locale
finsight overview # see your portfolio
```

Expand Down Expand Up @@ -122,12 +123,12 @@ $ finsight overview --json | jq

| Decision | Most trackers | FinSight |
|---|---|---|
| Where data lives | Their cloud | Your laptop, in plain text files |
| Source of truth | Their database | Your text files; the app's DB is a copy |
| Where data lives | Their cloud | Your laptop, in a local SQLite database |
| Source of truth | Their database | Your local SQLite database |
| AI access | Maybe a chat box | A documented JSON output any AI can read |
| Base currency | Hard-coded | `finsight config set base-currency JPY` |
| Schema changes | Their migration | You edit the file |
| Backup | Vendor lock-in | `git commit` your folder |
| Schema changes | Their migration | Local SQLite migrations |
| Backup | Vendor lock-in | `finsight backup create` |
| Account model | Sign up first | None — runs as you, on your machine |

## 🎯 What it does and doesn't do
Expand All @@ -154,7 +155,7 @@ For budgeting, you can pair FinSight with:
- [**Actual**](https://actualbudget.org/) — local-first envelope budgeting (open source)
- [**YNAB**](https://www.ynab.com/) / [**Lunch Money**](https://lunchmoney.app/) — commercial, polished

Since FinSight uses plain text files, running both side by side is easy.
Since FinSight runs locally and exposes JSON, running both side by side is easy.

## 🤖 Let an AI agent drive it

Expand Down Expand Up @@ -195,18 +196,14 @@ wire it into your specific assistant.
└─────────┬───────────┴─────────┬───────────┘
│ │
┌────▼─────┐ ┌─────▼─────┐
│ Hono API │ ◄─────► │ SQLite │ ← working copy
└────┬─────┘ └─────▲─────┘
│ Hono API │ ◄─────► │ SQLite │ ← authoritative local store
└────┬─────┘ └─────┬─────┘
│ │
│ finsight ledger sync (once a day)
│ backup create / verify
│ ▼
│ ┌───────────────┐
└────────────►│ your folder │ ← source of truth
│ accounts.yaml│ (git-tracked)
│ fx-rates.yaml│
│ transactions │
│ snapshots/ │
│ decisions/ │
└────────────►│ native backup │ ← recovery copy
│ *.sqlite3 │
└───────────────┘
```

Expand All @@ -224,7 +221,9 @@ finsight config set ledger-dir ~/notes/finance/ledger
```

Your settings live in `~/.finsight/config.json`. The `FINSIGHT_DB_PATH`
environment variable can override where the SQLite working copy lives.
environment variable can override where the authoritative SQLite database lives.
The optional `ledger-dir` setting is only for explicit legacy export/import
interoperability; it is not required for normal use.

### 🔒 Note on security

Expand Down Expand Up @@ -278,11 +277,15 @@ finsight quote update --dry-run # preview, don't write
```bash
finsight reconcile <acc> # compare to what your broker app shows
finsight reconcile log # past cross-check results
finsight ledger sync # save today's database snapshot into your folder
finsight ledger verify # check that the DB and your files match
finsight ledger restore --yes # rebuild the DB from your files (disaster recovery)
finsight backup create --json # create a verified native SQLite backup
finsight backup verify <file> --json # verify an existing native backup
finsight doctor --json # inspect DB integrity and portfolio health
```

`ledger sync`, `ledger verify`, and `ledger restore` are retained only as
explicit legacy interoperability commands. Ledger export is lossy and is not
the canonical recovery path.

**Hand the portfolio to an LLM**
```bash
finsight context | pbcopy # Markdown briefing → clipboard
Expand Down Expand Up @@ -338,18 +341,19 @@ for the full guide.
## 🗃 What lives in your folder

```
ledger/
├── README.md (auto-generated)
├── accounts.yaml — your accounts + holdings (you can edit this directly)
├── fx-rates.yaml — exchange rates between currencies
├── transactions.jsonl — every event, appended one per line
├── snapshots/ — daily JSON snapshots
└── decisions/ — markdown notes per investment decision
legacy-ledger/ # only if you explicitly configure ledger-dir
├── README.md (auto-generated)
├── accounts.yaml — exported account + holding state
├── fx-rates.jsonl — exported dated exchange rates
├── transactions.jsonl — exported transactions
├── snapshots.jsonl — exported snapshots
├── reconciliations.jsonl — exported reconciliation rows
└── decisions/ — exported decision notes
```

This layout is deliberately simple. Paste `accounts.yaml` into any AI and
ask for advice; commit the diff after a buy; restore the database from any
point in your git history.
This directory is an optional compatibility format. It is generated only by
an explicit ledger command and can be useful for inspection or interoperability,
but it is not a native SQLite backup and is not imported automatically.

## 🚧 Status

Expand Down
61 changes: 32 additions & 29 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,20 @@ Built by **[ApeCode.ai](https://apecode.ai)** · Sponsored by **[BytePass.ai](ht

FinSight 走另一条路:

- 🗂 **你的文件就是真相。** 持仓存在你硬盘上的纯文本里(YAML,人能读懂),用 `git` 备份,任何编辑器都能改,任何机器都能打开。App 里那个数据库只是工作副本。
- 🗂 **SQLite 是事实源。** 持仓、交易、快照和决策都保存在本机
`~/.finsight/data/finsight.db`。需要恢复点时,运行
`finsight backup create` 创建经过完整性检查的原生备份。
- 🌍 **基准币你说了算。** USD / CNY / JPY / EUR,挑一个,其他币种自动换算到这个。没有地区锁定。
- 🤖 **AI 是一等用户。** 每个命令都能输出结构化 JSON;仓库里有一个 markdown 文件(叫 [skill](./skills/finsight/SKILL.md)),任何 AI 助手(Claude / Cursor / Codex / ChatGPT)读完就知道怎么帮你操作。
- 🔒 **数据不出本机。** 无云端、无注册、无埋点。Dashboard 默认只跑在 `localhost`。

> 一个好的投资追踪工具,应该先是一个文件格式,然后是命令行,最后才是 Dashboard。
> 一个好的投资追踪工具,应该本地优先、命令行友好,而且方便 AI agent 检查和操作。

## ⚡ 安装

```bash
npm install -g finsight
finsight init # 问你基准币、地区、文件存哪里
finsight init # 问你基准币和地区
finsight overview # 看你的组合
```

Expand Down Expand Up @@ -109,12 +111,12 @@ $ finsight overview --json | jq

| 维度 | 大多数工具 | FinSight |
|---|---|---|
| 数据存哪儿 | 它的云 | 你的笔记本上,纯文本文件 |
| 真相在谁手里 | 它的数据库 | 你的文件;App 的 DB 只是副本 |
| 数据存哪儿 | 它的云 | 你的笔记本上,本地 SQLite 数据库 |
| 真相在谁手里 | 它的数据库 | 你的本地 SQLite 数据库 |
| AI 怎么用 | 也许给你一个聊天框 | 有文档的 JSON 输出,任何 AI 都能读 |
| 基准币 | 写死 | `finsight config set base-currency JPY` |
| Schema 变化 | 它的迁移脚本 | 你自己改文件 |
| 备份 | 绑在它身上 | `git commit` 你的文件夹 |
| Schema 变化 | 它的迁移脚本 | 本地 SQLite 迁移 |
| 备份 | 绑在它身上 | `finsight backup create` |
| 账户模型 | 必须注册 | 没有 —— 以你的身份在你机器上跑 |

## 🎯 在做什么 / 不在做什么
Expand Down Expand Up @@ -174,18 +176,14 @@ finsight context --json # 结构化数据,给自主 agent 用
└─────────┬───────────┴─────────┬───────────┘
│ │
┌────▼─────┐ ┌─────▼─────┐
│ Hono API │ ◄─────► │ SQLite │ ← 工作副本
└────┬─────┘ └─────▲─────┘
│ Hono API │ ◄─────► │ SQLite │ ← 本地事实源
└────┬─────┘ └─────┬─────┘
│ │
│ finsight ledger sync (每日)
│ backup create / verify
│ ▼
│ ┌───────────────┐
└────────────►│ 你的文件夹 │ ← 真相(git 追踪)
│ accounts.yaml│
│ fx-rates.yaml│
│ transactions │
│ snapshots/ │
│ decisions/ │
└────────────►│ 原生 SQLite 备份 │ ← 恢复副本
│ *.sqlite3 │
└───────────────┘
```

Expand All @@ -203,7 +201,8 @@ finsight config set ledger-dir ~/notes/finance/ledger
```

配置存在 `~/.finsight/config.json`,`FINSIGHT_DB_PATH` 环境变量可以
改 SQLite 工作副本的位置。
改事实源 SQLite 数据库的位置。`ledger-dir` 是可选的旧版导出/导入
互操作配置,日常使用不需要配置。

### 🔒 关于安全

Expand Down Expand Up @@ -255,11 +254,14 @@ finsight quote update --dry-run # 预览不写入
```bash
finsight reconcile <acc> # 和券商 App 显示的对比
finsight reconcile log # 历史对账记录
finsight ledger sync # 把今天的 DB 镜像存到你文件夹里
finsight ledger verify # 检查 DB 和文件是否一致
finsight ledger restore --yes # 灾难恢复:从文件重建 DB
finsight backup create --json # 创建已校验的原生 SQLite 备份
finsight backup verify <file> --json # 验证已有原生备份
finsight doctor --json # 检查数据库完整性和组合状态
```

`ledger sync`、`ledger verify`、`ledger restore` 只保留作显式的旧版
互操作命令。ledger 导出是有损格式,不是规范的灾难恢复路径。

**把组合喂给 LLM**
```bash
finsight context | pbcopy # Markdown 简报 → 剪贴板
Expand Down Expand Up @@ -313,17 +315,18 @@ provider。新增语言改 `packages/core/src/i18n/index.ts`。完整说明见
## 🗃 你文件夹里有什么

```
ledger/
├── README.md (自动生成)
├── accounts.yaml — 你的账户 + 持仓(可以直接手编辑)
├── fx-rates.yaml — 币种间的汇率
├── transactions.jsonl — 每个事件一行,只追加不修改
├── snapshots/ — 每日 JSON 快照
└── decisions/ — 每个投资决策一份 markdown 笔记
legacy-ledger/ # 只有显式配置 ledger-dir 时才会有
├── README.md (自动生成)
├── accounts.yaml — 导出的账户和持仓状态
├── fx-rates.jsonl — 导出的带日期汇率
├── transactions.jsonl — 导出的交易
├── snapshots.jsonl — 导出的快照
├── reconciliations.jsonl — 导出的对账记录
└── decisions/ — 导出的决策笔记
```

这个结构故意保持简单。把 `accounts.yaml` 喂给任何 AI 问意见;
买完之后 commit 一下 diff;任意 git 历史点都能 restore 出当时的 DB。
这是可选的兼容格式,只会在显式执行 ledger 命令时生成,适合检查或
与旧工具互操作;它不是原生 SQLite 备份,也不会自动导入。

## 🚧 项目状态

Expand Down
17 changes: 11 additions & 6 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Security policy

FinSight is a **local-first, single-user** tool. Your data lives on your
machine (`~/.finsight/`) and your vault directory. There is no server-side
component, no telemetry, no account system.
machine (`~/.finsight/`) in a local SQLite database and optional native backup
files. There is no cloud account, telemetry, or multi-user account system.

The optional ledger directory is only an explicitly generated legacy
export/import format. It is not synchronized automatically and is not the
canonical recovery source; use `finsight backup create` for native recovery
copies.

That said, a few security-relevant things still apply.

Expand All @@ -29,8 +34,8 @@ In scope:
is bound to a non-loopback interface
- Connector code that mishandles untrusted upstream responses (e.g., quote
feed returning malicious payloads)
- Vault/ledger code that could be tricked into writing outside the
configured `ledger_dir`
- Ledger export/import code that could write outside the explicitly configured
`ledger_dir`

Out of scope:

Expand All @@ -44,8 +49,8 @@ Out of scope:

## Hardening tips for users

- Keep your `ledger_dir` in a private git repo or an encrypted filesystem.
It contains your full position list.
- Keep native backups and any configured `ledger_dir` in a private or encrypted
location; they contain portfolio data.
- Don't pipe `finsight context` into a third-party LLM if you consider your
portfolio sensitive — `finsight context --json` and the Markdown form
both include account names and dollar amounts.
Expand Down
37 changes: 30 additions & 7 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,45 @@
# Example portfolios

Drop one of these YAML files into your `ledger_dir` as `accounts.yaml` to bootstrap a demo.
These YAML files are synthetic demo data. The normal FinSight source of truth is
local SQLite; examples are loaded by `finsight init --demo` or by the demo
script.

| File | Profile | Base currency |
|---|---|---|
| `seed-portfolio.en.yaml` | US-leaning: VOO / VTI / AAPL / NVDA / cash / BTC | USD |
| `seed-portfolio.zh.yaml` | China-leaning: A-share funds + HK + US stocks | CNY |
| `tickers.cn.yaml` | Chinese-name → ticker mapping (drop in ledger as `tickers.yaml`) | — |
| `tickers.cn.yaml` | Chinese-name → ticker mapping for optional legacy exports | — |

## Use as demo

```bash
finsight ledger init ~/finsight-demo
cp examples/seed-portfolio.en.yaml ~/finsight-demo/accounts.yaml
finsight ledger restore --yes
finsight init --non-interactive \
--base-currency USD \
--display-locale en-US \
--labels-language en \
--demo en
finsight overview
```

## Use as template
Or run the isolated dashboard demo:

Treat these as a starting point — edit account names, paste in your real positions, then `finsight ledger restore --yes`.
```bash
pnpm demo
# pnpm demo zh
```

The demo uses a temporary database and does not touch the user's real
`~/.finsight/` data.

## Optional legacy export

If an older tool needs the plain-text representation, configure a directory
explicitly and export from SQLite:

```bash
finsight ledger init ~/finsight-legacy-export
finsight ledger export
```

The export is for interoperability and inspection. It is not a native backup
and should not be treated as the canonical recovery source.
Loading
Loading