WSL2 + pnpm 环境下部署 Paperclip:从 Node 版本到权限控制【免费下载链接】paperclipThe open-source app everyone uses to manage agents at work项目地址: https://gitcode.com/GitHub_Trending/papercl/paperclipPaperclip 把自己定位为"每个人用来管理工作智能体的开源应用",但把它跑起来这件事本身,就足以让不少 Windows 用户卡上一整晚:仓库根目录写着engines.node: >=24.11.0、packageManager: pnpm@9.15.4,而你在 WSL2 里敲node -v得到的却很可能是一个旧版本,或者压根不是 systemd 正在用的那个 Node。本文基于 Paperclip 源码(package.json、pnpm-workspace.yaml、live-events-ws.ts 等)与社区实测反馈,把 WSL2 部署中最容易踩的三个坑讲透:Node 版本策略、pnpm 依赖管理与 WebSocket 状态同步、以及沙箱与本地文件访问的权限边界。一、Node.js 24 是硬门槛:版本策略与 WSL2 环境基线社区文章(如 CSDN 上多篇 Paperclip 实战帖)反复强调"Node.js LTS 环境配置 + WSL2 验证"是第一步,这不是套话——仓库里对 Node 版本的控制是系统性、强制性的。根目录 package.json 声明了双重约束:"engines": { "node": ">=24.11.0" }, "packageManager": "pnpm@9.15.4"同时.nvmrc固定为24,packages/shared/src/node-version.ts中写死MINIMUM_NODE_VERSION = "24.11.0"。这还不是全部:仓库里的 scripts/check-node-version-policy.mjs 会递归扫描所有package.json,强制每个子包的engines.node都必须是>=24.11.0、@types/node必须是^24.0.0,连 CI 工作流里的node-version: 24和所有Dockerfile的FROM node:24都在检查范围内。换句话说,任何一个子包悄悄降级 Node 版本,pnpm typecheck之前的策略检查就会直接失败。对本地开发而言,这意味着用nvm装一个 LTS 18/20 是走不通的。WSL2 下真正隐蔽的坑不在"装哪个版本",而在"哪个进程在用哪个版本"。官方文档 doc/INSTALLING.md 专门花了一整节讲这个问题:Check the Node executable used by the running service, not onlynode --versionin an interactive shell. Systemd and launchd do not load shell version-manager configuration.WSL2 上 Paperclip 默认注册为systemd user service,而 systemd 单元不加载 shell 的 nvm/nodenv 配置。你在终端里node -v是 24,后台服务实际跑的可能还是系统自带的旧版 Node。文档给出的排查方法是直接看进程:# 查看正在运行的 server 进程真实使用的 Node 可执行文件 readlink /proc/<server-pid>/exePaperclip 的托管安装(managed install)会在paperclipaishim 里固定一个校验过的 Node 可执行文件,并把它的目录前置到子进程PATH上(包括带/usr/bin/env nodeshebang 的 ACP 服务)。如果你换过 Node 运行时,必须用受支持的 Node重新执行npx paperclipai@latest install --yes再重启服务,旧 shim 会故意继续用之前固定的运行时。另外注意 WSL 版本差异:systemd只在 WSL2 且启用了用户级 systemd 时可用;容器、WSL1 和没有受支持服务管理器的系统,不会硬失败,而是引导用户以前台paperclipai run方式运行。部署时先确认systemctl --user是否可用,否则你会困惑于"为什么没有后台服务"。环境基线本身很轻量:docs/deploy/local-development.md 明确写了零外部依赖——嵌入式 PostgreSQL,不需要 Docker,不需要外部数据库:pnpm install pnpm dev # API server: http://localhost:3100 # UI: API server 同源托管二、pnpm 依赖管理:workspace、patchedDependencies 与 WebSocket 状态同步Paperclip 是一个多包 monorepo(server、ui、cli 以及packages/下大量子包),pnpm-workspace.yaml 定义了包范围:packages: - packages/* - packages/adapters/* - packages/plugins/* - "!packages/plugins/sandbox-providers/**" - "!packages/plugins/examples/plugin-orchestration-smoke-example" - server - ui - cli注意那两个排除项——sandbox-providers 插件和 orchestration smoke 示例被刻意排除在 workspace 之外,注释写得很直白:让它们作为独立包可安装,避免第三方依赖变动引发整个pnpm-lock.yaml的改动。这解释了为什么社区帖子里有人抱怨"某些插件装不进 workspace"——这不是 bug,是设计。pnpm 9 时代最大的坑在 patch 配置的读取位置。根 package.json 里有 13 条patchedDependencies,而 pnpm-workspace.yaml 里同样维护了一份,并注释:Keep in sync with package.json#pnpm.patchedDependencies. Newer pnpm versions read patch configuration only from the workspace manifest.新版本 pnpm 只从 workspace 清单读取 patch 配置——如果你在 WSL2 里用的 pnpm 版本偏新,改了根package.json的 patch 却没同步pnpm-workspace.yaml,patch 不会生效,pnpm install会静默装出未打补丁的依赖(例如postgres@3.4.9、embedded-postgres@18.1.0-beta.16的补丁直接影响数据库驱动行为)。这类"装好了但行为不对"的问题最难排查。overrides则是另一个容易忽视的雷区:仓库强制了react/react-dom ^19.2.8、rollup >=4.59.0,还专门注释解释了为什么必须把所有 CodeMirror 包压到单一解析版本——CodeMirror 用instanceof校验扩展,两副本会导致编辑器崩溃;Lezer 则要求所有 parser 共享同一份NodePropID,混装会把节点元数据误读为高亮标签。在 WSL2 上如果因为某种原因产生了多副本(比如手动往某个子包塞了独立依赖),UI 会出现莫名其妙的运行时错误。CLI 调用安全是 pnpm 场景下另一个必须知道的坑。官方 CLI 文档 doc/CLI.md 用了很大篇幅警告:npx paperclipai <command> <args>:安全,参数以惰性argv传递;pnpm paperclipai <command> <args>:不安全,pnpm 会把参数拼进/bin/sh命令串重新求值,反引号、$( )、$NAME都会在 CLI 启动前被 shell 解释,甚至可能把环境变量里的密钥展开进持久化参数;pnpm exec paperclipai:不可用,根 workspace 不依赖paperclipai包,会报Command "paperclipai" not found。在 WSL2 的 bash 里粘贴文档命令时,这个差异尤其致命——shell 会先于任何 CLI 处理$展开。从源码仓库运行时,安全形式是node cli/node_modules/tsx/dist/cli.mjs cli/src/index.ts <command> <args>。WebSocket 状态同步:实时事件通道的实现社区文章中反复出现的"WebSocket 状态同步",对应的是 server/src/realtime/live-events-ws.ts。它以WebSocketServer({ noServer: true })挂到现有 HTTP server 的upgrade事件上,路径形如/api/companies/:id/events/ws。三个工程细节值得注意:心跳保活:每 30 秒对全体客户端ping(),收不到pong的直接terminate()。WSL2 下 Windows 与 Linux 之间的网络栈差异可能导致长连接假死,这套心跳是兜底;背压保护:每个 socket 挂起事件数超过 1000 会close(1013, "event backlog"),防止慢客户端拖垮订阅队列;升级时鉴权 + 逐事件授权:连接升级阶段区分local_trusted(隐式 board 身份)、会话、以及 sha256 哈希后的 agent API key;此后每个事件投递前还会做一次实时授权决策(issue:read、project:read、heartbeat run 隐私检查),注释明确"Never cache successful privacy decisions"——权限被撤销时,已建立的连接也不会再收到敏感事件。部署在 WSL2 上时要注意:local_trusted模式(pnpm dev默认)只绑定 loopback,事件通道里"本机浏览器=board 身份"是隐式信任的;一旦用pnpm dev --bind lan或authenticated模式暴露到局域网,浏览器升级请求必须带有效会话或 API key,否则 403。三、权限控制:沙箱与本地文件访问边界Paperclip 的权限模型分两层:平台 API 层的授权边界,与执行运行时层的沙箱边界。社区里"OpenClaw 权限控制""沙箱安全运行"的说法,对应到源码就是 doc/LOW-TRUST-PRESETS.md。仓库内置两档信任预设:standard(默认)与low_trust_review(针对可能消费恶意/注入输入的自动化工作,如不信任的 PR、外部工单、依赖 diff)。低信任预设的解析遵循"收窄者胜":agent 权限、项目策略、issue/run 策略三处trustBoundary交叉取交集,解析不出"具体的公司内项目、根 issue 或 issue-id 范围"就fail closed。运行时层面的硬性要求(不满足直接拒绝执行):执行环境必须使用sandboxdriver;工作区模式必须是isolated_workspace;敏感环境变量(API key、token 等内联值)一律拒绝,secret 必须用边界显式允许的 binding id 引用;没有配置 workspace 时,沙箱为每个公司/任务使用私有目录,跨 turn 与 reassignment 持久,且"never imports the shared project directory or agent home"——低信任任务拿不到共享项目目录和 agent 主目录。这与安装文档中的表述互相印证:doc/INSTALLING.md指出本地文件系统/网络隔离("Local filesystem/network confinement")必须显式选择 CLI 引擎;Codex ACP workspace 会话默认开启网络,要显式设sandbox_workspace_write.network_access=false才能关掉。也就是说,"Agent 能不能读写本地文件、能不能联网"不是运行时临时决定,而是部署时由执行引擎与工作区策略预先钉死的。本地文件访问的最终边界落盘在数据目录上:docs/deploy/local-development.md 给出的布局是数据路径配置~/.paperclip/instances/default/config.json数据库~/.paperclip/instances/default/db存储~/.paperclip/instances/default/data/storage密钥~/.paperclip/instances/default/secrets/master.key代码与实例数据分离(managed install 下 CLI 在~/.paperclip/cli/,实例数据在~/.paperclip/instances/)。对 WSL2 用户这意味着两件事:其一,~/.paperclip是 Linux 侧路径,不要把它放到/mnt/c/...这类 drvfs 挂载点上——嵌入式 PostgreSQL 在这种跨文件系统路径上性能与锁行为都不理想,这也是社区部署经验里反复提到的教训;其二,涉及"沙箱隔离"的目录归属判断、备份与恢复,全部以 Linux 侧路径为准,Windows 侧的AppData之类概念在这里不适用。小结:三条部署自查清单把全文压缩成可执行的清单,WSL2 部署前逐一核对:Node:终端node -v是 24.x 只是必要条件,readlink /proc/<server-pid>/exe确认 systemd user service 实际在用的运行时;换过 Node 后必须用受支持的版本重新install并重启服务。pnpm:版本对齐packageManager(9.15.4);修改 patch 时同步package.json与pnpm-workspace.yaml两份清单;CLI 带参数一律走npx paperclipai,别用pnpm paperclipai传内容型参数。权限:确认部署模式(local_trusted/authenticated)与你暴露网络的范围匹配;低信任任务必须满足sandbox+isolated_workspace,否则 fail closed;~/.paperclip/instances保留在 Linux 文件系统内。Node 版本、依赖解析、权限边界——这三件事在 Windows 上被 WSL2 的路径与进程模型放大成了三倍的排查成本。而 Paperclip 的仓库本身已经把答案写进了策略脚本与文档里:它要的不是"能跑",而是"被验证过的运行时、可复现的依赖图、以及默认失败的权限边界"。【免费下载链接】paperclipThe open-source app everyone uses to manage agents at work项目地址: https://gitcode.com/GitHub_Trending/papercl/paperclip创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
WSL2 + pnpm 环境下部署 Paperclip:从 Node 版本到权限控制【免费下载链接】paperclipThe open-source app everyone uses to manage agents at work项目地址: https://gitcode.com/GitHub_Trending/papercl/paperclipPaperclip 把自己定位为"每个人用来管理工作智能体的开源应用",但把它跑起来这件事本身,就足以让不少 Windows 用户卡上一整晚:仓库根目录写着engines.node: >=24.11.0、packageManager: pnpm@9.15.4,而你在 WSL2 里敲node -v得到的却很可能是一个旧版本,或者压根不是 systemd 正在用的那个 Node。本文基于 Paperclip 源码(package.json、pnpm-workspace.yaml、live-events-ws.ts 等)与社区实测反馈,把 WSL2 部署中最容易踩的三个坑讲透:Node 版本策略、pnpm 依赖管理与 WebSocket 状态同步、以及沙箱与本地文件访问的权限边界。一、Node.js 24 是硬门槛:版本策略与 WSL2 环境基线社区文章(如 CSDN 上多篇 Paperclip 实战帖)反复强调"Node.js LTS 环境配置 + WSL2 验证"是第一步,这不是套话——仓库里对 Node 版本的控制是系统性、强制性的。根目录 package.json 声明了双重约束:"engines": { "node": ">=24.11.0" }, "packageManager": "pnpm@9.15.4"同时.nvmrc固定为24,packages/shared/src/node-version.ts中写死MINIMUM_NODE_VERSION = "24.11.0"。这还不是全部:仓库里的 scripts/check-node-version-policy.mjs 会递归扫描所有package.json,强制每个子包的engines.node都必须是>=24.11.0、@types/node必须是^24.0.0,连 CI 工作流里的node-version: 24和所有Dockerfile的FROM node:24都在检查范围内。换句话说,任何一个子包悄悄降级 Node 版本,pnpm typecheck之前的策略检查就会直接失败。对本地开发而言,这意味着用nvm装一个 LTS 18/20 是走不通的。WSL2 下真正隐蔽的坑不在"装哪个版本",而在"哪个进程在用哪个版本"。官方文档 doc/INSTALLING.md 专门花了一整节讲这个问题:Check the Node executable used by the running service, not onlynode --versionin an interactive shell. Systemd and launchd do not load shell version-manager configuration.WSL2 上 Paperclip 默认注册为systemd user service,而 systemd 单元不加载 shell 的 nvm/nodenv 配置。你在终端里node -v是 24,后台服务实际跑的可能还是系统自带的旧版 Node。文档给出的排查方法是直接看进程:# 查看正在运行的 server 进程真实使用的 Node 可执行文件 readlink /proc/<server-pid>/exePaperclip 的托管安装(managed install)会在paperclipaishim 里固定一个校验过的 Node 可执行文件,并把它的目录前置到子进程PATH上(包括带/usr/bin/env nodeshebang 的 ACP 服务)。如果你换过 Node 运行时,必须用受支持的 Node重新执行npx paperclipai@latest install --yes再重启服务,旧 shim 会故意继续用之前固定的运行时。另外注意 WSL 版本差异:systemd只在 WSL2 且启用了用户级 systemd 时可用;容器、WSL1 和没有受支持服务管理器的系统,不会硬失败,而是引导用户以前台paperclipai run方式运行。部署时先确认systemctl --user是否可用,否则你会困惑于"为什么没有后台服务"。环境基线本身很轻量:docs/deploy/local-development.md 明确写了零外部依赖——嵌入式 PostgreSQL,不需要 Docker,不需要外部数据库:pnpm install pnpm dev # API server: http://localhost:3100 # UI: API server 同源托管二、pnpm 依赖管理:workspace、patchedDependencies 与 WebSocket 状态同步Paperclip 是一个多包 monorepo(server、ui、cli 以及packages/下大量子包),pnpm-workspace.yaml 定义了包范围:packages: - packages/* - packages/adapters/* - packages/plugins/* - "!packages/plugins/sandbox-providers/**" - "!packages/plugins/examples/plugin-orchestration-smoke-example" - server - ui - cli注意那两个排除项——sandbox-providers 插件和 orchestration smoke 示例被刻意排除在 workspace 之外,注释写得很直白:让它们作为独立包可安装,避免第三方依赖变动引发整个pnpm-lock.yaml的改动。这解释了为什么社区帖子里有人抱怨"某些插件装不进 workspace"——这不是 bug,是设计。pnpm 9 时代最大的坑在 patch 配置的读取位置。根 package.json 里有 13 条patchedDependencies,而 pnpm-workspace.yaml 里同样维护了一份,并注释:Keep in sync with package.json#pnpm.patchedDependencies. Newer pnpm versions read patch configuration only from the workspace manifest.新版本 pnpm 只从 workspace 清单读取 patch 配置——如果你在 WSL2 里用的 pnpm 版本偏新,改了根package.json的 patch 却没同步pnpm-workspace.yaml,patch 不会生效,pnpm install会静默装出未打补丁的依赖(例如postgres@3.4.9、embedded-postgres@18.1.0-beta.16的补丁直接影响数据库驱动行为)。这类"装好了但行为不对"的问题最难排查。overrides则是另一个容易忽视的雷区:仓库强制了react/react-dom ^19.2.8、rollup >=4.59.0,还专门注释解释了为什么必须把所有 CodeMirror 包压到单一解析版本——CodeMirror 用instanceof校验扩展,两副本会导致编辑器崩溃;Lezer 则要求所有 parser 共享同一份NodePropID,混装会把节点元数据误读为高亮标签。在 WSL2 上如果因为某种原因产生了多副本(比如手动往某个子包塞了独立依赖),UI 会出现莫名其妙的运行时错误。CLI 调用安全是 pnpm 场景下另一个必须知道的坑。官方 CLI 文档 doc/CLI.md 用了很大篇幅警告:npx paperclipai <command> <args>:安全,参数以惰性argv传递;pnpm paperclipai <command> <args>:不安全,pnpm 会把参数拼进/bin/sh命令串重新求值,反引号、$( )、$NAME都会在 CLI 启动前被 shell 解释,甚至可能把环境变量里的密钥展开进持久化参数;pnpm exec paperclipai:不可用,根 workspace 不依赖paperclipai包,会报Command "paperclipai" not found。在 WSL2 的 bash 里粘贴文档命令时,这个差异尤其致命——shell 会先于任何 CLI 处理$展开。从源码仓库运行时,安全形式是node cli/node_modules/tsx/dist/cli.mjs cli/src/index.ts <command> <args>。WebSocket 状态同步:实时事件通道的实现社区文章中反复出现的"WebSocket 状态同步",对应的是 server/src/realtime/live-events-ws.ts。它以WebSocketServer({ noServer: true })挂到现有 HTTP server 的upgrade事件上,路径形如/api/companies/:id/events/ws。三个工程细节值得注意:心跳保活:每 30 秒对全体客户端ping(),收不到pong的直接terminate()。WSL2 下 Windows 与 Linux 之间的网络栈差异可能导致长连接假死,这套心跳是兜底;背压保护:每个 socket 挂起事件数超过 1000 会close(1013, "event backlog"),防止慢客户端拖垮订阅队列;升级时鉴权 + 逐事件授权:连接升级阶段区分local_trusted(隐式 board 身份)、会话、以及 sha256 哈希后的 agent API key;此后每个事件投递前还会做一次实时授权决策(issue:read、project:read、heartbeat run 隐私检查),注释明确"Never cache successful privacy decisions"——权限被撤销时,已建立的连接也不会再收到敏感事件。部署在 WSL2 上时要注意:local_trusted模式(pnpm dev默认)只绑定 loopback,事件通道里"本机浏览器=board 身份"是隐式信任的;一旦用pnpm dev --bind lan或authenticated模式暴露到局域网,浏览器升级请求必须带有效会话或 API key,否则 403。三、权限控制:沙箱与本地文件访问边界Paperclip 的权限模型分两层:平台 API 层的授权边界,与执行运行时层的沙箱边界。社区里"OpenClaw 权限控制""沙箱安全运行"的说法,对应到源码就是 doc/LOW-TRUST-PRESETS.md。仓库内置两档信任预设:standard(默认)与low_trust_review(针对可能消费恶意/注入输入的自动化工作,如不信任的 PR、外部工单、依赖 diff)。低信任预设的解析遵循"收窄者胜":agent 权限、项目策略、issue/run 策略三处trustBoundary交叉取交集,解析不出"具体的公司内项目、根 issue 或 issue-id 范围"就fail closed。运行时层面的硬性要求(不满足直接拒绝执行):执行环境必须使用sandboxdriver;工作区模式必须是isolated_workspace;敏感环境变量(API key、token 等内联值)一律拒绝,secret 必须用边界显式允许的 binding id 引用;没有配置 workspace 时,沙箱为每个公司/任务使用私有目录,跨 turn 与 reassignment 持久,且"never imports the shared project directory or agent home"——低信任任务拿不到共享项目目录和 agent 主目录。这与安装文档中的表述互相印证:doc/INSTALLING.md指出本地文件系统/网络隔离("Local filesystem/network confinement")必须显式选择 CLI 引擎;Codex ACP workspace 会话默认开启网络,要显式设sandbox_workspace_write.network_access=false才能关掉。也就是说,"Agent 能不能读写本地文件、能不能联网"不是运行时临时决定,而是部署时由执行引擎与工作区策略预先钉死的。本地文件访问的最终边界落盘在数据目录上:docs/deploy/local-development.md 给出的布局是数据路径配置~/.paperclip/instances/default/config.json数据库~/.paperclip/instances/default/db存储~/.paperclip/instances/default/data/storage密钥~/.paperclip/instances/default/secrets/master.key代码与实例数据分离(managed install 下 CLI 在~/.paperclip/cli/,实例数据在~/.paperclip/instances/)。对 WSL2 用户这意味着两件事:其一,~/.paperclip是 Linux 侧路径,不要把它放到/mnt/c/...这类 drvfs 挂载点上——嵌入式 PostgreSQL 在这种跨文件系统路径上性能与锁行为都不理想,这也是社区部署经验里反复提到的教训;其二,涉及"沙箱隔离"的目录归属判断、备份与恢复,全部以 Linux 侧路径为准,Windows 侧的AppData之类概念在这里不适用。小结:三条部署自查清单把全文压缩成可执行的清单,WSL2 部署前逐一核对:Node:终端node -v是 24.x 只是必要条件,readlink /proc/<server-pid>/exe确认 systemd user service 实际在用的运行时;换过 Node 后必须用受支持的版本重新install并重启服务。pnpm:版本对齐packageManager(9.15.4);修改 patch 时同步package.json与pnpm-workspace.yaml两份清单;CLI 带参数一律走npx paperclipai,别用pnpm paperclipai传内容型参数。权限:确认部署模式(local_trusted/authenticated)与你暴露网络的范围匹配;低信任任务必须满足sandbox+isolated_workspace,否则 fail closed;~/.paperclip/instances保留在 Linux 文件系统内。Node 版本、依赖解析、权限边界——这三件事在 Windows 上被 WSL2 的路径与进程模型放大成了三倍的排查成本。而 Paperclip 的仓库本身已经把答案写进了策略脚本与文档里:它要的不是"能跑",而是"被验证过的运行时、可复现的依赖图、以及默认失败的权限边界"。【免费下载链接】paperclipThe open-source app everyone uses to manage agents at work项目地址: https://gitcode.com/GitHub_Trending/papercl/paperclip创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考