mcpField
F
Facthouse

Facthouse

本地服务
github.com/gordonkjlee记忆与知识33 周前更新

关于 Facthouse

Facthouse 是面向 AI 工具的本地记忆引擎,将会话活动整理为相互关联的知识并存入 SQLite。它支持复制会话记录或通过 MCP 捕获事实,并可选语义搜索。

主要功能

  1. 01基于 SQLite 的本地存储
  2. 02实体关联的知识图谱
  3. 03支持可选嵌入的混合搜索
  4. 04复制会话记录或捕获事实
  5. 05整合知识并处理冲突

适用场景

  1. 01在不同 AI 会话间延续有用事实
  2. 02搜索与主题或实体相关的知识
  3. 03整合复制来的会话记录

MCP 相关

提供用于记录、读取、搜索和整合记忆的 MCP 工具,以及简报和个人资料资源。MCP 客户端可通过复制会话记录或直接捕获事实来使用它。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"gordonkjlee-facthouse": {
"command": "npx",
"args": [
"-y",
"@facthouse/mcp"
]
}
}
}
启动命令npx -y @facthouse/mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@facthouse/mcp0.31.0

工具

10

收录的工具列表 · 更新于 2 周前

参数类型必填说明
roleenum是生成此事件的通道(user、assistant、system、tool)。对于群组记录中有姓名的人物,将 role 保持为 user,并传入 speaker。user | assistant | system | tool
contentstring|null是事件的文本内容
speakerstring|null否记录中有姓名的参与者(例如 Alex)。role 保持为通道;不要虚构人物角色。
metadataany否任意元数据
event_typeenum是事件类型message | tool_call | tool_result | artifact
content_refstring|null否非文本内容的 URI 或路径
content_typeenum否内容的解释方式。消息默认使用 'text'。结构化数据使用 'json',屏幕截图或生成的图像使用 'image',语音或音频片段使用 'audio',其他所有非文本内容使用 'binary'。text | json | image | audio | binary

详细介绍

Facthouse

Facthouse

Facthouse 是面向 AI 工具的本地记忆引擎。大多数“记忆”产品会为聊天记录建立索引。Facthouse 获取 Agent 活动——消息、工具使用以及其他 MCP 流量——并运用受神经科学启发的巩固机制,使其依次经历 数据(会话中发生的事)→ 信息(提取出的事实)→ 知识(在实体图谱上整合的信念)。在此过程中,Facthouse 会关联实体、删除重复项、协调冲突,并以最新信息取代过时内容。向量嵌入可在此图谱之上提供可选的语义搜索。存储内容保存在你磁盘上的 SQLite 文件中。

npm CI License: MIT

快速开始

需要 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 是另一种策略(仅在条件满足时提取)。

自动执行

时机CopyExtract(D→I)Integrate(I→K)
Facthouse MCP 服务启动是是(上限 50)是
调用 Facthouse 工具或资源是,前提是已指定来源且 JSONL 有新增内容否否
Facthouse MCP 进程退出否否是

可调用

调用来源CopyExtract(D→I)Integrate(I→K)
consolidateMCP 工具或命令行。调用方会等待。是是(上限 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 中的 facthousenpm 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
Ollamahttp://localhost:11434/v1(省略 URL 时的默认值)
LM Studiohttp://localhost:1234/v1
vLLMhttp://localhost:8000/v1
llama.cpphttp://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 跳过无关紧要的事件。请先测量再决定。数据量和价值并不是同一维度。

判断依据是可访问性,而不是时间。 只有同时满足以下三项,事件才会被删除:

  1. 提取流程已经读取过该事件。位于整合水位线之后的内容仍是输入。
  2. 没有任何事实的溯源信息引用该事件。
  3. 该事件已不在其所属会话最近的 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。
  • 实时首条事实评测需要 claude CLI。运行 npm run test:first-fact。
  • 实时编码存储评测(具有仓库结构的 Cursor 转录)也需要 claude CLI。运行 npm run test:coding-store。
  • 本地 HTTP 提取需要 OpenAI 兼容主机上的聊天模型,以及 FACTHOUSE_HTTP_MODEL(已在 qwen2.5vl:7b 上验证)。运行 npm run test:http-intelligence。

缺少依赖时,这些脚本都会报错而不是跳过,因此测试全部通过就意味着相关说法确实经过验证,而不是被悄悄略过。

参与贡献

欢迎提交问题和拉取请求。如果改动不只是修正拼写错误,请先提交问题。

许可证

MIT

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。