🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

账本助手 ding112/MoneyPal

DeepSeek Harness
ding1126 天前有提交已提供中文文档扫描:含敏感能力

让你的 AI 助手真正会记账。

33.6/100
综合分
5
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/28 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查未通过:缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add ding112/MoneyPal
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · other
装得上吗
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 6 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装

缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包moneypal-workspace(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=22.18 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✗入口文件缺少入口声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/28 15:42:54

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 52 处,展示前 47 条)
  • 读取本地文件
    src/finance/engine.ts:39
    async function assertMainLedger(workspace: string): Promise<void> { try { await access(join(workspace, "default", "main.beancount")); } catch { throw
  • 执行外部命令来自配置/变量
    src/finance/engine.ts:48
    const child = spawn(options.pythonExecutable, ["-I", "-X", "utf8", bridge], { shell: false, stdio: ["pipe", "pipe", "pipe"] });
  • 写入本地文件
    src/finance/runtime.ts:45
    await mkdir(locks.use, { recursive: true, mode: 0o700 });
  • 删除本地文件
    src/finance/runtime.ts:52
    await rm(path, { force: true }).catch(() => undefined);
  • 删除本地文件
    src/finance/runtime.ts:57
    release: async () => { await lease.close().catch(() => undefined); await rm(path, { force: true }).catch(() => undefined); },
  • 读取本地文件
    src/finance/runtime.ts:85
    try { await access(executable, constants.X_OK); } catch {
  • 写入本地文件
    src/finance/runtime.ts:108
    await mkdir(dirname(directory), { recursive: true, mode: 0o700 });
  • 读取本地文件
    src/finance/runtime.ts:113
    try { await stat(executable); } catch {
  • 写入本地文件
    src/finance/runtime.ts:183
    if (mutate) await mkdir(recovery, { recursive: true, mode: 0o700 });
  • 读取本地文件
    src/finance/runtime.ts:185
    try { claims = await readdir(recovery); } catch (error) {
  • 删除本地文件
    src/finance/runtime.ts:190
    if (state.kind === "stale") { if (mutate) await rm(join(recovery, claim), { force: true }); }
  • 写入本地文件
    src/finance/runtime.ts:197
    try { await rename(path, claim); } catch (error) {
  • 删除本地文件
    src/finance/runtime.ts:202
    if (claimed.kind === "stale") await rm(claim, { force: true });
  • 删除本地文件
    src/finance/runtime.ts:213
    await rm(path, { force: true }).catch(() => undefined);
  • 写入本地文件
    src/finance/runtime.ts:232
    await mkdir(recovery, { recursive: true, mode: 0o700 });
  • 写入本地文件
    src/finance/runtime.ts:234
    try { await rename(path, claim); } catch (error) {
  • 删除本地文件
    src/finance/runtime.ts:238
    if ((await lockState(claim)).token === lock.token) await rm(claim, { force: true });
  • 读取本地文件
    src/finance/runtime.ts:243
    const value = JSON.parse(await readFile(path, "utf8")) as { ownerPid?: unknown; token?: unknown };
  • 读取本地文件
    src/finance/runtime.ts:253
    try { names = await readdir(directory); } catch (error) {
  • 读取本地文件
    src/finance/runtime.ts:260
    const value = JSON.parse(await readFile(path, "utf8")) as { ownerPid?: unknown; childPid?: unknown };
  • 执行外部命令来自配置/变量
    src/finance/runtime.ts:273
    function run(executable: string, args: string[], input?: string, lease?: ManagedRuntimeLease, env?: NodeJS.ProcessEnv): Promise<string> { return new P
  • 读取本地文件
    src/finance/write.ts:87
    ledgerRoot: await realpath(ledgerDirectory),
  • 读取本地文件
    src/finance/write.ts:116
    try { currentRoot = await realpath(ledgerDirectory); } catch { throw new FinanceError("preview_stale", "预览后账本目录状态已变化;请重新生成预览并再次确认。"); }
  • 读取本地文件
    src/finance/write.ts:142
    const mode = batch.createsFile ? 0o600 : (await stat(targetPath)).mode;
  • 删除本地文件
    src/finance/write.ts:150
    await rm(replacement, { force: true });
  • 写入本地文件
    src/finance/write.ts:155
    await rename(replacement, targetPath);
  • 删除本地文件
    src/finance/write.ts:163
    await rm(lockPath, { force: true });
  • 删除本地文件
    src/finance/write.ts:173
    if (replacement !== undefined) await rm(replacement, { force: true }).catch(() => undefined);
  • 删除本地文件
    src/finance/write.ts:180
    if (replacement !== undefined) await rm(replacement, { force: true }).catch(() => undefined);
  • 删除本地文件
    src/finance/write.ts:185
    if (!keepLock) await rm(lockPath, { force: true }).catch(() => undefined);
  • 读取本地文件
    src/finance/write.ts:249
    const root = await realpath(resolve(ledgerDirectory));
  • 读取本地文件
    src/finance/write.ts:253
    const resolved = await realpath(absolute);
  • 读取本地文件
    src/finance/write.ts:259
    hash: createHash("sha256").update(await readFile(resolved)).digest("hex"),
  • 发起网络请求
    src/host.ts:12
    connection: { fetch: { register(route: { path: string; methods: string[]; requestBody: "buffered"; fetch(request: Request): Promise<Response> }): () =
  • 发起网络请求
    src/host.ts:30
    async fetch(request) {
  • 读取本地文件
    src/host.ts:85
    async function exists(path: string): Promise<boolean> { try { await access(path); return true; } catch { return false; } }
  • 写入本地文件
    src/init-ledger.ts:49
    await mkdir(ledgerWorkspace, { recursive: true, mode: 0o700 });
  • 写入本地文件
    src/init-ledger.ts:52
    await mkdir(ledgerDirectory, { mode: 0o700 });
  • 写入本地文件
    src/init-ledger.ts:66
    await mkdir(transactions, { mode: 0o700 });
  • 写入本地文件
    src/init-ledger.ts:68
    await writeFile(accounts, accountsBeancount(year), { encoding: "utf8", flag: "wx", mode: 0o600 });
  • 写入本地文件
    src/init-ledger.ts:70
    await writeFile(transactionFile, "", { encoding: "utf8", flag: "wx", mode: 0o600 });
  • 写入本地文件
    src/init-ledger.ts:73
    await writeFile(main, MAIN_BEANCOUNT, { encoding: "utf8", flag: "wx", mode: 0o600 });
  • 读取本地文件
    src/init-ledger.ts:101
    await access(join(ledgerWorkspace, "default"));
  • 删除本地文件
    src/init-ledger.ts:111
    if (path === join(ledgerDirectory, "transactions")) await rmdir(path).catch(() => undefined);
  • 删除本地文件
    src/init-ledger.ts:112
    else await rm(path, { force: true }).catch(() => undefined);
  • 删除本地文件
    src/init-ledger.ts:114
    await rmdir(ledgerDirectory).catch(() => undefined);
  • 读取本地文件
    src/main.ts:40
    const manifest = JSON.parse(await readFile(profilePackage, "utf8")) as {
扫描于 2026/11/2(1 天前) · 范围 全包扫描 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 个人记账
  • 结构化账本

面向 DSH 的个人记账插件,基于结构化的beancount账本工具

README

由 DeepSeek 最新模型翻译生成
MoneyPal 让你的 AI 助手真正会记账。 把从支付宝、微信或银行导出的账单文件交给 AI 整理,核对预览,确认后记入账本。再用自然语言查流水、看收支和账户余额,减少逐笔录入。 账本以标准文本保存在自己的电脑上,可以自行备份和迁移,底层基于 Beancount。 使用演示 MoneyPal 使用演示:整理账单、预览确认与查询结果 ▶ 点击封面观看 MoneyPal 使用演示 MoneyPal 能帮你做什么 - 减少逐笔录入:让 AI 整理导出的账单,把精力放在核对结果上。 - 写入前可以核对:查看交易明细和疑似重复提醒,需要调整时先修改预览,确认后再入账。 - 便于长期保存:标准文本账本可自行备份和迁移,方便持续维护个人财务记录。 你可以这样使用 | 你想做什么 | 可以这样说 | | 导入账单 | “整理这份账单,先展示预览,等我确认后再写入。” | | 查询支出 | “列出 2026 年 8 月的餐饮支出。” | | 查询资产负债 | “查看截至 2026-08-31 的资产负债表。” | | 记录一笔交易 | “记一笔 2026-09-07 的午餐 35 元,现金支付,先给我确认。
展开完整文档(README 剩余 1 节)
MoneyPal

让你的 AI 助手真正会记账。

把从支付宝、微信或银行导出的账单文件交给 AI 整理,核对预览,确认后记入账本。再用自然语言查流水、看收支和账户余额,减少逐笔录入。

账本以标准文本保存在自己的电脑上,可以自行备份和迁移,底层基于 Beancount。

使用演示

MoneyPal 使用演示:整理账单、预览确认与查询结果

▶ 点击封面观看 MoneyPal 使用演示

MoneyPal 能帮你做什么

- 减少逐笔录入:让 AI 整理导出的账单,把精力放在核对结果上。
- 写入前可以核对:查看交易明细和疑似重复提醒,需要调整时先修改预览,确认后再入账。
- 便于长期保存:标准文本账本可自行备份和迁移,方便持续维护个人财务记录。

你可以这样使用

| 你想做什么 | 可以这样说 |
| 导入账单 | “整理这份账单,先展示预览,等我确认后再写入。” |
| 查询支出 | “列出 2026 年 8 月的餐饮支出。” |
| 查询资产负债 | “查看截至 2026-08-31 的资产负债表。” |
| 记录一笔交易 | “记一笔 2026-09-07 的午餐 35 元,现金支付,先给我确认。” |

选择你的使用方式

| 我正在使用 | 下一步 |
| DeepSeek Harness Web | 在 DSH 中开始使用 |
| WorkBuddy | 查看 MoneyPal Skill 安装指南 |
| Qoder / QoderWork | 按当前宿主查看接入指南 |
| 其他本地 MCP Agent | 查看 MCP 配置指南 |

本仓库是 MoneyPal 产品主页,并维护 DSH Web 插件;MoneyPal Skill 仓库分发通用技能目录,供支持 Skill 的 Agent 应用使用。

在 DSH 中开始使用

以下步骤适用于已有 DSH Web(0.2.1-rc.2 或更新版本)的用户。环境要求和手动排查见使用指南。

1. 安装插件

dsh plugin --profile web add dsh-moneypal

2. 打开 MoneyPal 会话

选择准备保存账本的文件夹作为工作区,在新会话中选择 MoneyPal 预设。如宿主提示需要重启,按提示操作。

3. 让助手完成首次准备

把下面这句话发给助手:

帮我开始使用 MoneyPal:检查并按需准备运行环境,使用当前工作区的账本;如果还没有账本,先展示初始化内容,等我确认后创建。最后检查账本并查询一次余额。

DSH 可以代你执行环境检查与准备,并通过原生确认框创建新账本;已有符合布局的账本可直接复用。完成首次余额查询后,就可以导入账单或用自然语言记账。

导入第一份账单

完成对应入口的安装与账本准备后:

1. 提供导出文件:将账单交给助手,或告知助手可读取的文件位置。
2. 核对预览:检查日期、账户、金额、收支汇总、写入文件和疑似重复提醒;需要调整时先修改。
3. 确认入账并查询结果:确认后由助手写入,再查询流水复核实际结果。

可以直接发送:

请导入这份账单,先整理交易并展示记账预览,提示可能重复的记录,等我确认后再写入。

DSH 和 Skill 的确认方式及完整操作步骤见账单导入指南。

账本与隐私

账本文件保存在本地,但账单内容、查询结果和交易信息可能进入宿主配置的模型上下文。本地保存不代表所有处理都在离线环境中完成,使用前请了解所选宿主和模型的数据处理方式。

常见问题

需要先准备什么?

需要对应的 Agent 应用和可用的 MoneyPal 运行环境。DSH 用户查看环境要求;其他宿主从使用方式进入对应指南。

已有 Beancount 账本可以使用吗?

已有符合 MoneyPal 布局的账本可以复用。先让助手检查账本布局,不要直接覆盖或重新初始化已有账本。

支持哪些账单文件?

可以将从支付宝、微信或银行导出的账单文件交给助手。具体能否读取和整理取决于文件格式、内容及宿主能力,不代表支持所有银行或格式。先让助手检查文件能否读取,再核对整理结果;MoneyPal 不会自动连接银行账户同步账单。

正式写入前如何确认?

先核对预览,再确认写入。DSH 使用原生确认框,Skill 在对话中请求确认。疑似重复记录会提示,不会自动删除;详细确认流程和结果不确定时的处理见使用指南。

开始体验与更多资料

用自己的真实账单开始体验

选择你正在使用的 AI 助手,完成首次准备,再导入一份账单。

- 使用指南:安装、操作、账本布局、排障与升级卸载。
- 开发说明:源码安装、构建、测试与发布。

致谢

感谢 Linux.do 社区对本项目的推广与宝贵反馈。
预览分享卡片长什么样 ↓ding112/MoneyPal
分享 · DeepSeek Harness Hub
ding112/MoneyPal

让你的 AI 助手真正会记账。

这是你的仓库?认领条目

回到顶部