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

p2p-cit

v0.2.0

Published

去中心化、无服务器的端到端加密终端聊天(命令名 cit)

Readme

cit

去中心化、无服务器的端到端加密终端聊天。

没有账号,没有服务器,没有中继。房间里的成员直接互联,聊天内容在传输层由 DTLS 强制加密,在应用层再由房间密钥加密一次。

$ cit new study-group --name alice
房间已创建 cit-9f3a2b1c
邀请码已复制到剪贴板,发给对方即可

$ cit join cit1.XK3... --name bob      # 扫二维码或粘贴邀请码
已接受 alice 的邀请码
把下面的应答码发回给对方,连接才会建立:

› /link citr1.QP9...                  # 在 alice 那个会话里输入

安装

npm install -g p2p-cit

安装后的命令名是 cit(cit --help)。npm 上的包名是 p2p-cit,因为 cit 已被其它项目占用。

这是一个早期版本(0.2.0)。请先读已知边界:首次握手可能需要 20-60 秒,且不做 TURN 中继。

安装发布包要求 Node 20 及以上。平台支持由 node-datachannel 的预编译二进制决定:Linux(glibc 与 musl,x64/arm64)、macOS(x64/arm64)、Windows(x64/arm64)和 Android arm64。其他平台会由原生依赖报错,不会自动退化成源码编译。本次发布验证在 Windows x64 上完成。

用法

全屏应用

在终端中直接运行 cit,进入全屏大厅,用方向键选择「创建房间」或「加入房间」,回车进入表单。Tab 切换房间名/邀请码、显示名和可选的 STUN 地址,Enter 提交,Esc 返回。

创建房间后把邀请码发给对方;对方加入后把应答码发回,邀请者在房间里按 F3 粘贴应答码。连接建立后直接输入消息回车发送。连接码也支持 @文件路径,粘贴内容需要按 Enter 才提交。

| 按键 | 作用 | | --- | --- | | F2 | 生成新的邀请码(替换未完成的邀请) | | F3 | 接受对方发回的应答码 | | F4 | 查看最近生成的连接码 | | C(连接码界面) | 重新复制连接码 | | Page Up / Page Down | 滚动聊天记录、帮助或长连接码 | | Esc | 返回;聊天界面中离开房间,需确认 | | Ctrl+C | 退出;房间内先提示未送达消息并确认 |

全屏模式支持下方的会话命令,展示在线成员、输入状态和待送达/已送达/已读回执。离开房间回到大厅,可创建或加入另一个房间,旧房间的聊天记录不会保留。最小终端尺寸为 40 列 × 18 行。

cit --name alice 可预填显示名,--stun、--passphrase、--ephemeral、--no-clipboard 继续生效。cit new / cit join 保留逐行界面;管道、--json 和 --help 不进入全屏。

开房间

cit new <房间名> [--name <显示名>] [--qr] [--json]

创建房间并打印邀请码。邀请码里已经包含房间口令,对方拿到就能加入,不需要事先另行约定。邀请码自动复制到剪贴板,--qr 会额外打印二维码供手机扫。

邀请码是一次性的:一张邀请码对应一条具体的 PeerConnection,每个加入者都要单独生成一次(在会话里用 /invite)。

加入房间

cit join <邀请码>      # 也支持 cit join @invite.txt 从文件读

会打印一个应答码,把它发回给对方,在对方的会话里执行:

/link <应答码>

两步交换是无信令服务器的固有代价:没有任何第三方帮你们牵线。

多人组网

第三个人加入时,只需要和任意一个已有成员交换一次邀请码。成员名单沿既有连接传播,节点通过这些连接转发新的握手请求和应答,为每对成员生成独立的连接信息,之后尝试补齐全连接。静态连接名片不能在不同 PeerConnection 之间复用,见 ADR-0007。

会话内命令

| 命令 | 作用 | | --- | --- | | /invite | 生成新的邀请码并复制到剪贴板 | | /link <应答码> | 接受应答码完成连接 | | /who | 列出在线成员 | | /pending | 查看未送达的消息 | | /id | 显示本机指纹 | | /block <指纹> | 本地拒绝该成员 | | /unblock <指纹> | 解除本地拒绝 | | /quit | 退出 |

发消息直接输入回车。@某人 或 @指纹 开头表示只发给该成员,其余是广播。

脚本化

--json 会把事件以 JSON 行输出到 stdout,stdin 不是终端时自动进入管道模式:

cit new room --json | jq -r 'select(.kind=="invite").code'

安全模型

请如实理解它提供什么、不提供什么:

  • 传输层:WebRTC DataChannel,DTLS 强制加密,无法降级成明文
  • 应用层:口令经 scrypt 派生房间密钥,消息用 ChaCha20-Poly1305 加密,header 作为 AAD 防篡改
  • 身份:每个节点有 Ed25519 密钥,签名覆盖 header 与密文
  • 防重放:每个发送方单调递增序号,回退或重复的帧直接丢弃
  • 防反射:消息密钥按收发方排序派生,无法把对方的密文原样退回给它自己

不提供前向保密。 口令泄露等于全部历史消息泄露,这是单一房间密钥模型的代价。任何文档或输出都不会暗示相反的保证。

邀请码等同口令。 邀请码只是 base64 编码,不是加密。它能进入房间、能以任意身份加入,拿到它就等于拿到口令。传递它的渠道安全性就是房间的安全性。

签名证明的是"这把密钥签的",不是"这个人是谁"。成员准入完全依赖口令保密。

已知边界

  • 不做 TURN 中继。两端都在对称型 NAT 后时无法直接打洞。这种情况会如实报错,不会假装成功或静默超时。同一局域网内正常可用;跨网场景建议开启 STUN:cit new room --stun stun.l.google.com:19302(默认关闭,不联系任何外部服务)
  • 待发消息只在内存。崩溃或强杀会丢失未确认的消息,这是有意为之:落盘意味着聊天明文留在磁盘上。退出前会提示还有多少条未送达
  • 同一进程内建两条连接不可靠。libdatachannel 在同进程多 ICE agent 下表现不稳定,正常使用是两个终端各跑一个 cit
  • 不做的:文件传输、消息持久化、同时加入多个房间、成员撤回(需要所有成员协同,无中心的 mesh 里无法诚实实现)

开发

源码开发要求 Node 22.18 及以上(直接运行 TypeScript),使用 pnpm 9.15.0。

pnpm install
pnpm build
pnpm test          # 单元测试 + 端到端测试
pnpm typecheck
pnpm cli          # 全屏应用(须在交互式终端中运行)

代码分两层:cit-core 是纯 TypeScript 的协议与加密,不依赖原生模块,可以单独测试;cit-cli 承载 WebRTC 传输与终端界面。

端到端测试会启动真实进程、走真实 WebRTC。在本机实测,握手可能需要 20-60 秒——Windows 防火墙会丢弃最初几个 ICE 连通性检查,libjuice 需要重传才能收敛。测试因此有较长的超时和建连重试,这不是掩盖问题,而是网络本身如此。

设计决策记录在 docs/adr/,领域词汇在 GLOSSARY.md。

发布

同步根目录和 packages/cit-cli/package.json 的版本,更新本 README 中的版本说明。仅发布 p2p-cit;@cit/core 由构建内联,不独立发布。

pnpm build
pnpm typecheck
pnpm test
pnpm --dir packages/cit-cli pack --pack-destination <产物目录>
npm publish <产物目录>/p2p-cit-<版本>.tgz --access public --tag latest

构建会从根 README 生成 npm 包的 README,勿手工编辑生成副本。发布前检查 tarball 的文件清单并从 tarball 安装验收;提交与版本 tag 推送后创建同名 GitHub Release。发布后核对 npm latest、tarball integrity 和 Release 指向的 commit。

许可

MIT