关于 chamber
chamber 是面向使用本地笔记的 AI Agent 的 MCP 服务,用确定性字符串匹配检查回答中的数字、名称等是否出现在引用文本中。它还可索引笔记、跟踪引用内容变化并验证已记录的主张;检查本身不使用模型或网络。
主要功能
- 01核对数字、名称、域名和文件名
- 02索引本地笔记并检索内容
- 03验证引用段落是否发生变化
- 04记录无来源主张的引用债务
- 05按句检查带引用的回答
适用场景
- 01检查 Agent 引用笔记时是否错报数字
- 02发现笔记修改后已引用依据发生变化
- 03为笔记问答生成可核验的来源引用
MCP 相关
MCP 服务向 MCP 客户端提供 chamber_check,用于检查主张与引用笔记之间的术语匹配。配置启用后也可提供 chamber_ask;该问答功能需要模型。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @bu7umaid/chamberCHAMBER_PYTHONPath to a Python interpreter with onnxruntime, used by the local embedder. Optional: defaults to python3 on PATH; without onnxruntime, semantic search degrades and Chamber says so.CHAMBER_API_KEY密钥API key for the configured model endpoint. Only read when model.base is not a loopback address; a local endpoint needs no key.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
4收录的工具列表 · 更新于 3 天前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| claims | array | 是 | 要核查的主张及其各自的来源笔记。 |
| record | boolean | 否 | 将 SUPPORTED 主张作为信念提交,并固定来源,以便 chamber_verify 检查内容漂移。默认值为 false:不会写入任何内容。 |
详细介绍
Chamber
发现 AI Agent 引用了其所引用笔记中没有的数字或名称。当 Claude Code(或任何 MCP 宿主)根据你的笔记作答时,系统会要求它先用 chamber_check 检查每条主张。实际输出(已精简):
2 claim(s): 1 supported · 1 terms absent · 0 nothing to check · 0 not judged
[TERMS_ABSENT] Q3 revenue was $420k, up 18% on Q2.
the cited text does not contain: 420k
checked: q3-review.md#p0
[SUPPORTED] Enterprise renewals moved to Dana Ortiz in August.
every term Chamber recognises occurs in the cited text
checked: q3-review.md#p0
笔记中写的是 $240k。Agent 写成了 $420k。之后编辑笔记,同一项检查会针对新文本进行判断,结果还会显示 index is behind this file,因为索引中仍保留着旧副本。
在 Claude Code 中,以插件形式使用。它会询问你的笔记文件夹,并添加服务和 chamber-check 技能:
/plugin install chamber --marketplace abm9111/chamber
在低于 2.1.275 的 Claude Code 版本中,请先运行 /plugin marketplace add abm9111/chamber,然后运行 /plugin install chamber@chamber。插件需要一个文件夹路径,可以是绝对路径,也可以以 ~/ 开头;还需要一个以逗号分隔的跳过文件夹列表(.obsidian,*sync-conflict*;名称中不能含逗号)。使用 /plugin configure chamber@chamber 可更改其中任一项。它会运行版本固定的 Chamber 发布版,通过小型启动器(plugin/launch.mjs)在不使用 shell 的情况下启动 npm 的 npx。原生 Windows 上无法启动裸 npx。
Claude Code 不会自动更新第三方市场。要获取较新的固定版本,请开启自动更新(/plugin,切换到 Marketplaces 标签页,选择 chamber,然后选择 Enable auto-update),或运行 claude plugin update chamber@chamber。如果你还通过 claude mcp add 手动添加了服务,chamber_check 会列出两次:保留插件添加的那项,并运行 claude mcp remove chamber。
或者,仅在任意 MCP 宿主中运行服务:
claude mcp add -s user chamber -- npx -y @bu7umaid/chamber mcp --notes ~/Notes
{
"mcpServers": {
"chamber": {
"command": "npx",
"args": ["-y", "@bu7umaid/chamber", "mcp", "--notes", "/absolute/path/to/Notes"]
}
}
}
在 Codex 中,命令行、IDE 扩展和桌面应用都读取同一个 ~/.codex/config.toml。使用命令行添加服务:
codex mcp add chamber -- npx -y @bu7umaid/chamber mcp --notes /absolute/path/to/Notes
也可以手动编辑该文件。首次运行时会下载软件包,耗时可能超过 Codex 为服务启动预留的 10 秒,因此配置表中设置了更长的超时时间:
[mcp_servers.chamber]
command = "npx"
args = ["-y", "@bu7umaid/chamber", "mcp", "--notes", "/absolute/path/to/Notes"]
startup_timeout_sec = 60
此格式来自 OpenAI 的 Codex MCP 页面:codex mcp add、包含 command 和 args 的 [mcp_servers.<name>] 表,以及默认值为 10 的 startup_timeout_sec。Chamber 尚未在 Codex 中测试。
无需模型、账号或网络:这项检查会使用 node:sqlite 和你磁盘上的文件,进行确定性的字符串匹配。它会检查数字、首字母大写的名称、域名、文件名和数量。它不会检查含义,因此,即使是根据笔记原文构造出的否定句或反转句,也仍会通过。请参阅经过验证的引用能证明什么、不能证明什么。
不止于检查:提供带来源引用的回答,并运行每日任务,告知你某个来源何时发生变化,而你此前已经信任的结论仍基于该来源。
运行检查
上面的 npx 命令行足以满足大多数人的需求。在 --notes 后可重复使用 --exclude <pattern>。配置中的摄取根目录及其排除项也会计入。还有另外两种使用方式:
从代码检出目录运行(Node 23.6+)。 TypeScript 可直接从代码仓库运行,无需构建步骤。try 会构建一个临时工作区,运行实际代码路径,然后将其删除。已发布的软件包可在 Node 22 上运行(实测版本为 22.23.1,会显示 Node 的 experimental-SQLite 警告)。Node 20.20.2 会因缺少 node:sqlite 而以 ERR_UNKNOWN_BUILTIN_MODULE 退出。代码检出运行仍要求 Node 23.6 或更高版本。
git clone https://github.com/abm9111/chamber.git && cd chamber && npm ci && node --experimental-strip-types src/cli.ts try
**如果 /mcp 未列出 chamber_check,**说明宿主启动服务时使用了精简的 PATH。从你自己的 shell 中运行 command -v node 获取解释器路径,并让它指向已发布版本的 bin 文件,或代码检出目录中的 src/mcp_server.ts。这两者是不同的文件:
# published bin: bin/chamber.js loads dist/. This is not src/mcp_server.ts.
claude mcp add -s user chamber -- "$(command -v node)" /path/to/node_modules/@bu7umaid/chamber/bin/chamber.js mcp
# checkout only. src/mcp_server.ts is not in the npm install.
claude mcp add -s user chamber -- "$(command -v node)" --experimental-strip-types /path/to/chamber/src/mcp_server.ts
摄取和 chamber_ask 需要配置。如果已设置配置中的摄取根目录,检查也会读取它们。请参阅配置:摄取、chamber_ask 和检查的配置根目录。
人们的实际做法
目前还没有公开的 Chamber 用户记录。以下是 X 上相关的失败案例,也是这项检查存在的原因。
- 将 Obsidian 文件夹交给 Claude Code,只会读取文件,不会检查句子。Richard Kovacs,2026 年 9 月 28 日:Claude 会返回来源列表,由他来检查。他指出,剩下的问题是确认偏误,并把应对方式归结为自律。
- 必须由 Agent 记得调用的工具,并不能充当关卡。
Saksham Arora,2026 年 10 月 2 日:共享记忆 MCP 只有在另一个 Agent 决定搜索时,才会回想起某个会话,因此他在每条消息之前都加了一个钩子。
chamber_check也是同样的形式。MCPinstructions会要求 Claude 调用它。如果 Claude 跳过,整个回合不会受到阻拦。缺少的关键环节是一个要求提供回执的 Stop 钩子;它目前还不在这个仓库里。 - 传播广泛的知识库帖子(99.7% 召回率、几分钟内加入数千个链接)并不是测量结果。这个仓库里的数字来自
docs/KNOWN_LIMITATIONS.md第 2 节中的 200 条声明集:大多能抓出编造的值,但抓不出否定句。
两分钟了解它
上面的检出命令会构建一个一次性工作区,在其中运行真正的代码路径,然后将其删除(加上 --keep 即可查看)。它不会打开数据库。

这段录制是根据 assets/demo.tape 脚本生成的,而不是手动录制的,因此输出变化时会重新生成,不会悄悄展示一个已经不存在的 Chamber 版本。以下内容都是该检出命令的实际输出,经过了删减:
$ chamber believe belief "Customers may return any purchase within 30 days of delivery."
committed blf_ddcf4f3c9b2e81b8
an unsourced assertion is not refused — it mints citation debt.
$ chamber debts
dbt_18bd1c1171cdbfcb [pending]
$ chamber pay-debt
proposed 2 source(s), 2 pinned; best=0.694
$ chamber verify
blf_ddcf4f3c9b2e81b8 2/2 pins verified
这是常见状态:一个有证据支撑且证据仍然成立的信念。接着,有人编辑了它所依据的笔记——30 days 变成了 14 days:
$ chamber ingest ./notes
ingested 2 file(s) as 4 passage(s)
$ chamber verify
blf_ddcf4f3c9b2e81b8 1/2 pins verified
hash_mismatch: refunds.md#p0
没人要求它重新审视这个信念。结论没有变化;变化的是它赖以成立的依据,而且退出码非零,因此计划任务可以据此采取行动。这就是整个产品。
另外四种场景——由外部锚点发现已回滚的账本、沙箱拒绝运行而不是降级、拒绝恶意工具目录——位于 demos/ 中,并会在 CI 中运行,确保它们不会偏离代码。
上述词语的定义
Chamber 的所有操作都记录在一个 SQLite 文件的行中。对话记录中的每个术语都对应一个表或哈希值:
| 词语 | 实际含义 |
|---|---|
| passage | 一个 Markdown 文件中的一个片段。refunds.md#p0 表示文件路径 + 片段索引。 |
| belief | belief 表中的一行:一条断言句,关联到为其提供支撑的片段。 |
| pin | 对引用片段存储的标题、正文和 ref 计算出的 SHA-256 哈希值,在引用时生成并保存在 belief_source 中。 |
| verify | 重新读取每个已固定的片段,重新计算哈希值并进行比较。任何不匹配都会以非零状态退出。不涉及模型。 |
| citation debt | citation_debt 表中的一行,在某条断言没有来源却提交时创建。同一条声明必须先还清欠账,才能再次提交。 |
| pay-debt | 检索为欠账的声明推荐片段;接受后会固定这些片段。 |
| APORIA | 没有检索到任何支持答案的片段时给出的判定。回复为“我不知道”,并以此记录。 |
| gate | 在同一个 SQLite 事务中执行检查和写入——要么两者都提交,要么都不提交。 |
| audit log | 只追加的 audit_event;每一行的哈希值都涵盖上一行的哈希值,因此编辑历史会使其后每个哈希值都失效。 |
| anchor | 存储在数据库之外的日志根哈希,因此可以检测到日志被截断,而不是悄无声息地发生。 |
| the scheduler | 运行 ingest + verify 的 launchd/systemd 任务,只在出现偏差时发出通知。 |
这些都不是隐藏机制:运行 sqlite3 ~/.local/share/chamber/chamber.sqlite '.tables' 即可查看全部内容。
为答案提供来源引用
配置模型后,chamber ask 会逐句检查引用。使用同样的两篇示例笔记,在本地 30B 模型上:
$ chamber ask "summarise our refund policy"
Customers may return any purchase within 30 days of delivery [2]. Refunds
are issued to the original payment method, usually within five working days
of the returned item arriving at the warehouse [2]. However, perishable goods
and personalised items cannot be returned once dispatched [1].
[ALLOWED] Customers may return any purchase within 30 days of delivery [2]. Refu
sources: refunds.md#p0 — refunds › Refund policy, refunds.md#p1 — refunds › Refund policy › Exceptions
模型看到的是 [1]…[k],而不是文档 ID 或哈希,因此从原理上说,它无法伪造引用——答案生成后,系统会将这些编号解析回对应文件。没有引用的句子会标记为
UNSUPPORTED:系统会记录,但不会将其视为关键依据。如果句子中的编号、名称或领域不在它引用的段落中,该引用也会被移除,并指出缺少哪些术语(terms_absent)——真实的段落并不能为其中未提及的主张提供证据。答案中的标题会显示为 [HEADING],不会被记录。
语料库无法回答的问题更值得关注:
$ chamber ask "what should a customer do if they want to return a perishable
item after the office has closed?"
I don't know
[APORIA] I don't know
两篇笔记都已编入索引,且都与问题相关。但它们都无法回答这个问题,因此系统不会拼凑内容来作答。
配置:ingest、chamber_ask 和检查所用的配置根目录
npm link # puts `chamber` on your PATH
chamber init # writes ~/.config/chamber/config.json
然后编辑该配置,添加笔记文件夹和模型:
{
"database": "~/.local/share/chamber/chamber.sqlite",
"model": { "base": "http://127.0.0.1:8087/v1", "name": "your-model", "mode": "openai" },
"ingest": [{ "root": "~/Notes", "exclude": ["transcripts", "attachments"] }]
}
--exclude <pattern> 可在 --notes 后重复指定;配置中的 ingest 根目录及其排除规则也会被视为已声明文件夹,若某条排除规则没有匹配任何内容,就会拒绝该文件夹。仅保存在索引行中的根目录,不会授权读取索引中没有的文件。
model.base 可以指定任何兼容 OpenAI 的端点。回环地址无需 API 密钥;其他地址会从环境中读取 CHAMBER_API_KEY,绝不会从文件中读取。
chamber ingest # index every configured root
chamber ask "..." # ask, with citations
chamber verify # re-check stored pins against the corpus
chamber corpus # what is actually in the index
你使用的嵌入器取决于安装方式。 npm 或 Docker 安装会使用 local-hash-v1 向量进行嵌入,且不会发出警告;但如果本地 Ollama 服务在 127.0.0.1:11434 上响应,或设置了 CHAMBER_EMBEDDER=ollama,则会改用 Ollama:npm 包和两个 Dockerfile 都不包含 models/minilm/(23 MB 的 MiniLM 权重),因此使用哈希向量时,chamber ingest 及 chamber_ask 背后的检索会根据字符 n-gram 匹配,而非根据含义匹配。chamber_check 不受影响;它不使用模型。
如需使用 MiniLM,请克隆此仓库,使用
pip install --require-hashes -r scripts/requirements-embed.txt 安装其 Python 依赖,并将
CHAMBER_PYTHON 设置为安装了这些依赖的解释器。若克隆仓库所用的解释器缺少 onnxruntime,也会退回到哈希向量,并在 stderr 中发出警告。
首次 ingest 前请设置排除规则。 默认没有排除列表。如果将导出的聊天记录文件夹作为目标,Chamber 会照单全收并据此作答——请参阅 chamber corpus 和
docs/KNOWN_LIMITATIONS.md 中的第 11 条。
如果根目录是 Obsidian 库,请在首次 ingest 前排除 .obsidian、.trash 和
*sync-conflict*。符号链接文件夹会按链接路径编入索引。检查也会读取真实路径,因为它使用与 ingest 相同的逐条规则。若链接指向已声明文件夹之外,则不会读取。
将其用作 CI 漂移门禁
同样的验证流程也适用于仓库:将文档中的主张固定到代码或策略段落上,当依据发生变化时,让 chamber verify --json 使构建失败。只需在工作流中添加一行——此仓库提供了对应的 action:
- uses: abm9111/[email protected]
docs/CI_DRIFT_GATE.md 是一页式操作指南;
demos/06_ci_drift_gate.ts 是可运行的操作记录。
每日运行
deploy/launchd/com.chamber.verify.plist(macOS)和 deploy/systemd/
(Linux)会按计划运行 ingest 和 verify,并且只在发生漂移时发出通知。如果检查大多数日子都能正确报告“无变化”,你就会不再查看它;因此它会保持安静,直到确有变化。
在 Obsidian 中呈现
配套插件 Chamber Drift
会将 verify --json 的报告呈现为库侧边栏面板和每篇笔记的横幅,仅此而已。它从不验证,也从不写入;这两件事都由 Chamber 在 Obsidian 之外按自己的计划完成。设置说明,包括用于写入报告的单行命令和 Obsidian Sync 的注意事项:docs/OBSIDIAN.md。
在 AI 编码 Agent 中使用
使用自身工具读取你的库的 Agent,可以检查自己即将告诉你的内容。chamber_check 接收 Agent 的说法及其声称依据的笔记,并按说法逐条作答(简略版):
[SUPPORTED] One NVIDIA A100 80GB or an L40S can serve about 1,000 users for code completion.
found in: ai-coding-setups-march-2026.md#p25
[TERMS_ABSENT] One NVIDIA A100 80GB can serve about 2,000 users for code completion.
the cited text does not contain: 2000
检查不使用模型。路径为绝对路径且文件位于已声明文件夹中时,它会读取磁盘上的文件。已编入索引的笔记即使后来发生变化,仍会根据磁盘文本进行判断,结果还会添加 index is behind this file。段落引用依据已编入索引的文本进行判断。SUPPORTED 表示识别出的术语出现在该文本中,并不表示句子由此成立。然后,它会检查说法中的每个数字、大写名称、域名、文件名和计数是否出现在笔记中,以此捕捉捏造的值。它不会检查小写名称或普通词语,也无法捕捉由笔记自身词语拼成的否定句或反转句——关于它经测量能够捕捉的内容,见
docs/KNOWN_LIMITATIONS.md §2。除非以 record: true 调用,否则它不会写入任何内容。此时,受支持的说法会通过门控提交,并固定到支持它们的段落;笔记重新摄取后,chamber_verify 会报告固定段落发生变化的说法。
服务会通过 MCP instructions 将这些信息告知宿主,Claude Code 会将其放入 Agent 的上下文中。这是提示词约定,而非运行时门控。
工具有四个,不是三个。上面介绍的是 chamber_check。其余三个负责其他工作:chamber_ask(Chamber 配置的模型作答,并提供相同的逐条说法判定)、chamber_verify(检查已记录说法的漂移)和 chamber_corpus(查看已编入索引的内容)。CHAMBER_PYTHON 是可选项,仅供 chamber_ask 的语义检索使用;缺少 onnxruntime 时会回退到哈希向量。摄取仍通过 CLI 执行,以免模型重新索引自己的证据。
使用上面的命令注册服务。该 npx 会运行已发布的 bin(dist/)。
服务会在每次工具调用时重新读取配置,因此编辑 model 后,下次调用就会生效,无需重新连接;但服务自身环境中设置的 CHAMBER_* 变量仍优先于文件。数据库是例外:它会在进程整个生命周期内保持固定,因为调用可能会在数据库打开时等待模型响应——要切换数据库,请重新连接服务。首次使用以及解析后的数据库、模式和基地址发生变化时,这些信息都会输出到 stderr,因此宿主的 MCP 日志可以确认服务正在使用的配置。
这些接口都无法激活技能、批准待处理的写入或执行摄取——设置这些门控是为了让人类通过它们;把批准权限交给模型只会颠倒门控的作用,而非削弱它们。
chamber_ask 不是只读操作,写入也不只是记账:每条说法都会经过提交门控,因此带有已验证引文的说法会作为带有固定引用的信念记录下来——这正是 chamber verify 之后会重新检查是否漂移的内容。没有来源的断言会产生引文债务;支出也会被记录。这与命令行中的 chamber ask 行为一致。这里的保证是不会绕过门控,而不是不会写入任何内容。
已验证的引用能证明什么,不能证明什么
Chamber 能证明被引用的段落就是它声称的那个段落——未经修改、仍然存在,而且表达的内容仍与引用所说的一致。
它无法判断某项主张是否能从该段落推导出来。模型可能引用真实来源却误读它,而这里的每一层都会放行。这是明确声明的非目标,也已观察到此类情况,且尚未解决。
信任任何输出前,请阅读 docs/KNOWN_LIMITATIONS.md。其中记录了 21 项限制,包括最不光彩的两项。默认情况下必须使用沙箱,且默认行为是拒绝:工具代码(tool-run、tool-synth、sandbox-test、MCP 工具验证)只有在 bubblewrap 下运行,且探测确认 bubblewrap 能实现隔离后才会运行。没有这样的后端时,程序会拒绝运行;CHAMBER_SANDBOX_REQUIRED=0(或 false、no、off)是明确的退出选项,会在清理过的环境中运行普通子进程。该选项不提供隔离:一次经探测的运行读取了 $HOME 并解析了 DNS(docs/KNOWN_LIMITATIONS.md §1)。macOS 没有 bubblewrap,因此无法在 macOS 上测试隔离。该路径不属于 chamber_check。使用退出选项时,不要把“沙箱”理解为隔离。引用欠账能可靠地阻止逐字复述,但其上的释义环节只是启发式判断:校准发现,没有任何余弦相似度阈值能区分改述与矛盾。现在,数值和否定检查排除了其中最严重的问题——操作者纠正一项欠账主张时,不会再因为复述该主张而遭拒——但五个真实释义中仍有两个会漏过,而既非数值相关也未使用否定表述的矛盾仍会被判定为重复内容。
不变量
任何断言只有经过一道门才能变为可执行、可引用或可作为依据;这道门必须在同一事务中完成检查和写入——其他任何内容都可能衰退、搁置或被推翻,但绝不能在不知不觉中通过。
| 门 | 在以下情况下阻止 |
|---|---|
commitBelief | 存在尚未解决的阻断性引用欠账的断言;缺少标记或无法验证标记;将反证作为来源;快速路径上的信念类型提交 |
tryActivateSkill | 存在未解决的保留项;存在过时且作为依据的信念;内容 ≠ 最近一次经审查清除问题的哈希;能力清单请求超限 |
两道门都会写入哈希链式审计日志——entry_hash = sha256(prev_hash || canonical JSON),并配有增量 Merkle 树——因此,篡改过去的决策会破坏其后的每个哈希。撤回类型(defeater、unknown)可自由提交,且绝不会产生阻断性欠账。
默认行为是拒绝:记忆和技能写入需要审批;学习到的技能会进入隔离区,而不是被静默应用;过期的待处理写入不算已获批准。
开发
npm test # 308 tests
npm run typecheck
npm run probes # adversarial probes; each one asserts a defect is absent
目前,npm run probes 可以通过,但这句话从写下那一刻起就已过时——请实际运行,而不要盲目信任。两个探测(sandbox_escape、debt_paraphrase)在修复合入前,曾连续数周因真实存在且尚未解决的缺陷而报红;它们之所以被设为门,正是因为之后仍可能再次报红。无法失败的门,只会宣称它从未检查过的安全性。
目录结构
src/ask.ts retrieval → prompt → per-claim citation gate
src/mcp_server.ts MCP surface: ask, check, verify, corpus
src/commit_belief.ts the belief gate; check and write in one transaction
src/pins.ts content pins and drift verification
src/audit.ts hash-chained log + incremental Merkle
src/config.ts settings: flag → env → config file → default
src/db.ts opens the database, loads every schema
probes/ adversarial probes, run by npm run probes
demos/ the four scenarios above, run in CI so they cannot rot
docs/KNOWN_LIMITATIONS.md what does not work, and what it costs
docs/NEXT_LEVEL_PLAN.md historical plan; several items already shipped
MIT。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。