ThePrimeagen/99: An Agentic AI Plugin for Neovim Built Around Search
Neovim AI agent done right
At a glance
- What is it?
- 99 is a Neovim plugin that connects the editor to AI providers and exposes an agentic search workflow: the user describes what to find or change, and 99 queries the project and surfaces results in the quickfix list. The author frames it as an augmentation tool, not a replacement for writing code.
- Who is it for?
- 99 is worth trying for Neovim developers who want AI-assisted project search and selected-text operations without leaving the editor and without replacing their workflow with a fully AI-driven assistant. It is not ready for teams that need API stability: the README states that APIs can disappear or change and calls it a beta product.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 111 days ago.
- What is it written in?
- Mainly Lua, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What 99 is and the workflow it targets
99 is a Neovim plugin written in Lua by ThePrimeagen. The README describes it as the AI client that Neovim deserves, built by those that still enjoy to code. The core thesis is that AI is most useful when it augments a programmer who is still driving, rather than generating large blocks of code autonomously. The README references the comparison between opencode and claude code as context for this position: both are tools the author uses as examples of hand-coded products.
The primary operation is `search`. The user calls `_99.search()` with a prompt describing something to locate or understand in the project. The plugin runs an AI query against the codebase and returns a list of locations with notes, which are placed into Neovim's quickfix list. The developer reviews those locations and acts on them directly. This keeps the programmer in control of what actually changes.
The secondary operations are `vibe` (undescribed in the README but listed in the API table) and `visual`. The `visual` operation sends the current visual selection along with a prompt to the AI and replaces the selection with the result. A third entry point, `open`, opens a selection window showing the last interaction.
Setting up 99 in a Neovim configuration
99 is a standard lazy.nvim-compatible plugin. The README gives a basic setup block:
{
"ThePrimeagen/99",
config = function()
local _99 = require("99")
local cwd = vim.uv.cwd()
local basename = vim.fs.basename(cwd)
_99.setup({
-- provider = _99.Providers.ClaudeCodeProvider, -- default: OpenCodeProvider
logger = {
level = _99.DEBUG,
path = "/tmp/" .. basenameThe default AI provider is OpenCodeProvider. The README shows `ClaudeCodeProvider` as a commented alternative. The `setup` call must be made before the plugin works. The `md_files` option accepts a list of markdown file paths whose content is injected into requests as context. The `auto_add_skills` option controls whether skill files are automatically included. The `completion` option configures inline completion behavior.
The `logger` configuration writes log output to a file at the specified path. The README notes this is for debugging purposes and suggests using the in-plugin logging mechanisms for bug reports rather than the file logger.
The search function and quickfix-driven workflow
The search operation is described in the README as the primary direction for the project. When called with a prompt, it launches an AI job in the background. That job examines the project according to the prompt and generates a list of source locations with notes explaining what it found. Those locations are written to Neovim's quickfix list, which the developer navigates with standard `:cn`, `:cp`, or the quickfix window.
The README provides an example of using `additional_prompt` in a keymap to automate a common search pattern:
remap("n", "<leader>9d", function()
_99.search({
additional_prompt = [[
run `make test` and debug the test failures and provide me a comprehensive set of steps where
the tests are breaking ]]
})
end)This binding fires off a search that runs the test suite and diagnoses failures, returning results to the quickfix list. The `additional_prompt` field means the user is not prompted interactively; the search starts immediately when the keybinding fires. This pattern is suitable for workflows where the same diagnostic step repeats frequently.
The `additional_rules` option on search operations allows injecting named skills into the request. A skill named cloudflare, for instance, adds Cloudflare-specific context to the AI query.
Extensions.Worker for persistent task tracking
The `_99.Extensions.Worker` provides a way to define a unit of work and track what remains to be done. The README describes it as a persistent mechanism: the developer calls `set_work` with a description of the task, and then calls `search` on the worker to find what parts of the task are still incomplete.
The `set_work` function accepts an optional `description` field. If no description is provided, the plugin prompts for one interactively. Once the work description is set, `_99.Extensions.Worker.search()` calls the underlying `_99.search` function with the work description as context, looking across the project for any code that still needs to be written or modified to complete the task.
The README notes this feature is where the most future change is expected, and expresses an intent to move toward worktree territory, meaning the ability to swap between multiple concurrent work items. The current implementation is described as a single bit of work. Developers who need multi-branch or multi-task management should wait for that evolution or handle it manually.
Beta status and API instability
The README carries two explicit warnings. The first says that APIs can disappear or change and calls 99 a beta product. The second says that prompts are temporary and could be massively improved. These are not hedges: the README includes a warning addressed directly to people arriving from a YouTube video, stating that so many things have changed and urging caution.
This means that a configuration block that works today may break with the next commit. The `setup` options listed in the README include fields like `model`, `in_flight_options`, `md_files`, `provider`, `display_errors`, `auto_add_skills`, `completion`, and `tmp_dir`, most of which have no description beyond the type signature. A developer adopting 99 in a shared configuration management repository should expect to revisit it when upstream changes.
The project has no GitHub releases. The last commit was on 2026-06-12. The Makefile includes targets for Lua formatting (`lua_fmt`), linting (`lua_lint`), and testing (`lua_test`), which runs the test suite under Plenary:
nvim --headless --noplugin -u scripts/tests/minimal.vim \
-c "PlenaryBustedDirectory lua/99 {minimal_init = 'scripts/tests/minimal.vim'}"This shows that the project has a test infrastructure, but the coverage of the undocumented fields is unclear.
Request Management and Repository Layout
Three API functions handle in-flight and past requests. `stop_all_requests` kills the underlying AI process (OpenCode by default) and discards any in-progress result; the README notes this means the underlying process is killed, not just paused. `clear_previous_requests` removes the records of all previous search and visual operations from the plugin's internal state. `view_logs` opens the most recent logs and sets up the editor to view older and new log files. The README calls view_logs still pretty rough and says it will change in the near future, which reinforces the beta caveat.
The repository layout reflects an active development project rather than a stable library. The top-level directory includes AGENTS.md, which typically carries instructions for AI coding agents working in the repository; TODO.md, which the conclusion in the README directs developers to check for known gaps; a queries/ directory that likely contains Tree-sitter query files for syntax-aware operations; a scratch/ directory for experimental code; a syntax/ directory for any custom Neovim syntax definitions; and docs/ for generated documentation alongside the gen-docs build script. The .luacheckrc and .luarc.json files configure the linter and language server for the Lua source in lua/. The Makefile pr_ready target runs lua_lint, lua_test, and lua_fmt_check in sequence, which means every pull request is expected to pass all three checks before merging.
Comparing 99 to other Neovim AI plugins
Several Neovim AI plugins exist, including avante.nvim, CodeCompanion, and CopilotChat.nvim. These tools generally provide chat panels, inline suggestions, and code generation. The key difference with 99 is the explicit search-into-quickfix model: 99 returns a list of project locations rather than generating code at the cursor. The README author makes the philosophy explicit by comparing 99's direction to opencode, which is described as a hand-coded product, and contrasting it with more fully autonomous tools.
For a developer who wants AI to write large amounts of code from a description, 99 is not the right tool. It does not generate full files or run autonomous multi-step agents. For a developer who wants AI to act as an informed search assistant that surfaces relevant code without modifying anything until the developer makes that choice, 99's search-into-quickfix approach is a reasonable model.
The `visual` function does modify selected text, so 99 is not purely passive. But the modification scope is exactly the selection, not the wider file or project.
Editorial conclusion
99 is worth trying for Neovim developers who want AI-assisted project search and selected-text operations without leaving the editor and without replacing their workflow with a fully AI-driven assistant. It is not ready for teams that need API stability: the README states that APIs can disappear or change and calls it a beta product. Before adopting it, verify that your preferred AI provider (OpenCode by default) is configured, test the search function against a real codebase query, and check the TODO.md in the repository for known gaps.
Frequently asked questions
What AI providers does 99 support?
The README shows OpenCodeProvider as the default and ClaudeCodeProvider as a commented alternative in the setup block. The providers are configured via the provider option passed to _99.setup().
Is 99 stable enough for daily use?
The README calls it a beta product and states that APIs can disappear or change. It notes that prompts are temporary and could be massively improved. The README also warns people arriving from a YouTube video that many things have changed since the video was published.
How does 99 use the Neovim quickfix list?
When _99.search() completes, it writes a list of project locations with notes into the Neovim quickfix list. The developer navigates those locations using standard Neovim quickfix commands. The plugin does not modify any files; it only surfaces locations for the developer to review.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/theprimeagen-99)