Available for rolesPiotr Czerwiński

Writing · August 5, 2026 · 9 min read

Why I stopped loading every skill into every Claude Code session

Claude Code · AI agents · context engineering · workflow

TL;DR: I had roughly 25 skills, a handful of subagents, and several MCP servers loading into every Claude Code session, regardless of which project I opened. The symptom I kept hitting was "the agent loses context." The cause was not missing documentation. It was the absence of layers: everything was global, so every session paid for tooling it would never use. The fix was three layers - a tiny global core, a storage library that nothing is switched on from, and a per-project manifest that pulls in only what that repo needs. This post is about what actually enters the context window and when, because until you know that, you optimize the wrong thing.

What actually loads, and when

The whole design rests on one distinction that is easy to miss: descriptions load eagerly, bodies load lazily. A skill does not put its full instructions into your context at startup. It puts its one-line description there, so the model knows the skill exists and when to reach for it. The body is read only when the skill is actually invoked.

Once that clicks, the cost model falls out of it:

ResourceWhen it enters context
Root project instruction fileAt startup, in full
Instruction file in a subdirectoryLazily, only when the model reads files in that directory
SkillDescription at startup, body only on use
SubagentDescription at startup, prompt only when it runs
MCP serverTool definitions at startup (expensive for large servers)

The consequence: descriptions sum. Twenty-five skills means twenty-five descriptions in every session, including the twenty that have nothing to do with the repo in front of you. That is a tax you pay on every single start. A subdirectory instruction file, by contrast, is lazy, so it costs nothing until you work in that directory. Knowing which is which is the difference between trimming fat and trimming muscle.

The three layers

Layer one, global. Only what applies to every repo I will ever open: universal code standards, git identity and conventions, security defaults, language rules. Two universal skills at most. The test is blunt - if a rule does not apply to every project, it does not belong here. Everything that survives that test is worth its permanent seat in the context window; nothing else is.

Layer two, the storage library. A single directory that holds every skill and subagent I have, and from which nothing is switched on. It is a library, not a runtime. New skills land here first. Keeping the catalog separate from what is active is what makes the whole thing sane: I can own fifty skills without any session paying for fifty descriptions.

Layer three, per project. Each repo declares the skills and agents it actually uses in a small committed manifest, plus its own settings and its own MCP configuration. A one-line script reads the manifest and recreates the links to the storage library. The manifest is committed; the generated links are gitignored, because they carry absolute paths that make no sense on another machine. So the source of truth travels with the repo, and reconstructing the setup anywhere is a single command.

The manifest itself is deliberately boring - a list of names, one per line, nothing clever:

# <repo>/.claude/skills.manifest
code-standards
nextjs
supabase-postgres
ui-design-system

That is the entire interface. Add a name, run the link script, restart. The real value lives in the skills themselves, which stay in the private library; the manifest just says which of them this repo is allowed to see.

Where you start the agent matters

This one cost me real confusion before I understood it. The working directory you launch from decides what loads, and not everything inherits upward. Instruction files and skills are looked up from your current directory up to the repo root (and lazily downward). But the settings file and the MCP configuration are read only from the directory you actually started in - they do not walk up the tree.

The trap is concrete. Launch the agent from a deep subdirectory and you still get your instruction files and skills, but you silently lose the project settings and MCP config - which is exactly the layer that holds your safety rules and your permission denials. You drop the guardrails without any warning that you dropped them. The rule I follow now is simple: always start from the repo root.

Memory has its own wrinkle worth knowing: the per-project memory slug is derived from the git repository, not from the directory you happen to start in, so every subdirectory of a repo shares one memory. A folder that merely contains many repos, but is not itself a repo, gets its own slug - which turns out to be what you want, because it keeps the memory for a whole product family in one place instead of scattering it across twenty drawers.

A couple of sharp edges

Two things I learned the annoying way. First, do not copy universal rules into a project's instruction file - link to the global ones. A duplicated doc drifts, and a drifted doc starts lying to you. It is the same DRY principle you apply to code, applied to instructions. Second, be aware that some third-party skill installers copy their files into the config directories of several different AI tools at once; those are duplicates of one thing, not separate resources, and treating them as separate will confuse your accounting of what is really loaded.

The payoff

On one project the move took a session from around 25 skill descriptions down to 12 plus the 2 global ones, from 5 subagents to 4, and from 4 MCP servers to 2 - the two that project never touches simply stopped loading. Nothing about the model changed. The context window just stopped being clogged with descriptions for tooling that had no bearing on the work, and "the agent loses context" stopped being a recurring complaint.

The general lesson, if there is one: with agent tooling, more installed is not more capable. Everything that loads eagerly competes for the same finite attention. The job is to make sure the things in the room are the things this task needs, and to keep everything else one manifest entry away rather than permanently present.

What carries over

  • Know your eager vs lazy costs. Descriptions sum on every start; subdirectory docs are free until used. Optimize the eager ones.
  • Global holds only the universal. If a rule does not apply to every repo, it belongs in a per-project layer, not in the context window of every session.
  • A library is not a runtime. Own as many skills as you like in storage; activate per project through a committed manifest.
  • Start from the repo root. Settings and MCP config do not inherit upward, and that is the layer your guardrails live in.
  • Link, do not copy. Duplicated instructions drift, and drifted instructions mislead the agent.