ThePrimeagen/99: An Agentic Workflow Inside Neovim, Still in Beta
Neovim AI agent done right
At a glance
- What is it?
- 99 is a Lua plugin that puts an LLM agent in your Neovim buffer, aimed at search and work rather than wholesale code replacement. The API is explicitly unstable, and the README warns that prompts are temporary.
- Who is it for?
- Adopt 99 if you already work in Neovim and want an LLM that searches your project and returns results to the quickfix list, and if you accept that the README calls the project a beta where APIs can disappear. Do not adopt it if you need a stable interface, if you rely on Cursor rules (the README shows cursor_rules commented out until the author understands the problem), or if you cannot tolerate the warning that changing cwd likely breaks md_files.
- 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 96 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 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What 99 Is Trying to Fix in the Neovim AI Workflow
Most AI coding tools ask you to leave the editor, paste context into a chat window, and copy results back. 99 takes the opposite position. The README describes it as "an agentic workflow that is meant to meld the current programmers ability with the amazing powers of LLMs," and states that the goal is augmentation rather than replacement. The project direction section is blunt about the author's view: hand coding is still important, and the best products he knows of still do it.
The intended user is a Neovim user who already has a working configuration and wants the agent to operate over the project rather than over a single file. The README says the original YouTube video focused on replacing specific pieces of code, but that the author's own usage shifted toward search and work. That shift matters for anyone evaluating the plugin: the center of gravity is project-wide retrieval with notes, not inline autocomplete.
Search, Vibe and Visual: What the Exposed Functions Actually Do
The module table lists setup, search, vibe, open, visual, view_logs, stop_all_requests, clear_previous_requests, and Extensions. Search is the one the README recommends: it "performs a search across your project with the prompt you provide and return out a list of locations with notes that will be put into your quick fix list." That is a concrete data flow. You type a prompt, the agent scans the project, and the result lands in Neovim's quickfix list, where you can jump between locations using the editor's existing navigation.
Vibe has no description in the README at all, which is a real gap. The open function is documented: it opens a selection window for the last interaction and displays the contents in a way that suits its type. For search and vibe, that means the quickfix window. Visual takes a visual selection, and the README notes that whatever your last visual selection was will be used, which is why the example keymap binds it to visual mode only. The author acknowledges this is fragile: "likely ill add a mode check and assert on required visual mode."
Every one of these entry points returns a TraceID, except open and the stop and clear functions. The TraceID is not explained further in the supplied material, so what you can do with it beyond identifying a request is not documented here.
Providers, tmp_dir and the Permission Trap Outside the CWD
Setup takes a provider option. The README shows ClaudeCodeProvider commented out and states that the default is OpenCodeProvider. The comment attached to tmp_dir is the most operationally important line in the README: "When setting this to something that is not inside the CWD tools such as claude code or opencode will have permission issues and generation will fail." Two documentation links are given for resolving this, one for OpenCode permissions and one for Claude Code permissions. If you set tmp_dir to an absolute path outside your project, expect failures until you configure the provider's external directory permissions.
The logger block takes a level, a path, and print_on_error. The example writes to /tmp/<basename>.99.debug using vim.uv.cwd() and vim.fs.basename. The README is clear that this file logging is for debugging requests and that for bug reports you should use the logging mechanisms inside 99 instead. That distinction is worth respecting: the file log is not the supported reporting path.
Completion, AGENT.md Discovery and the cwd Warning
Completion has three parts. The source key accepts "native" (the default), "cmp", or "blink". File completion is driven by git ls-files in git repositories, which respects .gitignore automatically, and falls back to filesystem scanning with manual excludes otherwise. Both paths apply the configured exclude list on top of gitignore. Defaults include a max_file_size of 102400 bytes and a max_files cap of 5000, both overridable.
custom_rules expects directories containing a SKILL.md per subfolder, with the format /path/to/dir/<skill_name>/SKILL.md. The example path is scratch/custom_rules/, which would produce entries like {path = "scratch/custom_rules/vim/SKILL.md", name = "vim"}. Note that cursor_rules is commented out in the example, with the author explaining he is disabling it until he understands how application rules inside cursor rules should be applied differently.
md_files is a list of filenames to look for and auto-add based on the location of the originating request. From /foo/bar/baz.lua, with /foo as project root, the system looks for /foo/bar/AGENT.md and then /foo/AGENT.md. The warning above this block is direct: "if you change cwd then this is likely broken." If your workflow involves changing directories mid-session, AGENT.md discovery will not follow you correctly.
Getting It Running: Keys, Commands and What to Verify
The setup block goes in your plugin manager's config function. You require("99"), call _99.setup with your options, then bind keys. The README's example binds three: <leader>9v to _99.visual() in visual mode, <leader>9x to _99.stop_all_requests() in normal mode, and <leader>9s to _99.search() in normal mode. The stop binding is described as the way to cancel a request you do not want applied, which implies requests can run long enough that you would want to abort them.
setup must be called for the library to work; the README says it sets up in-flight request spinners, default values, and completion. Before you commit to a configuration, verify three things that the README leaves open. First, the licence, which is not stated in the material reviewed here. Second, whether your provider needs external directory permissions for your chosen tmp_dir. Third, whether your visual selection behavior matches the plugin's assumption that the last visual selection is reused.
Where 99 Is the Wrong Tool
The README carries a warning section that says prompts are temporary and could be massively improved, and that the project is officially in beta with APIs that can still change. A separate warning at the top says APIs will disappear or change. This is not a plugin to build a team workflow on top of right now, because the surface you would build against is explicitly moving.
There are narrower failure modes too. The md_files feature depends on cwd stability, and the author says changing cwd likely breaks it. The visual function depends on the last visual selection, which the author calls out as a footgun. The cursor_rules completion option is commented out and not usable. The vibe function has no description whatsoever, so its behavior, return value semantics, and failure modes are undocumented in the supplied material. If your work depends on any of those, 99 is not the tool for it yet.
The Alternative: Staying With a Terminal Agent
The obvious comparison is running an agent in a terminal pane beside Neovim, which is how OpenCode and Claude Code are typically used. The difference is not quality; it is where the context lives. A terminal agent starts from the shell's working directory and whatever you paste or point it at. 99 starts from your buffer, your visual selection, and the AGENT.md files discovered upward from the file you are editing, and it returns results into Neovim's quickfix list rather than into a chat transcript.
That integration is the entire argument for 99. If you do not want search results in the quickfix list, and you are comfortable switching windows, a terminal agent gives you the same underlying models with a more stable interface. The README itself references opencode and claude code as the comparison points for hand coding, and the default provider is OpenCodeProvider, so 99 is not replacing those tools so much as wrapping one of them in editor-native plumbing.
Maintenance Cost and the Licence Question
The cost of running 99 is mostly the cost of tracking a beta. The README says API changes are unlikely at this point, but the warning at the top of the document says they will happen. That means pinning a commit rather than tracking the default branch, and reading the changelog before upgrading, since no releases were retrieved in the material reviewed here. There are no released versions to pin to, which makes the default branch the only reference point.
The licence is not stated in the supplied material, so no conclusion about redistribution, modification, or commercial use can be drawn from it. Check the repository for a licence file before you vendor the plugin or ship it in a shared configuration. That check is a five-second look at the repo root, and it is the first thing to do before anything else in this article matters.
Editorial conclusion
Adopt 99 if you already work in Neovim and want an LLM that searches your project and returns results to the quickfix list, and if you accept that the README calls the project a beta where APIs can disappear. Do not adopt it if you need a stable interface, if you rely on Cursor rules (the README shows cursor_rules commented out until the author understands the problem), or if you cannot tolerate the warning that changing cwd likely breaks md_files. Before installing, verify the licence file in the repository, since the licence is not stated in the material reviewed here, and check whether your chosen provider (OpenCode or Claude Code) has permission to read directories outside the current working directory.
Community notes