# How the Marks System Tracks AI-Assisted Edits in ThePrimeagen/99

> Discover how the marks system in ThePrimeagen/99 uses Neovim extmarks to track AI-assisted edits ensuring accurate AI responses and cleanup. Learn about its persistent markers.

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

---

**The marks system uses Neovim extmarks to create persistent top and bottom markers around visual selections, validating their positions before inserting AI-generated responses and automatically cleaning them up after the request completes.**

ThePrimeagen's *99* repository is a Neovim plugin that streamlines AI-assisted coding workflows. At its core, the **marks system for tracking AI-assisted edits** ensures that when you send a visual selection to an AI model, the plugin remembers exactly where that text lives—even if you edit other parts of the buffer while waiting for the response.

## Core Architecture of the Marks System

The system is built on three interconnected components that wrap Neovim's native extmarks API.

### The Mark Class ([`ops/marks.lua`](https://github.com/ThePrimeagen/99/blob/main/ops/marks.lua))

The [`lua/99/ops/marks.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/ops/marks.lua) file defines the `_99.Mark` class, which abstracts extmark creation and management. Key methods include:

- **`Mark.mark_above_range(range)`** – Places a mark one line above the start of the visual selection (lines 15-38)
- **`Mark.mark_point(buf, point)`** – Creates a mark at an exact coordinate (lines 56-68)
- **`Mark.mark_range(range)`** – Returns both start and end marks for a range (lines 40-47)
- **`Mark:is_valid()`** – Verifies the underlying extmark still exists (lines 49-54)
- **`Mark:delete()`** – Removes the extmark (lines 49-52)

### Request Context Management ([`request-context.lua`](https://github.com/ThePrimeagen/99/blob/main/request-context.lua))

The [`lua/99/request-context.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/request-context.lua) file maintains per-request state through the `RequestContext` class. It stores marks in a dedicated `marks` table (line 13) and provides **`RequestContext:clear_marks()`** (lines 49-53), which iterates through stored marks and calls `:delete()` on each to prevent ghost extmarks from persisting after the AI request completes.

### Visual Selection Workflow ([`ops/over-range.lua`](https://github.com/ThePrimeagen/99/blob/main/ops/over-range.lua))

The [`lua/99/ops/over-range.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/ops/over-range.lua) file orchestrates the actual AI-assisted editing workflow. It bridges the Mark class and RequestContext by:

1. Creating the top and bottom marks at lines 22-26
2. Storing them on the context's marks table
3. Registering cleanup logic at lines 43-48 that calls `context:clear_marks()` when the request finishes, is cancelled, or errors

## How Marks Track AI-Assisted Edits Step by Step

When you trigger an AI edit over a visual selection, the marks system executes the following workflow:

1. **Mark Creation**: [`ops/over-range.lua`](https://github.com/ThePrimeagen/99/blob/main/ops/over-range.lua) creates two extmarks:
   - A **top mark** positioned one line above your selection via `Mark.mark_above_range(range)`
   - A **bottom mark** at the exact end of your selection via `Mark.mark_point(range.buffer, range.end_)`

2. **Persistence**: These marks survive buffer edits because they are native Neovim extmarks. If you type elsewhere in the file while the AI generates a response, the marks automatically adjust their positions to stay anchored to the original text.

3. **Validation**: Before inserting the AI response, the plugin checks `top_mark:is_valid() and bottom_mark:is_valid()`. If either mark is invalid (meaning the original text was deleted), the plugin aborts with a fatal error to prevent corruption.

4. **Range Reconstruction**: Valid marks are converted back into a `Range` object via `Range.from_marks(top_mark, bottom_mark)`, which determines exactly where to insert the AI-generated lines.

5. **Cleanup**: Regardless of success or failure, `RequestContext:clear_marks()` deletes both extmarks, ensuring no tracking artifacts remain in the buffer.

## Practical Code Examples

### Creating a Simple Point Mark

```lua
local Mark = require("99.ops.marks")
local geo = require("99.geo")
local Point = geo.Point

local buf = vim.api.nvim_get_current_buf()
local point = Point:from_1_based(3, 5)  -- line 3, column 5 (1-based)
local mark = Mark.mark_point(buf, point)

-- Retrieve position
print(vim.inspect(Point.from_mark(mark)))  -- → {row = 3, col = 5}

-- Clean up
mark:delete()

```

*Implementation reference*: `Mark.mark_point` (lines 56-68) and `Mark:delete` (lines 49-52) in [`lua/99/ops/marks.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/ops/marks.lua).

### Marking a Full Range

```lua
local Mark = require("99.ops.marks")
local geo = require("99.geo")
local Point = geo.Point
local Range = geo.Range

local buf = vim.api.nvim_get_current_buf()
local start = Point:from_1_based(2, 3)
local finish = Point:from_1_based(4, 10)
local range = Range:new(buf, start, finish)

local mark_start, mark_end = Mark.mark_range(range)

assert(Point.from_mark(mark_start) == start)
assert(Point.from_mark(mark_end) == finish)

-- Clean-up
mark_start:delete()
mark_end:delete()

```

*Implementation reference*: `Mark.mark_range` (lines 40-47) in [`lua/99/ops/marks.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/ops/marks.lua).

### Using Marks in Visual Selection Requests

```lua
local over_range = require("99.ops.over-range")
local RequestContext = require("99.request-context")

local ctx = RequestContext.from_current_buffer(_99_state, 1)  -- state & xid
local visual_range = geo.Range.from_visual_selection()

over_range(ctx, visual_range)  -- creates top/bottom marks, runs AI request,
                               -- and automatically clears marks when done

```

*Key lines*: Mark creation (lines 22-26) and cleanup registration (lines 43-48) in [`lua/99/ops/over-range.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/ops/over-range.lua).

## Summary

- The **marks system for tracking AI-assisted edits** wraps Neovim extmarks to create persistent anchors around visual selections.
- Two marks are created for each request: a **top mark** above the selection and a **bottom mark** at the exact end point.
- Marks automatically adjust to buffer edits but are validated with `is_valid()` before AI responses are inserted.
- The `RequestContext` class manages mark lifecycle through `clear_marks()`, ensuring no extmarks leak after requests complete.
- All mark operations are implemented in [`lua/99/ops/marks.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/ops/marks.lua) and consumed by [`lua/99/ops/over-range.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/ops/over-range.lua) and [`lua/99/request-context.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/request-context.lua).

## Frequently Asked Questions

### How do marks survive if I edit other parts of the buffer while waiting for the AI?

Neovim's native **extmarks** automatically track text movements. When you create a mark via `Mark.mark_point` or `Mark.mark_above_range`, the underlying extmark binds to the text at that position. If you insert or delete lines above the marked region, Neovim shifts the extmark's position accordingly, ensuring the AI response inserts at the correct location when it arrives.

### What happens if I delete the text that was originally selected?

Before inserting any AI-generated content, the plugin validates both marks using `Mark:is_valid()` (lines 49-54 in [`lua/99/ops/marks.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/ops/marks.lua)). If you deleted the original visual selection, the underlying extmarks become invalid, `is_valid()` returns false, and the plugin aborts the operation with a fatal error to prevent corrupting your buffer with misplaced text.

### How are marks cleaned up after the AI request finishes?

Every request creates a `RequestContext` that stores marks in a dedicated table (line 13 in [`lua/99/request-context.lua`](https://github.com/ThePrimeagen/99/blob/main/lua/99/request-context.lua)). When the request completes, errors out, or is cancelled, the `over_range` function triggers `context:clear_marks()` (lines 49-53), which iterates through all stored marks and calls `mark:delete()` on each. This ensures no "ghost" extmarks remain in the buffer after the AI interaction ends.