Ich habe Vibe Coding gestoppt und mit 'Prompt Contracts' begonnen — Claude Code wurde vom Glücksspiel zum erfolgreichen Deployment
Nicht weil es schlechter Code war. Er kompilierte. Er lief. Er sah sogar sauber aus.
Aber er löste das falsche Problem. Ich hatte nach einem Supabase Auth-Flow mit Row-Level Security gefragt. Was ich bekam, war ein wunderschönes, produktionsreifes Auth-System — mit Firebase.
Claude Code zog eine klassische Uno-Wendekarte auf meinen gesamten Stack. Wie eine Pizza bestellen und ein perfekt gekochtes Risotto bekommen. Technisch beeindruckend. Grundlegend falsch.
Das war der Moment, in dem mir etwas Unbequemes klar wurde: Ich codete nicht mit Claude Code. Ich zockte damit.
Und falls du natürlichsprachige Prompts in Claude Code 🧑💻 tippst und auf das Beste hoffst, würfelst du auch. Nur dass der Dungeon Master eine KI mit null Kontext und unendlichem Selbstvertrauen ist.

Die Vibe-Coding-Falle
So sieht Vibe-Coding in freier Wildbahn aus:
> Bau mir ein Dashboard für meine SaaS
Claude Code schreibt 3.000 Zeilen über 14 Dateien. Du starrst auf die Ausgabe, als würdest du versuchen, ein Magic-Eye-Poster zu erkennen. Manches sieht richtig aus.
Du startest es.
Etwas bricht.
Du sagst "reparier es."
Es repariert eine Sache, bricht drei andere. Das ist kein Debugging. Das ist Whack-a-Mole mit einem 100€/Monat-Abo.
Vor ein paar Wochen bin ich über ein Konzept eines Ex-OpenAI-Ingenieurs gestolpert: Prompt Contracts
Fünfundvierzig Minuten später hast du etwas ausgeliefert, das funktioniert, aber das du nicht vollständig verstehst. Glückwunsch, du wartest jetzt eine Codebase, die von einer außerirdischen Intelligenz geschrieben wurde, die sich nicht daran erinnert, sie geschrieben zu haben. Was könnte schon schiefgehen.
Ich lebte monatelang in dieser Schleife. Ich lieferte zwei SaaS-Produkte fast vollständig mit Claude Code aus, und ich übertreibe nicht, wenn ich sage, dass 30% meiner Zeit damit verbracht wurde, Dinge rückgängig zu machen, die Claude Code selbstbewusst in die falsche Richtung gebaut hatte. Es ist wie Pair Programming mit einem Genie, das Amnesie hat und null Ahnung von deinem Repo.
Das Problem war nie Claude Codes Intelligenz. Opus 4.6 ist absurd fähig — es ist im Grunde ein Senior Engineer, der jede Stack Overflow-Antwort gelesen hat, die jemals gepostet wurde, und alle behalten hat, einschließlich der falschen.
Das Problem war, dass meine Prompts Vibes waren, keine Spezifikationen.
"Mach es responsive." "Füg Error Handling hinzu." "Verwende Best Practices."
Das sind keine Anweisungen. Das sind Horoskope. Und Claude Code ist kein Wahrsager — es ist ein Auftragnehmer. Du würdest einem Auftragnehmer keine Serviette geben, auf der steht "bau Haus, mach schön" und dein Traumhaus erwarten. Du würdest ein Haus bekommen. Es hätte vielleicht sogar Wände. Aber die Toilette wäre in der Küche, weil du nie gesagt hast, dass sie nicht da sein sollte.
Prompt Contracts: Die Lösung
Vor ein paar Wochen bin ich über ein Konzept eines Ex-OpenAI-Ingenieurs gestolpert: Prompt Contracts. Die Idee ist simpel — anstatt Prompts wie kreative Briefings zu schreiben, schreibst du sie wie Rechtsverträge mit vier durchsetzbaren Klauseln:
Goal — die exakte Erfolgsmetrik. Constraints — harte Grenzen, die nicht überschritten werden dürfen. Output Format — die spezifische Struktur, die du erwartest. Failure Conditions — was die Ausgabe inakzeptabel macht.
Ich dachte: "Das ist niedlich für ChatGPT-Blogposts. Aber kann es überleben, wenn Claude Code um 3 Uhr morgens ein echtes Backend baut, während du auf Koffein und schlechten Lebensentscheidungen läufst?"
Also testete ich es. Drei Wochen lang, über zwei SaaS-Projekte hinweg, ersetzte ich jeden Vibe-Prompt durch einen Prompt Contract.
Spoiler: Ich schlafe jetzt.
Komponente 1: GOAL — Hör auf zu sagen "Bau mir X"
Das größte Upgrade war, mich zu zwingen zu definieren, wie fertig aussieht, bevor Claude Code eine einzige Zeile schreibt.
Vorher (vibe):
> Füg ein Abo-System zur App hinzu
Das ist das Prompt-Äquivalent dazu, deinem GPS zu sagen "bring mich irgendwo hin, wo es schön ist." Du landest irgendwo. Es könnte ein Michelin-Stern-Restaurant sein. Es könnte eine Tankstelle in der Pampa sein.
Nachher (contract):
> GOAL: Implementiere Stripe-Abo-Management, wo Nutzer sich für 3 Stufen
> (free/pro/team) anmelden, sofort up-/downgraden können und den
> Billing-Status auf /settings/billing sehen.
> Erfolg = ein Free-User kann Pro abonnieren,
> die Abbuchung im Stripe-Dashboard sehen und innerhalb von 5 Sekunden
> auf gesperrte Features zugreifen.
Der Unterschied ist nicht nur Detail — es ist Testbarkeit. Wenn Claude Code fertig ist, kann ich das Ziel in unter einer Minute verifizieren. Keine Mehrdeutigkeit. Kein "naja, es funktioniert irgendwie" — die Schrödingers Katze der Software-Demos.
Das allein reduzierte mein Hin und Her mit Claude Code um etwa die Hälfte. Wenn die KI weiß, wie die Ziellinie aussieht, hört sie auf, auf der Strecke herumzuwandern und Selfies zu machen.
Komponente 2: CONSTRAINTS — Die Mauern, die dich retten
Hier wird es Claude Code-spezifisch, denn ohne Constraints wird Claude Code absolut deinen Stack für dich neu erfinden. Es ist, als würdest du einen Küchenrenovierer anheuern, der auftaucht und sagt "Ich hab auch deine Wohnzimmerwand eingerissen, weil das Feng Shui daneben war."
Ich halte jetzt eine CLAUDE.md im Root jedes Projekts, die als permanente Constraint-Schicht fungiert:
# CLAUDE.md — Projekt-Constraints (immer aktiv)
## Stack (nicht verhandelbar, ich werde dich mass git reverten)
- Frontend: Next.js 14+ App Router, TypeScript strict
- Backend: Convex für Real-time Data, Supabase für Auth + Storage
- Auth: Clerk (nie custom Auth rollen, wir sind keine Tiere)
- Styling: Nur Tailwind — keine CSS Modules, keine styled-components
## Harte Regeln
- Nie eine neue Dependency installieren ohne vorher zu fragen
- Nie das Database Schema modifizieren ohne Migration Plan zu zeigen
- Alle API Calls über Convex Functions, nie direkte Supabase
Client Calls aus Components
- Environment Variables in .env.local, nie hardcoded
(Ich werde dich finden und ich werde dich reverten)
## Patterns
- Server Components by default, Client Components nur wenn
Interaktivität erforderlich ist
- Error Boundaries auf jedem Route Segment
- Zod Validation bei jedem User Input
Vor CLAUDE.md entschied Claude Code zufällig, Prisma statt Convex zu verwenden, oder Clerk gegen NextAuth zu tauschen, weil "es häufiger verwendet wird." Das ist, als würde dein Barista entscheiden, dass du eigentlich Tee wolltest, weil global mehr Menschen Tee trinken. Ich habe keine Demokratie verlangt. Ich habe Clerk verlangt.
Jetzt? Es bleibt in seiner Spur. Jedes einzelne Mal.
Pro-Tipp: Wenn du eine neue Claude Code-Session startest, sollte deine erste Nachricht sein:
> Lies CLAUDE.md und bestätige, dass du die Projekt-Constraints verstehst,
> bevor du irgendetwas machst.
Das erzwingt einen Handshake. Denk daran wie an die Miranda-Rechte deiner Codebase. Claude Code echot die Constraints zurück, ihr einigt euch beide auf die Realität, und dann beginnt die Arbeit. Ohne das startest du im Grunde jede Session, indem du jemandem die Schlüssel gibst, der nicht weiß, welches Auto er fährt.
Komponente 3: FORMAT — Sag ihm genau, was es dir geben soll
Vibe-Coding lässt Claude Code die Struktur entscheiden. Das ist, als würdest du einem Koch sagen "überrasch mich" und dann schockiert sein, wenn du einen dekonstruierten Caesar Salad in einem Schuh serviert bekommst.
Vorher:
> Erstelle einen API-Endpoint für User Onboarding
Claude Code entscheidet: eine massive Datei, Inline-Validation, keine Types, alles in einer einzigen 800-Zeilen-Funktion, die Auth, Database Calls und E-Mail-Versand in einem Atemzug macht. Es funktioniert. Es ist auch ein Kriegsverbrechen gegen das zukünftige Du, das es warten muss.
Nachher:
> FORMAT:
> 1. Convex Function in convex/users.ts (mutation, nicht action)
> 2. Zod Schema für Input Validation in convex/schemas/onboarding.ts
> 3. TypeScript Types exportiert aus convex/types/user.ts
> 4. JSDoc auf der public Function einschließen
> 5. Return { success: boolean, userId: string, error?: string }
Jetzt bekomme ich modularen, getypten, dokumentierten Code — jedes Mal. Nicht weil Claude Code das nicht von allein produzieren kann, sondern weil es ohne explizite Format-Anweisungen für Geschwindigkeit optimiert, nicht für Wartbarkeit. Es speedrunt deine Codebase. Du brauchst es, um das lange Spiel zu spielen.
Das ist noch wichtiger, wenn du Claude Codes Agent Teams Feature verwendest, um Arbeit zu parallelisieren. Wenn deine Sub-Agents nicht dem gleichen Format-Contract folgen, endest du damit, Code zu mergen, der aussieht, als wäre er von fünf Entwicklern geschrieben worden, die ausschließlich über passiv-aggressive Commit-Messages kommunizieren.
Komponente 4: FAILURE CONDITIONS — Die Geheimwaffe
Das ist die Komponente, die alles verändert hat. Wenn das Goal die Karotte ist, sind Failure Conditions der Stock. Und Claude Code reagiert auf Stöcke wie ein Entwickler auf eine Production ist down Slack-Nachricht — sofort und mit voller Aufmerksamkeit.
Zu definieren, was den Contract bricht, gibt Claude Code ein negatives Ziel. Es ist wie einen Hund zu trainieren: "Sitz" ist gut, aber "NICHT auf dem Sofa, NICHT auf dem Tisch, NICHT auf den besuchenden Schwiegereltern" ist das, was tatsächlich deine Möbel rettet.
Hier ist ein echter Prompt Contract, den ich letzte Woche verwendet habe:
> Bau die /dashboard Seite.
>
> GOAL: Zeige aktive Projekte des Users mit Real-time Updates an.
> First Meaningful Paint unter 1 Sekunde. User kann Projekte inline
> erstellen, archivieren und umbenennen.
>
> CONSTRAINTS: Convex useQuery für Daten, kein Polling, kein SWR.
> Clerk useUser() für Auth Check. Redirect zu /sign-in wenn
> unauthenticated. Max 150 Zeilen pro Component-Datei.
>
> FORMAT: Page Component in app/dashboard/page.tsx (Server Component
> Wrapper), Client Component in components/dashboard/ProjectList.tsx,
> Convex Query in convex/projects.ts. Nur Tailwind.
>
> FAILURE CONDITIONS:
> - Verwendet useState für Daten, die in Convex gehören
> - Jede Component überschreitet 150 Zeilen
> - Fetcht Daten client-side, wenn es server-side könnte
> - Verwendet jede UI Library außer Tailwind Utility Classes
> - Fehlende Loading und Error States
> - Fehlende TypeScript Types bei Function Parametern
Als ich das laufen ließ, produzierte Claude Code ein sauberes, Real-time Dashboard beim ersten Versuch. Kein Firebase. Kein Prisma. Keine mysteriösen npm-Packages von 2019 mit 12 GitHub-Sternen und einer README, die "TODO" sagt. Keine 1.200-Zeilen-Gott-Component, für deren Refactoring das zukünftige Ich eine Therapie bräuchte.
Vergleich das mit dem, was im Monat davor passierte, als "bau mir ein Dashboard" eine Component produzierte, die Material UI importierte (ich verwende kein Material UI), useEffect für Data Fetching verwendete (wir haben Convex aus einem Grund) und null Loading States hatte. Nur roher, ungeschützter Optimismus, dass die Daten immer sofort da wären. Das Software-Äquivalent dazu, dein Haus unverschlossen zu lassen, weil "das ist eine nette Nachbarschaft."
Die Failure Conditions fungieren als Leitplanken. Claude Code muss nicht raten, was "gut" bedeutet, wenn du ihm bereits gesagt hast, wie "schlecht" aussieht. Es ist der Unterschied zwischen "fahr vorsichtig" und "nicht über 130, keine roten Ampeln überfahren, nicht die Autobahn während der Rushhour nehmen." Das eine ist ein Gebet. Das andere ist ein Navigationssystem.
🔄 Update: Ein Contract, den ich in der ursprünglichen Version dieses Artikels nicht erwähnt habe, weil er noch nicht existierte: `/security-review`. Tipp es ein, bevor du pushst. Claude scannt deine anstehenden Änderungen nach SQL Injection, Auth Bypasses, hardcoded Secrets — das Zeug, das du übersiehst, wenn du tief im Feature-Modus bist. Ich habe eine vollständige Aufschlüsselung geschrieben, wie es funktioniert und wie du es für deinen Stack anpasst. Kürzeste Version: Es ist das Post-Contract-Sicherheitsnetz. Deine Prompt Contracts lassen Claude das Richtige bauen. `/security-review` stellt sicher, dass das Richtige kein Loch hat.
Die Ergebnisse (3 Wochen Prompt Contracts)
Ich verfolgte meinen Workflow über zwei aktive Projekte. Die Zahlen sind nicht peer-reviewed — ich bin ein Entwickler in einem dunklen Raum, kein Forschungslabor — aber das Muster war unverkennbar.
Undo/Revert-Rate fiel von etwa 1 von 3 Generationen auf etwa 1 von 10. Claude Code hörte auf, Dinge zu bauen, nach denen ich nicht gefragt hatte. Mein git revert Muskelgedächtnis verblasst bereits. Ich muss den Befehl vielleicht irgendwann neu lernen. Oder auch nicht. Ich bin im Frieden damit.
Zeit von Prompt zu verwendbarem Code ging von durchschnittlich 3 Runden Hin und Her auf 1,2 Runden runter. Die meisten Prompt Contract Outputs waren beim ersten oder zweiten Versuch verwendbar. Das befreite Zeit, die ich jetzt für wichtige Dinge verbringe, wie meine CLAUDE.md zu over-engineeren und Failure Conditions für Failure Conditions hinzuzufügen.
CLAUDE.md-Verletzungen (falsche Library, falsches Pattern, hardcoded Values) gingen von ein paar pro Tag auf im Wesentlichen null, sobald ich den Constraint-Handshake beim Session-Start hinzufügte. Die CLAUDE.md + Handshake-Combo ist im Grunde eine Pre-Flight-Checkliste. Piloten überspringen sie nicht. Du solltest es auch nicht. Es sei denn, du genießt es, wenn dein Code in einen metaphorischen Berg kracht.
Die größte Überraschung? Meine Prompts wurden über die Zeit kürzer, nicht länger. Sobald CLAUDE.md die permanenten Constraints hält und du die 4-Komponenten-Struktur verinnerlicht hast, dauert ein Prompt Contract für ein komplexes Feature vielleicht 60 Sekunden zu schreiben. Das sind 60 Sekunden, die dir 45 Minuten Debugging und Infragestellung deiner Karriereentscheidungen sparen.
Wie du heute anfängst
Du musst deinen Workflow nicht komplett umkrempeln. Du musst kein 400-Seiten-Buch über Prompt Engineering lesen. Du musst kein 3-Stunden-YouTube-Video schauen, wo jemand das Konzept in den ersten 4 Minuten erklärt und dir dann für die verbleibenden 2 Stunden und 56 Minuten einen Kurs verkauft.
Fang mit zwei Dingen an:
- Erstens, erstelle eine
CLAUDE.mdin deinem Projekt-Root mit deinem Stack, harten Regeln und Patterns. Das ist deine permanente Constraints-Schicht. Jede Claude Code-Session beginnt damit, sie zu lesen. Denk daran wie an die Verfassung deines Repos — nur dass diese tatsächlich befolgt wird. - Zweitens, das nächste Mal, wenn du dabei bist, einen Vibe-Prompt wie "füg User Settings Seite hinzu" zu tippen, stopp. Nimm dir 30 Sekunden und füge ein GOAL, ein CONSTRAINT und eine FAILURE CONDITION hinzu. Nur eins von jedem. Du wirst den Unterschied sofort spüren. Es ist wie von "Ich hoffe, das funktioniert" zu "Ich weiß, das funktioniert" zu gehen — ein Gefühl so selten in der Softwareentwicklung, dass es als kontrollierte Substanz klassifiziert werden sollte.
Das Prompt Contract Framework geht nicht darum, mehr zu schreiben. Es geht darum, 60 Sekunden zu denken, damit Claude Code nicht 60 Minuten raten muss.
Ich ging vom Zocken zum Ausliefern. Du bist dran.
Falls du SaaS mit Claude Code baust und mehr taktische Breakdowns wie diese willst, folge mir für wöchentliche Deep Dives. Ich liefere aus, breche und mass-reverte Dinge öffentlich, damit du es nicht musst.
Wie du mit 'Prompt Contracts' aufhörst, KI-Code zu würfeln und stattdessen zielgerichtet zu bauen — meine wöchentlichen Einblicke in produktionsreife AI-Entwicklung.