Agent Skills Compose Right Up Until Two of Them Disagree. Then Nothing Decides Who Wins.
Two of the most-installed skills on GitHub give your coding agent opposite orders. The format has no precedence field, no scope field, and no way to tell you it happened. Here is where the collision lives and how to scope around it.
The community index of agent skills now lists more than a thousand of them, installable into Claude Code, Codex, Gemini CLI, Cursor and a dozen other hosts with a single npx skills add. Two of the most popular entries in that index are pointed in exactly opposite directions.
ponytail tells your agent to build less. Before it writes code it climbs a seven-rung ladder: does this need to exist, is it already in the codebase, does the stdlib do it, does the platform do it, is it in an installed dependency, can it be one line, and only then the minimum that works. Ask for a date picker and it answers with <input type="date"> and a comment.
unlazy tells your agent not to stop. It writes acceptance gates to a file before real work starts, each with a CHECK: command and an EXPECT: string, and in Claude Code it installs a Stop hook that mechanically blocks the agent from ending its turn while any box sits unchecked. Its README states the premise flatly: prose cannot enforce prose.
Both are MIT licensed. Both install into roughly twenty hosts. Both are trending this week. And nothing anywhere in the skill format tells you what happens if you install both.
The claim the docs make, and the one they never make
Anthropic's Agent Skills overview lists three benefits at the top of the page. The third is "Compose capabilities: Combine Skills for complex, multistep tasks."
Read the rest of that page looking for how composition resolves and you will not find it. The spec requires two fields, name and description. There is no priority field, no scope field, no phase field, no declaration of what a skill governs or when it should yield. The Limitations section is real and specific, covering cross-surface sync, sharing models and network access per surface, and it says nothing about two skills disagreeing.
The loading model makes this sharper. Skill metadata sits in the system prompt from startup at roughly 100 tokens each, which is exactly why installing many skills feels free. The body loads when the description matches your request, and once it loads it stays in the conversation for the rest of the session. So a skill that fired on turn 2 is still arguing its case on turn 40, against a skill that fired on turn 39, and the resolution happens inside a single forward pass with no log line and no warning.
That is the thing worth sitting with. Composition is not implemented anywhere. It is inferred, per turn, from whichever text the model weighs more heavily in that moment.
Where these two actually collide
The collision is not philosophical. It sits at a specific point in the loop.
unlazy's gates get written early, before real work starts, which is the whole design: intentions written at minute 2 stay sharp at minute 90. ponytail's ladder runs later, at the moment code gets written, after the agent has read the surrounding code and traced the flow.
So the agent writes a gate that says the pricing section renders three tiers with a working annual toggle, with a CHECK: command that proves it. Then it reaches rung four of ponytail's ladder and concludes the platform already gives it most of that behavior, or reaches rung one and concludes a piece of it should not exist at all. Now there is a checkbox on disk whose EXPECT: string will never match, and a Stop hook standing between the agent and the end of its turn.
The meters point opposite ways too, and both projects measured them. ponytail's corrected agentic benchmark reports 22 percent fewer tokens, 20 percent cheaper, 27 percent faster across twelve feature tickets on a real FastAPI and React repo. unlazy's token economy notes report the reverse by design: roughly 1.5 to 4 times baseline output in solo mode, and cost multiplying with leaf count in orchestrated mode, because that spend buys pre-delivery bug hunts and robustness sweeps. One skill is optimizing for less. The other is buying more on purpose. Install both and your agent is being graded on two scoreboards that disagree about which direction is up.
Neither maintainer is careless here. That is what makes this a format problem rather than a project problem.
The maintainers already know, and they built workarounds
Look at what these projects had to invent because the format gave them nothing.
ponytail's FAQ answers the composition question directly, but only for one specific partner. Asked whether it works with caveman, the README says yes, and the reasoning is pure scope arithmetic: caveman shrinks what the agent says, ponytail shrinks what it builds, "different halves, no overlap." Caveman leaves code byte-for-byte exact. ponytail stays out of the prose. That is a maintainer manually proving disjointness for one pair, in a FAQ, because there is nowhere structured to declare it.
ponytail also injects its ruleset into every subagent spawned through the Agent tool, and shipped an environment variable, PONYTAIL_SUBAGENT_MATCHER, so you can keep it off read-only search agents with a regex against the subagent type. That is a scoping mechanism the skill format does not have, rebuilt inside one skill, configured through the shell.
unlazy built the other half of the same admission. Its Stop hook releases the agent with a warning after six consecutive blocked stops with no gate progress, and an ABANDON: <gate> <reason> line always counts as an honest exit. Read that as engineering humility: the author assumed his own enforcement would sometimes be wrong, and shipped a valve. If you run both skills, that valve is the thing that eventually breaks the deadlock I described above. It breaks it after six wasted stops, silently, in a way that looks like the agent succeeded.
Put this into practice
Five things, in the order I would do them, none of which need a new tool.
Sort your installed skills by the moment they govern. Write the list down. Most skills act at one of four points: how the agent talks, how it designs, how it writes code, and how it decides it is done. Two skills at the same point are the ones that can fight. ponytail and caveman are safe because they sit at different points. ponytail and unlazy both have opinions about done.
Read the FAQ before the feature list. For any skill you are about to install alongside another, the composition answer, if it exists at all, lives in the FAQ or a compatibility note. Its absence is information. A skill that has never been asked how it interacts with anything has probably never been tested that way.
Check whether the skill reaches your subagents. ponytail documents that it injects into every spawned subagent by default. Most skills do not document this either way. If you fan work out to subagents, a skill you installed for the main loop may be steering ten parallel workers you never thought about.
Run the pair against one deliberate over-build. The cheapest test I know: pick a task with a real over-build trap, the date picker or the color picker from ponytail's own benchmark, and run it three times. Once with each skill, once with both. Read the diff and the transcript, not the summary. If the combined run produces more code than the ponytail-only run, ponytail lost the argument, and now you know which way your stack leans.
Write the precedence yourself, in your own file. Your AGENTS.md or CLAUDE.md is the one place you control that loads before any skill body. One sentence is enough. Something like: gates describe acceptance, not implementation, and a gate that requires code the reuse ladder would refuse gets rewritten, not satisfied. You are not adding a feature to the format. You are stating the tiebreak the format declined to state, in the highest-priority text you own.
Where this argument is weaker than it sounds
I have not measured the collision. I am reasoning from two READMEs, both of which I read in full, plus a docs page that omits a mechanism. What I can show is that the mechanism is absent and that both maintainers built private substitutes for it. What I cannot show you is a failure rate.
It may also be that models handle this better than the format does. Anthropic's guidance elsewhere suggests more specific instructions tend to win when instructions conflict, and a good model reading both a reuse ladder and a gate ledger might reasonably conclude the gate should be rewritten. That would be the right call. It would also be a call made silently, by judgment, differently on different models, and reversible by a single wording change in either skill. Depending on judgment is fine. Depending on judgment you cannot inspect is what I would push back on.
The frequency question is real too. Most people install one or two skills, not forty, and at that scale the odds of two skills governing the same moment are low. This gets worse as the index grows, not because any skill got worse, but because a thousand independently authored files that were never tested against each other is a combinatorics problem nobody owns.
And ponytail's own numbers argue for humility about all such claims. The project shipped 80 to 94 percent less code as a headline, issue #126 pointed out the baseline was a chatty bare model padding its answer with prose and options, and the maintainer rebuilt the benchmark as a real agentic run and published 54 percent instead, demoting the old figure to a per-task ceiling. InfoQ covered the correction. That is the healthiest thing in this whole story, and it is also a reminder that the numbers on both sides of this collision are young.
What I would do this week
Open your skills directory. Count what is in it. For each one, write a single line naming the moment it governs, and look for duplicates.
That exercise takes ten minutes and it is currently the only conflict detection that exists. The format gives you free installs, portable files, and a promise of composition, and it hands the resolution to a model that will never tell you it made a call. Until a precedence field shows up in the spec, the scoping is yours to do, and it is much cheaper to do it before the install than to debug it at minute 90 with six blocked stops behind you.
Sources: Agent Skills overview, Claude Platform Docs; DietrichGebert/ponytail README and benchmark writeup; ponytail issue #126; InfoQ, Ponytail Agent Skill Corrects its Own Benchmark; Leonxlnx/unlazy README; VoltAgent/awesome-agent-skills.