Published: Jul 14, 2025|19 min read19 minutes read
If you are using AI coding assistants or agents, they will only be as helpful as their knowledge of the libraries you use. LLMs know a lot about the world from their training set, but that might not include a library's documentation at all or include an older version. Agents can browse the Internet looking for more recent information, but this might not be precise enough. For instance, the web might be littered with outdated examples, and the latest information might only be available in the official docs.
Hence, if you are a library author, how do you prepare your documentation for consumption by coding agents? If you are a library user, how do you pull the docs of your favorite library so that they are efficiently used as part of your prompts?
That’s what I asked about on X, BlueSky, and LinkedIn, and mainly got converging results; below is the summary. It’s an evolving field, so there's no single answer or standard yet, but several options are available to explore.
As a library author myself, I’ve, of course, tried the described options. So far, my attempts have been scoped to the Ox Scala concurrency & resiliency library, but if it proves to be useful, I’ll expand the same setup to other libraries that we maintain (including Jox, Tapir, and sttp-client).
I’ll focus on features available when using the Cursor IDE. Other editors might have similar features.
If you are using Cursor, the fastest and most straightforward option might be to try the built-in documentation indexing feature. Select @Docs -> Add New Doc in the editor, or go to Cursor -> Settings -> Cursor Settings -> Indexing & Docs -> Add docs. In the address field, enter the address of the docs of the library, followed by a /, e.g. https://ox.softwaremill.com/latest/. After a while, the documentation should be indexed, in our case, using the Ox name.
Information is scarce on how this works, but by analogy with code indexing, this seems to store embeddings of documentation pages on Cursor's servers, which are then used for relevant user queries. Or, using AI terminology, it's a RAG (Retrieval Augmented Generation) system.
You can then use @Docs Ox to hint to Cursor to use Ox's documentation:
Rules guide the LLMs, either by adding the content of the rule as context for each request (Auto Attached), by having the models request the content of a rule (Agent Requested), or by explicitly mentioning it in the prompt (Manual).
Rules might be project-scoped or tied to the user. Project rules are stored in the .cursor/rules directory.
In the case of Ox, I generated the rules using an LLM since all the information should already be in the project’s documentation. We just need a different projection of the text that is stored there, tailored toward AI coding agents and following the rule format.
The generation itself was a two-step process. I used the Claude-4-sonnet model, first with a prompt to generate a list of rules. I requested the result to be written to a file: a list of rule names and descriptions, grouped into topics. This list was quite good but needed some amendments, which were relatively easy to do since this was just editing a text file.
The second step was to generate the rules themselves, using another prompt. Once again, the LLM got this mostly right. In some places, some APIs have been hallucinated, so you still need to read everything that’s there. And here’s the result:
1---
2description:
3globs:
4alwaysApply: true
5---
6# Ox Library Overview
7
8Ox is a Scala 3 library for **safe direct-style streaming, concurrency and resiliency** on the JVM. Requires JDK 21+ and Scala 3.
9
10## Key Concepts
11
12**Direct-Style Programming**: Write blocking-style code using virtual threads instead of async/await or reactive streams. This provides readable, debuggable code without callback hell.
13
14**Dual Error Handling**:
15- Use **exceptions** for bugs and unexpected situations
16- Use **Either values** for application logic errors with `.ok()` unwrapping
17
18**Structured Concurrency**: All concurrent operations happen within high-level operations or low-level scopes that ensure proper cleanup and resource management.
19
20**Streaming with Flows**: Use `Flow[T]` for lazy, composable, reactive-streams compatible data transformation pipelines with built-in concurrency control.
21
22(...)
For some reason, I couldn’t get the LLM to generate the correct metadata header for the .mdc files. I suspect that the Cursor app somehow messes this up since there’s a special editor view for this format. Hence, as a post-processing step, I had to update each rule’s metadata to either be “auto attached” or “agent request” with a description.
To leverage the rules, the user has to fetch the rules directory from the library’s GitHub and put all files into their project’s .cursor/rules directory.
Most of the rules are Agent-Requested since this exposes the rule list & their descriptions to the model without always including the text of each rule. If the LLM decides that a particular rule would be helpful based on the description, it can then fetch the more detailed information:
Context7 is an open-source MCP (Model Context Protocol) server that aims to provide up-to-date documentation for AI coding assistants. You can use the managed, global MCP server or run your own.
Since this is an MCP server, it’s independent of any particular IDE. It should work just fine with Cursor, VS Code, and others. You can rely on Cursor7’s crawler or provide guidance as to which directories to include and exclude when indexing. Moreover, you can give a set of rules that guide the models when generating code using the library.
Once again, for Ox, I generated this using an LLM and then made a few adjustments. The resulting context7.json file starts as follows:
4 "description": "Safe direct-style concurrency and resiliency for Scala on the JVM",
5 "folders": [
6 "generated-doc"
7 ],
8 "rules": [
9 "Use high-level concurrency operations like par(), race(), and timeout() when possible",
10 "For manual concurrency, always use structured concurrency with supervised scopes to ensure proper cleanup of threads and resources",
11 "Keep concurrency scopes as small as possible, creating short-lived scopes for single requests or jobs",
12 "Use useCloseableInScope() for automatic resource management that ensures cleanup on scope exit",
13 "Handle errors through either exceptions (for bugs/unexpected situations) or application errors as values using Either",
14 “(...”)
15 ]
16}
In the case of Ox, its documentation is indexed on the global server. To reference it in a prompt, be sure to add use context7 (the context of the prompt isn’t enriched automatically):
Another initiative aimed at standardizing LLM-accessible documentation is the llms.txt file, which should be available at the root of the documentation's web page. It is described in more detail on the llms.txt website.
However, it is unclear whether any tools (especially IDEs) actually utilize this. Hence, for now, Ox does not support this format, especially since Sphinx does not support it out of the box, so a custom generator would be needed. However, if support for the llms.txt format becomes more widespread, we'll include it in Ox’s documentation as well.
Which approach works best?
In short, that’s yet to be determined on a larger project. Feedback welcome :)
As a baseline, when generating a simple demo-like application without additional context using Cursor & Claude 4, the results are based on what has been included in the LLM’s training set. Eventually, the agent resorts to conducting a web search, and the results are correct, but it takes longer to obtain them.
Indexing the docs in Cursor helps, but the LLM initially ended up with a “naive”, longer solution. There wasn’t a noticeable difference compared to the “bare bones” approach.
Using Cursor Rules and Context7 yielded the best results. With Context7, you often don’t even have to add the use context7 prompt; the LLM will try to fetch the docs on its own. The way Context7 works is by providing snippets derived from the entire documentation, so you always get everything. For the test prompt, the solution generated this way was the most comprehensive but also the most complex (you might say, overly complex) than necessary.
When relying on the rules, Cursor quickly converged on a correct result. There were some superfluous constructs, indicating that the auto-generated rules will need to be adjusted. The good aspect here is that only the relevant rules are requested by the agent. Moreover, it’s possible to collaborate and share rule sets (for example, here’s a set of rules for Java development. That’s also a drawback: writing and maintaining rules require some manual labor.
Remember that for some languages, you may achieve even better results by combining the above approaches with an MCP server, which enables you to explore the available APIs in the project and run compilation and tests. In the case of Scala, such an MCP server is available.
What are your experiences when it comes to providing LLMs and coding agents with up-to-date and precise information about the libraries that you use? What works best, and what doesn’t work? What do you think about the strategy of generating LLM-friendly docs using LLMs - can you come up with a better prompt? Let us know; this will help us improve the documentation for our OSS projects!