1. 项目概述打造你的本地AI对话记忆库如果你和我一样每天都要和Claude Code、Cursor、Codex这些AI编程助手打交道那么你一定遇到过这个场景上周明明和AI助手一起解决了一个棘手的Webhook重试问题但今天想回顾一下当时的解决方案却怎么也想不起来是在哪个项目、哪次对话里讨论的了。你只能凭感觉在历史记录里翻找或者干脆重新问一遍。这种“对话失忆”不仅浪费时间更关键的是那些宝贵的、结合了你具体上下文的解决方案就这么被埋没了。aii这个工具就是为了解决这个痛点而生的。它本质上是一个本地化的、全功能的AI对话搜索引擎。它的核心工作流程非常直观自动扫描你电脑上所有主流AI编程助手目前支持Claude Code、Codex、Cursor产生的对话记录将这些零散的、非结构化的聊天数据统一索引到一个本地的SQLite数据库中并利用FTS5全文搜索技术让你能像使用Google一样瞬间从海量历史对话中定位到你需要的信息。这个工具最吸引我的几个特点是纯静态二进制、零网络依赖、以及原生为AI Agent设计。这意味着你下载一个可执行文件就能用所有数据都在你本地绝对隐私并且它还能通过MCPModel Context Protocol协议直接成为你AI助手的一个“外挂大脑”让AI助手也能主动查询你的历史对话。接下来我将详细拆解它的设计思路、核心用法、以及我在深度使用中积累的一些实战技巧和避坑指南。2. 核心设计思路与架构解析2.1 为什么是SQLite FTS5aii选择SQLite作为存储后端是一个极其务实且高明的决策。对于个人本地工具而言SQLite几乎是最完美的选择它是一个零配置、服务器进程、自包含、事务性的SQL数据库引擎。这意味着aii无需依赖任何外部数据库服务如MySQL、PostgreSQL用户安装后就是一个独立的二进制文件数据库文件aii.db就静静地躺在你的~/.local/share/aii/目录下。而FTS5是SQLite的全文搜索扩展模块。aii巧妙地使用了双索引并行搜索的策略messages_fts索引使用porter分词器支持词干提取如“running”会匹配“run”和去除变音符号。这非常适合自然语言查询例如搜索“webhook retry”能很好地匹配到相关讨论。messages_fts_tri索引使用trigram三元组分词器。它将文本按每三个连续字符进行切分。这个索引的核心价值在于匹配代码标识符和任意子字符串。例如当你搜索一个驼峰命名的变量SessionUID或下划线命名的函数normalize_match时porter分词器可能会在大小写或下划线处将其拆分成独立的词条导致匹配失败。而trigram索引则能精准匹配到这些连续的字符组合。搜索时aii会同时查询这两个索引合并结果并根据算法对分数进行加权三元组索引的分数会乘以0.7以便在平局时让自然语言索引胜出。对于短于3个字符的查询则会跳过三元组索引因为无法构成有效的三元组。这种混合搜索策略确保了无论是模糊的自然语言提问还是精确的代码片段、错误信息搜索都能有很高的召回率。2.2 数据源解析与增量索引机制aii目前支持三个数据源其解析方式体现了对各自数据结构的深度理解Claude Code: 解析~/.claude/projects/*/*.jsonl文件。JSONLJSON Lines格式便于逐行读取和增量更新。Codex: 同时解析会话文件 (~/.codex/sessions/**/rollout-*.jsonl) 和全局历史文件 (~/.codex/history.jsonl)。Cursor: 这是一个特例因为它将对话存储在SQLite数据库 (state.vscdb) 中。aii需要直接读取这个数据库文件并解析其中特定的表结构来提取对话。增量索引是aii保持高效的关键。默认情况下aii index命令是增量的对于JSONL文件Claude Code, Codex它会记录上次读取的字节偏移量byte offset下次只读取新增的部分。对于Cursor的SQLite它使用“气泡计数”bubble count作为指纹只重新读取有新“气泡”即消息的会话。所有数据源解析出的新消息批次会被发送到一个单写者协程这个协程负责以会话为单位进行事务写入。这种设计避免了并发写入SQLite可能导致的锁冲突和性能问题保证了数据的一致性。注意aii在索引时默认会进行内容脱敏。它会识别并替换掉消息中的敏感信息如API密钥、访问令牌、JWT、私钥等替换为[REDACTED:label]。这个功能在internal/redact/redact.go中定义规则。如果你需要索引原始内容例如为了搜索某些特定的令牌格式可以使用--no-redact参数。--redact-sources参数则会直接重写原始的JSONL文件此操作不可逆Cursor的SQLite文件则不会被修改。2.3 为AI Agent而生的设计哲学aii不仅仅是一个给人用的CLI工具它的更高阶目标是成为AI Coding Agent的“长期记忆体”。这体现在以下几个设计上MCP服务器通过实现一个标准的MCPModel Context Protocol服务器aii可以无缝集成到Claude Code等支持MCP的AI助手环境中。AI助手可以直接调用aii提供的工具如search,get_session来查询你的历史对话从而获得更丰富的上下文做出更准确的判断。稳定的引用令牌Cite Token每条消息或摘要都有一个唯一且稳定的标识符格式如cc/32e869ac:319。AI助手可以像人类使用超链接一样在回答中引用这个令牌。当你或另一个工具需要查看原文时可以通过这个令牌精确定位。机器友好的输出除了给人看的彩色终端输出pretty模式aii默认在输出被管道重定向时会自动切换为ndjsonNewline Delimited JSON格式。每一行都是一个完整的JSON对象方便其他程序如AI Agent进行流式解析和处理。令牌预算Token Budgets通过--max-bytes和--max-msg-chars参数可以严格控制输出的大小。这对于需要将aii的输出作为上下文喂给有长度限制的LLM的场景至关重要。ndjson模式下它会在预算内输出完整的最后一行并追加一个截断标记保证输出的仍然是合法JSON流。这种设计使得aii从一个被动的查询工具转变为一个主动的、可被AI调用的知识服务真正实现了人机协作的闭环。3. 从安装到精通完整实操指南3.1 环境准备与安装aii是Go语言编写的因此最直接的安装方式是使用Go工具链。确保你的系统已经安装了Go1.21版本推荐。安装方法一使用go install推荐这是最快捷的方式适合绝大多数用户。go install github.com/ericmason/aii/cmd/aiilatest安装完成后确保$GOPATH/bin通常是~/go/bin在你的系统PATH环境变量中。你可以通过运行aii version或aii help来验证安装是否成功。安装方法二从源码编译如果你想体验最新可能不稳定的特性或者进行二次开发可以克隆仓库并自行编译。git clone https://github.com/ericmason/aii.git cd aii go build -o ~/.local/bin/aii ./cmd/aii同样请确保~/.local/bin在你的PATH中。首次运行与数据库初始化安装后直接运行aii index命令。aii会自动在默认路径~/.local/share/aii/aii.db创建SQLite数据库文件并开始扫描所有已支持的数据源。你可以通过AII_DB环境变量来指定自定义的数据库路径。实操心得第一次索引可能会花费一些时间具体取决于你的历史对话数据量。建议在首次运行时加上--verbose参数这样可以看到每个会话被索引的进度心里有底。aii doctor是一个很好的诊断命令运行后它会显示数据库路径、各数据源路径以及已索引的会话/消息数量帮你快速确认一切是否就绪。3.2 核心命令详解与实战用例aii的核心功能通过一系列子命令暴露。下面我们结合具体场景来深入理解每个命令。3.2.1aii index构建与更新你的知识库这是所有搜索的基础。通常你只需要在安装后运行一次aii index之后aii会在每次搜索前自动进行快速的增量更新。但你也可以手动管理索引过程。基础索引aii index。扫描所有数据源只索引新增或修改的内容。完整重建aii index --full。这会清空现有索引并从头开始重建。当你修改了脱敏规则或者怀疑索引数据出现不一致时可以使用。指定数据源aii index --source cursor。如果你只使用Cursor或者想单独更新某个助手的数据可以用这个参数。查看详情aii index --verbose。输出详细的处理日志并在最后执行ANALYZE命令来优化SQLite查询计划适合在性能调优或排查问题时使用。3.2.2aii search像使用搜索引擎一样查找对话这是最常用的命令。其查询语法经过精心设计兼顾了易用性和强大功能。基础搜索aii search webhook retry。这会同时在自然语言和代码标识符中搜索包含“webhook”和“retry”的记录。精确短语aii search api key rotation。使用双引号来搜索完整的短语避免单词被拆分。过滤搜索# 只搜索Claude Code中的对话 aii search deploy --agent cc # 搜索过去7天内我用户角色提出的问题 aii search 测试失败 --since 7d --role user # 只搜索某个特定工作区下的对话 aii search bug --workspace $HOME/projects/my-app输出控制# 强制以JSON格式输出便于用jq等工具处理 aii search error --json | jq .[0].excerpts # 限制输出字节数防止结果过长 aii search long log --max-bytes 4096注意事项搜索时如果发现完全匹配的代码标识符如SessionUID搜不到很可能是三元组索引没有正确构建。可以运行aii index --full重建索引或者手动在数据库上执行SQL命令来重建该索引sqlite3 ~/.local/share/aii/aii.db INSERT INTO messages_fts_tri(messages_fts_tri) VALUES(rebuild);。3.2.3aii show查看完整的对话上下文当你通过搜索找到感兴趣的会话后aii show可以让你查看完整的对话内容并且支持灵活的“切片”查看。查看完整会话aii show 会话UID。UID可以在aii search的结果中找到也可以用前8位缩写。查看最近会话aii show --last。快速打开最近索引的一个会话。上下文切片这是非常强大的功能。# 查看以第42条消息为中心的附近3条消息前1条后1条 aii show cc/32e869ac:42 --around 42 --span 3 # 查看第10条到第20条消息 aii show cc/32e869ac --from 10 --to 20 # 只查看用户发送的消息快速回顾自己当时问了什么 aii show cc/32e869ac --role user格式化输出--format md会以Markdown格式输出适合复制到笔记中--format ndjson则是机器可读的流式格式。3.2.4aii ask让本地LLM基于你的历史对话回答问题这是aii的“杀手级”功能之一。它结合了搜索Retrieval和本地LLM实现了一个私有的、基于你所有对话历史的问答系统。基础问答aii ask 我之前是怎么解决SSL证书验证失败的。aii会将问题转化为查询执行aii search。获取最相关的K个结果默认6个。为每个结果提取最佳摘要并扩展其上下文默认前后各2条消息。将所有上下文片段、引用令牌以及你的原始问题组合成一个结构化的Markdown提示词。调用配置好的本地LLM命令行工具如claude -p,ollama run llama3将提示词输入并返回LLM生成的答案。配置LLM命令如果claude或codex不在你的PATH中你需要通过环境变量或参数指定。# 方式一设置环境变量持久化 export AII_ASK_CMDollama run llama3 # 方式二通过参数指定单次有效 aii ask 问题 --cmd ollama run llama3仅生成提示词aii ask 问题 --dry-run。这个参数非常有用它会输出将要发送给LLM的完整提示词而不实际调用LLM。你可以检查aii为你检索到的上下文是否相关。将提示词手动发送给其他LLM服务如ChatGPT网页版。学习aii构建提示词的模板用于你自己的项目。显示来源aii ask 问题 --show-sources。在LLM回答的同时也会打印出它参考了哪些具体的对话片段包含引用令牌方便你追溯和验证。3.2.5aii related发现相关的对话有时候一个问题会在多个不同的对话线程中被讨论。aii related可以帮助你找到这些相关的会话。基本用法aii related 会话UID。它会提取目标会话的标题或首条用户消息作为查询种子去搜索其他相似的会话并自动排除源会话本身。使用场景当你回顾一个关于“用户登录流程”的旧对话时运行aii related可能会发现你在其他项目中讨论过“OAuth2.0集成”或“会话管理”这些在语义上是相关的能帮你更全面地回顾知识。3.2.6aii mcp启动MCP服务器这是让AI助手获得记忆能力的关键。运行aii mcp会启动一个标准的stdio MCP服务器。与Claude Code集成最简单的方式claude mcp add aii aii mcp这条命令会自动配置Claude Code使其在启动时加载aii作为MCP服务器。之后你在Claude Code中就可以直接使用aii提供的工具了。手动配置你也可以在Claude Code的配置文件如~/.claude.json中手动添加{ mcpServers: { aii: { command: aii, args: [mcp] } } }配置成功后你的AI助手就具备了查询你全部历史对话的能力。当你在对话中说“记得我们之前讨论过如何优化数据库查询吗”助手就可以主动调用aii search来寻找相关上下文从而给出更连贯、更个性化的回答。4. 高级用法与集成策略4.1 输出模式与自动化处理理解aii的输出模式对于将其集成到自动化流程中至关重要。自动检测当标准输出是终端TTY时aii默认使用pretty模式提供彩色、格式化的易读输出。当标准输出被重定向到管道或文件时则自动切换为ndjson模式每行一个JSON对象。强制模式你可以用--ndjson,--json,--pretty来显式指定。对于脚本或AI Agent设置环境变量AII_AGENT1会强制所有命令使用ndjson输出。与jq配合ndjson和json模式非常适合与jq这类JSON处理工具搭配使用进行复杂的数据提取和转换。# 提取所有搜索结果的会话UID和标题 aii search panic --ndjson | jq -r [.session.uid[:8], .session.title] | tsv # 统计各AI助手产生的会话数量 aii search --limit 0 --json | jq group_by(.session.agent) | map({agent: .[0].session.agent, count: length})4.2 为AI助手安装技能Skillaii项目自带了一个针对Claude Code的“技能”文件skills/aii/SKILL.md。这个技能文件的作用是“教育”Claude Code告诉它在什么场景下应该使用aii例如用户提到“上次”、“记得”、“如何修复”时。如何使用aii的工具搜索 - 获取会话详情。如何理解和使用引用令牌cite token的语法。安装这个技能后Claude Code会变得更加“主动”和“记忆敏感”。安装方法很简单# 全局安装对所有项目生效 mkdir -p ~/.claude/skills cp -R /path/to/aii/skills/aii ~/.claude/skills/ # 或项目级安装仅对当前项目生效 mkdir -p .claude/skills cp -R /path/to/aii/skills/aii .claude/skills/安装后重启Claude Code即可。你会发现当你提出需要历史上下文的问题时Claude Code会主动建议或直接使用aii进行查询。4.3 自定义与扩展aii的代码结构清晰易于扩展。添加新的数据源如果你使用的AI助手不在支持列表中你可以实现internal/source/Source接口。该接口主要需要实现Scan方法用于增量读取数据并生成Batch结构。可以参考internal/source/claudecode等现有实现。自定义脱敏规则敏感信息模式定义在internal/redact/redact.go的patterns切片中。如果你所在的公司或项目有特定格式的令牌、密钥可以在这里添加正则表达式规则以保护你的隐私。调整搜索权重搜索的混合排名逻辑在internal/store/search.go中。如果你发现某种类型的查询结果不理想可以在这里调整两个FTS5索引结果的分数合并策略。5. 常见问题排查与实战技巧5.1 安装与运行问题问题运行aii命令提示“command not found”。排查说明Go二进制安装目录不在PATH中。执行echo $GOPATH查看路径通常二进制在$GOPATH/bin下。将其添加到PATH例如在~/.bashrc或~/.zshrc中添加export PATH$PATH:$(go env GOPATH)/bin然后执行source ~/.zshrc。问题aii index运行很久没反应或者报错。排查首先运行aii doctor检查各数据源路径是否存在且可读。确认你使用的AI助手如Cursor正在运行或已生成历史文件。首次索引大量数据确实需要时间使用--verbose参数查看进度。5.2 搜索与索引问题问题搜索某个确切的函数名或变量名没有结果。排查这通常是三元组索引未生效。首先确认查询词长度3。然后检查三元组索引是否已构建sqlite3 ~/.local/share/aii/aii.db SELECT COUNT(*) FROM messages_fts_tri_docsize;这个数应该约等于SELECT COUNT(*) FROM messages;。如果为0或很小运行aii index --full重建索引。问题aii ask提示“no LLM command available”。排查aii ask默认按顺序查找claude -p、codex exec。你需要确保其中一个在PATH中或者通过--cmd参数或AII_ASK_CMD环境变量指定一个有效的本地LLM命令行工具例如ollama run llama3。使用--dry-run可以测试检索部分是否正常。5.3 MCP集成问题问题在Claude Code中无法使用aii的工具。排查确保aii mcp服务器能独立运行。在终端直接运行aii mcp不应立即退出。检查Claude Code的MCP配置。运行claude mcp list查看aii是否在列表中。查看Claude Code的日志。在Claude Code界面中有时会有MCP服务器连接失败的提示。一个简单的MCP连通性测试echo {jsonrpc:2.0,id:1,method:initialize,params:{protocolVersion:2024-11-05,capabilities:{},clientInfo:{name:test,version:0}}} | aii mcp。你应该能看到一个包含result的JSON响应。5.4 性能与维护技巧数据库文件过大SQLite数据库会随着时间增长。你可以定期使用SQLite的VACUUM;命令来整理数据库文件回收空间sqlite3 ~/.local/share/aii/aii.db VACUUM;。注意这会在整理期间锁定数据库aii命令在此期间无法运行。索引速度优化增量索引通常很快。如果你发现索引变慢可以检查是否有单个会话文件异常巨大。aii在处理每个会话时是事务性的但极大的会话仍可能影响体验。目前没有内置的按大小过滤功能如有需要可考虑手动清理某些AI助手的历史记录。定期运行索引虽然aii会在搜索前自动增量索引但为了保持数据最新你可以设置一个定时任务如cron job每小时或每天自动运行一次aii index。例如在crontab中添加0 * * * * /path/to/aii index /dev/null 21。经过一段时间的深度使用我个人最大的体会是aii的价值不仅仅在于“找到”更在于“连接”。它把我与不同AI助手在不同时间、不同项目下的碎片化思考串联了起来形成了一个私有的、可检索的“第二大脑”。尤其是与MCP集成后AI助手从被动的工具变成了主动的合作伙伴它能基于我过去的经验提供建议这种体验上的提升是质的飞跃。如果你也重度依赖AI编程助手那么花一点时间部署和熟悉aii绝对是一项高回报的投资。