关于 Vnsh
Vnsh 是面向 AI Agent 与协作者的可移植工作区,通过一个加密链接共享同一份可读写文档。内容在浏览器中加密后上传,服务端无法读取明文,超过 24 小时未编辑会被删除。
主要功能
- 01单一稳定链接,支持读写与只读两种权限
- 02客户端端到端加密,密钥位于 URL 片段中
- 03版本号机制防止多个 Agent 相互覆盖
- 04支持历史版本查看与恢复
- 05提供 MCP 服务、命令行与浏览器入口
适用场景
- 01在 Claude Code、Cursor 等 Agent 之间交接上下文
- 02将构建产物或失败测试日志通过链接分享给他人
- 03在 CI 任务中生成可查看的结果链接
MCP 相关
vnsh-mcp 是 MCP 服务,向客户端暴露工作区与一次性内容的创建、读取、更新、历史和恢复等工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
14收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| url | string | 是 | 包含 #k=/iv= 的旧版 /v/ URL,或公开的 /p/{id} URL |
详细介绍
vnsh
一个供所有 AI Agent 读写的工作区
网站 • 开始使用 • 三种链接 • 工作原理 • API • 自托管
现在,你需要把相同的上下文分别粘贴到 Claude Code、Cursor 和 Slack 中。
vnsh 为这些上下文提供一个统一地址。只需放入一次,就能获得一个链接;每个 Agent 和收到链接的人都可以打开同一份持续更新的文档并修改它。文档会在上传前由浏览器加密,因此 vnsh 无法查看;最后一次编辑后 24 小时,文档就会被删除。
kubectl logs pod/app | vn
# https://vnsh.dev/w/k2p9xf...#w=... edit link — read and write
# https://vnsh.dev/w/k2p9xf...#r=... view-only — read, never write
为什么不用粘贴板
粘贴板提供的是快照。工作区有一个固定地址和版本,因此下一个 Agent 可以在同一位置写回内容,而不是另起一个。以下两项特性让分享更安全:
- 服务器无法读取内容。 内容在客户端加密,密钥放在 URL 片段中,不会通过 HTTP 传输。服务器存储的是密文和写入令牌的 SHA-256 哈希,而不是令牌本身。文件名也使用相同的密钥加密,因此接收者下载的是
analysis.py,而 vnsh 保存的只是无法解码的字符串。这一点可以从外部验证:伪造令牌会得到 403 响应。 - 两个 Agent 无法悄无声息地覆盖彼此的内容。 写入操作必须基于读取时的版本。系统会直接拒绝无条件写入;过期版本的写入则会收到 412 响应,提示重新读取并合并。我们在生产环境中用 5 个并发写入者进行了测试:1 个成功,另外 4 个收到提示,没有内容丢失。
开始使用
面向 Agent——这正是它的用途
将以下内容粘贴到 Claude Code、Cursor、OpenHands、Cline、Windsurf、Zed,或任何支持 MCP 的工具中:
Set up vnsh workspaces — one link to hand work between people and agents: https://vnsh.dev/llms.txt
它会读取协议、安装 MCP 服务,并在自己的指令文件中写入一条长期规则,以便之后继续使用工作区。也可以手动操作:
claude mcp add vnsh -- npx -y [email protected]
该服务提供 vnsh_artifact_create、vnsh_artifact_list、
vnsh_artifact_read、vnsh_artifact_update、vnsh_workspace_create、vnsh_workspace_read、
vnsh_workspace_update、vnsh_workspace_history、vnsh_workspace_restore、
vnsh_workspace_renew 和 vnsh_workspace_open,另外还提供
vnsh_share、vnsh_share_file 和 vnsh_read,用于一次性内容。
从终端
npx vnsh # or: npm i -g vnsh
# or: curl -sL vnsh.dev/i | sh (one-shot links only)
vn ./report.html # create a workspace from a file
git diff | vn # or from stdin
vn read "<any vnsh url>" # read one back — workspace, public, or legacy blob
vn write "<edit url>" ./new # replace the contents; refuses to clobber
vn history "<workspace url>" # list the latest 20 retained versions
vn restore "<edit url>" 3 # restore v3 as a new latest version
vn init . # teach agents in this project to use vnsh
vn init 会在项目的 Agent 指令文件中添加一个幂等的托管区段。它适用于不同的 Agent 供应商;当该 CLI 之后创建工作区时,只会记录匿名的“项目已初始化”维度,因此可以衡量实验效果,而不会收集项目名称或路径。
--public 会以未加密的形式发布(见下文)。--blob 会明确创建一次性链接。--ttl 也适用于工作区,最长为 168 小时;后续写入会保留该有效期,而 vn renew 无需编辑即可延长有效期。
依赖零额外组件的 shell 函数 curl -sL vnsh.dev/i | sh 仅处理一次性链接。工作区需要 HKDF-SHA256 和 AES-256-GCM,而 macOS 自带的 openssl 是 LibreSSL,不支持这两者——如果有 Node,它会将 /w/ 链接交给 npx vnsh 处理;如果没有,也会明确说明。
从浏览器
https://vnsh.dev — 拖入文件或粘贴内容,即可获取这两种链接。加密之前不会上传任何内容。
从 CI
upload-to-vnsh 会上传构建输出或失败的测试日志,并在作业摘要中打印链接。
从 Chrome
扩展 会在 GitHub、Slack 和 Discord 上内联预览 vnsh 链接,并可通过 ⌘D 将截图、控制台错误和页面 URL 打包成一个链接。
三种链接
| 链接 | 携带内容 | 谁能读取 | 谁能写入 |
|---|---|---|---|
vnsh.dev/w/{id}#w=<secret> | 根密钥 | 任何拥有链接的人 | 任何拥有链接的人 |
vnsh.dev/w/{id}#r=<key> | 内容密钥 | 任何拥有链接的人 | 无人 |
vnshcontent.dev/p/{id} | 无 | 任何人 | 只有作者的 #w= 链接 |
只读级别并不是服务器强制执行的一项设置,而是由数学决定的。内容密钥是 HKDF(secret, "vnsh/enc/v2"),这是单向派生,因此持有者可以解密每个版本,却无法还原密钥,也就无法派生写入令牌。
公共工作区之所以存在,是因为打开链接的人有浏览器代为解密,而 Agent 的 fetch 做不到。公共工作区会按原样存储,并作为普通文档提供,因此任何支持 HTTP 的程序无需密钥或配置即可读取。选择时会明确说明代价:**vnsh 可以读取公共工作区。**它绝不会是默认选项,也不会被自动推断;其可见性在创建时固定,更改仍需写入令牌。
公共工作区由 vnshcontent.dev 提供服务,这是一个独立的可注册域名,这并非表面功夫。公共文档由陌生人写入,并作为顶层页面呈现,而安全信誉系统——Safe Browsing、邮件网关、企业代理——列出的是域名,而不是路径。如果 vnsh.dev 上出现一个滥用页面,就会连 API、网站以及所有已安装的 CLI、MCP 服务和扩展一并拖垮。子域名也无济于事;关键单位是可注册域名。沙箱是另一回事,而且已得到处理:公共文档通过带有 sandbox CSP 指令的方式提供,因此会加载到一个不透明来源中,不含 Cookie、存储、网络,也无法访问任何其他页面。/w/ 链接仍留在 vnsh.dev,因为片段中的密钥是真正的门槛——服务器从未见过这些链接的明文,爬虫也同样看不到。
不要自行拼接公共 URL。创建公共链接时,响应的 url 字段会返回准确链接,这也能确保可自托管的单域名实例正常工作。
工作原理
you ──encrypt──▶ [ vnsh: ciphertext, no key ] ──decrypt──▶ agent / person
│
deleted 24h after the last write
密钥安排
S = random(32) root secret, lives only in the fragment
K = HKDF-SHA256(S, "vnsh/enc/v2") content key — AES-256-GCM
W = HKDF-SHA256(S, "vnsh/write/v2") write token, sent as 64 hex chars
H = SHA-256(W) the only derived value the server stores
工作区使用 AES-256-GCM,而非一次性数据块使用的 AES-256-CBC,因为可变内容需要完整性保护:没有认证标签,任何能够重写存储内容的人(包括主机)都能在不被察觉的情况下翻转密文位,从而彻底破坏整个安全保证。每次写入都会使用随机随机数,并将其置于内容前面,绝不会根据版本号推导。
查看器会在带有 sandbox="allow-scripts" 的框架中渲染 HTML 和 Markdown,并特意不设置 allow-same-origin,因此内容会在不透明来源中运行,无法从 location.hash 读取密钥;注入的 default-src 'none' 会移除其网络访问权限。
整个协议(包括创建流程)都在 /llms.txt 中进行了规范,因此你可以使用任何语言和加密库来实现,而且完全不必运行任何 vnsh 代码。有人已经用大约 200 行代码实现了它。
API
| 端点 | 用途 |
|---|---|
POST /api/workspace | 创建。需要 X-Vnsh-Write-Hash;设置 X-Vnsh-Public: 1 以发布。公开时返回 url。 |
GET /api/workspace/:id | 读取密文。ETag 是版本号。 |
PUT /api/workspace/:id | 替换。需要 X-Vnsh-Write 和 If-Match。 |
GET /w/:id | 查看器。在客户端解密并以沙盒方式渲染。 |
GET /p/:id | 位于 vnshcontent.dev 上的公开工作区,以纯文档形式呈现。 |
POST /api/drop | 一次性数据块(v1)。使用 ?ttl= 和 ?price=。 |
GET /api/blob/:id | 读取一次性数据块。 |
GET /llms.txt | 为 Agent 编写的协议说明。 |
写入请求若缺少 If-Match,会返回 428;版本过期时返回 412;写入令牌无效时返回 403。完整参考见 docs/api.md。
安全模型
账户和永久制品
匿名分享无需账户,且仅为临时分享。使用魔法链接登录
https://account.vnsh.dev,即可保留新建的工作区和 /artifact/ 页面,直到你将其删除。浏览器创建内容时会自动使用已登录的会话。对于 CLI,请运行 vn login,并在浏览器中批准设备。MCP 和 CI 可以通过 VNSH_TOKEN 使用账户令牌;对于能力链接工作区,内容仍在本地加密,账户数据库只存储所有权元数据,不存储密钥或明文。
在免费预览期间,每个账户最多可保留 100 份文档,总计 1 GB,其中包含保留的版本。
请保留返回的链接:其片段是解密/编辑密钥的唯一副本,因此账户可以管理保留和删除,但无法恢复丢失的密钥。
第 1 阶段的账户制品新增了一种独立的协作模式:经过身份验证的用户和 Agent 令牌可以发现私有制品内容并为其创建版本,无需携带片段密钥。这种便利性有不同的安全边界——vnsh 在技术上可以读取账户制品内容。此模式绝不会被悄然替换为匿名加密工作区,且默认情况下只有用户可以批准或发布。
vn login
vn artifact create report.md --title "Release report" --type report
vn artifact list --query release --status draft
vn artifact read <artifact-id>
vn artifact update <artifact-id> report.md --base-version 1 --change-summary "Verified production"
如果其他程序或 Agent 将使用结果,可在任何制品命令后添加 --json。
安全保障。 vnsh 无法读取加密内容、无法写入其中,也无法从其存储的任何内容中恢复写入令牌。渲染后的内容无法访问同源内容,也无法访问网络,因此恶意文档既无法获取密钥,也无法向任何地方发送内容。
不提供的保障。
- 把链接交给别人,就等于把密钥也交给了他们,包括该 Agent 的模型提供商。限制密钥有效期的是 24 小时时限,而非加密机制;每次写入都会重新计时,因此每天编辑的工作区会一直存在。
- 边界在客户端,而不在传输过程中。 执行加密的任何一方都会先接触到你的明文,MCP 服务和 CLI 也不例外。
npx -y每次启动都会重新获取最新发布版本;请固定版本([email protected])、一次性全局安装,或者在审查运行内容后从源代码构建。 - 按照设计,vnsh 可以读取公开工作区。 这就是该服务层级的特性。
- 元数据并非私密。 任何托管服务都会产生时间、大小和地址信息。只有内容不包含在内。
自托管
Cloudflare Workers 加一个 R2 存储桶。无需数据库,也无需 KV。
git clone https://github.com/raullenchai/vnsh.git
cd vnsh/worker && npm install
wrangler r2 bucket create vnsh-store
wrangler deploy
wrangler.toml 绑定了 R2、两个原生速率限制器和一个 Analytics Engine 数据集。早期版本使用 KV 命名空间存储元数据和计数器;免费层级的写入上限曾导致整个网站宕机,因此已将其移除,而且现在不再需要 KV——如果你参考的旧指南要求创建 KV 命名空间,则无需照做。请参阅 docs/self-hosting.md。
仓库
| 路径 | 内容 |
|---|---|
worker/ | Cloudflare Worker:API、查看器、主页、llms.txt |
mcp/ | vnsh-mcp——Agent 使用的 MCP 服务 |
cli/npm/ | vnsh——vn 命令 |
cli/ | install.sh 和无依赖的 shell 函数 |
extension/ | Chrome 扩展 |
docs/ | 架构、API、CLI、MCP、运维、自托管文档 |
docs/plans/ | 设计文档,包括 v2 工作区计划 |
npm test # every package
cd worker && npm run dev # local worker
四个软件包各自包含一份密钥计划副本,因为它们是独立发布的。每个软件包都固定使用相同的测试向量:如果一个软件包生成的链接无法在另一个软件包中打开,系统会将其视为损坏,而不是版本不一致,因此这种故障会悄无声息地发生。如果你更改派生过程,这些测试可以防止此类问题悄然出现。
贡献
欢迎提交问题和拉取请求,包括指出我们有误的内容 —
迄今最有价值的贡献,是有人根据
llms.txt 重新实现了该协议,并指出了文档中遗漏的所有内容。
请从 CONTRIBUTING.md 开始。文档介绍了这个代码库中两个容易让所有人踩坑的地方:工作器的客户端代码位于 模板字符串中,因此反斜杠必须加倍;而多余的反引号会在编译器报错位置往前一百行处结束 字符串。
发现安全问题?请不要公开提交问题 — SECURITY.md 中有私密报告表单,并列出了哪些内容属于声明范围,哪些内容被明确排除。
许可证
MIT — 详见 LICENSE。
vnsh.dev · 该协议 · 文档 · 为何采用这种构建方式
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。
