AI News · Tools
Caveman vs. the
built-in output styles.
DE Auf Deutsch lesen
Claude Code ships with four built-in output styles: Default, Concise, Explanatory and Learning. Caveman is a separately installed skill with the same goal as Concise: fewer tokens in the response. I answered the same small task on real PlantWiz code five times, once per style, and counted characters and words.
SKILL.md of the npm package caveman-skill, followed to the
letter. The technical solution is identical across all five answers; only the wording and
length of the prose differ, so the comparison targets the style, not different solution
approaches.
The task
backend/scripts/import-trefle.ts recursively calls the function
trefleGet again after a 5-second wait whenever the Trefle API returns a rate
limit (HTTP 429), with no upper bound. If the API keeps the limit in place, the import runs
indefinitely with no visible error. Instructions given to the agent: "Cap the number of
retries on rate limits, so the script aborts with a clear error message after a few
attempts."
Five styles, one task
Default (Proactive)
Claude Code, built-in default style · "helps complete software engineering tasks efficiently"
Explains the cause, implements the fix, summarizes afterward, moderate length, no special formatting.
Ich schaue mir die Funktion trefleGet an: Bei einem 429 (Rate-Limit) wartet
sie 5 Sekunden und ruft sich selbst erneut auf, ohne Obergrenze. Hält die
Trefle-API das Limit dauerhaft, läuft der Import unbegrenzt weiter, ohne
sichtbaren Fehler.
Ich ergänze einen Zähler-Parameter, der bei jedem Rate-Limit-Treffer hoch-
gezählt wird, und breche nach fünf Versuchen mit einer Fehlermeldung ab.
Die bestehende Wartezeit bleibt unverändert.
[... Code ...]
Ich habe trefleGet um den Parameter retries erweitert, Standardwert 0. Ab
dem sechsten Versuch wirft die Funktion einen Fehler statt weiter zu
rekursieren, die Meldung nennt die Anzahl der Versuche. Bestehende Aufrufe
der Funktion sind nicht betroffen, weil der neue Parameter optional ist.
Concise
Claude Code, built-in style · "result first, no recap, answer briefly", from version 2.1.237
Result first, no preamble, no summary afterward, same technical depth as Default.
trefleGet bricht jetzt nach fünf Rate-Limit-Versuchen mit Fehler ab, statt
endlos zu rekursieren.
[... Code ...]
Wartezeit zwischen Versuchen bleibt bei 5s.
Explanatory
Claude Code, built-in style · educational insights before and after implementation, "★ Insight" format
Like Default, plus short framing: why this pattern is a problem, which trade-offs were deliberately not implemented.
★ Insight ─────────────────────────────────────
Unbegrenzte Rekursion bei Rate-Limits wirkt harmlos, kann ein Skript bei
einer länger anhaltenden API-Störung aber stundenlang ohne sichtbaren
Abbruch blockieren. Eine feste Obergrenze macht den Fehlerfall sichtbar.
Ein wachsendes Zeitintervall zwischen Versuchen (exponentielles Backoff)
wäre der nächste sinnvolle Schritt, hier bewusst weggelassen, um die
Änderung klein zu halten.
─────────────────────────────────────────────────
[... Code ...]
★ Insight ─────────────────────────────────────
Der neue Parameter retries ist optional mit Standardwert 0, bestehende
Aufrufe von trefleGet bleiben unverändert lauffähig. Dieses Muster, ein
optionaler Zähler-Parameter für rekursive Hilfsfunktionen, taucht in
PlantWiz noch an anderen Stellen auf und lohnt sich als wiederkehrendes
Erkennungsmerkmal für ähnliche Fehlerklassen.
─────────────────────────────────────────────────
Learning
Claude Code, built-in style · leaves 5–10 lines for the user to write at decision points, marked with TODO(human)
Sets up the frame and context, leaves the actual design decision to the user, with reasoning about the alternatives.
Die Anzahl maximaler Versuche und die Reaktion danach sind eine Design-
Entscheidung mit mehreren vertretbaren Antworten. Dafür überlasse ich
Ihnen die Kernzeile.
async function trefleGet(url: string, retries = 0): Promise<any> {
...
if (res.status === 429) {
// TODO(human): Abbruchbedingung nach zu vielen Rate-Limit-Versuchen
console.warn('\nRate-Limit erreicht, warte 5s...')
await sleep(5000)
return trefleGet(url, retries + 1)
}
...
}
In backend/scripts/import-trefle.ts, in der markierten Zeile: Entscheiden
Sie, wann trefleGet aufgeben soll. Zwei vertretbare Richtungen: nach einer
festen Anzahl Versuche mit Fehler abbrechen (einfach, verliert aber alle
restlichen Pflanzen bei einer kurzen API-Störung), oder nur die aktuelle
Pflanze überspringen und mit der nächsten weitermachen (robuster,
verschleiert aber eine dauerhafte Störung im Log). Beides ist in der
bestehenden Codebasis vertreten, schauen Sie sich zum Vergleich an, wie
fetchDetail mit einzelnen Fehlern umgeht.
Caveman
npm package caveman-skill, version 1.0.0 · "full" tier, followed literally from SKILL.md
Articles dropped, filler words dropped, fragments allowed, code and error messages remain quoted exactly.
trefleGet: infinite retry on 429, no cap. Risk: dauerhaft rate-limited →
endless loop, kein Fehler sichtbar.
Fix: retries param, default 0. Cap 5. Über Cap: throw.
[... Code ...]
Wait 5s unchanged. Backoff wachsend: nicht drin, extra Schritt.
Measured
The code is technically identical across all five answers, so the table below counts the prose separately from the code block, plus both combined as the total response length:
| Style | Prose (characters) | Prose (words) | Total incl. code (characters) |
|---|---|---|---|
| Default | 726 | 104 | 1,368 |
| Explanatory | 911 | 97 | 1,553 |
| Learning | 707 | 92 | 1,270 |
| Caveman | 230 | 35 | 872 |
| Concise | 143 | 19 | 785 |
Prose length by style
Text only, no code block. Ordered by length.
Caveman and Concise visibly pursue the same goal, short prose, but don't land at the same level: Concise, at 143 characters, is noticeably leaner still than Caveman's 230 characters. The difference lies in the pattern itself: Concise drops transitions entirely where they add nothing, while Caveman shortens every sentence but keeps sentence structure as a fragment, "Fix: retries param, default 0" instead of just "retries param."
SKILL.md with every call, 3,466
characters, roughly 860 to 900 tokens. For a single short answer like this test, that's more
than the leaner answer itself saves. The one-time loaded rule only pays off across several
answers in the same session, and even then Concise remains the leaner option at zero extra
cost wherever both are available.
Where Explanatory and Learning still bring something of their own
Neither Concise nor Caveman replaces Explanatory or Learning, because they pursue a different goal. Explanatory explains why a solution looks the way it does, in this example the difference between a fixed cap and true exponential backoff, a piece of framing that is simply missing from the Caveman or Concise version. Learning goes further and deliberately leaves the design decision, whether too many failed attempts abort the whole action or only individual items get skipped, to the user, pointing to an existing comparison pattern in the same code. Both styles cost more text because they accomplish something other than pure brevity.
Which style, when
Everyday tasks, result matters more than derivation
Concise, built-in, no extra overhead, shortest prose in this measurement.
Onboarding, code reviews, unfamiliar codebase
Explanatory, when the reasoning behind a decision matters as much as the decision itself.
Learning context, your own team should follow along
Learning, when design decisions should deliberately stay with the human instead of being made automatically.
Caveman is additionally useful for
Tools without their own style configuration, or when the three-tier escalation (lite/full/ultra) is needed depending on the situation. Where Concise is available, it is the leaner and free option in this measurement.
Which output style fits your team?
I set up Claude Code in developer teams, including the question of which output style fits which task. 30-minute intro call, free of charge.