Undercut for Kilo Code
Undercut is a free, MIT-licensed policy file Kilo Code's own Agent Skills feature discovers and loads — cheap tier first, escalate only on evidence, never on a vibe. Kilo Code began as a VS Code extension forked from Roo Code (itself a Cline fork), then grew its own CLI and JetBrains clients with 500+ selectable models; this exists because the same overpay-by-default pattern we measured elsewhere in the agent ecosystem (one self-reported ccusage-style breakdown of default routing behavior in a different agent showed 93.8% of tokens going to the top-tier model by default, anthropics/claude-code#27665 — one account's data, from Claude Code rather than Kilo Code) shows up anywhere an agent defaults every task to its strongest model.
How this maps onto Kilo Code
Kilo Code (the extension is still published as kilocode.kilo-code on the VS Code Marketplace, under the company's rebranded "Kilo" name) began as a fork of Roo Code, which is itself a Cline fork — but on Agent Skills specifically it has diverged into its own convention, confirmed directly against Kilo's own Skills docs: skills load from a project-level .kilo/skills/<name>/SKILL.md and a global ~/.kilo/skills/ (Windows: \Users\<you>\.kilo\skills\) — different directory names than Roo Code's .roo/skills/, not a shared path. Kilo also loads the cross-agent .agents/skills/ convention by default, and .claude/skills/ for Claude Code compatibility (opt-in in the VS Code extension, on by default in the CLI). Discovery is the same progressive-disclosure model as the wider Agent Skills spec: only each skill's name/description frontmatter is read at startup, and the full file loads on demand once the agent decides a request matches. The frontmatter name must match the parent directory — Undercut's skill is already named firstpass, so it satisfies that as-is.
One notable difference from Roo Code: Kilo's docs are explicit that its skills platform "does not use mode-specific skill directories" (no skills-{mode}/ variant) — every skill loads into one shared pool regardless of mode, and a skill's own description is the only thing that scopes when it fires. Separately, Kilo Code also reads plain-instructions rules from a .kilo/rules/ directory, wired up via an instructions array in kilo.jsonc — a different, older mechanism from skills, and its docs note it stays backward-compatible with the legacy .kilocode/rules/ directory from before the rebrand. Neither of those is the path this page installs to.
Undercut's tier names — cheap, standard, frontier, apex — are generic on purpose. models.md gives the rule of thumb rather than a fixed slug for Kilo Code specifically, since Kilo Code is provider-agnostic across its 500+-model picker: cheap maps to the smallest/fastest model in whatever family you've configured, standard to your default work model, frontier to the highest-reasoning production model, apex to the single batched tie-break call. Nothing about this sits between Kilo Code and your model provider — it's a policy file Kilo's own skill loader reads on demand, no proxy, no network hop, nothing to route around if you remove the directory.
Install for Kilo Code
Run this from the repo root. Kilo Code scans .kilo/skills/ for SKILL.md files when a session starts and loads the full file on demand when a request matches its description — the folder name has to match the name: field in the file's frontmatter. Undercut's is already named firstpass, so the directory copies straight across.
Same folder, user scope. Kilo Code also scans ~/.kilo/skills/ for every project (Windows: \Users\<you>\.kilo\skills\).
skills.sh lists Kilo as a supported target. If it writes to the cross-agent .agents/skills/ convention — one of Kilo's own documented compatibility directories, loaded by default — that lands directly on a path Kilo already scans, no translation needed. We haven't independently run the installer against a live Kilo Code session to confirm the exact directory it targets, so if it doesn't show up, use Option 1 above, which we checked directly against Kilo's own docs.
testing/README.md and the raw JSON in testing/results/node src/main.js --mockZero lock-in. It's a policy Kilo Code's skill loader reads — remove the directory and you're back to status quo.
How it works
The Undercut Rubric · v1This is a named, versioned spec — not internal logic we could quietly change. When the rubric changes (a new flag, a different cap), the version number moves and the changelog says why.
Every unit of work gets scored against six flags, then assigned the cheapest tier that can plausibly handle it. It only moves up a tier when something objective proves it needs to — a failed check, a measured disagreement, an explicit uncertainty flag. It never moves up on a guess, and it never moves back down mid-task.
0 flags → cheap · 1–2 → standard · 3+ or any ownership/judgment call → frontier. Apex only when you can write one sentence stating why the marginal intelligence pays for the cost.
Cheap-to-verify ⇒ cheap-to-generate. If output can be checked mechanically, it starts at the lowest tier regardless of how hard it looks — verification catches failure. Only unverifiable work needs to start high.
The next tier up gets only the failed or uncertain items, plus verification notes. It resolves the residue — it never redoes the batch.
Never de-escalate mid-task. Max one retry per tier. Anything still unresolved goes to a single batched apex tie-break call. One hard file in a 700-file job doesn't drag the other 699 up a tier.
unit of work
|
6-flag rubric
|
+---+----+
| 0 flags|--> cheap
| 1-2 |--> standard
| 3+/own |--> frontier
+---+----+
| fail x2 / disagree / uncertain
v
escalate +1 tier
(residue only)
|
still unresolved?
v
single batched
apex tie-break
Why it holds up
Even when the rubric flags are scored imperfectly, the escalator still routes work to the right tier almost every time — because a wrong flag only ever costs one extra cheap attempt, never a wrong answer or a big bill.
A stock dispatcher model reproduces the rubric flags imperfectly — Haiku hits 90% agreement, Sonnet 93%. The weakest flag (format-strict) is only 60%. None of that matters: under the shipped policy, both dispatchers still route 100% of units to the correct tier. A wrong flag changes the ladder cap, never the base tier — worst case, one extra cheap attempt.
Every rule is a property of the unit of work — verifiable, ambiguous, blast-radius — never a specific model's known weakness. Vendor cards go stale as models change; work properties don't. It's also hard-won — a format-strict rule that worked on Anthropic backfired on Gemini, which is exactly why the rubric no longer encodes per-vendor behavior.
Honest limits
Not a proxy, not a gateway, doesn't auto-flag in production (Kilo Code scores the flags itself — measured robust to getting them wrong, see above). Doesn't promise a dollar figure for your workload, and doesn't prove your number until you run it — every figure here is a reproducible observation from our tasks and graders, not a guarantee about yours. The skills-CLI target directory for Kilo specifically is documented on skills.sh but hasn't been independently confirmed end-to-end by us against a live session — treat that one detail as unverified until tested; the .kilo/skills/ path above is the one we checked directly against Kilo's own docs. Kilo Code shares history with Roo Code and Cline, but its Agent Skills directories, mode-agnostic loading, and rules mechanism are its own — don't assume anything from those pages carries over uncited. Full list of general limits, with the finance/procurement note and the paid-tier disclosure, is on the main page.
Nothing about this page expires. What does keep happening is the token bill, one session at a time, on whatever Kilo Code is currently doing with mechanical work.