npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@npm_xiyuan/encrypted-notes-sync

v1.0.0

Published

End-to-end encrypted, bidirectional sync for local plaintext notes across your own Git repositories. Self-hosted, AES-256, multi-repo load balancing, crash-safe recovery.

Readme

加密笔记同步

English

npm license node

将本地明文笔记加密后同步到你自己的一组 Git 仓库的双向同步工具。自托管、无第三方服务器、AES-256 + Brotli 压缩、多仓库负载均衡、崩溃安全恢复。

本地明文笔记  <->  ens sync  <->  加密清单 + 加密 Git 对象

特性

  • 端到端加密 - AES-256(AEAD V2 GCM,兼容旧版 ECB)+ Brotli 压缩。明文从不离开你的机器。
  • 多仓库分发 - 一主 + N 从;新文件按当前仓库体积负载均衡分配。
  • 双向合并 - 文本走三方行级合并,图片按时间戳取新,无法自动合并时写入冲突标记。
  • 自托管 - 运行在你自己的 Git 仓库上(Gitee、GitHub、GitLab,任意 Git 托管)。无账号、无云锁定。
  • 崩溃安全恢复 - 发布日志、原子写入、预提交恢复,中断后保持清单与文件一致。
  • 删除安全 - 高风险删除在任何写入前暂停,等待显式确认。
  • 双语 CLI - 面向人的输出支持 zh-CN/en--json 输出稳定、与语言无关。

安装

要求:Node.js 20+、Git、自有仓库访问权限。

全局安装(推荐):

npm install -g @npm_xiyuan/encrypted-notes-sync

免安装运行

npx @npm_xiyuan/encrypted-notes-sync sync

从源码(开发):

git clone https://gitee.com/xiyuan/distributed_notes.git
cd distributed_notes
npm install

全局命令为 ens(也可用 encrypted-notes-sync)。下文使用 npm run <脚本>;全局安装后 ens <命令> 与之等价,见 ens help

快速开始

  1. 在项目根目录创建 config.json5。可从模板复制:

    cp config.example.json5 config.json5

    最小可用配置:

    {
      "notesDir": "./notes",
      "secret": "替换为长随机密钥",
      "gitRepos": {
        "master": {
          "url": "https://your-git-host.example.invalid/you/notes-manifest.git",
          "branch": "main"
        }
      }
    }

    设置一个长随机 secret 并安全备份——丢失后无法解密。CLI 不会强制它非空或达到最低强度。完整字段见配置

  2. 运行同步:

    npm run sync

    sync 会先确认所有配置的远程仓库已存在,然后准备缺失的本地 clone、目录、分支和 manifest.json,并拉取加密笔记。它绝不会创建远程仓库。

  3. 如果远程仓库还不存在,先运行 setup:

    npm run setup

    setup 可以创建远程仓库、clone、初始化分支和存储目录。运行前请检查配置。

就这样。用任意编辑器在 notesDir 下编辑笔记,然后 npm run sync 同步。

全局安装后,ens <命令> 等价于 npm run <命令>(例如 ens sync)。完整映射见 ens help

使用方式

日常同步

npm run sync

输出显示简洁的阶段进度(预检查、扫描、远程更新、计划)与结果摘要(推送、拉取、合并、无变更)。除非有冲突需要处理,否则不显示笔记路径。终端输出语言随 language 配置(默认中文),--json 输出始终为语言无关的结构化文档。

恢复新设备

npm install
npm run sync

当所有远程仓库已存在时,sync 会自动准备缺失的本地状态并拉取所有加密笔记。除非远程仓库不存在,否则不需要 setup

确认高风险删除

当删除计划触发以下任一阈值时,sync 会在任何写入之前停止:

  • notesDir 为空但 manifest 仍有条目
  • 将删除 ≥ 10 个文件
  • 删除量 ≥ manifest 条目的 20%
  • 将删除全部条目

交互终端——输入提示显示的精确值:

DELETE <数量>

非交互 / JSON 模式——使用标志重跑:

npm run sync -- --confirm-delete
npm run sync -- --json --confirm-delete

该标志仅确认已展示的删除计划,不会绕过任何其他安全检查。确认前务必检查 notesDir 和实际文件。

自动化与帮助

npm run sync -- --help
npm run sync -- --json

帮助无副作用。JSON 同步成功时向 stdout 写入一个结构化结果,失败时向 stderr 写入一个结构化失败结果。

何时使用 setup

npm run setup

仅当你需要创建远程仓库、初始化远程分支或修复配置时使用。对于已有部署和远程已存在的新设备,直接用 sync

工作方式

三个由工具管理的部分:

| 部分 | 位置 | 是否加密 | | --- | --- | --- | | 明文笔记 | notesDir | 否 | | 本地清单(manifest.json) | 项目根目录 | 否(本地状态) | | 远程清单(manifest.config) | 主仓库 | 是 | | 加密笔记对象 | 主仓库 + 内容仓库 | 是 |

数据流:本地明文笔记 <-> sync <-> 加密清单 + 加密 Git 对象

  1. sync 扫描 notesDir,与本地 manifest.json 比较。
  2. 解密远程 manifest.config,比较远程状态。
  3. 选择:无变更、推送、拉取、合并或恢复。
  4. 新内容按仓库体积分配;manifest 记录其位置。
  5. 内容仓库先于主仓库发布。本地清单最后写入。

不要手动创建、编辑、重命名或删除 manifest.jsonmanifest.config

{
  "schemaVersion": 2,
  "generation": 3,
  "parentDigest": "0000000000000000000000000000000000000000000000000000000000000000",
  "files": {
    "projects/example.md": {
      "filePath": "projects/example.md",
      "fileGitPath": "projects/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
      "gitId": "git.example.invalid/example/notes-content@main",
      "size": "128",
      "md5": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
      "contentHash": {
        "algorithm": "sha256",
        "value": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
      }
    }
  }
}

配置

真实配置只放在仅运行时克隆中,不要放在开发工作树里。不要提交真实的密钥、令牌或私有仓库地址。优先使用 SSH,让 token 字段保持为空。

{
  language: "zh-CN",
  notesDir: "./notes",
  defaultBranch: "main",
  defaultNoteRoot: "./encrypted-notes",
  defaultToken: "",
  secret: "replace-with-a-long-random-secret",
  saveBuffer: true,

  crypto: {
    writeFormat: "aead-v2",
    maxPlaintextBytes: 1073741824,
  },

  gitRepos: {
    master: {
      url: "https://git.example.invalid/example/notes-manifest.git",
      branch: "main",
      token: "",
      noteRoot: "./encrypted-notes",
      description: "Encrypted manifest and note content",
      isPrivate: true,
    },
    subList: [
      {
        url: "https://git.example.invalid/example/notes-content.git",
        branch: "main",
        token: "",
        noteRoot: "./encrypted-notes",
        description: "Additional encrypted note content",
        isPrivate: true,
      },
    ],
  },
}

| 字段 | 默认值 | 用途 | | --- | --- | --- | | language | zh-CN | 控制所有 CLI 命令面向人的终端输出语言。仅接受 zh-CNen;省略时默认值为 zh-CN--json 不受语言设置影响,保持稳定的机器可读 schema 和字符串。 | | notesDir | notes | 本地明文笔记目录(相对于项目根目录)。 | | defaultBranch | master | 仓库未指定 branch 时使用的分支。 | | defaultNoteRoot | notes | 仓库未指定 noteRoot 时使用的加密存储根目录。 | | defaultToken | null | 仓库未指定 token 时使用的 HTTPS 令牌。优先用 SSH。 | | secret | 空 | 加密密钥。设为长随机值并安全备份。CLI 不强制强度;空或弱不安全。 | | saveBuffer | true | true:二进制封装。false:文本表示。 | | crypto.writeFormat | aead-v2 | 新写入格式。保持 aead-v2 以使用认证加密。 | | crypto.maxPlaintextBytes | 1073741824 | 笔记加密/解密/迁移的最大明文大小。清单解密有单独固定的 64 MiB 限制,不使用此设置。 | | crypto.migrationConcurrency | 2 | 规范化到 1–4。迁移目前是串行的,无运行时效果。 | | gitRepos.master | 必填 | 主仓库:存储加密 manifest.config,可选存储笔记对象。 | | gitRepos.subList | [] | 可选的额外加密笔记对象仓库。 |

仓库条目字段(master 和每个 subList 项):

| 字段 | 用途 | | --- | --- | | url | 必填。Git SSH 或 HTTPS URL。用 branch 字段,不要在 URL 中编码分支。 | | branch | 可选,覆盖 defaultBranch。 | | token | 可选,覆盖 defaultToken。使用 SSH 时通常不需要。 | | noteRoot | 可选,覆盖 defaultNoteRoot。 | | description | 托管平台创建仓库时使用的描述。 | | isPrivate | 创建时请求私有可见性。请使用私有仓库。 | | instanceUrl | 支持的自托管实例端点。 |

故障排除

文本冲突

当文本合并无法自动解决时,sync 仍会发布带 Git 冲突标记的结果。退出码为 0(发布已成功),但结果需要你处理。

JSON 结果:

{
  "ok": true,
  "mode": "merge",
  "requiresAttention": true,
  "conflicts": ["projects/example.md"]
}

在继续编辑或同步前,解决每个列出文件中的标记:

并发修改文本的不同区域会自动合并;只有修改同一位置时才保留冲突标记。

<<<<<<< <local-device> 本地内容 ======= 远程内容 >>>>>>> <remote-device>

移除所有 <<<<<<<=======>>>>>>> 标记。<local-device><remote-device> 是设备名称占位符。两台设备同时编辑可能产生冲突——不会像协作文档那样自动合并。

恢复与错误

发布中断时,保留日志、锁和仓库状态。运行 npm run sync 进行验证和继续,不要手动回滚。

| 错误或状态 | 安全操作 | | --- | --- | | sync 时 SETUP_REQUIRED | 远程或本地状态无法安全准备。检查配置;当远程已存在时 sync 会自动准备本地状态。仅在需要创建远程或修复时运行 npm run setup。 | | DELETE_CONFIRMATION_REQUIRED | sync 在高风险删除阈值处停止。检查 notesDir 和文件。用 DELETE <数量>npm run sync -- --confirm-delete 确认。 | | PENDING_PUBLICATION | 运行 npm run sync 进行验证的向前恢复。若仍停止,保留日志。 | | CRYPTO_MIGRATION_PENDING | 运行 npm run crypto:migrate:status,再运行 npm run crypto:migrate 继续。 | | SYNC_LOCKEDACTIVE_LOCK | 确认没有其他同步在运行,运行 npm run doctor,然后重试。不要手动删除锁。 | | 仓库领先或分叉 | 用 git fetchgit status --short --branchgit log --oneline --left-right HEAD...@{upstream} 检查。不要 reset 或 force-push。 | | 清单 generation 冲突 | 停止并运行 npm run doctor。保留两边历史和清单以供诊断。 | | 解密 / AEAD 认证失败 | 确认正确的 secret、完整的密文、兼容的版本。不要用猜测替换。 | | 认证 / fetch / push 失败 | 检查 URL、分支、权限、令牌或 SSH。日志中脱敏密钥。 |

安全性

新写入默认使用 AEAD V2:AES-256-GCM、scrypt 派生密钥、每个封装随机 salt 和 nonce。仅在 Brotli 压缩能减小时才压缩。AEAD V2 提供保密性和认证性——解密失败必须视为不安全数据。

AES-256-ECB 仍可读取旧版密文,也可通过 crypto.writeFormat: "legacy-ecb-v1" 显式写入。旧版写入未认证,不建议使用。

本工具不是密钥管理器、实时协作系统或语义冲突解决器。不要因为笔记对象已加密就存入凭据或恢复密钥。

  • 使用私有仓库。 加密是纵深防御,不意味着可以公开仓库元数据。
  • 保留备份:明文笔记、secret 和仓库数据。丢失密钥后加密数据不可恢复。
  • 不要提交令牌、密钥、带凭据的 URL 或笔记内容到 Git、日志或 issue。
  • Git 历史保留旧的加密对象。今天删除文件不会移除历史密文。密钥轮换或历史清除是独立项目。
  • 在首台设备发布 AEAD V2 清单前升级所有设备。V2 发布后不要降级。
  • 不要并发同步。 工具有本地锁和远程检查,但设备排序是你的责任。

命令与副作用

日常

| 命令 | 说明 | | --- | --- | | npm run sync | 同步。确认远程已存在,准备缺失的本地状态,然后拉取/合并/加密/推送。绝不创建远程。 | | npm run sync:prepare | setup + sync。有 setup 的副作用。兼容命令。 |

同步选项

| 命令 | 说明 | | --- | --- | | npm run sync -- --help | 输出用法。无副作用。 | | npm run sync -- --json | 成功时 stdout 输出一个 JSON,失败时 stderr 输出一个 JSON。 | | npm run sync:prepare -- --help | 输出用法。无副作用。 | | npm run sync:prepare -- --json | setup + sync,结构化 JSON 输出。 | | npm run sync -- --confirm-delete | 在非交互模式中确认已审核的风险删除计划。 | | npm run sync -- --json --confirm-delete | JSON + 删除确认。 |

准备与诊断

| 命令 | 说明 | | --- | --- | | npm run setup | 创建远程、clone、初始化分支和存储。仅用于创建远程或修复。 | | npm run doctor | 只读人类可读诊断。 | | npm run doctor:json | 同样的检查,以 JSON 输出。 |

迁移

| 命令 | 说明 | | --- | --- | | npm run crypto:migrate | 将符合条件的旧版密文重写为 AEAD V2 并发布。 | | npm run crypto:migrate:status | 读取迁移状态,不重写。 |

笔记治理

| 命令 | 说明 | | --- | --- | | npm run notes:audit | 清点源笔记树。只读。 | | npm run notes:plan | 生成迁移规划报告。只读。 |

开发

| 命令 | 说明 | | --- | --- | | npm test | 运行 Node.js 测试套件。不是同步健康检查。 | | npm run lint | 对 bin/script/test/ 运行 ESLint。 | | npm run lint:fix | 自动修复安全的 ESLint 问题。 |

进阶文档

贡献

Node.js ESM CLI。提交变更前安装依赖并运行测试:

npm install
npm test

保持 setup、sync-first 同步、诊断、迁移和笔记治理之间的边界。行为变更应包含测试。不要在报告中包含真实凭据或私有笔记。

许可证

源代码采用 GNU General Public License v2.0GPL-2.0-only)许可证。