# How the 99 Plugin's Request History System Tracks Previous Operations

> Discover how the 99 plugin's request history system tracks previous operations using a centralized state object and efficient data structures. Get fast lookups and track status from start to finish.

- Repository: [ThePrimeagen/99](https://github.com/theprimeagen/99)
- Tags: internals
- Published: 2026-02-16

---

**The 99 Neovim plugin maintains a comprehensive audit trail of every AI request through a centralized state object that stores operations in ordered arrays and hash maps, enabling fast lookup by unique trace IDs and persistent tracking of status from initiation to completion.**

ThePrimeagen's **99** plugin implements a robust request history system that records every interaction with AI providers. This system enables users to review past operations, navigate to previous request locations, and manage the lifecycle of AI-generated content. By maintaining structured state across multiple data structures in [`lua/99/init.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/init.lua), the plugin ensures that no operation is lost and every request remains queryable by its unique identifier.

## Core State Architecture for Request History

### The _99_State Object and History Fields

The request history system centers on the `_99_State` object defined in [`lua/99/init.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/init.lua). When the plugin initializes, `create_99_state()` instantiates several critical fields that form the backbone of the tracking system:

```lua
--- @field __request_history _99.RequestEntry[]
--- @field __request_by_id table<number, _99.RequestEntry>
...
local function create_99_state()
  return {
    ...
    __request_history = {},
    __request_by_id = {},
    __tutorials = {},
    __searches = {},
    ...
  }
end

```

These fields serve distinct purposes within the request history system:

- **`__request_history`**: An ordered array of `_99.RequestEntry` objects representing every request chronologically, including both in-flight and completed operations.
- **`__request_by_id`**: A hash map enabling O(1) lookup of any request entry by its unique trace identifier (`xid`).
- **`__tutorials`** and **`__searches`**: Specialized collections that cache successful tutorial and search results for rapid retrieval and display.

## How Operations Are Tracked

### Initiating Requests with track_request

When a user triggers an AI operation—whether a `search`, `tutorial`, or `visual` command—the plugin constructs a `RequestContext` (defined in [`lua/99/request-context.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/request-context.lua)) and immediately registers it with the history system via `_99_State:track_request(context)`.

```lua
function _99_State:track_request(context)
  assert(context.operation, "must have an operation defined to track the request")
  local point = context.range and context.range.start or Point:from_cursor()
  local entry = {
    context = context,
    status = "requesting",
    point = point,
    started_at = time.now(),
    operation_data = nil,
  }
  table.insert(self.__request_history, entry)      -- append to the ordered list
  self.__request_by_id[context.xid] = entry       -- map id → entry
  return entry
end

```

This method performs three critical actions:

1. **Captures metadata** including the cursor position (`point`) and timestamp (`started_at`) to support later navigation and timing analysis.
2. **Sets the initial status** to `"requesting"`, marking the entry as in-flight.
3. **Indexes the entry** in both the chronological array and the ID-based hash map using the context's unique `xid`.

### Completing Requests with finish_request

When the AI provider returns a response—success or failure—the plugin invokes `_99_State:finish_request(context, status)` to finalize the history entry.

```lua
function _99_State:finish_request(context, status)
  local id = context.xid
  local entry = self.__request_by_id[id]
  if not entry then return end

  entry.status = status                     -- e.g. "success" or "error"
  local data = entry.operation_data
  if entry.status == "success" and data then
    if data.type == "tutorial" then
      table.insert(self.__tutorials, data)
    elseif data.type == "search" then
      table.insert(self.__searches, data)
    end
  end
end

```

This method updates the entry's status and, for successful operations, migrates the data to specialized collections. Tutorial results populate `__tutorials`, while search results populate `__searches`, enabling rapid access to historical AI outputs without traversing the entire request history.

## Querying and Managing Request History

### Counting and Clearing Previous Requests

The request history system provides utility methods for inventory management. The `_99_State:previous_request_count()` method iterates through `__request_history` to tally completed operations:

```lua
function _99_State:previous_request_count()
  local count = 0
  for _, entry in ipairs(self.__request_history) do
    if entry.status ~= "requesting" then count = count + 1 end
  end
  return count
end

```

To reclaim memory and declutter the interface, `_99_State:clear_previous_requests()` purges all completed entries while preserving in-flight operations:

```lua
function _99_State:clear_previous_requests()
  local keep = {}
  for _, entry in ipairs(self.__request_history) do
    if entry.status == "requesting" then
      table.insert(keep, entry)
    else
      self.__request_by_id[entry.context.xid] = nil
    end
  end
  self.__request_history = keep
  self.__searches = {}
  self.__tutorials = {}
end

```

### Exporting to Quickfix List

For interactive navigation, the plugin exposes `previous_requests_to_qfix()`, which transforms the entire request history into Vim's quickfix list:

```lua
function _99.previous_requests_to_qfix()
  local items = {}
  for _, entry in ipairs(_99_state.__request_history) do
    table.insert(items, request_entry_to_qfix_item(entry))
  end
  vim.fn.setqflist({}, "r", { title = "99 Requests", items = items })
  vim.cmd("copen")
end

```

This enables users to browse historical AI requests alongside their original buffer locations, leveraging Neovim's native navigation infrastructure.

## Practical Examples

### Example 1: Running a Search and Inspecting History

Trigger an AI search and subsequently review the request history through the quickfix interface:

```lua
-- Initiate a search operation (automatically tracked)
require("99").search({ additional_prompt = "How does Lua table.concat work?" })

-- After the AI responds, open the quickfix list to see all historical requests
require("99").previous_requests_to_qfix()

```

The `search` function internally invokes `track_request`, appending the operation to `__request_history`. Upon completion, `finish_request` updates the entry status, making it visible to `previous_requests_to_qfix`.

### Example 2: Manually Accessing the History Table

For custom UI integrations, access the raw history state directly:

```lua
local _99 = require("99")
local state = _99.__get_state()            -- internal accessor
local all = state.__request_history        -- raw array of request entries

for i, entry in ipairs(all) do
  print(string.format(
    "#%d – %s – %s – %s",
    i,
    entry.context.operation or "<none>",
    entry.status,
    vim.inspect(entry.point)
  ))
end

```

This iterates through the chronological request history, displaying each operation's type, current status, and original cursor position.

### Example 3: Clearing Completed History

Manage memory and clutter by purging finished operations while preserving in-flight requests:

```lua
require("99").clear_previous_requests()   -- removes all entries whose status ≠ "requesting"
print("Remaining in‑flight requests:", require("99").__get_state():active_request_count())

```

This demonstrates the cleanup workflow, ensuring that only active `"requesting"` entries remain in `__request_history`.

## Summary

- The **99** plugin implements a dual-structure request history system using `__request_history` (ordered array) and `__request_by_id` (hash map) to track every AI operation.
- **Tracking lifecycle**: `track_request` creates entries with `"requesting"` status, while `finish_request` updates status and migrates successful tutorial/search data to dedicated collections.
- **Fast lookup**: The unique `xid` (trace ID) from `RequestContext` serves as the primary key for O(1) access to any historical entry.
- **User interface**: The system exposes `previous_requests_to_qfix()` for quickfix navigation, `previous_request_count()` for inventory, and `clear_previous_requests()` for memory management.
- **Source location**: All history logic resides in [`lua/99/init.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/init.lua), with context creation handled in [`lua/99/request-context.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/request-context.lua).

## Frequently Asked Questions

### How does the 99 plugin store request history in memory?

The plugin stores request history in two complementary Lua tables within the `_99_State` object: `__request_history` maintains chronological order for iteration, while `__request_by_id` provides constant-time lookup using the request's unique `xid` identifier. This dual-structure approach enables both sequential access for UI display and instant retrieval for status updates when AI responses arrive.

### What information is captured for each request entry?

Each request entry stores the original `RequestContext` (including operation type and buffer coordinates), a `status` field tracking the lifecycle from `"requesting"` to `"success"` or `"error"`, the cursor `point` for navigation, and a `started_at` timestamp. For completed operations, successful tutorial and search results are additionally cached in separate `__tutorials` and `__searches` collections for rapid retrieval.

### How can I view or clear my request history in Neovim?

To view history, call `require("99").previous_requests_to_qfix()` to populate the quickfix list with all historical requests and their original buffer locations. To clear completed operations while preserving in-flight requests, invoke `require("99").clear_previous_requests()`, which purges finished entries from `__request_history` and empties the `__tutorials` and `__searches` collections.

### Where is the request history logic implemented in the source code?

The core request history system is implemented in [`lua/99/init.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/init.lua), which defines the `_99_State` object containing `track_request`, `finish_request`, and management utilities like `previous_request_count` and `clear_previous_requests`. The `RequestContext` objects that feed into this system are constructed in [`lua/99/request-context.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/request-context.lua), while operation-specific handlers in `lua/99/ops/*.lua` invoke the tracking methods at the appropriate lifecycle stages.