Keep Skills Flat, Keep Helpers in Source
Your AI skill folder is becoming a shadow codebase.
It starts innocently: a skill needs to parse a file, so you drop a little script next to it. Then another skill needs almost the same thing, so you copy it. Soon your skills directory is full of nested helpers, utility modules, and scripts — logic that is untested, duplicated across skills, and drifting away from the real code it was supposed to mirror. That's a shadow codebase, and it's the thing skills were meant to avoid.
Why nesting helpers backfires
A skill is a methodology — guidance the model reads and follows. A helper script is deterministic code — it runs the same way every time. Mixing them puts real logic somewhere with none of the safeguards real logic needs:
- No tests. Scripts buried in a skill folder aren't in your test suite. They break silently.
- Duplication. The same parse-this or format-that logic gets copied into every skill that needs it, and the copies diverge.
- Silent drift. When the real behavior changes in your source tree, the nested copies don't. Now the skill instructs the agent using stale logic.
- No review. Code that never lands in a reviewed pull request never gets the eyes that would have caught the bug.
The mechanism: flat skills, sourced helpers
Two rules keep the boundary clean:
- Keep each skill a flat, single file — one self-contained methodology per skill, no nested script tree. If a skill grows past what one file should hold, split it into flat sibling files, not into subfolders of code.
- Put deterministic helpers in your real source tree, where they are tested, reviewed, and versioned. The skill references the tool; it doesn't contain it.
# Anti-pattern: shadow codebase
skills/
release/
SKILL.md
scripts/
bump_version.py # untested, duplicated in two other skills
changelog_utils.py
# Better: flat skill, helper lives in source
skills/
release.md # methodology only; says "run scripts/release/bump.py"
src/
release/
bump.py # in the test suite, reviewed, single source of truth
changelog.py
tests/
release/test_bump.py
The skill tells the agent what to do and when; the source tree holds the code that does it deterministically.
Methodology vs. deterministic code
| Belongs in a skill | Belongs in source | |
|---|---|---|
| Nature | Judgment, guidance, when/why | Fixed, repeatable behavior |
| Tested | No (it's prose) | Yes, in your suite |
| Should be duplicated | Never | Never — import it |
| Changes via | Editing the doc | Reviewed pull request |
Progressive disclosure does the rest
Flat sibling skills pair naturally with progressive disclosure: the agent loads only the files a task actually needs, instead of pulling a whole nested tree into context. Fewer files loaded, each one focused, none of them a copy of code that lives — and is tested — somewhere else.
Power moves
- When you reach for a script inside a skill, stop. Ask whether that logic should be a tested function in
src/that the skill calls instead. - One methodology per skill file. If two concerns creep in, that's the signal to split into flat siblings.
- Grep for duplication. If the same helper appears in two skill folders, it belongs in source as one function.
- Reference by path, not by copy. A skill should name the tool to run, so the single tested implementation stays authoritative.
Resources
- Agent Skills — Anthropic docs (progressive disclosure)
- Engineering effective agent skills — Anthropic
- Model Context Protocol — tools
- Don't repeat yourself (DRY) — Wikipedia
Shipping AI or cloud systems? Yeda AI audits and hardens production LLM and agent pipelines. Talk to us · Read the blog