How 99 Handles AGENT.md File Discovery and Injection into AI Context

The 99 Neovim plugin automatically discovers AGENT.md files by walking up the directory tree from the current buffer and injects their contents into the AI prompt context before sending requests to the LLM.

ThePrimeagen's 99 plugin treats specially named markdown files as persistent context that should accompany every AI request. By default, the plugin searches for AGENT.md files using an upward directory traversal algorithm, ensuring that project-specific instructions follow the developer regardless of which nested file they are currently editing.

Configuring AGENT.md Discovery in 99

The plugin stores the list of context filenames in the md_files configuration option. According to the source code in lua/99/init.lua (lines 86-94), the default setup includes a single entry:

require("99").setup({
  md_files = { "AGENT.md" },
})

You can customize this list during initialization to include additional markdown files. The plugin accepts any filename or relative path, allowing you to maintain separate context documents for different aspects of your codebase.

The AGENT.md File Discovery Process

When you trigger an AI request, 99 creates a RequestContext object via RequestContext.from_current_buffer. During this initialization (implemented in lua/99/init.lua, lines 575-605), the current md_files configuration is copied into the request's md_file_names field.

The actual discovery logic resides in lua/99/request-context.lua (lines 82-108) within the _read_md_files method. The algorithm performs the following steps:

  1. Identify boundaries: Determines the current working directory (cwd) and the directory containing the active buffer (dir).
  2. Traverse upward: Uses a while loop to walk from the buffer's directory toward the project root, stopping when it reaches the cwd.
  3. Check each directory: For every level in the hierarchy, it checks for the existence of each filename listed in md_file_names.
  4. Collect contents: When a match is found, the file is opened, read entirely (*a pattern), and its contents stored.
-- Simplified excerpt from lua/99/request-context.lua
function RequestContext:_read_md_files()
  local cwd = vim.uv.cwd()
  local dir = vim.fn.fnamemodify(self.full_path, ":h")

  while dir:find(cwd, 1, true) == 1 do
    for _, md_file_name in ipairs(self.md_file_names) do
      local md_path = dir .. "/" .. md_file_name
      local file = io.open(md_path, "r")
      if file then
        local content = file:read("*a")
        file:close()
        table.insert(self.ai_context, content)
      end
    end
    if dir == cwd then break end
    dir = vim.fn.fnamemodify(dir, ":h")
  end
end

How 99 Injects AGENT.md Content into AI Context

Once the discovery phase completes, the collected content resides in the ai_context table of the request object. The injection occurs during the finalization stage in RequestContext:finalize (lines 136-146 of lua/99/request-context.lua).

The plugin concatenates all strings in ai_context and includes them as part of the complete prompt sent to the LLM provider. This ensures that instructions, coding standards, or project context defined in AGENT.md files are prepended or appended to the user's actual query, giving the AI persistent awareness of the project's requirements.

Customizing Markdown Context Files

You can extend beyond the default AGENT.md to maintain multiple context documents. For example, you might separate architectural decisions from coding standards:

require("99").setup({
  md_files = { 
    "AGENT.md",           -- General project context
    "ARCHITECTURE.md",    -- System design decisions
    ".cursorrules",       -- Coding standards
  },
})

The plugin discovers all specified files at each directory level, merging their contents in the order found during the upward traversal. Files closer to the buffer's directory take precedence in the discovery order, though all discovered files are included in the final context.

Summary

  • Default Configuration: The 99 plugin automatically searches for AGENT.md files via the md_files option, which defaults to {"AGENT.md"} in lua/99/init.lua.
  • Discovery Algorithm: The _read_md_files method in lua/99/request-context.lua walks upward from the current buffer's directory to the project root, checking each level for configured markdown files.
  • Context Injection: Discovered file contents are stored in the ai_context table and concatenated into the final prompt during RequestContext:finalize, ensuring persistent project context accompanies every AI request.
  • Customization: Users can override md_files in the setup configuration to include additional context documents like README.md or custom standards files.

Frequently Asked Questions

How does 99 decide which AGENT.md file to use when multiple exist in the project hierarchy?

The plugin discovers all AGENT.md files found during the upward directory traversal from the current buffer to the project root. According to the implementation in lua/99/request-context.lua, each discovered file's contents are appended to the ai_context table. This means nested projects can have specific instructions at lower levels and general instructions at higher levels, with all contexts being included in the final prompt.

Can I disable AGENT.md discovery entirely in 99?

Yes, you can disable the feature by setting the md_files option to an empty table in your setup configuration. In lua/99/init.lua, the default value is {"AGENT.md"}, but passing md_files = {} prevents the _read_md_files method from finding any files to inject, effectively disabling the automatic context injection while keeping other plugin features active.

What happens if an AGENT.md file is malformed or contains binary data?

The plugin uses Lua's io.open with the "r" (read) mode and file:read("*a") to read the entire file contents as text, as seen in lua/99/request-context.lua. If the file contains binary data or invalid UTF-8 sequences, the behavior depends on how the subsequent prompt construction and HTTP client handle the data. However, the plugin itself does not validate or sanitize the content—it simply reads and appends the raw text to the ai_context table.

Does 99 watch AGENT.md files for changes or cache their contents?

Based on the source code analysis, the plugin does not implement file watching or caching for AGENT.md files. The _read_md_files method reads the files synchronously during the request finalization phase (RequestContext:finalize) each time a request is created. This means changes to AGENT.md files take effect immediately on the next AI request without requiring a Neovim restart, but the plugin incurs the I/O cost of reading the files on every request.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →