How the Tutorial Operation Stores and Retrieves Learning Data in ThePrimeagen/99
The tutorial operation in ThePrimeagen/99 stores learning data in-memory within the global _99_state.__tutorials array, appending structured tutorial objects upon successful LLM completion and exposing them via require("99").__tutorials for retrieval.
ThePrimeagen/99 is a Neovim plugin that leverages LLMs to generate interactive learning content. Understanding how the tutorial operation stores and retrieves learning data reveals the plugin's state management architecture and enables developers to build custom integrations with persisted tutorial content.
Architecture Overview
The tutorial operation treats learning requests as specialized request entries whose results persist in global state for later consultation. Unlike standard one-off LLM queries, tutorials generate structured data objects containing titles and markdown content arrays that survive for the duration of the Neovim session.
The flow traverses seven distinct stages: context creation, prompt composition, request initiation, provider execution, request finalization, data storage, and retrieval exposure.
Step-by-Step Data Flow
1. Creating the Request Context
The process begins in lua/99/request-context.lua where RequestContext.from_current_buffer collects buffer metadata, model configuration, and temporary file paths:
local context = RequestContext.from_current_buffer(_99_state, trace_id)
context.operation = "tutorial"
The context captures:
tmp_file: A random temporary file path for the LLM responsemodel: The selected AI model configurationmd_file_names: Additional markdown context files- Per-request logging infrastructure
2. Composing the Tutorial Prompt
In lua/99/ops/make-prompt.lua, the make_prompt function injects user input into the static tutorial template defined in lua/99/prompt-settings.lua:
local prompt, refs = make_prompt(
context,
context._99.prompts.prompts.tutorial(), -- static tutorial prompt
opts
)
context:add_references(refs)
The resulting prompt combines the built-in tutorial instructions with user-specified additional context, while make_prompt returns any rule-derived references that augment the AI context.
3. Initiating the LLM Request
The Request object in lua/99/request/init.lua orchestrates provider interaction:
local request = Request.new(context)
request:add_prompt_content(prompt)
request:start(observer)
The start method writes the full prompt to <tmp_file>-prompt and invokes the provider's make_request method. The observer—created by CleanUp.make_observer—handles asynchronous completion callbacks.
4. Provider Execution and Response Streaming
lua/99/providers.lua implements BaseProvider:make_request, which spawns the external LLM binary (e.g., opencode run):
The provider streams stdout and stderr to the observer in real-time. Upon process termination, _retrieve_response reads the temporary file containing the LLM's complete output.
5. Finalizing the Request and Storing Data
When the request completes, the observer's on_complete callback triggers _99_state:finish_request in lua/99/init.lua:
local entry = self.__request_by_id[id]
entry.status = status
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
The operation_data field contains a structured object matching the RequestEntry.Data.Tutorial schema defined in lua/99/init.lua:
--- @class _99.RequestEntry.Data.Tutorial
--- @field type "tutorial"
--- @field title string
--- @field content string[]
Upon successful completion, this object appends to self.__tutorials, an array residing in the singleton _99_state object.
Data Structure and Storage Mechanism
The Tutorial Object Schema
Tutorial data adheres to a strict type definition ensuring consistent access patterns:
- type: Literal string
"tutorial"for type discrimination - title: Human-readable string identifying the tutorial topic
- content: Array of strings representing markdown content lines
In-Memory Storage Location
The storage mechanism relies on Lua module-level singletons rather than external databases or filesystem persistence:
-- Located in lua/99/init.lua
_99_state = _99_State.new()
The __tutorials array exists within this singleton, making it accessible globally through the module export:
local tutorials = require("99").__tutorials
Data persists only for the duration of the Neovim session. Terminating the editor destroys the Lua state and all stored tutorials.
Retrieving Stored Tutorials
Accessing historical tutorial data requires importing the global state module:
local ninety = require("99")
-- List all stored tutorials
for i, tut in ipairs(ninety.__tutorials) do
print(string.format("[#%d] %s", i, tut.title))
print(table.concat(tut.content, "\n"))
print("---")
end
The raw __tutorials array exposes the complete structured data, enabling custom UI components to render tutorial histories, implement search functionality, or export content to external formats.
Clearing and Resetting Tutorial Data
The plugin provides explicit cleanup functionality for session management:
require("99"):clear_previous_requests()
This method, defined in lua/99/init.lua (lines 241-244), resets both tutorial and search storage:
function _99_State:clear_previous_requests()
self.__request_by_id = {}
self.__tutorials = {}
self.__searches = {}
end
Invoking this function clears all learning data, effectively resetting the plugin's memory without restarting Neovim.
Key Implementation Files
| File | Responsibility |
|---|---|
lua/99/ops/tutorial.lua |
Entrypoint for the tutorial operation – builds requests, wires cleanup, and starts execution. |
lua/99/request/init.lua |
Implements the Request object that drives the provider and manages request-specific state. |
lua/99/request-context.lua |
Captures buffer, model, temp file, markdown files, and assembles the full AI context. |
lua/99/providers.lua |
Generic provider base that runs the external LLM binary and streams output. |
lua/99/init.lua |
Global singleton _99_state – stores __tutorials, tracks requests, and moves successful data into the tutorial store. |
lua/99/prompt-settings.lua |
Defines the static tutorial prompt text merged with user input. |
lua/99/ops/make-prompt.lua |
Composes the final prompt by injecting user content into operation-specific templates. |
Summary
- The tutorial operation stores learning data in-memory within the global
_99_state.__tutorialsarray, not on disk or external databases. - Data persistence lasts only for the Neovim session lifetime, clearing automatically when the editor closes.
- The storage flow involves seven stages: context creation, prompt composition, request initiation, provider execution, request finalization, data appending to
__tutorials, and global exposure viarequire("99"). - Tutorial objects follow a strict schema with
type,title, andcontentfields, ensuring consistent access patterns for UI components. - Developers can manually clear stored tutorials using
clear_previous_requests(), which resets the internal arrays without restarting Neovim.
Frequently Asked Questions
How long does tutorial data persist in the 99 plugin?
Tutorial data persists only for the duration of the current Neovim session. Because the storage mechanism uses Lua module-level singletons (_99_state.__tutorials) rather than filesystem persistence or databases, terminating the editor destroys all stored learning data automatically.
What is the exact data structure of a stored tutorial object?
The tutorial object adheres to the _99.RequestEntry.Data.Tutorial class definition found in lua/99/init.lua. It contains three fields: type (the literal string "tutorial"), title (a string describing the tutorial topic), and content (an array of strings representing markdown-formatted tutorial text).
Can I access stored tutorials from my own Neovim Lua scripts?
Yes, the global state module exposes the __tutorials array publicly. You can access stored tutorials by requiring the main module: local tutorials = require("99").__tutorials. This returns the raw array of tutorial objects, allowing you to iterate, filter, or display the content in custom UI components.
How do I clear the tutorial storage without restarting Neovim?
Invoke the clear_previous_requests() method on the 99 module: require("99"):clear_previous_requests(). This function, defined in lua/99/init.lua, resets the internal __tutorials array to an empty table, effectively clearing all stored learning data while keeping your Neovim session active.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →