关于 Facthouse
Facthouse 是面向 AI 工具的本地记忆引擎,将会话活动整理为相互关联的知识并存入 SQLite。它支持复制会话记录或通过 MCP 捕获事实,并可选语义搜索。
主要功能
- 01基于 SQLite 的本地存储
- 02实体关联的知识图谱
- 03支持可选嵌入的混合搜索
- 04复制会话记录或捕获事实
- 05整合知识并处理冲突
适用场景
- 01在不同 AI 会话间延续有用事实
- 02搜索与主题或实体相关的知识
- 03整合复制来的会话记录
MCP 相关
提供用于记录、读取、搜索和整合记忆的 MCP 工具,以及简报和个人资料资源。MCP 客户端可通过复制会话记录或直接捕获事实来使用它。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
10收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| role | enum | 是 | 生成此事件的通道(user、assistant、system、tool)。对于群组记录中有姓名的人物,将 role 保持为 user,并传入 speaker。user | assistant | system | tool |
| content | string|null | 是 | 事件的文本内容 |
| speaker | string|null | 否 | 记录中有姓名的参与者(例如 Alex)。role 保持为通道;不要虚构人物角色。 |
| metadata | any | 否 | 任意元数据 |
| event_type | enum | 是 | 事件类型message | tool_call | tool_result | artifact |
| content_ref | string|null | 否 | 非文本内容的 URI 或路径 |
| content_type | enum | 否 | 内容的解释方式。消息默认使用 'text'。结构化数据使用 'json',屏幕截图或生成的图像使用 'image',语音或音频片段使用 'audio',其他所有非文本内容使用 'binary'。text | json | image | audio | binary |
详细介绍
Facthouse
Facthouse 是面向 AI 工具的本地记忆引擎。大多数“记忆”产品会为聊天记录建立索引。Facthouse 获取 Agent 活动——消息、工具使用以及其他 MCP 流量——并运用受神经科学启发的巩固机制,使其依次经历 数据(会话中发生的事)→ 信息(提取出的事实)→ 知识(在实体图谱上整合的信念)。在此过程中,Facthouse 会关联实体、删除重复项、协调冲突,并以最新信息取代过时内容。向量嵌入可在此图谱之上提供可选的语义搜索。存储内容保存在你磁盘上的 SQLite 文件中。
快速开始
需要 Node 22.5 或 24+。
npx -y @facthouse/mcp
facthouse init
facthouse init --web 与浏览器表单执行相同的设置操作——它会打印一个 127.0.0.1 URL,但不会打开浏览器。
按 Enter 接受每项默认设置(copy = 磁盘上的 Claude Code、Cursor 或 Grok Build 会话日志;如果希望助手保存事实,则输入 record)。如果选择了 copy,init 会询问是否复制现有日志,接着询问是否提取并整合。写入存储后,init 会立即打印 MCP 代码片段——在复制/提取运行期间,将其添加到客户端的 MCP 配置中。init 完成后,重启客户端。
在客户端的普通对话中说出一条持久信息——无需使用记忆命令。
在下一个会话中询问这条信息,或运行 facthouse search。这就是存储的内容。
从 Claude Code、Cursor 或 Grok Build 日志中复制,或从任何 MCP 客户端记录:对话如何进入系统。回放:facthouse.dev/demo.html。CLI:见下文。
你将获得
- 本地 SQLite。 可选使用 Postgres。隔离依据是目录,而非列。
- 实体图谱。 人员、组织、项目、地点、产品——自动提取、分类并关联。
- 混合搜索。 BM25 + 结构化领域 + 实体图谱路径,通过 Reciprocal Rank Fusion 合并。嵌入提供方可增加第四类语义搜索;默认关闭。
- 会话内记忆。
get_session_context提供的简报与memory://briefing相同。仅支持工具的客户端应在会话开始时调用它。 - 不可变历史记录。 事实绝不会删除,只会被更新的信息取代。
工作原理
一个 SQLite 数据库。里面有三张表,而不是三个数据库:Data(会话中发生的事)→ Information(提取出的事实)→ Knowledge(整合后的认知)。
- D(
session_events)— 说过的话(复制的转录文本,或助手记录的内容) - I(
session_facts)— 刚提取的内容,或capture_fact - K(
facts)— 整合后的知识
FTS5(词语)和可选的嵌入(含义)是 K 的索引,不是第二个存储库。语义搜索默认关闭:search "shellfish" 能找到关于贝类的事实,search "food" 则找不到;除非你选择一个嵌入模型——模型决定了什么算“相似”。
两种速度。Copy 会将指定的转录文本追加到 Data。Extract 会把转录文本中的新行转成独立事实(D→I)。Integrate 会将它们整合到存储库已有的知识中:领域、实体、重复项、矛盾和图谱(I→K)。consolidate 是统称:将复制、提取和整合一起执行。每次运行的 Extract 最多处理 50 行,因此首次回填不会一次处理全部内容;Extract 运行时会选取最早的 50 行。整合不会凭空编造任何人都没说过的话。
钩子无法调用 MCP 工具——这些工具只存在于助手的连接中——而且不能等待模型处理。因此,它不会调用 consolidate,而是运行 facthouse notify …,告知正在运行的服务某个时刻已经发生,并立即返回。consolidate 是流水线动词(MCP 工具或命令行);调用方会等待。notify compaction 是向运行中的服务异步请求执行该动词。notify threshold 是另一种策略(仅在条件满足时提取)。
自动执行
| 时机 | Copy | Extract(D→I) | Integrate(I→K) |
|---|---|---|---|
| Facthouse MCP 服务启动 | 是 | 是(上限 50) | 是 |
| 调用 Facthouse 工具或资源 | 是,前提是已指定来源且 JSONL 有新增内容 | 否 | 否 |
| Facthouse MCP 进程退出 | 否 | 否 | 是 |
可调用
| 调用 | 来源 | Copy | Extract(D→I) | Integrate(I→K) |
|---|---|---|---|---|
consolidate | MCP 工具或命令行。调用方会等待。 | 是 | 是(上限 50) | 是 |
facthouse notify compaction | 其他进程(推荐使用 PreCompact;我们不会安装)。不会等待。 | 是 | 是(上限 50) | 是 |
facthouse notify threshold | 其他进程。不会等待。不是复制存储钩子。 | 否 | 是,满足条件时(上限 50) | 否 |
对于没有额外钩子的默认复制存储,只会运行自动执行表中的操作:Facthouse 启动时(执行全部三项);每次调用 Facthouse 工具或资源时,如果指定来源有新增内容,则执行复制;进程正常退出时执行整合。关闭聊天窗口可能会跳过退出这一行;下次启动时仍会进行整合。满足阈值的条件是:至少有 10 行未经检查,且距离上次受限运行已过去两分钟。consolidate --all 会取消 Extract 上限。建议将压缩配置为 PreCompact(notify compaction):在运行中的服务上执行与 consolidate 相同的三个步骤,且不会等待。我们不会安装该钩子。它不是 Stop 钩子。record 会在记录存储上触发阈值提取——不要在复制存储上安装 record 钩子。
存储需要 Node。智能处理需要语言模型。默认使用你现有订阅中的 Claude Code CLI。如果没有该 CLI,整合会回退到内置启发式方案,不会从转录文本中提取事实。capture_fact 仍会存储事实,但不会关联实体,也不会进行领域路由。
对话如何进入
有两种方式。每个存储区选择一种。
| 从记录中复制 | 由助手记录 | |
|---|---|---|
| 谁 | Claude Code、Cursor 或 Grok Build(客户端主目录下磁盘上的会话日志) | 磁盘上没有日志的任何 MCP 客户端(Desktop 等) |
| 如何操作 | 指定一个来源;Facthouse 会将这些日志中的新增行复制到存储区 | sources 为空;助手调用 capture_fact |
| 首次运行 | TTY 引导流程,选择 copy,设置 cwd;初始化时会询问是否复制现有日志,然后询问是否提取并整合 | TTY 引导流程,选择 record |
在 copy 存储区中,capture_fact 对每个 MCP 客户端来说都是用于更正的工具,不仅限于写入 JSONL 的那个客户端。若要在同一个存储区中使用 Claude Code 和 Grok Build,请指定一个 claude-code 来源和一个 grok 来源,并为二者设置相同的 cwd:二者都会复制日志,也都不会被要求记录。不要在该存储区中同时安装记录钩子。
facthouse init
选择 copy,设置 cwd。初始化时会询问是否复制现有日志,然后询问是否提取并整合(按 Enter = 所有已复制的行;选择 500 行或更多时,会要求再次输入选项)。拒绝提取的话,之后可以使用 facthouse consolidate 执行(--all 会处理剩余未检查的行,不包括因超出 7 天或 30 天窗口而跳过的行)。此后,服务会在处理 Facthouse 调用时复制新增行。提取和整合遵循工作原理中的表格。
压缩(推荐):facthouse notify compaction — 我们不会安装钩子。这不是回合结束时触发的 Stop 钩子。
MCP
适用于任何兼容 MCP 的工具。默认存储区:~/.facthouse。如需使用其他路径,请在 MCP 代码片段中设置 "env": { "FACTHOUSE_DATA": "/absolute/path" }。Windows 上的 JSON 接受正斜杠。
Cursor 会使用工具,但在适配器推出之前不会使用资源 — search_knowledge 和 get_entity 仍可在其中使用;请在会话开始时调用 get_session_context。
资源是客户端自动加载的上下文 — 无需调用工具。只有在助手记得主动调用时,工具才有用;资源则会直接呈现。
memory://briefing— 当前所有值得了解的信息:个人资料、上次整合中学到的内容、未解决的事项和近期知识。采用 Markdown,篇幅控制在大约一屏内。memory://profile— 核心身份事实,按重要性从高到低排列。
二者都是对同一数据库的只读视图,工具也会查询该数据库。对于从不加载资源的客户端(Cursor、Windsurf、Grok),只需在对话开始时调用 get_session_context,即可获取相同的简报。无需第二套个人资料架构。
工具
会话
log_event— 记录对话事件(消息、产物)。get_events— 检索当前或之前会话中的事件。get_session_context— 工作简报(与memory://briefing中的 Markdown 相同)以及本次会话中记录的事实。如果客户端未加载资源,请在每次对话开始时调用。
读取
get_entity— 获取有关任意命名主题(人物、组织、项目、地点、产品)的所有已知信息,以及它们之间的关联。如果不同类型下有多条同名记录,会返回所有记录中的事实。只有在不会将已存储为独立记录的两个名称合并时,连字符、下划线和多余标点才会被视为相同字母。如果没有该名称的实体,则会返回提及该表述的事实,而不是返回空结果。get_context— 获取与某个主题相关的所有信息(搜索 + 实体遍历)search_knowledge— 对整合后的知识进行混合搜索
写入
capture_fact— 存储事实。在副本存储中,这是用于补充提取时遗漏内容的修正;在sources为空的存储中,这是录入事实的方式。助手看到的描述也根据同一规则生成。consolidate— 将待处理事实整合到长期知识中。提取实体、合并重复项、检测矛盾并构建知识图谱。- 推理工具 — 需主动启用,默认关闭(在
config.json中设置inferences.enabled)。假设会引用已有事实 ID,并在确认前保持待处理状态。只有启用该开关后,这些工具才会注册。Consolidate 绝不会凭空编造无人说过的句子。
元信息
get_schemas— 可用领域及其结构get_stats— 事实数、实体数、领域分布、提取积压量、智能处理开销
CLI
MCP JSON 通过 npx 启动服务,无需全局安装。npm install -g 会将 facthouse 添加到 PATH,以便运行 init、settings、stats 和 inspect。无需 PATH 时,可使用同一 CLI 命令 npx -y -p "@facthouse/mcp" -- facthouse — 固定版本;请给软件包加引号,避免 PowerShell 将其拆分。-p 和 -- 可防止旧的全局二进制文件优先运行。没有 -p / facthouse 的 npx -y @facthouse/mcp 用于启动服务;不要将其作为 shell 命令来运行 init、settings 或 stats。MCP 配置片段用于启动服务,不会将 facthouse 添加到 PATH。若要在终端中检查文件,请参阅下方的 CLI。
这些 CLI 命令可在 bash、zsh 和 PowerShell 中运行。在 PowerShell 中,请给 @facthouse/mcp 加引号。Git Bash 的 /c/... 路径不能用于 PowerShell;请使用 C:/...,并传入 --data,不要使用 cd 或 export。在 Git Bash 中,请给反斜杠路径加引号,或写成 C:/... — 未加引号的 \ 会被视为转义符。所有平台都会展开 ~/。WSL 使用 /mnt/c/...。MCP 片段中的 FACTHOUSE_DATA 仅适用于该服务进程。终端中的 facthouse 命令需要使用 --data、在该 shell 继承的环境中设置 FACTHOUSE_DATA,或在此项目中使用 .facthouse 存储。Hooks 无法读取 mcp.json 中的 env。
npm install -g @facthouse/[email protected]
facthouse init --yes
如果 npm install -g 因为已存在名为 mcp 的命令而失败,请删除该遗留命令后重试。
npx -y -p "@facthouse/[email protected]" -- facthouse init --yes
npx -y -p "@facthouse/[email protected]" -- facthouse settings --json
npx -y -p "@facthouse/[email protected]" -- facthouse stats
npx -y -p "@facthouse/[email protected]" -- facthouse inspect
| 任务 | 用途 |
|---|---|
| MCP 服务(客户端启动的服务) | JSON 配置片段:使用带参数 -y 和固定版本 @facthouse/mcp@… 的 npx。无需全局安装。 |
PATH 中的 facthouse | npm install -g @facthouse/mcp@…(使用相同的固定版本)。更新配置片段时也要更新它。 |
| 稍后更改其他选项 | facthouse settings(或 settings --data <dir>)。不会重置文件。 |
| 不使用 PATH 运行单条 CLI 命令 | npx -y -p "@facthouse/mcp@…" -- facthouse … |
facthouse init [dir]
此引导流程用于帮助用户首次运行时写入 config.json。跳过此流程后,服务仍会在首次启动 MCP 时创建目录。
在终端中,init 会询问数据目录、复制对话记录还是助手记录(默认复制)、语义搜索和更多设置。--yes 不会显示提示,并会将 sources 留空。--web 会输出一个 127.0.0.1 URL,但不会打开浏览器;--yes 不接受 --web。在终端中,--force 仍会询问这些问题,然后替换整个文件;--yes --force 则会静默重置。--force 不会与之前的文件合并。
facthouse init --yes
facthouse init --yes ~/my-memory
facthouse init --yes --force
生成的 config.json 用于更改整合行为,最值得注意的是 intelligence.provider(默认为 cli;heuristic 表示零依赖的正则表达式回退方案,也可在运行时设置 FACTHOUSE_PROVIDER=heuristic)。Init 不会询问此字段。
facthouse settings
更改现有 config.json 中的额外选项(CLI 模型、超时、可选的本地提取)。不会重置文件的其余部分。如果不存在 config.json,则会拒绝执行(此命令不会创建存储)。--json / 非终端模式会输出当前选项且不会写入。--web 会在本地页面上显示相同选项(输出 URL,不会自动打开)。
facthouse settings
facthouse settings --data ~/my-memory
facthouse record
直接向数据库插入事件(无需运行中的服务)。适用于演示和没有命名来源的存储。不是 Claude Code 或 Cursor 的默认方式——默认方式是配置 sources,然后运行 facthouse consolidate。
# From a hook (reads JSON payload from stdin):
echo '{"hook_event_name":"UserPromptSubmit","prompt":"hello"}' | facthouse record --role user
# With explicit content:
facthouse record --role user --event-type message --content "hello world"
# Options:
# --role user | assistant | system | tool (default: user)
# --event-type message | tool_call | tool_result | artifact (default: message)
# --content-type text | json | image | audio | binary (default: text)
# --content Event content (or pipe via stdin)
# --speaker Named participant when the transcript has one
# --session-id Target session (default: most recent)
# --data Data directory (default: FACTHOUSE_DATA, a .facthouse store in this project, or ~/.facthouse)
facthouse consolidate
从 config.sources 复制新增内容行,从中提取候选事实,并将待处理事实整合到知识库中。这是唯一会调用模型的命令:
facthouse consolidate
facthouse consolidate --copy # copy only; spends nothing
facthouse consolidate --integrate # pending facts to knowledge; no extract pass
facthouse consolidate --all # extract the whole backlog now
facthouse consolidate --limit 200 # extract the oldest 200
# Steps — named steps run, in order; none named means all three:
# -c, --copy copy new transcript lines into the store
# -e, --extract turn new lines into candidate facts (the model call)
# -i, --integrate classify, link, dedupe, supersede, embed
# Extract is capped at 50 lines per run so a first backfill is never spent on
# the lot; the run says how many remain. --all lifts the cap, --limit N sets it.
# --json print the result object instead of the summary
# --data Data directory (default: FACTHOUSE_DATA, a .facthouse store in this project, or ~/.facthouse)
遵循已配置的提供方(默认为 claude -p)。sources 为空时,复制步骤不会执行任何操作。除非打算复制每个项目组,否则请为来源设置 cwd。对于有命名来源的存储,请勿同时运行 record 钩子。
facthouse notify <moment>
通知正在运行的 MCP 服务某个时刻已发生。服务会决定运行什么,并在后台执行,因此钩子会立即返回:
facthouse notify compaction # client about to compact: copy new JSONL, extract, integrate (does not wait)
facthouse notify threshold # events arrived: extract if the threshold is due
# Options:
# --data Data directory (default: FACTHOUSE_DATA, a .facthouse store in this project, or ~/.facthouse)
没有服务在监听并不算错误:命令会说明情况并以状态码 0 退出,下次会话启动时会处理。这是 PreCompact 钩子调用的命令。
facthouse search <query>
facthouse search "coffee"
facthouse search "coffee" --domain preferences
facthouse search "coffee" --json
# Options:
# --domain Prioritise a domain. Biases ranking; does not filter
# --limit Maximum results (default: 20)
# --json Emit the raw search payload
# --data Data directory (default: FACTHOUSE_DATA, a .facthouse store in this project, or ~/.facthouse)
--domain 会影响排序权重,而不是进行筛选。 硬性筛选会隐藏归档在近义领域下的事实。
facthouse stats
facthouse stats
facthouse stats --json
事实不可变——被取代的事实仍会保留——因此,只要有事实被取代,当前数量与总数就会有所不同。--json 会包含执行查询的二进制文件的包版本。智能处理开销指提取 / 分类 / 实体 / 对账 / 取代 / 摘要各阶段的调用次数、令牌数和耗时,并列出每个阶段使用的提供方和模型。嵌入不计入该数字。
facthouse inspect
抽样查看 D、I、K、实体和图谱。在数据目录下写入本地 HTML 文件(而非当前工作目录),并输出文件路径。不会打开浏览器。该文件是记忆导出——请像对待 stats --json 一样谨慎处理。同一页面还会显示智能处理开销(Graph / Spend)。
facthouse inspect
facthouse inspect --graph
facthouse inspect --layer k
facthouse inspect --json
facthouse inspect --entity Helios --limit 20 --output ~/inspect.html
--layer health|d|i|k|entities|graph|all 会输出终端表格(按最新优先排列,数量有限)。--graph(未指定 --layer / --json 时的默认选项)会写入 inspect.html。表格的 --limit 默认为 10,画布为 50。--all 会绘制所有节点——图面会变得杂乱,需明确指定。页面中的搜索和类型筛选仍可找到超出数量限制的节点。
高级
另一个存储目录
存储目录就是此目录。客户端使用相同路径即可共享。第二个存储对应的是第二个目录,而不是第二次安装。默认 MCP 服务名称为 facthouse。拆分存储并不是按写入记录的客户端进行筛选。工作和个人用途是拆分的一个原因,但并非必需的设置。
非默认数据目录会打印一个不同的 MCP 服务名称,这样两个存储就能共用一个 mcp.json。针对每个额外目录运行 Init 时,会打印相应配置片段。示例:
{
"mcpServers": {
"facthouse-personal": {
"command": "npx",
"args": ["-y", "@facthouse/[email protected]"],
"env": { "FACTHOUSE_DATA": "C:\\Users\\alex\\.facthouse-personal" }
},
"facthouse-work": {
"command": "npx",
"args": ["-y", "@facthouse/[email protected]"],
"env": { "FACTHOUSE_DATA": "C:\\Users\\alex\\.facthouse-work" }
}
}
}
将每个存储的 sources.cwd(或 hook --data)仅指向对应的存储目录。如果两个目录都复制了同一个主目录,那么这两个目录并不能隔离任何内容。
Postgres(可选)
SQLite 是默认选项,无需安装其他软件。若要改用 Postgres,请在对应存储的 config.json 中将 storage.provider 设为 "postgres",或在 MCP 条目上设置 FACTHOUSE_STORAGE=postgres,并将 FACTHOUSE_POSTGRES_URL 设为 postgres://(或 postgresql://)URL。密码应放在环境变量中,而不是 config.json 中。如果缺少 URL 或无法连接服务,Facthouse 会停止运行;不会创建 SQLite 文件。
数据目录仍是记忆的存储位置:config.json 和调度器套接字位于其中。数据表存储在 URL 指向的位置。两个记忆需要两个目录和两个数据库。
Init 不会询问要使用哪种引擎。facthouse init --yes 仍会写入 sqlite。
示例 — 仅作占位符;不要将真实密码写入已提交的文件:
{
"mcpServers": {
"facthouse": {
"command": "npx",
"args": ["-y", "@facthouse/[email protected]"],
"env": {
"FACTHOUSE_DATA": "C:\\Users\\alex\\.facthouse-work",
"FACTHOUSE_STORAGE": "postgres",
"FACTHOUSE_POSTGRES_URL": "postgres://USER:PASSWORD@localhost:5432/facthouse"
}
}
}
}
复制还是记录
每个存储选择一种机制。
推荐 — 复制。 指定一个 claude-code、cursor 或 grok 来源(设置 cwd),并先从 CLI 运行 facthouse consolidate。MCP 服务也会在会话开始时及处理调用时进行复制。Codex 是后续适配器。未知的 kind 值会被拒绝。
{
"sources": [
{
"kind": "claude-code",
"home": "~/.claude",
"cwd": "C:\\dev\\app"
}
]
}
home 是客户端配置目录(~/.claude 或 ~/.cursor — 路径示例,不会额外搜索其他位置)。Cursor 使用 "kind": "cursor",且只读取 home/projects/*/agent-transcripts/**/*.jsonl — 不读取 Composer SQLite。Cursor 会将 C:\\dev\\app 编码为 c-dev-app(Claude Code 使用 C--dev-app)。首次回填超过 50 行时,需要分多次运行,或运行一次 facthouse consolidate --all。
替代方案 — 记录,不配置 sources。 将 sources 留空。如果有客户端 hook 负载,可将其通过管道传给 facthouse record。MCP log_event / capture_fact 仍可正常工作。
不要在此存储上安装记录 hook — 两者会写入相同的行。Facthouse 不会检测或重写已有的 hook 配置。
仅 MCP 记录模式
若要跳过向导(仅记录 — 不复制对话记录),请粘贴以下内容。服务会在首次启动时创建 ~/.facthouse;系统不会询问这些问题。
{
"mcpServers": {
"facthouse": {
"command": "npx",
"args": ["-y", "@facthouse/[email protected]"]
}
}
}
Hooks
PreCompact notify compaction 很有用:客户端即将压缩时,一个短暂运行的 hook 会通知正在运行的服务,并立即返回。服务会复制新增的 JSONL 行,然后提取并整合——压缩不会删除对话记录,hook 也不会复制实时窗口。Init 会输出这段 JSON,并填入 --data。将其粘贴到 Claude Code 的 .claude/settings.json(用户级或项目级)中。我们不会安装它。不要安装 Stop hook。不要在这个存储上安装记录 hook——两者会写入相同的行。
mcp.json 中的 env 对 hook 不可见。传入相同的 --data(或在客户端自身继承的环境中设置 FACTHOUSE_DATA)。命令必须调用 CLI(facthouse),绝不能调用服务二进制文件。不带 -p / facthouse 的 npx -y @facthouse/mcp 会启动 MCP 服务,导致 hook 挂起。固定软件包版本;如果 hook 由 PowerShell 运行,则给版本加引号;并在 facthouse 前加上 --,以免 PATH 中全局安装的旧版二进制文件优先被调用。
PreCompact hook JSON
{
"hooks": {
"PreCompact": [
{
"hooks": [
{
"type": "command",
"command": "npx -y -p @facthouse/[email protected] -- facthouse notify compaction --data /absolute/path/to/the-same-store"
}
]
}
]
}
}
PreCompact notify compaction 会要求正在运行的服务进行整合:复制最新的 JSONL 行、提取并整合。hook 会立即返回;后续工作由服务完成。我们不会安装回合结束时触发的 Stop hook。在 Windows 上,--data 路径与填入 FACTHOUSE_DATA 的绝对目录相同(例如 C:\\Users\\alex\\AppData\\Local\\Temp\\facthouse-try)。
频繁增量复制会让对话在全局序列中交错:持续打开的长对话会被其他对话穿插分割。提取进度按对话分别记录,因此一个对话超时不会导致丢弃另一个对话的数据。减小 extraction.batch_size 会增加提取调用次数(超时的机会也更多),而不是对整个存储一概暂停处理。facthouse stats 会报告相对于提取水位线尚未提取的事件。
如果 MCP 服务未启动,或未列出任何工具,请检查客户端实际启动的软件包版本。PATH 中全局安装的 facthouse 可能比本 README 指定的版本落后多年。使用 facthouse stats --data <dir> 诊断(CLI 会显示调度器是否正在监听),并通过 stdio 检查 initialize 返回的 serverInfo.version 以及 tools/list。0.2.x 会对 initialize 作出响应,然后在 tools/list 时抛出异常。
Embeddings、模型、超时、双时态
在 config.json 中将 embedding.provider 设为 "ollama"(本地,无需 API 密钥)或 "voyage"(托管),然后运行 facthouse consolidate,搜索 "food" 就会开始返回过敏信息。事实会在整合时生成嵌入。Voyage 会实施 每分钟 3 次请求的速率限制,直到账户添加付款方式。
当向量集合较小时,语义搜索会精确扫描已存储的向量。集合较大时(当前模型默认达到 32 MiB),则改用这些向量的 HNSW 索引:在 SQLite 上使用进程内索引,或在启用扩展时使用 Postgres vector 侧车。小型存储仍使用精确搜索。如果缺少引擎,则继续进行精确搜索并打印警告;Facthouse 不会安装原生插件。embedding.ann 可以设为 null(自动)、false(从不)或 true(引擎允许时强制启用)。这不会启用嵌入功能。
intelligence.cli.model 和 intelligence.cli.timeout_ms 是额外的可调选项。首次运行时,可在“更多设置”(Y)中写入这些选项;之后可运行 facthouse settings。初始化不会询问 intelligence.provider;FACTHOUSE_PROVIDER=heuristic 是紧急停用开关。启发式回退不会从转录内容中提取事实。
未注明姓名的用户频道语音会归属于存储的所有者;显示名称仍不会创建人物。额外佐证(同意、工具观察、另一位发言者复述)会被记录,但不会参与评分,除非存储在 config.json 中设置了 interlocutor 排序权重。引擎不提供任何默认权重。权重键与存储的发言者字符串匹配,因此两个同名者会共用一个键。
将 temporal.mode 设为 bitemporal,即可记录系统何时撤回某项信念,从而让搜索能够回答存储在某个时刻相信什么。
智能处理开销
facthouse stats 和 get_stats 会报告计费的整合调用:各阶段(extract、classify、entities、reconcile、supersede、summarise)的 tokens、耗时,以及所用的提供方和模型。未报告 tokens 的运行不会显示这些字段,而不是显示为零。嵌入使用不同的 API,不计入此数字。
可选的 intelligence.token_budget 会按滚动时间窗口限制每个提供方的计费 extract 用量。未设置时不设上限。超过上限后,consolidate 会跳过 extract、保留水位标记,且不会回退到启发式处理。Stats 和 inspect Spend 会显示每项上限的已用量和剩余额度,以及该时间窗口中最早用量到期的时间(resets)。
"intelligence": {
"token_budget": {
"cli": { "week": "10M" }
}
}
hour、day、week 和 month 均为滚动窗口。省略某个粒度即可不设该项上限。facthouse stats、get_stats 和 inspect Spend 会显示剩余额度。在此存储的 config.json 中设置上限——没有 budget 命令。
可选的本地智能处理开关与嵌入开关不同。在兼容 OpenAI 的主机上添加 intelligence.http。协议为 POST /v1/chat/completions;只有端口会变化:
| 主机 | 常用 URL |
|---|---|
| Ollama | http://localhost:11434/v1(省略 URL 时的默认值) |
| LM Studio | http://localhost:1234/v1 |
| vLLM | http://localhost:8000/v1 |
| llama.cpp | http://localhost:8080/v1 |
模型字符串以该主机列出的名称为准。GET {base_url}/models 会打印这些名称。nomic-embed-text 仅用于嵌入,无法执行 extract。如果主机已启动且只提供一个聊天模型,Facthouse 会在本次运行中使用该模型,并提示你固定设置 intelligence.http.model。如果列出了多个聊天模型,请设置该字段;extract 不会自行猜测。
Extract 和 summarise 随后会使用该主机;reconcile 和 supersede 仍使用 CLI,除非你列出 intelligence.stages。每个阶段都可以将失败时的处理设为 cli、http 或 none(见下方 JSON)。HTTP extract 默认会在失败时重试 CLI(计入 CLI token 预算)。Contradiction 默认设为 none——不会切换提供方。none 会保留 extract 水位标记——不会回退到启发式处理。首次运行时,可在 More settings(推荐路径之后选择 Y)设置主机、模型和 extract 的失败处理方式。之后,facthouse settings 会将这些选项合并到现有文件中,不会重置文件。facthouse inspect Spend 会显示相同的选项并复制 JSON;它不会保存 config.json。
实时脚本 npm run test:http-intelligence 已在 qwen2.5vl:7b 上通过。
"intelligence": {
"http": {
"base_url": "http://localhost:11434/v1",
"model": "qwen2.5vl:7b"
},
"stages": {
"extract": { "provider": "http", "on_fail": "cli" },
"summarise": { "provider": "http", "on_fail": "cli" },
"reconcile": { "provider": "cli", "on_fail": "none" },
"supersede": { "provider": "cli", "on_fail": "none" }
}
}
CLI 演示(无对话记录来源)
临时存储,不是用于捕获真实 Claude Code 或 Cursor 主目录内容的路径。以下三行由用户输入。
export FACTHOUSE_DATA=/tmp/facthouse-demo
om() { npx -y -p "@facthouse/[email protected]" -- facthouse "$@"; }
om init --yes
om record --role user --content "I prefer dark mode in every editor, and I never want telemetry enabled."
om record --role user --content "I am allergic to shellfish, so avoid seafood restaurants when booking anything."
om record --role user --content "My colleague Robin at Acme is leading the Atlas migration project this quarter."
om consolidate
om search "Atlas"
om stats
$env:FACTHOUSE_DATA = Join-Path $env:TEMP "facthouse-demo"
function om { npx -y -p "@facthouse/[email protected]" -- facthouse @args }
om init --yes
om record --role user --content "I prefer dark mode in every editor, and I never want telemetry enabled."
om record --role user --content "I am allergic to shellfish, so avoid seafood restaurants when booking anything."
om record --role user --content "My colleague Robin at Acme is leading the Atlas migration project this quarter."
om consolidate
om search "Atlas"
om stats
allergies 不是 Facthouse 内置的领域。引擎没有内置词汇表——它读取对话后判断该事实需要归入一个类别。领域影响排序,而非过滤。清理命令:rm -rf /tmp/facthouse-demo(Git Bash / macOS / Linux)或 Remove-Item -Recurse -Force $env:TEMP\facthouse-demo(PowerShell)。
集成
Facthouse 的工具描述会告诉助手何时搜索,以及何时值得暂存一项更正。它们不是 Claude Code 对话进入存储的方式——对话是从指定来源复制进来的。
无需配置
Claude Code、Cursor 或 Grok Build:指定一个 sources 条目(设置 cwd),并先从 CLI 运行 facthouse consolidate。MCP 会话启动时也会复制内容。如果助手需要更正或补充复制加提取无法生成的内容,可使用 capture_fact。
没有复制适配器的客户端仍需依赖 log_event / capture_fact,直到其适配器推出为止。
Hook 点
| Hook 点 | 时机 | 调用内容 | 原因 |
|---|---|---|---|
| 会话开始 | 对话开始时 | memory://profile(自动)、search_knowledge | 助手从第一条消息起就了解你 |
| 更正 | 存储中缺少持久事实时 | capture_fact | 可选;Claude Code 对话已通过复制存入 session_events |
| 回复前搜索 | 生成回复前 | search_knowledge、get_context | 回复会参考已存储的知识 |
| 压缩前 | 压缩上下文窗口前 | facthouse notify compaction | 服务会复制新增行、提取并整合 |
| 自然断点 | 主题变更、任务完成时 | consolidate(可选) | 保持知识图谱最新 |
关于压缩前:facthouse notify compaction 会请求服务进行整合。它不是 record Hook。
Claude Code
在项目中创建 .claude/rules/facthouse.md(或在全局位置创建 ~/.claude/rules/facthouse.md):
# Facthouse
- Conversations are copied from the named Claude Code source (first backfill: `facthouse consolidate` on the CLI)
- Do not install record hooks on this store — both write the same rows.
- Identity context loads automatically from the `memory://profile` resource — no tool call needed
- Before answering questions this store might already know, call `search_knowledge`
- Call `capture_fact` only to correct or add something that is not in the transcript
- When the conversation is getting long, call `consolidate` (or rely on PreCompact `facthouse notify compaction`)
- At natural breakpoints (topic change, task completion), call `consolidate` to keep the knowledge graph current
要允许 Facthouse 工具在无需逐次调用审批提示的情况下使用,请将其添加到 .claude/settings.json 中的 permissions.allow 数组:
{
"permissions": {
"allow": [
"mcp__facthouse__*"
]
}
}
Cursor / Windsurf
在 Cursor Directory 上,Add to Cursor 按组件分别操作:在 MCP 服务上点击一次,再在规则上点击一次。这会在 ~/.facthouse 中启动一个记录存储,无需运行 facthouse init。Hooks 选项卡中的操作是复制到 ~/.cursor/hooks.json,而不是 Add to Cursor。要复制 Agent 转录记录,请运行 facthouse init,选择 copy,再选择 kind cursor。
在项目根目录的 .cursorrules(Cursor)或 .windsurfrules(Windsurf)中添加:
When the facthouse MCP server is available:
- At the start of every conversation, before answering, call get_session_context unless you already loaded the memory://briefing resource. That call returns the same working briefing the resource would have injected. Tools-only clients never fetch resources.
- Before answering questions this store might already know, call search_knowledge
- To find out everything known about a particular person, project, or thing, call get_entity
- Call capture_fact only to correct or add something copy or extraction missed
Cursor 和 Windsurf 会使用工具,但不会使用资源,因此 memory://profile 不会在这两者中自动加载。Cursor 对话本身会以 kind: "cursor" 复制(存储在 ~/.cursor/projects/ 下的 JSONL 文件中,而非 SQLite composer 存储)。
Grok Build 对话会以 kind: "grok" 复制:~/.grok/sessions/(或 GROK_HOME)下的 chat_history.jsonl,而非 updates.jsonl。推理内容、系统行、注入的提醒以及子 Agent 运行记录(父会话在其 subagents/ 下列出的会话)都会跳过。
Claude Desktop / 其他 MCP 客户端
目前还没有复制适配器。工具描述会处理搜索和可选的 capture_fact;在后续适配器推出前,不会持续读取对话。
释放空间
Facthouse 会将原始对话和工具输出记录到 session_events。在接入 Agent 客户端的存储中,这几乎会占据整个数据库。在一个日常使用中的存储里,21 条已整合事实对应着 47,000 条事件和 493 MB 数据。
facthouse stats 会在报告知识的同时报告原始数据层,包括其中可释放的空间。要释放这些空间:
facthouse prune # report only — nothing is deleted
facthouse prune --apply --vacuum # delete, then rebuild the file
在 config.json 中将 retention.disk_budget 设置为 "2GB" 之类的大小,以限制 memory.db。未设置时不限制;初始化时不会写入上限。设置上限后,如果文件已满,系统会自动清理无法访问的原始事件,让新日志复用这部分空间;如果没有未使用的空间,则会拒绝更多原始事件。绝不会为了达到上限而删除事实。压缩(--vacuum)仍需手动执行——它会复制整个文件,让操作系统看到文件变小。
如果你认为这些数据大多是无用的工具输出,可以通过 extraction.event_types 和 extraction.roles 限制检查范围,并通过 extraction.min_content_length 跳过无关紧要的事件。请先测量再决定。数据量和价值并不是同一维度。
判断依据是可访问性,而不是时间。 只有同时满足以下三项,事件才会被删除:
- 提取流程已经读取过该事件。位于整合水位线之后的内容仍是输入。
- 没有任何事实的溯源信息引用该事件。
- 该事件已不在其所属会话最近的
extraction.working_memory_size条事件范围内——这段余量让整合流程仍能查看近期的原始记录。这个窗口用于提供当前主题的依据,而不是充当代词词典。
事实、实体、嵌入或搜索结果均不受影响。删除行本身不会缩小文件——这需要执行 --vacuum。如果未设置上限,就不会自动清理任何内容。
开发
git clone https://github.com/gordonkjlee/facthouse
cd facthouse
npm install
npm run build
npm test
npm test 始终运行隔离的流水线(fixture JSONL → copy → extract →
search),并使用记录型提取器;需要真实模型的实时评测则会跳过:
- 语义召回需要 Ollama 和
nomic-embed-text。启动它,然后运行npm run test:semantic。 - 实时首条事实评测需要
claudeCLI。运行npm run test:first-fact。 - 实时编码存储评测(具有仓库结构的 Cursor 转录)也需要
claudeCLI。运行npm run test:coding-store。 - 本地 HTTP 提取需要 OpenAI 兼容主机上的聊天模型,以及
FACTHOUSE_HTTP_MODEL(已在qwen2.5vl:7b上验证)。运行npm run test:http-intelligence。
缺少依赖时,这些脚本都会报错而不是跳过,因此测试全部通过就意味着相关说法确实经过验证,而不是被悄悄略过。
参与贡献
欢迎提交问题和拉取请求。如果改动不只是修正拼写错误,请先提交问题。
- 问题咨询:GitHub 讨论区
- 如何构建和测试:CONTRIBUTING.md
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。