
【免费下载链接】plannotatorAnnotate and review coding agent plans and code diffs visually, share with your team, send feedback to agents with one click.项目地址https://gitcode.com/gh_mirrors/pl/plannotator点击查看免费下载本篇技术指南基于 Plannotator 仓库官方文档 self-hosting.md 展开覆盖自托管体系的三大组件——Hook、Share Portal 与 Paste Service——的职责划分、分享链路的数据流URL 片段与 AES-256-GCM 加密短链、完整的构建部署步骤Nginx / S3CloudFront / 静态托管平台以及环境变量配置。读完本文你将能够独立搭建一套私有化的 Plannotator 方案评审分享服务并理解短链密文存储、CORS 白名单、TTL 自动清理等底层实现。官方文档中的现状说明开源的异步链接分享open source asynchronous link sharing正移向 deprecated 支持Workspaces 是团队分享的主方向自托管 Portal 与 Paste Service 目前仍保留文档以维持兼容性且官方未公布移除日期。一、组件总览三个组件只有 Hook 是必需的Plannotator 的自托管体系由三个组件构成依赖关系如下表所示继承自官方文档组件是否必需职责Hook是本地二进制拦截ExitPlanMode拉起评审 UIShare Portal否静态站点负责在浏览器中渲染被分享的 plan打开分享链接时实际加载的就是它Paste Service否Share Portal 的存储后端当 plan 内容过大无法塞进 URL 时paste service 保存压缩数据portal 在页面加载时拉取三者关系是单向的Hook 在本地生成分享链接指向 Portal 域名或 paste 短链Paste Service 为 Portal 提供短链密文存储Portal 自身是纯静态 SPA、没有任何应用数据库。二、分享机制的数据流URL 片段 vs 加密短链理解自托管部署之前先弄清楚分享数据到底走哪条路径——这直接决定了你是否真的需要部署 Paste Service。小型 Markdown 分享URL 片段fragment-only小型 markdown 分享会把压缩后、未加密的内容放在 URL fragment#之后里。Portal 在浏览器端读取 fragment 并渲染而 fragment不会包含在发往 Portal 服务器的 HTTP 请求中。这意味着 Portal 主机收不到正文内容但任何持有完整 URL 的人或中转服务IM、邮件网关等都能读到明文内容——这是无后端方案的天然权衡。从源码看默认分享基址定义在 share-url.tsconst DEFAULT_SHARE_BASE https://share.plannotator.ai;当未设置PLANNOTATOR_SHARE_URL时分享链接指向该官方地址自托管后所有链接前缀都会换成你的域名见第五节。大型 Markdown 与 Raw HTMLAES-256-GCM 加密短链大型 markdown 与 raw HTML 无法走纯 hash 流程官方文档描述了完整的短链生成路径Markdown 用户在 Export 弹窗中确认创建短链本地 raw HTML可以通过页头分享动作或已配置的回调动作立即创建短链远程 raw HTML则在会话启动时自动创建。无论哪种入口流程都是浏览器先用AES-256-GCM加密 payload把密文ciphertext发给 paste service解密密钥内嵌在 URL fragment#key...中不会出现在发往 paste service 或 portal 的任何 HTTP 请求里。打开完整链接时portal 拉取密文并在浏览器端解密。同样地任何持有完整链接的人都可以完成相同操作。两种部署形态的取舍官方文档原文归纳不部署 paste service只要内容能塞进 URL 片段Markdown 分享依然可用。没有后端保存分享 payload但 Portal 主机仍会收到正常的请求元数据且任何用于传递完整链接的服务都能看到其内容Raw HTML 无法通过这条路径分享。部署 paste service大型 Markdown 与 raw HTML 分享获得短 URL服务保存客户端加密的密文直到配置的 TTL 过期自动删除。三、第 1 步安装 HookHook 是唯一必需的组件负责拦截ExitPlanMode事件并在本地拉起评审界面。其安装步骤请参见仓库安装文档与 Hook 组件 README原文档指向 marketing 站点的/docs/getting-started/installation/章节。Hook 服务端与自托管相关的核心接线在 apps/hook/server/index.ts// Custom share portal URL for self-hosting const shareBaseUrl process.env.PLANNOTATOR_SHARE_URL || undefined; // Paste service URL for short URL sharing const pasteApiUrl process.env.PLANNOTATOR_PASTE_URL || undefined;也就是说Hook 进程启动时读取这两个环境变量把它们透传给分享 URL 生成逻辑——这正是第五节“组件连线”的原理所在。四、第 2 步部署 Share Portal官方文档对 Portal 的关键定性它是一个没有应用数据库的静态单页应用。它在浏览器中加载 share hash 内容、为短链拉取密文并且每次应用加载都会执行 Plannotator 的 GitHub 版本检查目前没有可关闭该检查的设置——自托管时请为这一出站请求做好网络预期。构建产物捆绑了默认的 Inter 与 Geist Mono 字体以及经由 diff renderer 引入的语法高亮器 Shiki 与主题因此这些默认资源不依赖 Google Fonts 或任何 CDN但被渲染的文档本身如果引用了远程资源仍会发起相应请求。4.1 构建bun install bun run build:portal产物输出到apps/portal/dist/。该命令对应仓库根 package.json 中的脚本build:portal: bun run --cwd apps/portal build而 apps/portal/package.json 中build即vite build依赖plannotator/editor与plannotator/ui两个 workspace 包——因此在仓库根目录安装依赖是构建成功的前提。4.2 部署到静态托管将dist/上传到任意静态托管即可。官方文档给出三类典型配置NginxSPA 路由回退server { listen 80; server_name plannotator.internal.example.com; root /var/www/plannotator; try_files $uri /index.html; }AWS S3 CloudFrontaws s3 sync apps/portal/dist/ s3://your-bucket/ --delete并将 CloudFront 分发配置为对 404 返回/index.htmlSPA 路由需求。Vercel / Netlify / Cloudflare Pages指向仓库根目录即可Build commandbun run build:portalOutput directoryapps/portal/dist五、第 3 步部署 Paste ServicePaste Service 的职责在官方文档中一句话概括接收浏览器加密的分享 payload返回一个短 ID——进去的是密文出来的是包含浏览器持有解密密钥的链接paste 在配置的 TTL 后自动删除无需数据库。5.1 运行方式一平台二进制从项目 Releases 页面下载对应平台的 paste service 二进制。支持 macOSARM64、x64、Linuxx64、ARM64、Windowsx64chmod x plannotator-paste-* ./plannotator-paste-darwin-arm64 # 或匹配你平台的版本paste 默认存储于~/.plannotator/pastes/。5.2 运行方式二源码直接运行Paste service 完全开源就是本仓库内的 apps/paste-service。其 package.json 提供两种运行目标bun run dev # 等价于 bun run apps/paste-service/targets/bun.ts本地文件系统存储 bun run dev:cf # wrangler devCloudflare Workers KV 存储Cloudflare 目标的配置见 wrangler.toml需要PASTE_KV命名空间且自托管者必须覆盖ALLOWED_ORIGINS改文件或用wrangler secret put否则默认值指向官方share.plannotator.ai你的服务将对官方 Portal 开放 CORS[vars] ALLOWED_ORIGINS https://share.plannotator.ai,http://localhost:30015.3 配置项环境变量Bun 目标的环境变量解析在 targets/bun.ts与文档表格完全一致变量默认值说明PASTE_PORT19433服务端口PASTE_DATA_DIR~/.plannotator/pastes存储目录PASTE_TTL_DAYS7N 天后自动删除PASTE_MAX_SIZE5242880加密 payload 上限5 MB字节数PASTE_ALLOWED_ORIGINShttps://share.plannotator.ai,http://localhost:3001CORS 白名单逗号分隔对应的源码const port parseInt(process.env.PASTE_PORT || 19433, 10); const dataDir process.env.PASTE_DATA_DIR || join(homedir(), .plannotator, pastes); const ttlDays parseInt(process.env.PASTE_TTL_DAYS || 7, 10); const maxSize parseInt(process.env.PASTE_MAX_SIZE || String(DEFAULT_PASTE_MAX_SIZE), 10); const allowedOrigins getAllowedOrigins(process.env.PASTE_ALLOWED_ORIGINS);其中DEFAULT_PASTE_MAX_SIZE 5 * 1024 * 1024定义于 core/handler.ts。六、Paste Service 源码解析API 面、ID 生成与清理策略Paste service 的 HTTP 面非常小全部逻辑集中在 core/handler.ts 的handleRequestPOST /api/paste接收{ data: 密文 }JSON 体。缺字段返回 400超过maxSize返回 413错误文案带格式化后的字节上限如 “5 MB”成功返回201与 8 位短 IDGET /api/paste/:id命中返回{ data }响应头带Cache-Control: private, no-store防止 CDN/浏览器缓存密文未命中或已过期返回 404Paste not found or expired其他路径统一 404并提示合法路径POST /api/paste, GET /api/paste/:id。短 ID 生成值得展开handler.ts 用 Web Crypto 生成8 位 base62 ID约 47.6 bit 熵并采用拒绝采样避免取模偏差只接受小于 248 的字节248 是 62 的倍数中不超过 256 的最大值。47.6 bit 意味着暴力猜测的期望尝试量极大配合短 TTL撞 ID 不是现实威胁。存储层是可插拔接口定义在 core/storage.tsexport interface PasteStore { put(id: string, data: string, ttlSeconds: number): Promisevoid; get(id: string): Promisestring | null; }两个实现FsPasteStorestores/fs.ts每个 paste 落盘为id.json内容形如{ data, expiresAt }。清理策略是“启动时清扫 读取时惰性删除”——构造时sweep()删除已过期文件get时若expiresAt已过则当场unlink并返回 null。safePath还做了路径逃逸防护拒绝解析后跳出 dataDir 的 ID。KvPasteStorestores/kv.tsCloudflare KV供 Workers 目标使用。CORS 策略在 core/cors.ts未显式配置时白名单为https://share.plannotator.ai与http://localhost:3001即官方部署的默认值localhost任意端口的 Origin 始终放行以方便本地开发。注意corsHeaders对非白名单 Origin不返回任何 CORS 头——浏览器端跨域请求会被直接拦截而不是返回 403排查“portal 拉不到密文”问题时这是第一个该检查的点。七、第 4 步连接组件在 Hook 运行环境中导出两个环境变量self-hosting.md 第 4 节原文命令export PLANNOTATOR_SHARE_URLhttps://your-portal.example.com export PLANNOTATOR_PASTE_URLhttps://your-paste.example.com二者分别覆盖 Portal 基址与 paste API 基址默认分别为官方https://share.plannotator.ai与禁用短链。Portal 侧也感知 paste 地址当 raw HTML 走短链路径而PLANNOTATOR_PASTE_URL未配置时share-url.ts 会给出明确提示 HTML sharing uses the paste service; check PLANNOTATOR_PASTE_URL or try a smaller/self-contained HTML file.另外别忘了 paste service 自身的PASTE_ALLOWED_ORIGINS必须包含你 Portal 的实际 Origin否则浏览器 CORS 检查会拦截密文拉取见第六节。八、第 5 步验证官方文档给出的端到端验证清单在 Claude Code 或 OpenCode 中发起一次 plan 评审添加标注点击Export → Share确认分享 URL 以你配置的域名开头若 plan 较大按提示点击Create short link打开短链——plan 应正确渲染。补充两个排查点其一Portal 每次加载都会做 GitHub 版本检查内网环境若屏蔽了该出站请求确认其失败不阻断渲染其二短链 404 时先查 TTL默认 7 天是否已过再查 CORS 白名单。九、部署形态小结需求最低组件集本地单人使用内容较小的 Markdown 分享Hook 自托管 Portal大体积 Markdown / Raw HTML 分享短链Hook Portal Paste ServiceBun 或 CF Workers整套体系的工程特征可以概括为Portal 零数据库、纯静态Paste Service 无数据库、密文直存、短 TTL 自动清理密钥始终只存在于 URL fragment 与浏览器内存中服务端全程只接触密文。这与 apps/portal/SELF-HOSTING.md 中对 Portal 的补充说明一致后者额外提醒raw HTML 的页头 Copy Share Link 动作或回调可立即创建加密短链远程 raw HTML 会话在启动时自动创建这些路径不走 Markdown 的 “Create short link” 确认弹窗。赞分享【免费下载链接】plannotatorAnnotate and review coding agent plans and code diffs visually, share with your team, send feedback to agents with one click.项目地址https://gitcode.com/gh_mirrors/pl/plannotator点击查看免费下载相关推荐RustDesk Server 自托管部署完全指南从 Docker 到 Debian 的实战配置与原理剖析RustDesk Server 自托管部署完全指南从 Docker 到 Debian 的实战配置与原理剖析 本指南以 README DE.md https:/后端网络通信从0到1部署highlight.io自托管与云原生运维实战指南从0到1部署highlight.io自托管与云原生运维实战指南 引言 你是否在为开源监控平台的部署流程复杂而困扰是否需要同时支持小规模自用和企业级弹性扩展可观测性后端Maybe Docker自托管部署实战指南Maybe Docker自托管部署实战指南 本文详细介绍了Maybe个人财务管理系统的Docker自托管部署全流程涵盖Docker Compose环境配置、安后端前端金融科技上一篇10个CSS美化技巧让你的Obsidian笔记应用瞬间变专业下一篇如何永久保存微信聊天记录WeChatMsg完整数据备份终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考