name: treeline
description: 与您的 Treeline Money 财务数据对话。查询余额、支出、预算和交易记录。
user-invocable: true
homepage: https://treeline.money
metadata: {"openclaw":{"emoji":"🌲","requires":{"bins":["tl"]},"install":[{"id":"tl-mac","kind":"download","url":"https://github.com/treeline-money/treeline/releases/latest/download/tl-macos-arm64","bins":["tl"],"label":"安装 Treeline CLI (macOS)","os":["darwin"]},{"id":"tl-linux","kind":"download","url":"https://github.com/treeline-money/treeline/releases/latest/download/tl-linux-x64","bins":["tl"],"label":"安装 Treeline CLI (Linux)","os":["linux"]},{"id":"tl-win","kind":"download","url":"https://github.com/treeline-money/treeline/releases/latest/download/tl-windows-x64.exe","bins":["tl.exe"],"label":"安装 Treeline CLI (Windows)","os":["win32"]}]}}
与您的财务数据对话。 您可以提问,例如“我的净资产是多少?”、“我在食品杂货上花了多少钱?”或“我超预算了吗?”,并从您自己的财务数据中获得即时答案。
# 1. 安装 CLI(OpenClaw 会自动处理)
# 2. 启用演示模式(使用示例数据)
tl demo on
# 3. 尝试一下
tl status
给代理的提示: 如果
tl命令失败并显示“command not found”,则需要安装 CLI。OpenClaw 会通过技能元数据自动处理安装。从演示模式开始,以便用户可以立即尝试查询。
使用 tl --version 验证 CLI 是否可用。从演示模式开始,以便用户可以立即尝试查询。
可选: 下载桌面应用以可视化探索您的数据。
演示模式加载示例数据,用户无需连接银行即可尝试查询:
tl demo on
稍后切换到真实数据:
tl demo off
演示数据与真实数据是分开的。
tl demo on 会打印成功消息——如果看起来卡住,请等待几秒钟(首次运行会初始化数据库)tl demo status 验证演示模式是否已启用tl demo on当用户准备好超越演示模式时,请引导他们使用下方链接的指南设置数据源。
数据源选项:
- SimpleFIN ($1.50/月,美国和加拿大)
- Lunch Flow (~$3/月,全球)
- CSV 导入 (免费)
设置完成后,使用 tl sync 拉取银行交易记录,或使用 tl import 加载 CSV 文件。
Treeline Money 是一款本地优先的个人财务应用。您的所有数据都存储在您设备上的本地 DuckDB 数据库中。无需云账户,无需订阅(同步服务是可选的),并拥有对财务数据的完整 SQL 访问权限。
不支持加密数据库。 如果用户在 Treeline 中启用了数据库加密,CLI 命令将失败。他们需要:
- 如果他们希望 OpenClaw 能够访问,则需禁用加密
- 对于加密数据库,直接使用 Treeline 应用
如果您看到“database is encrypted”错误,请解释此限制。
为移动端/聊天环境格式化所有响应:
- 使用项目符号列表,而非 Markdown 表格
- 四舍五入数字以提高可读性(例如 $1,234 而非 $1,234.56)
- 先给出答案,再提供细节
- 保持响应简洁——聊天不是电子表格
- 使用换行分隔不同部分
良好响应示例:
您的净资产为 $125k
资产:$180k
- 退休账户:$85k
- 储蓄账户:$25k
- 支票账户:$10k
- 房屋净值:$60k
负债:$55k
- 抵押贷款:$52k
- 信用卡:$3k
不良响应示例:
| 账户 | 类型 | 余额 |
|---------|------|---------|
| 我的 401k 账户 | 资产 | 85234.56 |
...
这些命令是只读的,可以安全地自主运行:
tl status # 快速账户摘要(含余额)
tl status --json # 同上,但输出 JSON 格式
tl query "SQL" --json # 运行任何 SQL 查询(数据库以只读模式打开)
tl sql "SQL" --json # 同上(别名)
tl backup list # 列出可用备份
tl doctor # 检查数据库健康状况
tl demo status # 检查演示模式是否开启/关闭
注意:
tl query和tl sql默认以只读模式打开数据库。除非传递--allow-writes参数(见下方写入命令),否则它们无法修改数据。
使用 tl status 进行快速余额查询——它比 SQL 查询更快。
这些命令会修改本地数据。在运行它们之前,务必先询问用户进行确认,除非用户已在 PERMISSIONS.md 中明确允许(参见代理权限)。
tl query "SQL" --allow-writes --json # 以写入权限运行 SQL 查询
tl sql "SQL" --allow-writes --json # 同上(别名)
tl sync # 从银行集成同步账户/交易记录
tl sync --dry-run # 预览将要同步的内容(只读,可安全运行)
tl import FILE -a ACCOUNT # 从 CSV 导入交易记录
tl import FILE -a ACCOUNT --dry-run # 预览导入内容而不实际应用(只读,可安全运行)
tl import FILE -a ACCOUNT --json # 输出 JSON 格式(用于脚本)
tl backup create # 创建备份
tl backup restore NAME # 恢复备份
tl compact # 压缩数据库(回收空间,优化性能)
tl tag "groceries" --ids ID1,ID2 # 为交易记录应用标签
tl demo on|off # 切换演示模式(示例数据)
提示: 带有
--dry-run的变体是只读的,无需确认即可安全运行。在询问用户确认实际操作之前,使用它们进行预览。
如果用户提到查询速度慢,请使用 tl compact——它可以优化数据库。
tl import 会根据 CSV 表头自动检测列映射。大多数银行的 CSV 文件可以直接使用:
tl import bank_export.csv --account "Chase Checking"
--account / -a 标志接受账户名称(不区分大小写,支持子字符串匹配)或 UUID。
务必先使用 --dry-run 进行预览,以验证列检测是否正确:
tl import bank_export.csv -a "Checking" --dry-run --json
所有导入标志(除 --account 外均为可选):
| 标志 | 用途 | 示例 |
|---|---|---|
--date-column |
覆盖日期列 | --date-column "Post Date" |
--amount-column |
覆盖金额列 | --amount-column "Amt" |
--description-column |
覆盖描述列 | --description-column "Memo" |
--debit-column |
使用借方列(而非金额列) | --debit-column "Debit" |
--credit-column |
使用贷方列(而非金额列) | --credit-column "Credit" |
--balance-column |
运行余额(创建快照) | --balance-column "Balance" |
--flip-signs |
反转金额符号(信用卡 CSV) | --flip-signs |
--debit-negative |
将正数借方转为负数 | --debit-negative |
--skip-rows N |
在表头前跳过 N 行 | --skip-rows 3 |
--number-format |
us、eu 或 eu_space |
--number-format eu |
--profile NAME |
加载已保存的配置文件 | --profile chase |
--save-profile NAME |
将设置保存为配置文件 | --save-profile chase |
--dry-run |
预览而不导入 | --dry-run |
--json |
JSON 输出 | --json |
代理常用模式:
# 步骤 1:查找账户 UUID
tl status --json
# 步骤 2:预览导入
tl import transactions.csv -a "550e8400-e29b-41d4-a716-446655440000" --dry-run --json
# 步骤 3:执行导入
tl import transactions.csv -a "550e8400-e29b-41d4-a716-446655440000" --json
通过指纹识别,重复的交易记录在重新导入时会自动检测并跳过。
在运行任何写入命令之前,请检查此技能目录中是否存在 PERMISSIONS.md。
如果存在,请阅读它以了解用户预先批准了哪些写入命令。预先批准的命令无需每次询问确认即可运行。所有其他写入命令在执行前仍需用户明确确认。
如果 PERMISSIONS.md 不存在,在运行任何写入命令之前,务必先询问用户。
PERMISSIONS.md 模板:
# Treeline 代理权限
此处列出的命令已预先批准——代理无需每次询问确认即可运行它们。删除某行以要求确认。
## 允许的写入命令
- tl sync
- tl backup create
- tl demo on|off
在回答财务问题之前,请检查此技能目录中是否存在 CONTEXT.md。
如果存在,请先阅读它——它包含用户特定的知识:
- 账户含义(哪些是退休账户、哪些是经纪账户等)
- 标签约定和现金流规则
- 插件配置
- 个人偏好
学习新上下文: 当您发现有关用户设置的某些信息时:
1. 对于小的观察结果,将其记录在 CONTEXT.md 中,并简要说明您保存了什么
2. 对于重要的假设或更正,请询问:“您希望我将此保存到您的 Treeline 上下文中吗?”
有关模板,请参见末尾的用户上下文模式部分。
tl query "
WITH latest AS (
SELECT DISTINCT ON (account_id) account_id, balance
FROM sys_balance_snapshots
ORDER BY account_id, snapshot_time DESC
)
SELECT
SUM(CASE WHEN a.classification = 'asset' THEN s.balance ELSE 0 END) as assets,
SUM(CASE WHEN a.classification = 'liability' THEN ABS(s.balance) ELSE 0 END) as liabilities,
SUM(CASE WHEN a.classification = 'asset' THEN s.balance ELSE -ABS(s.balance) END) as net_worth
FROM accounts a
JOIN latest s ON a.account_id = s.account_id
" --json
tl query "
WITH latest AS (
SELECT DISTINCT ON (account_id) account_id, balance
FROM sys_balance_snapshots
ORDER BY account_id, snapshot_time DESC
)
SELECT a.name, a.classification, a.institution_name, s.balance
FROM accounts a
JOIN latest s ON a.account_id = s.account_id
ORDER BY s.balance DESC
" --json
检查 CONTEXT.md 中的 internal_transfer_tags。默认模式:
tl query "
SELECT SUM(ABS(amount)) as total_spent
FROM transactions
WHERE amount < 0
AND transaction_date >= date_trunc('month', current_date)
AND NOT (tags && ARRAY['transfer', 'savings', 'investment'])
" --json
tl query "
SELECT tags, SUM(ABS(amount)) as spent
FROM transactions
WHERE amount < 0
AND transaction_date >= '2026-01-01' AND transaction_date < '2026-02-01'
AND tags IS NOT NULL AND tags != '[]'
GROUP BY tags
ORDER BY spent DESC
" --json
tl query "
SELECT t.description, t.amount, t.transaction_date, a.name as account
FROM transactions t
JOIN accounts a ON t.account_id = a.account_id
ORDER BY t.transaction_date DESC
LIMIT 10
" --json
accounts
| 列 | 描述 |
|--------|-------------|
| account_id | UUID 主键 |
| name | 账户显示名称 |
| classification | asset 或 liability |
| account_type | credit、investment、Loan、other 或 null |
| institution_name | 银行/机构名称 |
| currency | 货币代码(例如 USD) |
| is_manual | 布尔值——手动添加 vs 同步 |
sys_balance_snapshots — 余额的真相来源
| 列 | 描述 |
|--------|-------------|
| snapshot_id | UUID 主键 |
| account_id | 外键,指向 accounts |
| balance | 快照时刻的余额 |
| snapshot_time | 记录时间 |
| source | sync、manual 等 |
transactions
| 列 | 描述 |
|--------|-------------|
| transaction_id | UUID 主键 |
| account_id | 外键,指向 accounts |
| amount | 带符号(负数 = 支出) |
| description | 交易描述 |
| transaction_date | 发生时间 |
| posted_date | 结算时间 |
| tags | 标签数组 |
标签 是 Treeline 中的主要概念——交易记录可以有多个标签。
类别 来自预算插件 (plugin_budget),它将标签映射到预算类别。并非所有用户都安装了此插件。
插件拥有自己的 DuckDB 模式:plugin_<name>.*
tl query "
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name LIKE 'plugin_%'
" --json
plugin_budget.categories — 预算类别
| 列 | 描述 |
|--------|-------------|
| category_id | UUID 主键 |
| month | YYYY-MM 格式 |
| type | income 或 expense |
| name | 类别名称 |
| expected | 预算金额 |
| tags | 用于匹配的标签数组 |
plugin_goals.goals — 储蓄目标
| 列 | 描述 |
|--------|-------------|
| id | UUID 主键 |
| name | 目标名称 |
| target_amount | 目标金额 |
| target_date | 目标日期 |
| completed | 布尔值 |
| active | 布尔值 |
plugin_subscriptions — 检测到的周期性扣款
plugin_cashflow — 现金流预测
plugin_emergency_fund — 应急基金跟踪
检查 CONTEXT.md 以了解用户安装了哪些插件以及关心哪些插件。
始终使用最新的快照:
WITH latest AS (
SELECT DISTINCT ON (account_id) account_id, balance
FROM sys_balance_snapshots
ORDER BY account_id, snapshot_time DESC
)
SELECT a.name, s.balance
FROM accounts a
JOIN latest s ON a.account_id = s.account_id
标签是数组:
-- 包含特定标签
WHERE tags @> ARRAY['groceries']
-- 包含这些标签中的任何一个
WHERE tags && ARRAY['food', 'dining']
-- 注意:在 DuckDB 中,UNNEST 并非在所有上下文中都有效
-- 相反,直接对 tags 进行 GROUP BY
-- 本月
WHERE transaction_date >= date_trunc('month', current_date)
-- 特定月份
WHERE transaction_date >= '2026-01-01'
AND transaction_date < '2026-02-01'
SELECT
c.name,
c.expected,
COALESCE(SUM(ABS(t.amount)), 0) as actual,
c.expected - COALESCE(SUM(ABS(t.amount)), 0) as remaining
FROM plugin_budget.categories c
LEFT JOIN transactions t ON t.tags && c.tags
AND t.amount < 0
AND t.transaction_date >= (c.month || '-01')::DATE
AND t.transaction_date < (c.month || '-01')::DATE + INTERVAL '1 month'
WHERE c.month = strftime(current_date, '%Y-%m')
AND c.type = 'expense'
GROUP BY c.category_id, c.name, c.expected
| 用户提问 | 处理方法 |
|---|---|
| “净资产?” | 净资产查询 |