In this article, I want to discuss how to better use LLM agents, specifically how to manage the CLAUDE.md/AGENTS.MD file effectively and it seems like there is no point it in.
Before we start
This article will not cover the standard prompt engineering techniques that have been described many times by Anthropic and other LLM providers. You won't find advice here like "avoid negative examples," "set the LLM role," "be specific in your instructions," or similar well-documented practices. If you need that foundation, check the official documentation from Anthropic or OpenAI—they cover it thoroughly.
Instead, this article focuses on how my workflow evolved through months of using Claude Code on real projects. It's about the practical patterns I discovered for organizing documentation and keeping the LLM effective as projects grow in complexity.
One more clarification: I'm not a "vibe coder." I don't create tasks that let the LLM run autonomously for hours or days. I use the LLM "as a keyboard"—it can read superfast, type superfast, and execute actions to verify what it did. But I'm always in control. If something is too abstract or unclear, I simply won't let it proceed. This hands-on approach is the foundation of everything I describe below.
The problem with growing CLAUDE.md files
Every project should have a CLAUDE.md file. It describes what the project does, how to navigate around it, what development workflows are available, and so on. However, the more you work on a project, the more content accumulates inside this file. At some point, you will end up in a situation where Claude Code cannot read it because it's too large. It can still try to read the first half, then the second half, but you should not allow this to happen at all.
Keep CLAUDE.md "useless"
Here is the catch: your CLAUDE.md should be only around 30 lines maximum. I am not kidding—you don't need more.
The idea is simple. Instead of putting all the documentation into CLAUDE.md, use it as an entry point that defines the workflow. The LLM then decides which docs to read depending on the task at hand.
Here is mine for example:
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
# YOUR ROLE
You are dick! You know it. I know it. Don't pretend you are not.
Pay attention to task and code. If you see stupid thing/idea stop and report it.
Be extremely concise. Sacrifice grammar for the sake of concision.
# THE MAIN FLOW
Create the following to-do list immediately.
- Analyze user request.
- Run `find docs/ -name "*.md" | sort` to see available docs.
- Read docs that may help to solve current task.
- Read tsconfig.app.json to understand what path shortcuts exists.
- Read packages.json to understand commands.
- Analyze examples from the docs.
- Revise execution plan and present it to the user with todo items.
- Once the user accepts, create revised todo items.
- Start work on the task.
- Use skills and commands that may help to solve current task.
DO NOT EDIT THIS FILE
IT IS THE FINAL FORM.
Organizing documentation in the docs folder
This approach implies that everything useful—every guideline, workflow, and explanation—lives inside the docs folder. Organize them logically into different folders with descriptive names so the LLM can understand why it would need to read them.
This structure really helps once the project becomes big and you have different layers and features. Depending on the task, you may need specific knowledge, but most of it won't be required for every task.
For example, here is how the docs structure looks in one of my projects:
docs/backend/graphql-api-patterns.md
docs/backend/rest-api-patterns.md
docs/backend/service-layer.md
docs/backend/data-layer.md
docs/backend/event-system.md
docs/frontend/actions/create-component.md
docs/frontend/actions/create-modal.md
docs/frontend/actions/create-data-form.md
docs/frontend/actions/create-entity-selection.md
docs/frontend/actions/create-graphql-service.md
docs/frontend/actions/create-rest-service.md
docs/frontend/actions/create-route.md
docs/frontend/actions/create-tree-view.md
docs/frontend/architecture.md
docs/frontend/design-tokens.md
docs/frontend/ui-ux.md
docs/build-deployment.md
docs/currency-system.md
docs/documentation.md
docs/error-handling.md
docs/localization.md
docs/security.md
docs/testing.md
As you can see, some documents are global and expand on high-level concepts, while others are targeted at performing specific actions.
Reducing context size while keeping the knowledge
The key benefit of this structure is that it dramatically reduces context size while keeping all the knowledge accessible. When the LLM runs the find command, it only sees file names—a few dozen lines at most. Based on those names alone, it decides which documents are relevant to the current task and reads only those.
You can create as many documentation files as you need without worrying about context limits. The LLM will never load everything at once. For example, if you're working on a front-end task, it will never read about how your data layer, event system, or GraphQL API patterns are designed. You simply don't need that information for the task at hand.
This approach gives you the best of both worlds: comprehensive documentation for your project and minimal context usage per task.
Managing documentation with LLM
Once you have lots of documents, you need a way to properly manage them. My recommendation is to use the LLM itself for this purpose.
Here is the workflow I use. While working on a task, I continuously monitor what the LLM does and try to catch errors it makes. I note how these errors were fixed and continue with the task. Once the task is complete and I'm ready to clean up the context, I run a /refine command.
Think about what we learned during the session. Focus on session memory analysis and minimal file reading to avoid LLM context window overflow. read the documentation, and refine things that you have learned during this session.
Create a todo list to track the refining process:
- Run `find docs/ -name "*.md" | sort` to see available docs.
- Read documentation on how to write documentation.
- Create todo items for new knowledge and guidelines we discovered
This command tells the LLM to reflect on what happened during the session: what kind of errors occurred, how they were overcome, and whether there is something beneficial to add to the documentation so these errors can be avoided in the future.
There is one prerequisite: you need a markdown file that describes how to write documentation for your project. With this in place, the LLM will think about the session, find an appropriate place inside existing documentation—or create a new document if needed—and elaborate on how to avoid the issue in the future.
This way, your documentation evolves organically based on real problems encountered during development. Every session becomes an opportunity to improve the knowledge base.
Action documents for consistent execution
This approach works not only for fixing errors—it works for any case when you create a new system or discover an important action that you want to ensure is done correctly and consistently.
If you look at my example docs folder, you'll notice a bunch of action documents for the frontend: create-modal.md, create-component.md, create-service.md, and so on. These documents define a strict structure of what to do when performing a specific task. They help eliminate the randomness of the LLM to some degree. This is especially useful when the action involves executing CLI commands or following a specific sequence of steps that must be done in a particular way.
Workflow techniques
The following techniques are not directly related to CLAUDE.md, but they significantly improve how you work with Claude Code.
Meta prompting
Instead of asking the LLM to perform a task directly, ask it to investigate the project, read the documentation, find problems in your prompt, and extend it to cover all the cases that were unclear.
This approach helps from two sides. First, you can start with a pretty simple prompt. Then, as you discuss it with the LLM, you can add more requirements, remove some, and adjust the scope—essentially having a conversation about what you plan to do. The LLM might point out edge cases you haven't considered or ask clarifying questions about ambiguous parts.
Second, once you're done refining, you have a well-defined prompt. At this point, you clean up the context and start a fresh session with this polished prompt. The LLM begins with a clear, comprehensive understanding of what needs to be done. Most of the time, you can be confident it will do exactly what you want because the context is well-defined from the start, not built up through a messy back-and-forth.
Don't be afraid to throw out the code
This might feel counterintuitive, but it's important: don't be afraid to discard what the LLM has created and start over.
Here's the scenario. You have a well-defined prompt, the LLM works on it, and it creates a structure based on your description. But then you see it's not exactly what you want. You know the changes could be made, but they would require a lot of back-and-forth, many adjustments, and the context would become cluttered with corrections and clarifications.
Instead of pushing through, just stop. Go back to your prompt, explain what was wrong with the result, add more information about what you actually need, clean up the context, and start from scratch.
With this additional information, the LLM may ask you clarifying questions about edge cases you missed. It might suggest a better approach or provide examples that help you refine your requirements further. The second attempt, armed with the lessons from the first, will almost always be closer to what you actually want—and it will be built on a clean foundation rather than a patchwork of fixes.
Don't be afraid to do it twice
Here's another technique I use often: don't be afraid to repeat an action.
For example, after the first iteration of meta-prompting, you have a nice, well-defined prompt. But what's stopping you from running meta-prompting on that meta-prompt? If everything is already fine, it will be super fast—the LLM will just confirm the prompt is solid. But sometimes, with a fresh context and a fresh look at the codebase, the LLM notices something that wasn't caught the first time.
This applies not only to meta-prompting. You can do the same with implementation: create two implementations and compare them against each other. Given how fast Claude Code types and executes, this is surprisingly easy to do when you have a well-defined prompt. The cost of a second attempt is low, and the potential benefit of catching issues or discovering a better approach is high.
You can also do partial implementations. For example, create a complete UI, but with all database queries and API calls done in memory with mock data. This way, you can quickly try multiple approaches to see which one feels right. Once you're satisfied with the result, you simply ask to replace the mocks with real API calls. This lets you iterate on the hard parts—the structure, the flow, the user experience—without getting bogged down in integration details too early.
Before Claude Code, this approach would be tedious—implement once, verify it works, test it, then repeat. With Claude Code, it's 15 minutes for UI with mock data and another 15 minutes for the database integration. Yes, you do additional work testing it multiple times, but finishing the job in an hour with the predictability you wanted is a much better result. I think it's worth it.
Conclusion
The key takeaway from this article is simple: keep your CLAUDE.md minimal and use it as an entry point, not a knowledge dump. Move everything else into a well-organized docs folder where the LLM can selectively read what it needs. This approach scales with your project—you can have dozens of documentation files without ever hitting context limits.
Use the LLM itself to maintain and evolve your documentation. Every session where you catch and fix an error is an opportunity to improve the knowledge base for future sessions. Create action documents for repetitive tasks to eliminate randomness and ensure consistency.
Finally, embrace the speed that Claude Code gives you. Use meta-prompting to refine your requirements before implementation. Don't be afraid to throw out code and start fresh. Run things twice. Build partial implementations with mocks to iterate quickly. The cost of repetition is low, and the benefit of getting exactly what you want is high.
These patterns transformed how I work with Claude Code. I hope they help you too.
Top comments (0)