内容
# 便携式LLM维基
**将您的个人上下文输送到任何LLM的开放协议。**
您的git仓库中的Markdown文件,通过HTTP和原生MCP暴露,这样
Cursor、Claude、ChatGPT、Gemini或本地模型都可以读取
**相同的您**,而无需重新注册。
<p align="center">
<a href="https://portablellm.wiki">
<img src="./docs/hero.png" alt="便携式LLM维基。 将您的上下文输送到任何LLM的开放协议。实时演示通过SSE流式传输带有Markdown引用的真实答案。" width="900">
</a>
<br>
<em>托管演示实时回答。试试 <a href="https://portablellm.wiki">portablellm.wiki</a></em>
</p>
<p align="left">
<a href="https://render.com/deploy?repo=https://github.com/professorpalmer/portable-llm-wiki">
<img src="https://render.com/images/deploy-to-render-button.svg" alt="部署到Render" height="40">
</a>
<a href="https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fprofessorpalmer%2Fportable-llm-wiki&project-name=portable-llm-wiki-frontend&repository-name=portable-llm-wiki-frontend&root-directory=frontend&env=NEXT_PUBLIC_BACKEND_URL&envDescription=URL%20of%20your%20Render-deployed%20backend%20(no%20trailing%20slash)&envLink=https%3A%2F%2Fgithub.com%2Fprofessorpalmer%2Fportable-llm-wiki%2Fblob%2Fmain%2Fscripts%2Fdeploy.md">
<img src="https://vercel.com/button" alt="部署到Vercel" height="40">
</a>
</p>
> **协议**:实现了 [llm-wiki spec v1](./SPEC.md)。任何支持该规范的LLM都可以与任何符合规范的维基对话。
> 思维模型:汽车座椅记忆按钮。当你坐进一辆新车时
你不需要重新解释你的身高。你按下按钮,座椅
就会调整。同样的想法适用于LLM会话:与其在每个新的聊天中重新解释
自己,不如接入你的维基,LLM就会调整。
## 它是什么
- **与厂商无关。** 您的上下文存储在您拥有的git文件夹中,而不是存储在厂商的RAG数据库中。明天从Cursor切换到Claude或ChatGPT,每個助手都能看到相同的页面。
- **三种协议,一个真实来源。** HTTP(`/.well-known/llm-wiki.json`)适用于任何客户端,**MCP** 适用于Cursor / Claude Desktop,浏览器中的聊天UI。所有这些都由相同的Markdown文件支持。
- **自我维护。** 可选的`puppetmaster`集成运行Karpathy摄入管道。粘贴Slack线程或上传PDF,维基会为您草拟实体,概念和交叉引用,并使用语义检查群组来检测矛盾和缺失的页面。
**在 [portablellm.wiki](https://portablellm.wiki) 上线**:一个托管的
多租户部署,与同一个仓库相同。 使用GitHub登录,您的
维基在不到一分钟的时间内就上线了,网址为 `portablellm.wiki/<您的GitHub登录>`。 或者浏览 [`/avery`](https://portablellm.wiki/avery) — Avery
Chen,一家合成生物初创公司的虚构创始工程师 —
看看在注册之前,填充的维基是什么样子。
## 三种使用方式
### 1. 托管 — 注册(零部署,~30秒)
前往 [portablellm.wiki](https://portablellm.wiki) 并点击 **使用GitHub登录**。托管后端为您的GitHub登录提供了一个租户,
创建(或连接)您的GitHub账户上的内容仓库,
并引导您完成一个2步的欢迎向导:
1. 连接您的维基仓库(我们建议使用一个名为
`my-portable-llm-wiki` 的新私有仓库;向导提供为您创建它的选项)。
2. 种子 - 粘贴个人简介,抓取投资组合网址,或跳过并开始
空白。
**您的内容存储在您的GitHub上。**托管后端将每个编辑
都推送回您的仓库,以防您想离开,
您的维基已经是一个您拥有并可以自行托管的Markdown语料库。
参见 [LEAVING.md](LEAVING.md) 获取移交路径。
这是在30秒内无需思考Render或Docker即可粘贴到ChatGPT / Claude / Cursor的个人LLM上下文的正确路径。
### 2. 您自己的云部署(~60秒)
点击上面的 **部署到Render** + **部署到Vercel** 按钮。Render从`render.yaml`配置后端;Vercel从`frontend/vercel.json`部署前端。Render自动生成您的
`OWNER_TOKEN` 并提示您输入 `WIKI_GIT_REMOTE` (您自己的私有
内容仓库)。
这是您想要拥有自己的基础设施(自定义
域名,审计日志,您卡上的账单)而无需管理服务器时的正确路径。
您获得与portablellm.wiki上运行的相同的OSS代码,
在单租户模式下(`SINGLE_TENANT_MODE=1`)。
→ 逐步指南参见 [scripts/deploy.md](scripts/deploy.md)。
### 3. 本地/自主托管(Docker或`init.sh`)
对于完全自主托管(您的笔记本电脑,Mac Mini,5美元的VPS),仓库
提供一个可用的`docker-compose.yml`,它启动后端和前端:
```bash
git clone https://github.com/professorpalmer/portable-llm-wiki
cd portable-llm-wiki
export OWNER_TOKEN="$(openssl rand -hex 32)"
docker compose up --build
# → http://localhost:3000
```
默认情况下,compose堆栈挂载捆绑的`wiki-demo/`,这样您可以在
用您自己的Markdown文件夹替换它之前查看它的工作原理。
对于开发工作(热重载,无Docker),请改用`init.sh`路径:
```bash
git clone https://github.com/professorpalmer/portable-llm-wiki
cd portable-llm-wiki
./scripts/init.sh # 生成OWNER_TOKEN,提示wiki位置
./scripts/dev-backend.sh # 终端1
(cd frontend && npm run dev) # 终端2
```
或搭建一个全新的内容仓库:
```bash
npx create-portable-llm-wiki my-wiki
cd my-wiki # → 推送到私有GitHub仓库,然后点击部署到Render
```
用于后端仅或自定义编排:
```bash
docker run --rm -p 8000:8000 \
-v /path/to/my-wiki:/app/wiki \
-e OWNER_TOKEN="$(openssl rand -hex 32)" \
-e DEFAULT_TIER=private \
$(docker build -q -f backend/Dockerfile .)
```
→ 完整的compose演练参见 [scripts/deploy.md → 自主托管](scripts/deploy.md#3-self-host-docker).
## 从任何LLM连接
一旦您的后端启动在例如 `https://<您的>.onrender.com`,请将
任何客户端指向它。
**Cursor / Claude Desktop / 任意MCP客户端** (软件包在npm上为
[`portable-llm-wiki-mcp`](https://www.npmjs.com/package/portable-llm-wiki-mcp)):
```json
{
"mcpServers": {
"portable-llm-wiki": {
"command": "npx",
"args": ["-y", "portable-llm-wiki-mcp"],
"env": {
"WIKI_API_BASE": "https://<您的后端>.onrender.com",
"WIKI_OWNER_TOKEN": "<粘贴来自Render的OWNER_TOKEN>"
}
}
}
}
```
前端的 `/connect` 页面渲染此配置,并预填充您的网址,
以便您可以直接复制粘贴到 `~/.cursor/mcp.json`。
**ChatGPT自定义GPT / OpenWebUI / 任意HTTP客户端:**
```
GET https://<您的后端>.onrender.com/.well-known/llm-wiki.json
```
那个众所周知的文档描述了每个端点(页面,搜索,
查询,流式聊天,清单),因此新鲜的LLM可以在无需
任何厂商特定胶水的情况下检查维基。
## 复刻检查清单(部署到Render后)
当Render Blueprint部署完成后,您的点击后运行流程是:
1. **阅读您的`OWNER_TOKEN`.** Render自动生成了一个。 在您的服务 → **环境** → 显示`OWNER_TOKEN`下找到它。 您将在前端的 `/owner` 页面上粘贴此内容。
2. **为您的维基内容创建私有GitHub仓库** (例如
`https://github.com/<您>/my-wiki`)。 最简单的路径:运行
`npx create-portable-llm-wiki my-wiki`,然后推送到该仓库。
3. **在 <https://github.com/settings/tokens?type=beta> 生成GitHub PAT**。 *仓库访问:*
仅限my-wiki;*权限:内容→ 读取和写入*。
4. **在Render仪表板中设置 `WIKI_GIT_REMOTE` ** 至
`https://USER:PAT@github.com/<您>/my-wiki.git`。 Render重新部署;
在下一次启动时,容器克隆您的内容仓库,每个写入都推送回去。 如果没有此设置,写入是短暂的,并在下一次冷启动时被清除。
5. **(可选)设置 `ANTHROPIC_API_KEY` 或 `OPENAI_API_KEY` ** 在相同的环境变量面板中,将 `/wiki/query` 从关键词后备升级为LLM支持的答案。
6. **点击部署到Vercel** ,设置 `NEXT_PUBLIC_BACKEND_URL` 为您的Render URL。 然后返回Render并收紧 `CORS_ORIGINS` +
`PUBLIC_BASE_URL` 至您的Vercel URL。
详细演练参见 [scripts/deploy.md](scripts/deploy.md)。
## 盒子里有什么
- **后端**:FastAPI服务,读取Markdown,暴露一个
厂商中立的HTTP API,强制执行4层身份验证模型(公开 /
招聘 / 朋友 / 私有),并可选地将每个突变推送回git远程仓库以实现免费层持久性。 单租户或多租户通过 `SINGLE_TENANT_MODE` 标志 - 相同的代码
为托管部署和OSS自主托管提供支持。 Render-ready
Dockerfile,健康检查,综合pytest覆盖安全关键路径(层过滤,OAuth流程,共享令牌,
捕获端点)。
- **前端**:Next.js + Tailwind应用。 浏览,图表,询问(流式
SSE聊天)。 所有者控制台( `/owner` )与GitHub同步面板(推送 /
拉取 / 强制重置,类型确认 + 文件丢失预览),
共享令牌面板,个人LLM网址面板,持久性设置,
切换仓库模态,危险区域。 捕获表面( `/capture` )
有六个选项卡:粘贴,网址抓取,**逐字** Markdown提交,
来自LLM会话的结构化JSON提交,截图OCR,
语音备忘录转录。 浏览器中的Markdown编辑器(前置元数据+正文,实时预览)。 托管模式签名的欢迎向导。 移动优先导航。 开放图元数据 + 动态 `/og`
图像内置。
- **托管多租户层**:GitHub OAuth登录,每个租户
路由( `/{tenant}/browse` , `/{tenant}/owner` 等),租户
从您的GitHub仓库启动,推送回每个所有者编辑,
产品源代码仓库守卫在注册时(拒绝绑定您的
租户意外绑定到此仓库)。 通过
`SINGLE_TENANT_MODE=0` 可选。 自主托管说明:
[HOSTED_DEPLOYMENT.md](./HOSTED_DEPLOYMENT.md)。
- **MCP服务器**:发布为
[`portable-llm-wiki-mcp`](https://www.npmjs.com/package/portable-llm-wiki-mcp)
在npm上。 暴露 `query_wiki` , `read_page` , `search_wiki` ,
`list_pages` , `get_neighbors` , `ingest_source` , `lint_wiki` 作为
一流的MCP工具。 继承后端的层过滤,免费。
- **`create-portable-llm-wiki` 搭建工具**:一键搭建
一个全新的内容仓库,带有启动页面, `.gitignore` 和
初始化的git仓库,准备推送到GitHub。
---
## 参考
本行以下的所有内容都是参考文档。 当您
想要了解内部工作原理时请阅读它。 而不是部署您自己的
副本。
- 有关线路协议,请参见 [SPEC.md](./SPEC.md)。
- 有关贡献指南,请参见 [CONTRIBUTING.md](./CONTRIBUTING.md)。
- 有关安全报告,请参见 [SECURITY.md](./SECURITY.md)。
- 有关每个版本的发布说明,请参见 [CHANGELOG.md](./CHANGELOG.md)。
## 架构
```
┌────────────────────┐ HTTP(厂商中立) ┌────────────────────┐
│ 任意LLM客户端 │ ─────────────────────► │ FastAPI后端 │
│ (Cursor / Claude │ │ (端口8000) │
│ / GPT / 浏览器) │ ◄───────────────────── │ │
└────────────────────┘ JSON + Markdown └──────────┬─────────┘
│
▼
┌────────────────────┐
│ ~/您的维基/ │
│ ├─ wiki/*.md │
│ └─ raw/*.md │
└────────────────────┘
▲
│
┌──────────┴─────────┐
┌────────────────────┐ ┌──────────┴─────────┐
│ 您 │ ─────────────────────► │ Next.js前端 │
│ (浏览器) │ │ (端口3000) │
└────────────────────┘ └────────────────────┘
```
四个顶级组件:
- **`后端/`**:FastAPI。 读取维基文件夹,暴露
`/wiki/manifest.json` , `/wiki/page/{slug}` , `/wiki/search` ,
`/wiki/query` , `/wiki/chat` ,以及所有者专有端点 `/owner/*`。
基于令牌的层级访问控制。
- **`前端/`**:Next.js + Tailwind。 浏览器UI,用于浏览,
查询,摄入,检查,层级管理。 与任何其他LLM使用的后端相同。
- **`mcp/`**:原生MCP服务器(TypeScript)。 代理FastAPI
后端,使MCP客户端(Cursor,Claude Desktop)看到类型化的工具。
作为`portable-llm-wiki-mcp`发布在npm上。
- **`create-portable-llm-wiki/`**:独立构建工具发布在
npm上; `npx create-portable-llm-wiki my-wiki` 生成一个全新的内容
仓库,带有启动页面和初始化的git仓库。
维基文件夹本身是您的。 任何遵循Karpathy模式的文件夹
都可以使用 `wiki/` + 可选的 `raw/` 子目录。
## 本地设置
一键设置(用于上述**本地**部署路径):
```bash
./scripts/init.sh
```
该脚本安装Python + Node依赖项,写入 `backend/.env` 并生成
一个全新的 `OWNER_TOKEN` ,并询问您的维基存储位置。 默认
是捆绑的演示维基 `wiki-demo/` (Avery Chen)。 选择
那个进行零配置的首次运行。 或选择“搭建一个全新的维基”来
克隆演示作为起点进行编辑。
然后启动开发服务器:
```bash
./scripts/dev-backend.sh # 终端1. 后端在:8000
(cd frontend && npm run dev) # 终端2. 前端在:3000
```
打开 <http://localhost:3000>。 将 `backend/.env` 中的 `OWNER_TOKEN`
粘贴到 `/owner` 页面进行身份验证。 后端的
<http://localhost:8000/healthz> 应该响应 `{"status":"ok",…}`。
有关云路径,请参见 [scripts/deploy.md](scripts/deploy.md)。
## 层级模型
每个维基页面都可以在其前置元数据中声明 `tier:`。 有效层级:
- `public`:任何拥有该URL的人。
- `recruiter`:公开 + 精选扩展的职业信息。
- `friend`:以上 + 个人项目和观点。
- `private`:以上 + 医疗,财务,法律,家庭身份材料。
没有明确 `tier:` 的页面默认为 **`private`** (可在
`backend/.env` 中通过 `DEFAULT_TIER` 配置)。 这是一个安全的默认设置,
以防在将后端指向现有维基时发生任何泄漏。
### 身份验证
- 匿名请求 → `public` 层级。
- `Authorization: Bearer <OWNER_TOKEN>` → `private`(所有内容可见)。
- `Authorization: Bearer <SHARE_TOKEN>` → 在 `SHARE_TOKENS`
环境变量(格式 `tokenA:recruiter,tokenB:friend`)中配置的层级。
## API
LLM面向的线路协议。 `/.well-known/llm-wiki.json` ,
`/wiki/manifest.json` , `/wiki/page/{slug}` , `/wiki/search` ,
`/wiki/query` , `/wiki/chat` , `/wiki/chat/stream`。 在
[SPEC.md](./SPEC.md) 中指定。 该文档是端点形状,
状态代码,身份验证/层语义和一致性的规范参考。
实现在 `/.well-known/llm-wiki.json` 处提供规范,并添加
所有者专有扩展。
所有者专有(`Authorization: Bearer <OWNER_TOKEN>` 在单租户
模式下,或在托管模式下使用有效的租户作用域会话cookie):
| 方法 | 路径 | 描述 |
|---|---|---|
| POST | `/owner/reload` | 重新扫描维基文件夹 |
| POST | `/owner/lint` | 结构检查报告(可正则表达式检查) |
| POST | `/owner/ingest` | 遗留原始源保存;有关每种模式的替换,请参见捕获部分 |
| POST | `/owner/page` | 创建或更新维基页面 |
| PUT | `/owner/page/{slug}` | 替换维基页面(由浏览器编辑器使用) |
| PATCH | `/owner/page/{slug}/tier` | 更改页面的层级 |
| GET | `/owner/raw` | 列出原始源(捕获历史记录的后台) |
| GET | `/owner/raw/{rel_path}` | 读取原始源 |
| POST | `/owner/share-tokens` | 铸造层级范围的共享令牌(标签 + 可选过期) |
| GET | `/owner/share-tokens` | 列出活动和已撤销的令牌及其点击次数 |
| DELETE | `/owner/share-tokens/{id}` | 撤销共享令牌(软删除) |
捕获端点在下面的 [无缝捕获和浏览器编辑,自动重新加载](#frictionless-capture-in-browser-editing-auto-reload) 中有单独的表格。
托管模式特定端点( `/auth/*` , `/onboarding/*` ,
`/owner/sync/*` )位于
[HOSTED_DEPLOYMENT.md](./HOSTED_DEPLOYMENT.md)。
## 查询后端
`/wiki/query`(一次性)和 `/wiki/chat`(多轮)按以下顺序选择LLM:
1. `ANTHROPIC_API_KEY` →Anthropic Messages API(默认 `claude-sonnet-4-5`,覆盖 `ANTHROPIC_MODEL`)。
2. `OPENAI_API_KEY` → OpenAI Chat Completions(`gpt-4o-mini`)。
3. 两者皆无 → 关键词评分后备(返回顶部匹配的页面及其摘录,
明确标记用户不知道使用了LLM)。
无论哪种方式,响应都包含引用列表(页面标题 + 斜杠),
前端可以渲染有源答案,无论哪个后端运行。
`/wiki/chat/stream` 是 `/wiki/chat` 的SSE变体。令牌流式传输
当上游LLM生成它们时,因此感知延迟为“约500毫秒内第一个令牌”
而不是“等待8秒完成整个完成”。事件
形状和一致性规则在
[SPEC.md → `/wiki/chat/stream`](./SPEC.md#post-wikichatstream).
前端 `/ask` 页面使用此功能进行聊天UI。如果配置的
Anthropic模型在流式传输过程中返回弃用错误,
实现会通过已知的良好模型链进行回退,
然后降级到关键词后备。参见 `backend/app/llm.py` 获取
链条逻辑。
## 指向不同的维基
编辑 `backend/.env` 中的 `WIKI_ROOT`。文件夹必须包含一个 `wiki/` 子目录
用于保存 Markdown 页面。可选的 `raw/` 目录用于保存不可变的源文件。
后端读取的页面前置信息:
```yaml
---
type: 实体 | 概念 | 决策 | 来源 | 查询 | 项目 | 概述
title: 页面标题
created: 2026-05-23
updated: 2026-05-23
tier: 公共 # 可选;默认为 DEFAULT_TIER
sources: # 可选
- raw/conversations/2026-05-23-example.md
tags: [标签1, 标签2] # 可选
---
```
`[[维基链接]]` 被识别并在目标标题匹配时解析为其他页面。
## 木偶大师编排
> **托管 vs. 自托管**:托管部署在 `portablellm.wiki`
> 没有附带木偶大师二进制文件(Render 上的路径中没有 Cursor SDK)。
> 它会回退到 `direct_drafter` —— 直接
> Anthropic/OpenAI 调用,生成 1-5 个页面,具有相同的 Karpathy
> 模式和 `tier: private` 层级。自托管并将木偶大师放在
> PATH 上可获得完整的基于代理的管道。下面两者最终
> 汇聚到的磁盘页面格式相同,因此用户端维基是
> 相同的。
`/owner/ingest` (以及带有 `run_orchestrator: true` 的捕获端点)运行完整的 Karpathy 摄入管道
服务端。底层调用:
```bash
puppetmaster cursor "<摄入目标>" --cwd $WIKI_ROOT --timeout-seconds 600
```
… 启动一个 Cursor SDK 工作器,进入维基根目录,读取新
来源,提取实体/概念/决策,起草具有适当
前置信息的维基页面,交叉引用 `[[维基链接]]`,
更新 `index.md`,追加到 `log.md`,并显式标记与现有
页面的任何矛盾,而不是静默协调。
所有者控制台(UI 中的 `/owner`)显示实时作业状态。每次
木偶大师调用都在 `backend/.jobs.json` 中跟踪,其流式
日志位于 `backend/.job-logs/<tracking_id>.log`。
端点:
| 方法 | 路径 | 描述 |
|---|---|---|
| POST | `/owner/ingest` 搭配 `run_orchestrator: true` | 保存原始内容 + 启动木偶大师 Cursor 代理 |
| GET | `/owner/jobs` | 列出所有跟踪的木偶大师作业 |
| GET | `/owner/jobs/{tracking_id}` | 实时状态 + 日志尾部 + 木偶大师 `status`/`show` 输出 |
需要 `puppetmaster` 位于 `PATH` 上(或通过 `PUPPETMASTER_BIN` 环境变量覆盖)
和一个可用的 Cursor SDK 设置(`CURSOR_API_KEY` 已设置)。运行
`puppetmaster doctor` 进行验证。
## 原生 MCP 服务器
对于 Cursor、Claude Desktop 和任何其他 MCP 感知 LLM 客户端,维基
暴露为带有类型化工具的原生 MCP 服务器。`query_wiki`、
`read_page`、`search_wiki`、`list_pages`、`get_neighbors`、
`ingest_source`、`lint_wiki`。推荐的安装是发布的
npm 上的软件包
[`portable-llm-wiki-mcp`](https://www.npmjs.com/package/portable-llm-wiki-mcp);
参见上面的 **从任意 LLM 连接** 以获取基于 `npx` 的客户端配置。
要自己开发 MCP 服务器,请在本地构建并将客户端指向
构建产物:
```bash
cd mcp
npm install
npm run build
# → 使用 "command": "node", "args": ["<abs-path>/mcp/dist/server.js"]
# 在您的 ~/.cursor/mcp.json 或 claude_desktop_config.json 中
```
MCP 服务器通过 FastAPI 后端进行代理,因此它继承了所有
层级过滤和身份验证逻辑。**没有**
设置 `WIKI_OWNER_TOKEN`,MCP 服务器只看到公共层级页面:
这正是您要公开给其他人使用的 Claude Desktop 安装的页面。
参见 `mcp/README.md` 以获取工具详细信息的详细信息和 `mcp/smoke-test.mjs`
以获取端到端示例。
## 语义 lint 群
Karpathy 概念文档中的第三个支柱:lint。现有的
`/owner/lint` 是结构性的。孤立页面、过时日期、损坏的溯源,
可正则化的内容。*语义* 版本使用并行木偶大师
Cursor 代理,读取维基的正文并查找:
- **矛盾** 页面之间(页面 A 断言 X,页面 B 断言非 X)
- **过时声明** 可能已被更新来源取代
- **缺失页面**:被提及 3 次或更多次的概念,应有自己的页面
所有者控制台中的一次点击可启动 3 个并行的木偶大师作业
(以及第 4 个公共泄漏工作器。参见 **共享前审计**)。
每个写入一个 JSON 查找文件到 `<WIKI_ROOT>/.lint/<swarm_id>/<worker>.json`。
前端轮询并渲染查找结果为可操作卡片(带有深层
链接到引用的页面和并排引用比较以进行矛盾查找)。
端点:
| 方法 | 路径 | 描述 |
|---|---|---|
| POST | `/owner/lint/swarm` | 启动群;返回 swarm_id |
| GET | `/owner/lint/swarm` | 列出过去的群 |
| GET | `/owner/lint/swarm/{id}` | 实时状态 + 综合查找结果 |
耗时:90-180 秒每次工作器;并行约 3 分钟总计。
成本:按当前 Anthropic 费率计算,约 0.30-0.90 美元每次群。
## 闭环自我维护
lint → 草稿 → 摄入循环是封闭的。每个缺失页面查找都有一个
**草稿此页面** 按钮,将启动摘要 +
证据引用输入到一个新的木偶大师 Cursor 代理,该代理草稿
实际页面。矛盾的 **草稿协调** (draft reconciliation)也是如此,它会发出一个新的 `wiki/queries/YYYY-MM-DD-reconcile-*.md` 页面,记录
紧张关系并提出解决方案,而不影响源页面。
端到端循环:
1. Lint 群识别空白 → `wiki/.lint/<id>/missing-pages.json`
2. 所有者点击“草稿此页面”以创建空白页面
3. 草稿程序启动 `puppetmaster cursor`,并附带一个紧密的提示,其中
包括启动摘要 + 证据引用
4. Cursor SDK 代理读取证据页面,起草新的
页面位于 `wiki/<section>/<slug>.md`,并带有适当的前置信息,维基链接
交叉引用每个证据/提到的页面,更新 `index.md`,
追加 `log.md`
5. 后端索引在下一个请求时重新加载 → 新页面加入图谱
6. 下一次 lint 群检查新状态
维基自我改进。所有者审查每个草稿,而不是让
代理直接写入磁盘。草稿位于一个真实路径,所有者可以
在文本编辑器中编辑。
端点:
| 方法 | 路径 | 描述 |
|---|---|---|
| POST | `/owner/lint/draft/missing-page` | 为缺失页面查找启动草稿程序 |
| POST | `/owner/lint/draft/contradiction` | 为矛盾查找启动草稿程序 |
两者返回 TrackedJob 负载;新作业出现在现有的 `/owner/jobs` 面板中,实时日志 + 木偶大师摘要。
## 无缝捕捉,在线编辑,自动重载
lint→draft→ingest 循环只有在摄入 *无缝* 时才会复合。
这完善了人类在环中的部分。
**无缝捕捉** (`/capture`) — 六种模式,两大类:
* 由 LLM 分解(草稿程序撰写 1-5 页,强制 `tier: private`):
- **粘贴**:将 Slack 线程、文章摘录、转录内容放入
文本框。立即保存到 `raw/<subdir>/YYYY-MM-DD-<slug>.md`;
草稿程序提取实体、概念、决策、项目、查询。
- **URL 抓取**:粘贴任意公共 URL(投资组合、博客帖子、关于
页面、GitHub README、Substack)。服务器端获取器拉取主
内容,草稿程序生成引用原始来源的维基页面。
- **截图**:拖放、点击或从剪贴板粘贴
(`⌘V` 在页面上任意位置)。发送到 Claude/GPT 视觉以进行忠实
的 Markdown 转录。二进制资产保存在 `raw/assets/` 下以备溯源。*仅自托管* — 托管部署
没有附带视觉密钥。
- **语音备忘录**:通过 `MediaRecorder` 在浏览器中录制,或上传现有音频文件。发送到 OpenAI Whisper 进行转录。转录内容成为源文件。*仅自托管*。
* 原样(无需 LLM 参与,用户的前置信息生效):
- **`from LLM`**:粘贴由外部 LLM 会话生成的结构化 JSON 对象,对公共
[`/llm-writeback-spec`](https://www.portablellm.wiki/llm-writeback-spec) 生效。
页面经过验证、去重并提交。层级仍强制为 `private`(LLM 生成;用户审查 + 提升)。
- **`verbatim`**:粘贴完整的 Markdown 文件,并附有 YAML
前置信息。按字节保存到 `wiki/<section>/<slug>.md`。**尊重前置信息的层级** — 这是唯一信任输入的捕获模式,因为用户直接编写了它。用于手稿页面或您已经审查过的 LLM 输出。
所有分解模式共享一个“从此捕获生成维基页面”的复选框(默认为开启);取消勾选以仅保存原始内容(批量审查、大型
PDF 转储、存档快照)。
**后端端点:**
| 方法 | 路径 | 执行操作 |
|---|---|---|
| POST | `/owner/capture/paste` | 保存粘贴的文本,可选草稿程序通过 |
| POST | `/onboarding/import-url` | 抓取 URL,可选草稿程序通过 |
| POST | `/owner/capture/structured` | 提交来自 `from-llm` 会话的预结构化 JSON |
| POST | `/owner/capture/verbatim` | 提交完整的 Markdown 文件(尊重前置信息,层级不强制) |
| POST | `/owner/capture/image` | 视觉转录图像,保存资产 + Markdown |
| POST | `/owner/capture/audio` | Whisper 转录音频,保存 Markdown |
| GET | `/owner/capture/config` | 告诉 UI 哪些后端可用 |
| GET | `/llm-writeback-spec` | 外部 LLM 获取的公共规范文档 |
| GET | `/owner/raw` | 列出原始捕获文件(备份 `/owner/captures` 历史页面) |
| DELETE | `/owner/raw/{path}` | 删除捕获 |
| POST | `/owner/raw/{path}/reingest` | 在保存的捕获上重新运行草稿程序 |
| POST | `/owner/raw/bulk` | 对多个捕获执行批量操作(删除 / 重新摄入) |
**在线编辑。** 所有者可以点击任意页面视图上的 `✎ 编辑` 以打开一个
Markdown 编辑器(前置信息 + 正文,带有实时预览的并排显示)
通过 `PUT /owner/page/{slug}` 写入。编辑器使用原始
Markdown,因此草稿页面可以在一个地方审查和调整,无需离开浏览器。层级选择器位于编辑按钮旁边。
**自动重载后捕获。** 捕获端点(和编排器运行时)调用 `index.reload()` 自动
当它们完成时。草稿页面、摄入输出、原样提交和
lint 生成的内容在请求返回时出现在清单中。无需手动点击“重新加载索引”。
## 审计、共享令牌和移动端捕获
**审计前共享**:
- **匿名预览**:所有者页面现在有一个预览选择器
(所有者 / 朋友 / 招聘者 / 公共)。选择查看层级,发送一个
`X-Preview-As` 头部到每个 API 调用,应用程序的其余部分显示
正是该层级看到的内容。该头部在服务端受到所有者限制。
非所有者无法通过发送它来授予自己访问权限。
- **公共泄漏 lint 工作器**:lint 群中的第四个木偶大师代理。
读取每个 `tier: public` 页面,识别专有名词 / ID /
美元金额 / 特定令牌,并标记任何仅在更高层级页面中也出现的令牌。
捕获状态下公共文档导入私有文档的失败模式。
**基于令牌的分享链接生成**(`/owner` → 分享令牌面板):
- `POST /owner/share-tokens` 生成一个 256 位 URL 安全令牌,带有标签、
层级和可选过期时间。纯文本 **仅一次** 返回;
仅存储 SHA-256 哈希值。
- `GET /owner/share-tokens` 列出活动和已撤销的令牌,并附有点击次数和
`last_used_at`。
- `DELETE /owner/share-tokens/{id}` 撤销(软删除,保留审计)。
- 存储:`<WIKI_ROOT>/.share-tokens.json`(gitignored)。
- 接收者流程:所有者复制 `https://wiki.example.com?share=ABC123` →
交给接收者 → 加载时,`ShareTokenCatcher` 存储令牌并
从 URL 中删除它。
**Apple Wallet 传递生成器**(`scripts/build-wallet-pass.py`):
生成一个 UNSIGNED `.pkpass` 包,包含您的姓名、职称、简介和
二维码,编码维基 URL。包括 NFC 有效负载,用于在配对的
iPhone 上点击打开。签名需要 Apple 开发者帐户(99 美元/年)或
第三方服务,如 walletpasses.io。说明在每次构建结束时打印。
**通过快捷方式的 iPhone 捕获**:
5 步快捷方式,让您在任何 iOS 应用中突出显示文本 → 分享 →“保存
到 Wiki” → 它 POST 到 `/owner/capture/paste`,木偶大师从源草稿
页面。演练位于 `/connect` → iPhone 选项卡。推荐的设置使用友人层级分享令牌
(可从所有者控制台生成),因此丢失的手机不会危及所有者凭证。
## 离开托管服务
您的维基是 GitHub 仓库中的 Markdown **您** 所有。托管层位于
[portablellm.wiki](https://portablellm.wiki) 是可选的。点击
**危险区域 → 删除我的托管租户** 进入 `/owner` 以清除
我们这边的所有内容;您的 GitHub 仓库不受影响。完整的移交
到自托管位于 **[LEAVING.md](LEAVING.md)**。
## 部署
预期的部署是 **两个服务**:后端 Render
(持久计算),前端 Vercel(CDN 服务的 Next.js)。两者
顶部有“一键”按钮。
完整的逐步演练。Render 环境变量、GitHub PAT
生成、CORS 收紧、Vercel 预填充链接。位于
**[scripts/deploy.md](scripts/deploy.md)**。快速总结:
1. `npx create-portable-llm-wiki my-wiki` → 推送到私有 GitHub 仓库。
2. 点击 **部署到 Render**。设置 `WIKI_GIT_REMOTE`
到您的内容仓库的克隆 URL,并嵌入 PAT。
3. 点击 **部署到 Vercel**。设置
`NEXT_PUBLIC_BACKEND_URL` 到您的 Render URL。
4. 返回 Render,收紧 `CORS_ORIGINS` + `PUBLIC_BASE_URL` 到您的
Vercel URL。
免费层在 15 分钟不活动后冷启动(~3-5 秒
唤醒)。对于始终在线,升级 Render 到 $7/mo Starter 计划或
安装 `$1/mo` 1GB 磁盘以实现更快的冷启动。
### 原型超出免费层时
将后端移至 ECS Fargate 或 Fly.io,并使用 5GB 卷。前端保留在
Vercel(已经生产级)。添加 Postgres 以实现
多租户共享令牌存储。估计 1 个用户:$0-15/mo。
估计 100 个用户:$50-150/mo。
## 路线图
GitHub 问题跟踪器是 **剩余内容** 的真实来源以及规划的内容。
欢迎在那里提出功能请求和错误报告。
## 开发
```bash
# 后端仅限
./scripts/dev-backend.sh
# 前端仅限
./scripts/dev-frontend.sh
# 两者
./scripts/run.sh
```
前端代理 `/api/backend/*` → `http://localhost:8000/*`(配置
在 `frontend/next.config.mjs` 中)。
## 测试
后端综合测试(pytest),前端单元测试
(vitest)和端到端(Playwright,headless Chromium)。新
功能以测试落地,确保合同安全
关键路径(层级过滤、OAuth、共享令牌、捕获
验证、强制重置预览)受到回归影响。
```bash
# 后端(pytest)
cd backend && .venv/bin/pytest
# 前端单元测试(vitest)
cd frontend && npm test
# 前端端到端测试(Playwright,headless Chromium)
cd frontend && npm run e2e
```
所有三个套件在每个 PR 上运行。参见 `.github/workflows/ci.yml` 和
[CONTRIBUTING.md](./CONTRIBUTING.md)。
### 运行 E2E 测试
小型 Playwright 烟雾套件位于 `frontend/e2e/`。它锻炼实际
浏览器 → 前端 → 后端 → 维基往返流量,跨越最繁忙的
页面(/,/browse,/graph,/ask,/connect)。仅限铬设计:
这些是烟雾测试,而不是跨浏览器覆盖。
**先决条件**(一次性):
```bash
cd frontend
npm install # 选取 @playwright/test
npx playwright install chromium
```
**运行套件:**
```bash
# 后端必须在 :8000 运行(/ask 测试需要它)。
./scripts/dev-backend.sh # 另一个终端,如果尚未启动
# 前端开发服务器由 Playwright 自动启动。单命令:
cd frontend && npm run e2e
```
有用标志:
- `npm run e2e -- --headed`:观察浏览器自行驱动
- `npm run e2e:ui`:Playwright 交互式测试运行器
- `CI=1 npm run e2e`:CI 模式(无 `reuseExistingServer`,重试,列表 + html 报告)
报告位于 `frontend/playwright-report/`(gitignored)。在第一次
重试失败的测试中,将捕获跟踪信息以备 `npx playwright show-trace`。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器