99
99 是一款专为 Neovim 打造的 AI 智能体客户端,旨在将程序员的手写代码能力与大语言模型的强大算力完美融合。它并非要取代开发者,而是作为得力助手,通过增强而非替代的方式提升编码效率。
99 主要解决了传统 AI 插件仅能片段式替换代码的局限,转而聚焦于更宏观的“搜索”与“工作流”代理模式。它能帮助开发者在复杂的代码库中快速定位信息、理解上下文,并执行连贯的开发任务,让 AI 真正融入日常编程习惯。
这款工具特别适合热爱 Neovim、重视手写代码价值且愿意尝试前沿工作流的资深开发者。如果你希望在使用 AI 辅助的同时,依然保持对代码逻辑的完全掌控,99 是理想之选。
其独特亮点在于高度可定制的规则系统(支持自定义 SKILL.md)和灵活的文件上下文发现机制,能够根据项目结构智能加载相关文档。此外,99 目前处于测试阶段,作者正积极探索"AI+ 传统编码”的最佳实践,虽然 API 可能随版本迭代有所调整,但其核心理念始终是为那些享受编码乐趣的人提供最原生的 Neovim AI 体验。
使用场景
一位资深后端工程师正在 Neovim 中重构一个遗留的 Python 微服务模块,需要理解复杂的调用链并安全地替换过时的异步逻辑。
没有 99 时
- 上下文切换频繁:为了理清函数依赖关系,不得不频繁离开编辑器去查阅文档或在终端运行 grep 搜索,打断心流。
- 手动整合困难:从 AI 网页端复制代码片段后,需手动调整缩进和变量名以适应现有项目规范,容易引入格式错误。
- 缺乏项目感知:通用 AI 助手不了解项目特有的目录结构和自定义工具类,生成的代码往往无法直接运行,需要大量二次修改。
- 调试成本高:遇到生成代码报错时,需人工逐行比对差异,难以快速定位是逻辑错误还是环境权限问题。
使用 99 后
- 沉浸式代理工作流:99 直接在 Neovim 内通过
search和work命令分析整个代码库,自动梳理调用链并在缓冲区呈现结果,无需切换窗口。 - 智能代码融合:基于项目内的
SKILL.md自定义规则,99 生成的代码自动符合团队规范,并利用@files补全功能精准引用相关模块。 - 深度项目感知:99 理解当前 Git 仓库结构及外部工具权限配置,生成的重构方案能直接调用项目内部的工具类,大幅减少适配工作。
- 实时追踪与反馈:内置的日志机制将请求追踪写入本地文件,出现错误时可立即回溯 Agent 的决策过程,快速修复权限或逻辑问题。
99 将 AI 从“外部聊天机器人”转变为 Neovim 内的“结对编程代理”,在保留手写代码控制权的同时,极大提升了复杂重构任务的效率与准确性。
运行环境要求
- Linux
- macOS
- Windows
未说明
未说明

快速开始
99
Neovim 应得的 AI 客户端,由那些依然热爱编码的人打造。
如果你是从 YouTube 视频 来的
很多事情都发生了变化。所以请务必小心!
警告 :: 当前 API 正在变化
API 可能会消失或被更改。抱歉,这是一款 BETA 产品。
项目方向
这个仓库旨在成为我探索将 AI 与传统编程结合使用的试验场。
我相信手工编码仍然非常重要,而当今我所知的最佳产品依然坚持这一点(参见 opencode 与 claude code)。
警告
- 提示目前是临时的,未来可以大幅改进。
- 正式处于 Beta 阶段,但 API 仍可能发生变化。不过现在不太可能了。
99
AI 的 Neovim 使用体验
_99
99 是一种代理式工作流,旨在将当前程序员的能力与大型语言模型的强大功能相结合。它并不是要取代程序员,而是用来增强程序员的工作。
目前,99 的发展方向是推进代理式编程和信息的呈现。最初以及最初的 YouTube 视频中提到的是用 AI 替换特定的代码片段。然而,随着我对 99 的使用越来越深入,我逐渐意识到它更好的用途在于“搜索”和“工作”。
基本设置
{
"ThePrimeagen/99",
config = function()
local _99 = require("99")
-- 用于日志记录,如果希望追踪请求以报告 bug,建议不要依赖此方式,而是使用 99 内置的日志机制。此配置主要用于调试目的。
local cwd = vim.uv.cwd()
local basename = vim.fs.basename(cwd)
_99.setup({
-- provider = _99.Providers.ClaudeCodeProvider, -- 默认:OpenCodeProvider
logger = {
level = _99.DEBUG,
path = "/tmp/" .. basename .. ".99.debug",
print_on_error = true,
},
-- 当设置为非当前工作目录的路径时,例如 claude code 或 opencode,可能会出现权限问题,导致生成失败。请参考相关工具的文档来解决:
-- https://opencode.ai/docs/permissions/#external-directories
-- https://code.claude.com/docs/en/permissions#read-and-edit
tmp_dir = "./tmp",
--- 补全功能:提示缓冲区中的 #rules 和 @files
completion = {
-- 我暂时禁用这些功能,直到更好地理解问题所在。光标规则中还包含应用规则,这意味着需要以不同的方式应用它们。
-- cursor_rules = "<自定义光标规则路径>"
--- 包含您自己的 SKILL.md 文件的文件夹列表
--- 预期格式:
--- /path/to/dir/<skill_name>/SKILL.md
---
--- 示例:
--- 输入路径:
--- "scratch/custom_rules/"
---
--- 输出规则:
--- {path = "scratch/custom_rules/vim/SKILL.md", name = "vim"},
--- ... 该目录下的其他规则 ...
---
custom_rules = {
"scratch/custom_rules/",
},
--- 配置 @file 补全(所有字段可选,有合理默认值)
files = {
-- enabled = true,
-- max_file_size = 102400, -- 字节,跳过大于此大小的文件
-- max_files = 5000, -- 总发现文件数上限
-- exclude = { ".env", ".env.*", "node_modules", ".git", ... },
},
--- 文件发现:
--- - 在 Git 仓库中:使用 `git ls-files`,自动尊重 .gitignore 文件。
--- - 非 Git 仓库:回退到文件系统扫描,并手动排除指定文件。
--- - 两种方法都会在 .gitignore 的基础上应用配置的 `exclude` 列表。
--- 使用哪种自动补全引擎。未指定时,默认使用原生(内置)引擎。
source = "native", -- "native"(默认)、"cmp" 或 "blink"
},
--- 警告:如果更改当前工作目录,此功能很可能失效
--- 我可能会在后续更新中修复这个问题。
---
--- md_files 是一个文件列表,系统会根据原始请求的位置自动查找并添加这些文件。也就是说,如果你位于 /foo/bar/baz.lua,
--- 系统会自动查找:
--- /foo/bar/AGENT.md
--- /foo/AGENT.md
--- 假设 /foo 是项目根目录(基于当前工作目录)。
md_files = {
"AGENT.md",
},
})
-- 请注意,我在视觉模式下才进行操作
-- 实际上,无论你上次选择的是什么内容,都会被使用
-- 因此我将其设置为视觉模式,以免误用之前的视觉选择。
--
-- 未来可能会增加模式检查,并断言必须处于视觉模式
-- 所以现在就做好准备吧。
vim.keymap.set("v", "<leader>9v", function()
_99.visual()
end)
--- 如果你有一个请求不想再继续,可以直接取消它。
vim.keymap.set("n", "<leader>9x", function()
_99.stop_all_requests()
end)
vim.keymap.set("n", "<leader>9s", function()
_99.search()
end)
end,
},
使用方法
我强烈推荐尝试 search 功能,因为这是该库的发展方向。
_99.search()
更多详情请参阅搜索部分。
描述
| 名称 | 类型 | 默认值 |
|---|---|---|
setup |
fun(opts?: _99.Options): nil |
- |
search |
fun(opts: _99.ops.SearchOpts): _99.TraceID |
- |
vibe |
fun(opts?: _99.ops.Opts): _99.TraceID | nil |
- |
open |
fun(): nil |
- |
visual |
fun(opts: _99.ops.Opts): _99.TraceID |
- |
view_logs |
fun(): nil |
- |
stop_all_requests |
fun(): nil |
- |
clear_previous_requests |
fun(): nil |
- |
Extensions |
_99.Extensions |
- |
API
setup
设置 _99。必须调用此函数,库才能正常工作。通过它我们可以设置正在进行的请求加载动画、设定默认值,并使补全功能按你期望的方式运行。
search
根据你提供的提示,在你的项目中执行搜索,并返回一个包含注释的位置列表,这些位置将被添加到快速修复列表中。
vibe
无描述。
open
打开一个选择窗口,供你选择最近的一次交互进行打开,并以适合其类型的方式显示内容。对于 search 和 vibe,会打开 qfix 窗口;对于 tutorial,则会打开教程窗口。
visual
获取当前选中的内容并连同提供的提示一起发送,然后用结果替换当前的视觉选区。
view_logs
查看最近的日志,并配置机器以便查看更早和更新的日志。目前这部分还比较粗糙,未来会有较大改动。
stop_all_requests
停止所有正在进行的请求。这意味着底层进程(OpenCode)会被终止,任何已产生的结果都将被丢弃。
clear_previous_requests
清除所有之前的搜索和视觉操作记录。
扩展
请查看 Worker,它为 search 和 vibe 提供了很酷的抽象层。
_99.Extensions.Worker
一种持久化的工单跟踪方式。
这很可能是未来开发的重点方向。我希望将其扩展到工作树的范畴,从而能够非常流畅地在不同任务之间切换。
在此之前,它只是一个简单的工单系统:你可以提供任务描述,然后使用 search 来查找尚未完成的工作。
描述
| 名称 | 类型 | 默认值 |
|---|---|---|
set_work |
fun(opts?: _99.WorkOpts): nil |
- |
search |
fun(): nil |
- |
API
set_work
为项目设置工单。如果 opts 中提供了描述,则无需再次输入工单描述。
search
将使用 _99.search 来查找该工单中尚未完成的部分,直到工单被视为已完成。
_99.Options
无描述。
描述
| 名称 | 类型 | 默认值 |
|---|---|---|
logger |
_99.Logger.Options | nil |
- |
model |
string | nil |
- |
in_flight_options |
_99.InFlight.Opts | nil |
- |
md_files |
string[] | nil |
- |
provider |
_99.Providers.BaseProvider | nil |
- |
display_errors |
boolean | nil |
- |
auto_add_skills |
boolean | nil |
- |
completion |
_99.Completion | nil |
- |
tmp_dir |
string | nil |
- |
API
logger
无描述。
model
无描述。
in_flight_options
无描述。
md_files
无描述。
provider
无描述。
display_errors
无描述。
auto_add_skills
无描述。
completion
无描述。
tmp_dir
无描述。
_99.ops.Opts
这些选项用于与 99 进行的所有交互,包括 search、visual 等操作。
描述
| 名称 | 类型 | 默认值 |
|---|---|---|
additional_prompt |
string | nil |
- |
additional_rules |
_99.Agents.Rule[] | nil |
- |
API
additional_prompt
通过提供 additional_prompt,你就不需要再单独提供提示。这样可以根据 remap 定义不同的操作。
remap("n", "<leader>9d", function()
--- 这个函数可以用来自动调试你的项目
_99.search({
additional_prompt = [[
运行 `make test` 并调试测试失败的原因,然后向我提供一套完整的步骤,说明测试在哪里出错 ]]
})
end)
这段代码会启动一个后台搜索任务,运行你的测试。一旦发现失败,就会进行诊断,并将结果转移到快速修复列表中。
additional_rules
可用于提供额外的参数。如果你有一个名为 “cloudflare” 的技能,就可以提供相应的规则,这些规则及其上下文将被注入到你的请求中。
_99.ops.SearchOpts
更多信息请参阅 _99.opts.Opts。
目前还没有具体属性。但我希望可以根据 opts 调整一些行为。
描述
| 名称 | 类型 | 默认值 |
|---|---|---|
| - | - | - |
API
无属性。
_99.WorkOpts
无描述。
描述
| 名称 | 类型 | 默认值 |
|---|---|---|
description |
string | nil |
- |
API
description
无描述。
_99.Completion
无描述。
描述
| 名称 | 类型 | 默认值 |
|---|---|---|
source |
"cmp" | "blink" | nil |
- |
custom_rules |
string[] |
- |
files |
_99.Files.Config? |
- |
API
source
无描述。
custom_rules
无描述。
files
无描述。
_99.InFlight.Opts
这是一个纯粹用于测试的类,有助于控制时间间隔。
描述
| 名称 | 类型 | 默认值 |
|---|---|---|
throbber_opts |
_99.Throbber.Opts | nil |
- |
in_flight_interval |
number | nil |
- |
enable |
boolean | nil |
- |
API
throbber_opts
左上角加载动画的相关选项。
in_flight_interval
控制加载动画显示或隐藏的频率。
enable
默认为 true。
_99.Logger.Options
无描述。
描述
| 名称 | 类型 | 默认值 |
|---|---|---|
level |
number? |
- |
type |
"print" | "void" | "file" | nil |
- |
path |
string? |
- |
print_on_error |
boolean | nil |
- |
max_requests_cached |
number | nil |
- |
API
level
无描述。
type
无描述。
path
无描述。
print_on_error
无描述。
max_requests_cached
无描述。
_99.Agents.Rule
无描述。
描述
| 名称 | 类型 | 默认值 |
|---|---|---|
name |
string |
- |
path |
string |
- |
absolute_path |
string? |
- |
API
name
无描述。
path
无描述。
absolute_path
无描述。
补全功能
在输入提示时,你可以引用规则和文件来为你的请求增加上下文。
#引用规则 — 在提示中输入#可以从你配置的规则目录中自动补全规则文件。@引用文件 — 输入@可以模糊搜索项目文件,但会排除 .gitignore 中列出的文件。
引用的内容会自动解析并注入到 AI 上下文中。默认情况下使用原生补全功能。如果使用 nvim-cmp 或 blink.cmp,则需设置 source = "cmp" 或 source = "blink"。
提供者
99 支持多种 AI CLI 后端。在你的配置中设置 provider 即可切换。如果你没有设置 model,则会使用提供者的默认模型。
| 提供者 | CLI 工具 | 默认模型 |
|---|---|---|
OpenCodeProvider(默认) |
opencode |
opencode/claude-sonnet-4-5 |
ClaudeCodeProvider |
claude |
claude-sonnet-4-5 |
CursorAgentProvider |
cursor-agent |
sonnet-4.5 |
GeminiCLIProvider |
gemini |
auto |
_99.setup({
provider = _99.Providers.ClaudeCodeProvider,
-- model 是可选的,会覆盖提供者的默认值
model = "claude-sonnet-4-5",
})
扩展
Telescope 模型选择器
如果你安装了 telescope.nvim,可以通过 Telescope 选择器实时切换模型:
vim.keymap.set("n", "<leader>9m", function()
require("99.extensions.telescope").select_model()
end)
所选模型将用于当前会话中的所有后续请求。
Telescope 提供者选择器
无需重启 Neovim 即可在 OpenCode、Claude、Cursor 和 Kiro 之间切换提供者。切换提供者时,模型也会重置为该提供者的默认值。
vim.keymap.set("n", "<leader>9p", function()
require("99.extensions.telescope").select_provider()
end)
fzf-lua
如果你使用 fzf-lua 而不是 telescope,同样可以使用这些选择器:
vim.keymap.set("n", "<leader>9m", function()
require("99.extensions.fzf_lua").select_model()
end)
vim.keymap.set("n", "<leader>9p", function()
require("99.extensions.fzf_lua").select_provider()
end)
报告 bug
要报告 bug,请提供完整的运行调试日志。这可能需要多次沟通确认。
请勿提出功能需求。我们将在 Twitch 上公开讨论功能需求,这将比你单独提交大量请求后再被关闭要高效得多。如果你仍然提交功能请求,我将会立即关闭它。
日志
要查看上次运行的日志,请执行 :lua require("99").view_logs()。
请注意
如果日志中包含敏感信息或其他需要删除的内容,请务必删除 query 的打印部分。这部分内容很可能包含你不希望公开的信息。
常见问题
相似工具推荐
openclaw
OpenClaw 是一款专为个人打造的本地化 AI 助手,旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚,能够直接接入你日常使用的各类通讯渠道,包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息,OpenClaw 都能即时响应,甚至支持在 macOS、iOS 和 Android 设备上进行语音交互,并提供实时的画布渲染功能供你操控。 这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地,用户无需依赖云端服务即可享受快速、私密的智能辅助,真正实现了“你的数据,你做主”。其独特的技术亮点在于强大的网关架构,将控制平面与核心助手分离,确保跨平台通信的流畅性与扩展性。 OpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者,以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力(支持 macOS、Linux 及 Windows WSL2),即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你
stable-diffusion-webui
stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面,旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点,将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。 无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师,还是想要深入探索模型潜力的开发者与研究人员,都能从中获益。其核心亮点在于极高的功能丰富度:不仅支持文生图、图生图、局部重绘(Inpainting)和外绘(Outpainting)等基础模式,还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外,它内置了 GFPGAN 和 CodeFormer 等人脸修复工具,支持多种神经网络放大算法,并允许用户通过插件系统无限扩展能力。即使是显存有限的设备,stable-diffusion-webui 也提供了相应的优化选项,让高质量的 AI 艺术创作变得触手可及。
everything-claude-code
everything-claude-code 是一套专为 AI 编程助手(如 Claude Code、Codex、Cursor 等)打造的高性能优化系统。它不仅仅是一组配置文件,而是一个经过长期实战打磨的完整框架,旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。 通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能,everything-claude-code 能显著提升 AI 在复杂任务中的表现,帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略,使得模型响应更快、成本更低,同时有效防御潜在的攻击向量。 这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库,还是需要 AI 协助进行安全审计与自动化测试,everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目,它融合了多语言支持与丰富的实战钩子(hooks),让 AI 真正成长为懂上
ComfyUI
ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎,专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式,采用直观的节点式流程图界面,让用户通过连接不同的功能模块即可构建个性化的生成管线。 这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景,也能自由组合模型、调整参数并实时预览效果,轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性,不仅支持 Windows、macOS 和 Linux 全平台,还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构,并率先支持 SDXL、Flux、SD3 等前沿模型。 无论是希望深入探索算法潜力的研究人员和开发者,还是追求极致创作自由度的设计师与资深 AI 绘画爱好者,ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能,使其成为当前最灵活、生态最丰富的开源扩散模型工具之一,帮助用户将创意高效转化为现实。
markitdown
MarkItDown 是一款由微软 AutoGen 团队打造的轻量级 Python 工具,专为将各类文件高效转换为 Markdown 格式而设计。它支持 PDF、Word、Excel、PPT、图片(含 OCR)、音频(含语音转录)、HTML 乃至 YouTube 链接等多种格式的解析,能够精准提取文档中的标题、列表、表格和链接等关键结构信息。 在人工智能应用日益普及的今天,大语言模型(LLM)虽擅长处理文本,却难以直接读取复杂的二进制办公文档。MarkItDown 恰好解决了这一痛点,它将非结构化或半结构化的文件转化为模型“原生理解”且 Token 效率极高的 Markdown 格式,成为连接本地文件与 AI 分析 pipeline 的理想桥梁。此外,它还提供了 MCP(模型上下文协议)服务器,可无缝集成到 Claude Desktop 等 LLM 应用中。 这款工具特别适合开发者、数据科学家及 AI 研究人员使用,尤其是那些需要构建文档检索增强生成(RAG)系统、进行批量文本分析或希望让 AI 助手直接“阅读”本地文件的用户。虽然生成的内容也具备一定可读性,但其核心优势在于为机器
LLMs-from-scratch
LLMs-from-scratch 是一个基于 PyTorch 的开源教育项目,旨在引导用户从零开始一步步构建一个类似 ChatGPT 的大型语言模型(LLM)。它不仅是同名技术著作的官方代码库,更提供了一套完整的实践方案,涵盖模型开发、预训练及微调的全过程。 该项目主要解决了大模型领域“黑盒化”的学习痛点。许多开发者虽能调用现成模型,却难以深入理解其内部架构与训练机制。通过亲手编写每一行核心代码,用户能够透彻掌握 Transformer 架构、注意力机制等关键原理,从而真正理解大模型是如何“思考”的。此外,项目还包含了加载大型预训练权重进行微调的代码,帮助用户将理论知识延伸至实际应用。 LLMs-from-scratch 特别适合希望深入底层原理的 AI 开发者、研究人员以及计算机专业的学生。对于不满足于仅使用 API,而是渴望探究模型构建细节的技术人员而言,这是极佳的学习资源。其独特的技术亮点在于“循序渐进”的教学设计:将复杂的系统工程拆解为清晰的步骤,配合详细的图表与示例,让构建一个虽小但功能完备的大模型变得触手可及。无论你是想夯实理论基础,还是为未来研发更大规模的模型做准备