ai newsDo., 15. Okt.
EilmeldungMeta and Apple team up to make Muse AI models run better on Macs

Claude Code: keep-coding-instructions wirkt nur im vollständigen Prompt

In Claude Code 2.1.289 mit Opus 5.5 entscheidet keep-coding-instructions: true, ob ein 1.044 Token großer Abschnitt im System Prompt bleibt, allerdings nur beim vollständigen Prompt. Im verkürzten Prompt fehlt diese Steuerung vollständig.

dev.toSamstag 04:17 · 10.10.DE17 Min. Lesezeit
Bild: dev.to

In Claude Code 2.1.289 mit Opus 5.5 entschied keep-coding-instructions: true darüber, ob eine 1.044 Token umfassende Sektion # Doing tasks im System-Prompt blieb, allerdings nur, wenn Claude Code seinen vollständigen Prompt sendete; im kürzeren Prompt, den dieses Konto standardmäßig erhielt, erzeugten ein Custom Style mit dem Schlüssel und derselbe Style ohne ihn identische Requests. Bei einer Einzeiler-Bugfix-Aufgabe machten 18 von 18 Durchläufen über drei Styles hinweg dieselbe Änderung, fügten keinen Kommentar hinzu und prüften das Ergebnis nach der Bearbeitung, und die Hauptwirkung des Custom Style bestand darin, die Länge der Abschlussmeldung zu verdoppeln.

Output Styles sind die Möglichkeit, die Art zu verändern, wie Claude während einer gesamten Claude Code Session spricht: kürzere Antworten, Erklärungen zu jeder Änderung oder eine völlig andere Rolle. Die Output-Styles-Seite fügt den selbst geschriebenen Custom Styles eine einzige Warnung hinzu. Sofern die Style-Datei nicht keep-coding-instructions: true in ihrem Frontmatter setzt, lässt Claude Code seine eingebauten Anweisungen für Software-Engineering weg, "wie etwa zum Umfang von Änderungen, zum Schreiben von Kommentaren und zur Verifikation der Arbeit".

Dieser Satz wirft für alle, die einen Style schreiben und ihn anschließend in einem Repository verwenden, zwei Fragen auf. Wie viel Text verschwindet tatsächlich, gemessen in Tokens? Und programmiert eine Session ohne diese Anweisungen anders: lässt sie die Tests aus, räumt sie Code auf, dessen Bereinigung niemand verlangt hat, hinterlässt sie überall Kommentare? Wir wollten beide Antworten aus den Requests haben, die Claude Code an die API sendet, und nicht aus dem, was das Modell über seine eigenen Anweisungen sagt, also bauten wir ein kleines Labor und führten es 40 Mal unter claude -p aus.

Alles Folgende lief am 2026-10-05 zwischen 16:23 und 16:33 UTC mit Claude Code 2.1.289 ( claude --version ) und claude-opus-5-5 (ausgewählt mit --model opus ) auf macOS. Die Output-Styles-Seite wurde mit trafilatura um 16:20 UTC am selben Tag abgerufen und um 16:34 UTC erneut abgerufen, ohne Änderung; die übrigen Dokumentationszitate stammen aus Abrufen zwischen 16:20 und 16:35 UTC.

Dies sind die Sätze, die das Labor testet, zitiert wie abgerufen von https://code.claude.com/docs/en/output-styles:

Der Schlüssel ist nicht neu. Der Changelog-Eintrag für 2.0.37 lautet "Output Styles: Added keep-coding-instructions option to frontmatter". Was die Seite nicht liefert, ist eine Größe für "die eingebauten Anweisungen für Software-Engineering" oder eine Liste davon über diese drei Beispiele hinaus, und der Standardwert ist false, sodass jeder Custom Style, der die Zeile weglässt, zur Gruppe der Verworfenen gehört.

Es gab drei Bedingungen, und jeder Durchlauf erhielt ein frisches Verzeichnis, das aus derselben Vorlage kopiert wurde:

Der Style bezieht sich absichtlich auf das Schreiben, also den Fall, den die Dokumentation als "Claude wird kein Software-Engineering betreiben" beschreibt:

--- name: Plain Writer description: Plain, friendly prose for documentation and explanations --- You are a writing assistant. Answer in plain, friendly prose paragraphs. Avoid bullet lists and headings unless the user asks for them.

Halte Sätze kurz und definiere jeden Fachbegriff bei der ersten Verwendung. Beende jede Antwort mit einem aus einem Satz bestehenden Fazit, das mit "In short:" beginnt. Condition (b) fügt keep-coding-instructions: true nach der Beschreibungszeile ein, und sonst ändert sich nichts.

Beide Versionen liegen unter.claude/output-styles/plain-writer.md in ihrem jeweiligen Ausführungsverzeichnis, sodass Style-Name und Body byte-identisch sind und sich nur das Frontmatter unterscheidet. Jeder Durchlauf wählt ihn über eine einzeilige.claude/settings.json, {"outputStyle": "Plain Writer"}. Der Satz mit "In short:" ist ein Marker: Endet eine Antwort damit, war der Style in Kraft.

Die Vorlage ist ein winziges Node-Projekt. sum.js enthält drei Funktionen. sum hat einen Off-by-one-Bug (seine Schleife beginnt bei Index 1 und überspringt dadurch die erste Zahl), average und formatTotal rufen beide sum auf, und formatTotal ist in einem anderen Stil geschrieben als der Rest der Datei ( var, keine Semikolons), als Köder für eine Bereinigung, die niemand verlangt hat. test/sum.test.js enthält vier node:test Tests, von denen drei wegen des Bugs fehlschlagen, und package.json mappt npm test auf node --test. Jedes Ausführungsverzeichnis bekam git init und einen Commit, sodass git status zu Beginn sauber war und git diff danach genau zeigt, was die Session geändert hat.

claude -p " $PROMPT " --setting-sources project,local --strict-mcp-config --model opus \ --permission-mode acceptEdits --output-format stream-json --verbose \ --session-id " $SID " --max-turns 40 < /dev/null --setting-sources project,local hält unsere Benutzereinstellungen samt der Hooks und Plugins, die sie aktivieren, aus den Durchläufen heraus. --strict-mcp-config ohne Konfigurationsdatei bedeutet keine MCP-Server. acceptEdits erlaubt der Session, Dateien ohne Rückfrage zu bearbeiten. Wir haben außerdem die CLAUDE_* Umgebungsvariablen zurückgesetzt, die die Claude Code Session, aus der heraus wir arbeiteten, exportiert, darunter CLAUDE_EFFORT, sodass die Kindprozesse mit ihrem eigenen Standard-Effort liefen, den jeder Request-Body als medium verzeichnete.

Ein Einrichtungsdetail ist es wert, weitergegeben zu werden. Unser erster Pilot legte auch Bash-Allow-Regeln in.claude/settings.json ab, und Claude Code gab Ignoring 7 permissions.allow entries from.claude/settings.json: this workspace has not been trusted aus. Die Ausführungsverzeichnisse waren neu und wurden nie interaktiv geöffnet, daher wurden sie nie als vertrauenswürdig eingestuft.

Wir verlagerten die Allow-Regeln ( npm test, node, git diff und einige weitere) in.claude/settings.local.json, von dem die Settings-Seite sagt, dass es sich verhält, solange die Datei untracked ist: "Claude Code wendet seine Allow-Regeln ohne den Workspace-Trust-Schritt an, den es für die committete Datei verlangt." Der outputStyle Schlüssel in derselben nicht vertrauenswürdigen.claude/settings.json wurde dennoch angewendet: das init Ereignis meldete "output_style": "Plain Writer" in 28 von 28 Durchläufen mit dem Style.

Das Session-Transkript zeichnet die Token-Nutzung auf, nicht aber den System-Prompt, und wir wollten uns nicht darauf verlassen, das Modell zu fragen, welche Anweisungen es sehen kann. Die Monitoring-Seite dokumentiert einen Weg, um an den Request selbst zu gelangen: OTEL_LOG_RAW_API_BODIES, das "den vollständigen Anthropic Messages API Request und Response JSON als api_request_body / api_response_body Log-Ereignisse ausgibt", mit " file:<dir> für ungekürzte Bodies auf der Festplatte mit einem body_ref Verweis im Ereignis". Mit CLAUDE_CODE_ENABLE_TELEMETRY=1, OTEL_LOGS_EXPORTER=console, OTEL_METRICS_EXPORTER=none und OTEL_LOG_RAW_API_BODIES=file:<dir> hinterließ jeder Durchlauf das exakte JSON jedes gesendeten Requests in seinem eigenen Ordner, und im stream-json Output erschien nichts zusätzlich.

Alles Folgende zum Inhalt eines Prompts stammt aus diesen Dateien. Die Token-Zählungen stammen aus dem Transkript unter ~/.claude/projects/: input_tokens + cache_creation_input_tokens + cache_read_input_tokens der ersten Assistant-Nachricht, was den gesamten ersten Request zählt, unabhängig davon, ob ein Teil davon aus dem Cache bedient wurde.

Die Piloten widersprachen bereits unseren Erwartungen. Mit dem trivialen Prompt war der Request von Style plus Schlüssel derselbe Text wie der Request von Style ohne Schlüssel, abgesehen vom Verzeichnisnamen des Durchlaufs, seinem Commit-Hash und einer anforderungsspezifischen ID. Keiner von beiden enthielt eine Sektion zu Software-Engineering-Aufgaben, und der Default auch nicht.

Die Erklärung findet sich auf der Seite zu den Umgebungsvariablen. CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT wird so beschrieben: "Set to 1 to use a shorter system prompt and abbreviated tool descriptions on any model. Set to 0, false, no, or off to opt out even on models where the experiment or server configuration would otherwise enable it." Mit unset Variable waren die Requests dieses Kontos die kürzere Variante: die Tool-Definitionen kamen auf 27.700 Zeichen JSON, und der System-Prompt des Default-Styles umfasste etwa 6.900 Zeichen mit fünf Überschriften ( # Harness, # Session-specific guidance, # Memory, # Environment, # Context management ) und einigen Absätzen ohne Überschrift.

Mit CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT=0 wuchsen die Tool-Definitionen auf 44.195 Zeichen und der System-Prompt auf etwa 28.300, dazu kamen # System, # Doing tasks, # Executing actions with care, # Using your tools, # Tone and style und # Text output (does not apply to tool calls).

Da die Dokumentation sagt, dass ein Experiment oder eine Server-Konfiguration den kurzen Prompt einschalten kann, kann es davon abhängen, welches Konto, welches Modell oder welche Woche man hat, welchen Prompt man erhält. Deshalb führten wir jede Messung unter beiden Varianten aus. Von hier an bedeutet der kurze Prompt das, was dieses Konto mit unset Variable erhielt, und der vollständige Prompt bedeutet CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT=0.

Der triviale Prompt lautete Reply with the single word OK. mit --max-turns 1, drei Durchläufe für jede der sechs Kombinationen, insgesamt 18 Durchläufe. Alle 18 antworteten OK; die Ein-Wort-Antwort setzte sich gegen den "In short:" Satz des Styles durch.

Wiederholungen einer Bedingung wichen um bis zu 7 Tokens ab, weil der Verzeichnisname, der Commit-Hash und eine Request-ID alle im Request auftauchen. Nachdem wir diese drei Werte durch Platzhalter ersetzt hatten, waren die drei Durchläufe jeder Kombination byte-identisch, was fünf unterschiedliche Prompts für sechs Kombinationen übrig lässt: Im kurzen Prompt ergaben Style ohne Schlüssel und Style plus Schlüssel in 6 von 6 Durchläufen denselben Text.

Im vollständigen Prompt ist der Schlüssel 1.044 Token wert (28.284 gegenüber 27.240 im Median; 1.043 bis 1.047, wenn wir die Läufe paarweise pro Runde vergleichen). Der Unterschied zwischen diesen beiden Anfragen ist genau ein Block, der Abschnitt # Doing tasks: 3.321 Zeichen, 530 Wörter, 12 Aufzählungspunkte. Ohne den Schlüssel war die erste Anfrage mit einem eigenen Stil 899 Token leichter als ganz ohne Stil, weil der Abschnitt entfiel und dafür etwa 145 Token an Stil hinzukamen.

Der Stil selbst kostete in beiden Prompts 143 bis 145 Token und taucht an zwei Stellen auf. Im obersten Systemprompt ändert sich ein Satz von "You are an interactive agent that helps users with software engineering tasks." zu "You are an interactive agent that helps users according to your "Output Style", which describes how you should respond to user queries.". Dieser Austausch fand mit und ohne Schlüssel statt. Der Stilkörper erscheint unter der Überschrift # Output Style: Plain Writer in einer Nachricht mit Systemrolle, die auf die erste Nutzernachricht folgt, neben den Umgebungsdetails, und gegen Ende derselben Nachricht steht "Plain Writer output style is active. Remember to follow the specific guidelines for this style.".

Im kurzen Prompt ist der Schlüssel nichts wert. In keiner der drei Kurzprompt-Bedingungen gibt es einen Abschnitt # Doing tasks, auch nicht im Standard, also hat der Schlüssel nichts zu bewahren.

Da der Abschnitt das ist, was der Schlüssel steuert, hier sein Inhalt. Er beginnt damit, Claude mitzuteilen, dass der Nutzer ihn "will primarily request you to perform software engineering tasks" und unklare Anweisungen in diesem Licht zu lesen sei. Er bittet Claude, dem Nutzer darin zu folgen, ob eine Aufgabe zu groß ist, vorzugsweise bestehende Dateien zu bearbeiten statt neue zu erstellen, und Sicherheitslücken wie Command Injection, XSS und SQL Injection zu vermeiden.

Dem Umfang (Scope) gelten zwei Aufzählungspunkte, von denen der erste beginnt: "Don't add features, refactor, or introduce abstractions beyond what the task requires. A bug fix doesn't need surrounding cleanup; a one-shot operation doesn't need a helper." Der zweite schließt Fehlerbehandlung und Validierung "for scenarios that can't happen" aus. Für Kommentare gibt es ebenfalls zwei Punkte, beginnend mit "Default to writing no comments.

Only add one when the WHY is non-obvious". Er schließt Hacks für Rückwärtskompatibilität aus und nennt, wohin Nutzer verwiesen werden, die Hilfe wollen oder Feedback geben möchten. Außerdem enthält er eine Regel für Fragen statt Aufgaben: "For exploratory questions ("what could we do about X?", "how should we approach this?", "what do you think?"), respond in 2-3 sentences with a recommendation and the main tradeoff." Dieser Punkt endet mit "Don't implement until the user agrees.".

Zur Verifikation enthält der Abschnitt einen einzigen Aufzählungspunkt, und er betrifft Schnittstellen: "For UI or frontend changes, start the dev server and use the feature in a browser before reporting the task as complete." Nichts anderes darin sagt, Tests auszuführen.

Einige derselben Punkte werden an anderer Stelle behandelt, in Teilen des Prompts, die der Schlüssel nicht berührt. Der Textausgabe-Abschnitt des vollständigen Prompts, vorhanden in allen drei Vollprompt-Bedingungen, sagt weiterhin "In code: default to writing no comments." und "End-of-turn summary: one or two sentences." Im kurzen Prompt tragen alle drei Bedingungen "Write code that reads like the surrounding code: match its comment density, naming, and idiom." und "Report outcomes faithfully: if tests fail, say so with the output; if a step was skipped, say that; when something is done and verified, state it plainly without hedging."

Von den drei Beispielen in der Dokumentation ist der Umfang also das, was mit dem Abschnitt wirklich verschwindet. Die Kommentar-Leitlinie verschwindet einmal und bleibt einmal erhalten. Verifikation entfällt nur bei UI-Arbeit, denn das ist die einzige Verifikation, die der Abschnitt erwähnt.

Die Codierungsaufgabe war der Prompt, den Fehler in sum.js zu beheben, drei Läufe für jede der sechs Kombinationen.

Was die Tabelle nicht zeigen kann, ist, wie ähnlich sich die Läufe waren. Der Diff war in 18 von 18 Fällen byte-identisch: eine Zeile in sum.js, let i = 1 wurde zu let i = 0. Kein Lauf fügte einen Kommentar hinzu, kein Lauf berührte formatTotal, sein var oder seine fehlenden Semikolons, kein Lauf erstellte eine Datei, und die Testsuite lief danach in allen 18 Verzeichnissen durch (wir haben sie in jedem Verzeichnis einmal ausgeführt, nachdem die Sitzungen beendet waren). Jeder Lauf folgte denselben drei Schritten: sum.js ansehen (mit ls und cat oder dem Read-Tool), eine Bearbeitung vornehmen, dann prüfen. Die beiden Läufe mit vier Toolaufrufen teilten die Prüfung in zwei Bash-Aufrufe. Kein Lauf führte die Tests vor der Bearbeitung aus: 0 von 18.

Die Prüfung nach der Bearbeitung geschah in 18 von 18 Läufen. In 15 Fällen war es die Testsuite des Projekts. In den anderen 3 importierte Claude das Modul und gab einige Ergebnisse aus, etwa node -e 'const s=require("./sum.js");console.log(s.sum([1,2,3]),s.average([2,4]),s.formatTotal())', und die Abschlussnachricht sprach von "a quick check", statt zu behaupten, die Tests seien durchgelaufen. Alle drei dieser Läufe stammten aus Bedingungen mit dem Abschnitt # Doing tasks: zwei aus dem Vollprompt-Standard, einer aus dem vollständigen Prompt mit dem Schlüssel. Drei Läufe pro Zelle sind zu wenig, um daraus einen Trend abzuleiten, und das tun wir nicht. Es ist dennoch das Gegenteil von "lässt man die Coding-Anweisungen weg, verschwindet die Verifikation mit ihnen".

Die Fehlerbehebung forderte die Umfangs- und Kommentar-Punkte heraus und fand nichts, das einen Unterschied zeigte. Der entfernte Abschnitt hat eine Regel mit zählbarem Ziel, die für explorative Fragen: zwei oder drei Sätze, eine Empfehlung, den wichtigsten Tradeoff, keine Implementierung. Deshalb haben wir die letzten 4 Läufe unseres 40-Läufe-Budgets für die Frage verwendet, was man an der Funktion formatTotal in sum.js verbessern könnte, im vollständigen Prompt, Stil ohne den Schlüssel gegen Stil mit ihm, je zwei Läufe.

Die Wortzahlen umfassen die Zeile "In short:". Keine der beiden Bedingungen kam auch nur nahe an zwei oder drei Sätze heran, was nicht überrascht, wenn dieselbe Anfrage Claude zudem auffordert, freundliche Absätze zu schreiben und jeden Begriff zu definieren. Keine der vier Antworten änderte eine Datei, und alle vier fanden das eigentliche Problem (den Fehler in sum) und boten an, es zu beheben.

Mit dem Abschnitt waren die Antworten jedoch im Durchschnitt 37% kürzer (157 Wörter gegenüber 248,5), jede machte einen Toolaufruf statt zwei oder drei, und eine verwendete das eigene Wort der Anweisung: "The tradeoff is that fixing sum changes what average returns as well." Einer der Läufe ohne den Schlüssel ging so weit, die Testsuite auszuführen, um eine Frage zu beantworten, die nach einer Meinung fragte. Zwei Läufe pro Zelle machen daraus einen Hinweis, keine Messung, auf die man bauen sollte, aber es ist die einzige Stelle unter den 22 Verhaltensläufen, an der sich die Läufe mit und ohne Abschnitt überhaupt nicht überschnitten.

Füge keep-coding-instructions: true zu jedem Stil hinzu, den du in einem Repository verwendest, in dem Claude Code bearbeitet. In diesen Läufen kostete er 0 zusätzliche Token, wenn Claude Code den kurzen Prompt sendete, und 1.044 Token bei der ersten Anfrage, wenn es den vollständigen sendete, und nach der ersten Anfrage ist dieser Teil des Prompts wie der Rest ein Kandidat für den Cache. Was er im vollständigen Prompt zurückbringt, sind die Umfangsregel, die Kommentarregel, der Sicherheitspunkt und die Regel, explorative Fragen kurz zu beantworten.

Verlasse dich bei der Verifikation nicht auf den Schlüssel. In dieser Version erwähnt der Abschnitt, den er steuert, Verifikation nur für UI- und Frontend-Arbeit, und bei einer Nicht-UI-Korrektur prüften alle 18 Läufe ihre Arbeit nach der Bearbeitung, mit oder ohne ihn. Wenn eine Prüfung jedes Mal laufen muss, zeigt die eigene Vergleichstabelle der Output-Styles-Seite auf etwas anderes: Für "Something to happen every time without exception" empfiehlt sie einen Hook, weil "Claude Code runs a hook itself at a lifecycle event, so it doesn't depend on Claude following an instruction".

Lasse den Schlüssel aber auch nicht weg, um Token zu sparen. Ein reiner Schreibstil ohne ihn war im vollständigen Prompt 899 Token leichter als der Standard, 3,2% einer ersten Anfrage mit 28.139 Token, und im kurzen Prompt sparte er nichts.

Rechne damit, dass der eigene Text des Stils eine Coding-Sitzung mehr verändert als der Schlüssel. Hier verdoppelte er die Abschlussnachricht, und im vollständigen Prompt setzte er sich über eine Ein-bis-zwei-Sätze-Regel hinweg, die in derselben Anfrage stand. Wenn ein Stil für Dokumentationsarbeit gedacht ist und auch bei der Fehlerbehebung im Code zum Einsatz kommen soll, schreibe in den Stil, wie die Coding-Antworten aussehen sollen.

Und wirf einen Blick auf deine eigene Anfrage, bevor du einer der obigen Zahlen vertraust, auch unseren. Was der Schlüssel erhält, hängt davon ab, welchen Systemprompt Claude Code wählt, und die Dokumentation sagt, dass ein Experiment oder eine Serverkonfiguration diese Wahl treffen kann. OTEL_LOG_RAW_API_BODIES=file:<dir> und ein grep nach # Doing tasks beantworten die Frage für dein Konto in einem Lauf.

Jeder Lauf war headless, auf einem Modell, einer Claude-Code-Version und unter macOS. Andere Modelle erhalten den vollständigen Prompt möglicherweise standardmäßig; wir erreichten ihn nur über die Umgebungsvariable. Wir haben keine interaktiven Sitzungen getestet, keinen Stilwechsel mitten in der Sitzung mit /output-style, keine Stile auf Benutzer- oder Plugin-Ebene, kein force-for-plugin und nicht die eingebauten Stile, von denen die Dokumentation sagt, dass sie die Coding-Anweisungen behalten.

Die Aufgabe war klein: ein offensichtlicher Bug, eine leicht zu findende Testsuite, kein echter Druck, die Änderung auszuweiten. Ein größeres Repository mit unklarem Umfang könnte die Bedingungen trennen, die hier nicht getrennt wurden, und der Punkt zur UI-Verifikation blieb ungetestet, weil hier keine UI existierte. Drei Läufe pro Zelle für die Bugfixes und zwei für die Frage sind absolute Zahlen, keine Quoten.

Wir haben nur die erste Anfrage jeder Session gemessen, nicht das, was Caching bei späteren bewirkt. Wir haben das Modell nicht gebeten, seine eigenen Anweisungen zu berichten, da die Request-Bodies das unnötig machten.

Die Style-Datei und das Template-Projekt sind wie oben beschrieben. Ein Lauf der Token-Messung, von innerhalb eines Run-Verzeichnisses:

printf '{\n "outputStyle": "Plain Writer"\n}\n' >.claude/settings.json CLAUDE_CODE_ENABLE_TELEMETRY = 1 OTEL_LOGS_EXPORTER = console OTEL_METRICS_EXPORTER = none \ OTEL_LOG_RAW_API_BODIES = "file: $PWD /../bodies/run1" CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT = 0 \ claude -p "Reply with the single word OK." --setting-sources project,local --strict-mcp-config \ --model opus --permission-mode acceptEdits --output-format stream-json --verbose \ --max-turns 1 --session-id " $( uuidgen | tr A-Z a-z ) " < /dev/null > out.jsonl grep -c '# Doing tasks'../bodies/run1/ *.request.json Enter fullscreen mode Exit fullscreen mode Lässt man CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT=0 weg, sieht man den Prompt, den das eigene Konto standardmäßig erhält, und lässt man die printf-Zeile weg, erhält man den Standard-Style. Für die Token-Zählung öffnet man ~/.claude/projects/<project>/<session-id>.jsonl, nimmt message.usage des ersten Assistant-Eintrags und addiert input_tokens, cache_creation_input_tokens und cache_read_input_tokens. Für die Verhaltensläufe ersetzt man den Prompt durch fix the bug in sum.js, erhöht --max-turns, legt die Bash-Allow-Regeln in.claude/settings.local.json ab und liest die Tool-Aufrufe aus demselben Transkript sowie die Änderung aus git diff.

Vierzig claude -p Läufe am 2026-10-05 zwischen 16:23 und 16:33 UTC, Claude Code 2.1.289 auf macOS, claude-opus-5-5, Effort medium laut den Request-Bodies: 18 Token-Läufe (3 für jede von 6 Kombinationen), 18 Bugfix-Läufe (3 für jede von 6 Kombinationen) und 4 Fragenläufe (2 für jede von 2 Kombinationen). Alle 40 endeten mit Exit-Code 0 und "subtype": "success". Die Token-Läufe dauerten jeweils 1,2 bis 3,5 Sekunden, die Bugfixes 11,2 bis 22,5 Sekunden und die Fragen 15,0 bis 22,7 Sekunden. Die gemeldeten Kosten für alle vierzig Läufe betrugen 3,62 $.

Ob ein Style die Coding-Anweisungen von Claude Code behält, steht in einer Zeile Frontmatter, und diese Läufe legen nahe, dass man prüfen sollte, auf welchen System-Prompt diese Zeile sich bezieht, bevor man bewertet, was sie kostet.

Wenn dein Konto standardmäßig den vollen Prompt erhält oder dein eigener Style mehr als 1.044 Token weglässt, teile deine Claude-Code-Version und die Zahl in den Kommentaren unten mit.

Templates ermöglichen es, FAQs schnell zu beantworten oder Snippets zur Wiederverwendung zu speichern.

DEV SUPPORTS DEV SUPPORTS DEV SUPPORTS Follow Joined Oct 9, 2026 • Oct 10 Dropdown-Menü Link kopieren Ausblenden Du musst dein Konto verifizieren. Enter fullscreen mode Exit fullscreen mode tr.ee/dev-to

Like-Kommentar: 1 Like, Like-Kommentar-Button, Antworten Code of Conduct • Missbrauch melden Möchtest du diesen Kommentar wirklich ausblenden? Er wird in deinem Beitrag verborgen, bleibt aber über den Permalink des Kommentars sichtbar.

Für weitere Maßnahmen kannst du diese Person blockieren und/oder Missbrauch melden.

Automatisch übersetzt. Das Original auf Englisch ist unten aufklappbar.

Original (Englisch) anzeigen

On Claude Code 2.1.289 with Opus 5.5, keep-coding-instructions: true decided whether a 1,044-token # Doing tasks section stayed in the system prompt, but only when Claude Code sent its full prompt; in the shorter prompt this account got by default, a custom style with the key and the same style without it produced identical requests. On a one-line bug fix, 18 of 18 runs across three styles made the same edit, added no comment and checked the result after editing, and the custom style's main effect was to double the length of the closing message.

Output styles are how you change the way Claude talks for a whole Claude Code session: shorter answers, explanations next to each change, or a different role altogether. The output-styles page attaches one warning to the custom ones you write yourself. Unless the style file sets keep-coding-instructions: true in its frontmatter, Claude Code leaves out its built-in software engineering instructions, "such as how to scope changes, write comments, and verify work."

That sentence raises two questions for anyone who writes a style and then uses it in a repository. How much text actually disappears, measured in tokens? And does a session without it code differently: skip the tests, clean up code nobody asked about, leave comments everywhere? We wanted both answers from the requests Claude Code sends to the API rather than from what the model says about its own instructions, so we built a small lab and ran it 40 times under claude -p.

Everything below ran on 2026-10-05 between 16:23 and 16:33 UTC with Claude Code 2.1.289 ( claude --version ) and claude-opus-5-5 (selected with --model opus ) on macOS. The output-styles page was fetched with trafilatura at 16:20 UTC the same day and fetched again at 16:34 UTC with no change; the other documentation quotes come from fetches between 16:20 and 16:35 UTC.

These are the sentences the lab tests, quoted as fetched from https://code.claude.com/docs/en/output-styles:

The key is not new. The changelog entry for 2.0.37 reads "Output Styles: Added keep-coding-instructions option to frontmatter". What the page does not give is a size for "the built-in software engineering instructions" or a list of them beyond those three examples, and the default is false, so every custom style that omits the line is in the dropped group.

There were three conditions, and every run got a fresh directory copied from the same template:

The style is deliberately about writing, the case the docs describe as "Claude won't be doing software engineering":

--- name: Plain Writer description: Plain, friendly prose for documentation and explanations --- You are a writing assistant. Answer in plain, friendly prose paragraphs. Avoid bullet lists and headings unless the user asks for them.

Keep sentences short, and define any technical term the first time you use it. End every response with a one-sentence summary that starts with "In short:". Enter fullscreen mode Exit fullscreen mode Condition (b) inserts keep-coding-instructions: true after the description line, and nothing else changes.

Both versions live at.claude/output-styles/plain-writer.md in their own run directory, so the style name and body are byte-identical and only the frontmatter differs. Each run selects it with a one-line.claude/settings.json, {"outputStyle": "Plain Writer"}. The "In short:" sentence is a marker: if a reply ends with it, the style was in force.

The template is a tiny Node project. sum.js holds three functions. sum has an off-by-one bug (its loop starts at index 1, so it skips the first number), average and formatTotal both call sum, and formatTotal is written in a different style from the rest of the file ( var, no semicolons) as bait for cleanup nobody asked for. test/sum.test.js has four node:test tests, three of which fail because of the bug, and package.json maps npm test to node --test. Each run directory got git init and one commit, so git status started clean and git diff afterwards shows exactly what the session changed.

claude -p " $PROMPT " --setting-sources project,local --strict-mcp-config --model opus \ --permission-mode acceptEdits --output-format stream-json --verbose \ --session-id " $SID " --max-turns 40 < /dev/null Enter fullscreen mode Exit fullscreen mode --setting-sources project,local keeps our user settings, and the hooks and plugins they enable, out of the runs. --strict-mcp-config with no config file means no MCP servers. acceptEdits lets the session edit files without a prompt. We also unset the CLAUDE_* environment variables that the Claude Code session we were working from exports, CLAUDE_EFFORT among them, so the children ran at their own default effort, which every request body recorded as medium.

One setup detail is worth passing on. Our first pilot also put Bash allow rules in.claude/settings.json, and Claude Code printed Ignoring 7 permissions.allow entries from.claude/settings.json: this workspace has not been trusted. The run directories are new and were never opened interactively, so they were never trusted. We moved the allow rules ( npm test, node, git diff and a few more) to.claude/settings.local.json, which the settings page says works differently while the file is untracked: "Claude Code applies its allow rules without the workspace trust step it requires for the committed file." The outputStyle key in the same untrusted.claude/settings.json was applied regardless: the init event reported "output_style": "Plain Writer" in 28 of 28 runs that had the style.

The session transcript records token usage but not the system prompt, and we did not want to rely on asking the model which instructions it can see. The monitoring page documents a way to get the request itself: OTEL_LOG_RAW_API_BODIES, which will "Emit the full Anthropic Messages API request and response JSON as api_request_body / api_response_body log events", with " file:<dir> for untruncated bodies on disk with a body_ref pointer in the event". With CLAUDE_CODE_ENABLE_TELEMETRY=1, OTEL_LOGS_EXPORTER=console, OTEL_METRICS_EXPORTER=none and OTEL_LOG_RAW_API_BODIES=file:<dir>, every run left the exact JSON of every request it sent in its own folder, and nothing extra appeared in the stream-json output.

Everything below about what a prompt contains comes from those files. Token counts come from the transcript under ~/.claude/projects/: input_tokens + cache_creation_input_tokens + cache_read_input_tokens of the first assistant message, which counts the whole first request whether or not part of it was served from cache.

The pilots already contradicted what we expected. With the trivial prompt, the request from style + key was the same text as the request from style, no key, except for the run's directory name, its commit hash and a per-request ID. Neither had a section about doing software engineering tasks, and neither did the default.

The explanation is on the environment variables page. CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT is described as: "Set to 1 to use a shorter system prompt and abbreviated tool descriptions on any model. Set to 0, false, no, or off to opt out even on models where the experiment or server configuration would otherwise enable it." With the variable unset, the requests from this account were the shorter kind: the tool definitions came to 27,700 characters of JSON, and the default style's system prompt was about 6,900 characters with five headings ( # Harness, # Session-specific guidance, # Memory, # Environment, # Context management ) and a few unheaded paragraphs.

With CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT=0, the tool definitions grew to 44,195 characters and the system prompt to about 28,300, gaining # System, # Doing tasks, # Executing actions with care, # Using your tools, # Tone and style and # Text output (does not apply to tool calls).

Since the docs say an experiment or server configuration can switch the short prompt on, which one you get may depend on your account, your model or the week. So we ran every measurement under both. From here on, the short prompt means what this account got with the variable unset, and the full prompt means CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT=0.

The trivial prompt was Reply with the single word OK. with --max-turns 1, three runs for each of the six combinations, 18 runs in all. All 18 replied OK; the one-word answer won over the style's "In short:" sentence.

Repeats of one condition differed by up to 7 tokens, because the directory name, the commit hash and a request ID all appear in the request. After we replaced those three values with placeholders, the three runs of each combination were byte-identical, which leaves five distinct prompts for six combinations: in the short prompt, style, no key and style + key came out as the same text in 6 of 6 runs.

In the full prompt, the key is worth 1,044 tokens (28,284 against 27,240 at the median; 1,043 to 1,047 when we pair the runs by round). The difference between those two requests is exactly one block, the # Doing tasks section: 3,321 characters, 530 words, 12 bullets. Without the key, a custom style's first request was 899 tokens lighter than no style at all, because the section went out and about 145 tokens of style came in.

The style itself cost 143 to 145 tokens in both prompts, and it arrives in two places. In the top-level system prompt, one sentence changes from "You are an interactive agent that helps users with software engineering tasks." to "You are an interactive agent that helps users according to your "Output Style", which describes how you should respond to user queries." That swap happened with and without the key. The style body arrives under the heading # Output Style: Plain Writer in a system-role message that follows the first user message, next to the environment details, and near the end of the same message comes "Plain Writer output style is active. Remember to follow the specific guidelines for this style."

In the short prompt, the key is worth nothing. There is no # Doing tasks section in any of the three short-prompt conditions, the default included, so the key has nothing to keep.

Since the section is what the key controls, here is what it says. It opens by telling Claude that the user "will primarily request you to perform software engineering tasks" and to read unclear instructions in that light. It asks Claude to defer to the user on whether a task is too large, to prefer editing existing files over creating new ones, and to avoid security holes such as command injection, XSS and SQL injection.

Scope gets two bullets, the first of which begins: "Don't add features, refactor, or introduce abstractions beyond what the task requires. A bug fix doesn't need surrounding cleanup; a one-shot operation doesn't need a helper." The second rules out error handling and validation "for scenarios that can't happen". Comments get two bullets as well, starting with "Default to writing no comments.

Only add one when the WHY is non-obvious". It rules out backwards-compatibility hacks and says where to send users who want help or to give feedback. And it has one rule about questions rather than tasks: "For exploratory questions ("what could we do about X?", "how should we approach this?", "what do you think?"), respond in 2-3 sentences with a recommendation and the main tradeoff." That bullet ends "Don't implement until the user agrees."

On verification, the section has a single bullet, and it is about interfaces: "For UI or frontend changes, start the dev server and use the feature in a browser before reporting the task as complete." Nothing else in it says to run tests.

Some of the same ground is covered elsewhere, in parts of the prompt the key does not touch. The full prompt's text-output section, present in all three full-prompt conditions, still says "In code: default to writing no comments." and "End-of-turn summary: one or two sentences." In the short prompt, all three conditions carry "Write code that reads like the surrounding code: match its comment density, naming, and idiom." and "Report outcomes faithfully: if tests fail, say so with the output; if a step was skipped, say that; when something is done and verified, state it plainly without hedging."

So of the docs' three examples, scope is the one that really leaves with the section. Comment guidance leaves once and stays once. Verification leaves only for UI work, because that is the only verification the section mentions.

The coding task was the prompt fix the bug in sum.js, three runs for each of the six combinations.

What the table cannot show is how alike the runs were. The diff was byte-identical in 18 of 18: one line in sum.js, let i = 1 became let i = 0. No run added a comment, no run touched formatTotal, its var or its missing semicolons, no run created a file, and the test suite passed afterwards in all 18 directories (we ran it in each one once the sessions were done). Every run followed the same three steps: look at sum.js (with ls and cat, or the Read tool), make one edit, then check. The two runs with four tool calls split the check into two Bash calls. No run ran the tests before editing: 0 of 18.

Checking after the edit happened in 18 of 18 runs. In 15 it was the project's test suite. In the other 3, Claude imported the module and printed a few results, for instance node -e 'const s=require("./sum.js");console.log(s.sum([1,2,3]),s.average([2,4]),s.formatTotal())', and the closing message said "a quick check" rather than claiming the tests passed. All three of those runs came from conditions that had the # Doing tasks section: two from the full-prompt default, one from full prompt with the key. Three runs per cell is too few to call that a trend, and we don't. It is still the opposite of "drop the coding instructions and the verification goes with them".

The bug fix exercised the scope and comment bullets and found nothing to separate. The dropped section has one rule with a target that can be counted, the one for exploratory questions: two or three sentences, a recommendation, the main tradeoff, no implementation. So we spent the last 4 runs of our 40-run budget on the question what could we do about the formatTotal function in sum.js?, in the full prompt, style without the key against style with it, two runs each.

Word counts include the "In short:" line. Neither condition came near two or three sentences, which is not surprising when the same request also tells Claude to write friendly paragraphs and define every term. None of the four replies changed a file, and all four found the real problem (the bug in sum ) and offered to fix it.

With the section present, though, the replies were 37% shorter on average (157 words against 248.5), each made one tool call instead of two or three, and one of them used the instruction's own word: "The tradeoff is that fixing sum changes what average returns as well." One of the runs without the key went as far as running the test suite to answer a question that asked for an opinion. Two runs per cell make this a hint, not a measurement we would build on, but it is the one place in the 22 behavior runs where the runs with and without the section did not overlap at all.

Add keep-coding-instructions: true to any style you use in a repository where Claude edits code. In these runs it cost 0 extra tokens when Claude Code sent the short prompt and 1,044 on the first request when it sent the full one, and after the first request that part of the prompt is a candidate for the cache like the rest. What it brings back in the full prompt is the scope rule, the comment rule, the security bullet and the rule for answering exploratory questions briefly.

Don't count on the key for verification. In this version, the section it controls mentions verification only for UI and frontend work, and on a non-UI fix all 18 runs checked their work after the edit, with or without it. If a check has to run every time, the output-styles page's own comparison table points elsewhere: for "Something to happen every time without exception" it recommends a hook, because "Claude Code runs a hook itself at a lifecycle event, so it doesn't depend on Claude following an instruction".

Don't leave the key out to save tokens, either. A writing-only style without it was 899 tokens lighter than the default in the full prompt, 3.2% of a 28,139-token first request, and it saved nothing in the short prompt.

Expect the style's own text to change a coding session more than the key does. Here it doubled the closing message, and in the full prompt it overrode a one-or-two-sentence rule that sat in the same request. If a style is meant for documentation work and will also be used while fixing code, say in the style what you want the coding replies to look like.

And look at your own request before trusting any of the numbers above, including ours. What the key keeps depends on which system prompt Claude Code chooses, and the docs say an experiment or server configuration can make that choice. OTEL_LOG_RAW_API_BODIES=file:<dir> and a grep for # Doing tasks answer the question for your account in one run.

Every run was headless, on one model, one Claude Code version and macOS. Other models may get the full prompt by default; we only reached it through the environment variable. We did not test interactive sessions, switching styles mid-session with /output-style, user-level or plugin styles, force-for-plugin, or the built-in styles, which the docs say keep the coding instructions.

The task was small: one obvious bug, a test suite that was easy to find, no real pressure to widen the change. A larger repository with unclear scope might separate the conditions where this one did not, and the UI verification bullet went untested because nothing here had a UI. Three runs per cell for the bug fix and two for the question are counts, not rates.

We measured only the first request of each session, not what caching does to later ones. We did not ask the model to report its own instructions, since the request bodies made that unnecessary.

The style file and the template project are as described above. One run of the token measurement, from inside a run directory:

printf '{\n "outputStyle": "Plain Writer"\n}\n' >.claude/settings.json CLAUDE_CODE_ENABLE_TELEMETRY = 1 OTEL_LOGS_EXPORTER = console OTEL_METRICS_EXPORTER = none \ OTEL_LOG_RAW_API_BODIES = "file: $PWD /../bodies/run1" CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT = 0 \ claude -p "Reply with the single word OK." --setting-sources project,local --strict-mcp-config \ --model opus --permission-mode acceptEdits --output-format stream-json --verbose \ --max-turns 1 --session-id " $( uuidgen | tr A-Z a-z ) " < /dev/null > out.jsonl grep -c '# Doing tasks'../bodies/run1/ *.request.json Enter fullscreen mode Exit fullscreen mode Leave out CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT=0 to see the prompt your account gets by default, and leave out the printf line for the default style. For the token count, open ~/.claude/projects/<project>/<session-id>.jsonl, take the first assistant record's message.usage, and add input_tokens, cache_creation_input_tokens and cache_read_input_tokens. For the behavior runs, swap the prompt for fix the bug in sum.js, raise --max-turns, put the Bash allow rules in.claude/settings.local.json, and read the tool calls from the same transcript and the change from git diff.

Forty claude -p runs on 2026-10-05 between 16:23 and 16:33 UTC, Claude Code 2.1.289 on macOS, claude-opus-5-5, effort medium as recorded in the request bodies: 18 token runs (3 for each of 6 combinations), 18 bug-fix runs (3 for each of 6 combinations) and 4 question runs (2 for each of 2 combinations). All 40 exited 0 with "subtype": "success". The token runs took 1.2 to 3.5 seconds each, the bug fixes 11.2 to 22.5 seconds and the questions 15.0 to 22.7 seconds. The reported cost for all forty was $3.62.

Whether a style keeps Claude Code's coding instructions is one line of frontmatter, and these runs say it is worth checking which system prompt that line is acting on before deciding what it costs.

If your account gets the full prompt by default, or your custom style drops more than 1,044 tokens, post your Claude Code version and the number in the comments below.

Expand DEV SUPPORTS DEV SUPPORTS DEV SUPPORTS Follow Joined Oct 9, 2026 • Oct 10 Dropdown menu Copy link Hide You need to verify your account. Enter fullscreen mode Exit fullscreen mode tr.ee/dev-to

Originaltitel: Claude Code's keep-coding-instructions kept 1,044 tokens in the full prompt, 0 in the short one, and 18 of 18 fixes matchedQuelle: dev.to (dev.to). Original öffnen