# Fallstudie: 52.000 Zeilen Legacy-Code mit Claude Code auf .NET 10 migriert – in einem halben Tag
Eine über zehn Jahre gewachsene Enterprise-Anwendung (52.300 LOC, .NET Framework 4.7 + AngularJS 1.4) wurde mit Claude Code in weniger als einem halben Manntag auf .NET 10.0 migriert.
TLDR
Eine über zehn Jahre gewachsene Enterprise-Anwendung (52.300 LOC, .NET Framework 4.7 + AngularJS 1.4) wurde mit Claude Code in weniger als einem halben Manntag auf .NET 10.0 migriert – inklusive Eliminierung von 13 proprietären NuGet-Paketen, Containerisierung und Frontend-Upgrade. Das Schlüsselpattern: Research → Plan → Execute. Ergebnis: 31 % weniger Code bei identischer Funktionalität, Cross-Platform-fähig und CI/CD-ready.
Einleitung
Jeder .NET-Entwickler kennt sie: Die Legacy-Anwendung, die seit Jahren zuverlässig auf einem Windows Server läuft, deren Migration aber „irgendwann" auf der Roadmap steht – nur hat dieses „irgendwann" die unangenehme Eigenschaft, nie einzutreten. Bei TimeWizard war es nicht anders. Eine über zehn Jahre gewachsene Enterprise-Anwendung mit 52.000 Zeilen Code, 23 SignalR Hubs und 13 proprietären NuGet-Paketen. Der Migrationsbedarf war offensichtlich, der manuelle Aufwand ebenso abschreckend.
Der letztendliche Auslöser war dann doch kein strategisches Erwachen, sondern schlicht Microsofts Kalender: Windows Server 2016 näherte sich dem Ende der Sicherheitsupdates. Da unsere Hosting-Infrastruktur mittlerweile auf Rancher RKE2 Kubernetes läuft, wäre ein Upgrade auf eine neue Windows-Server-Version nicht nur kostenpflichtig gewesen, sondern hätte den parallelen Tech-Stack dauerhaft aufgebläht. Die Migration per Coding Agent war daher ein Test – nicht nur wegen der erzielbaren Zeitersparnis, sondern auch des Vorgehenskonzepts.
Dieser Artikel dokumentiert, wie wir die Migration mit Claude Code als Coding Agent in weniger als einem halben Manntag durchgeführt haben – und welche Patterns sich dabei als übertragbar erwiesen.
Die Ausgangslage
TimeWizard ist eine mandantenfähige Enterprise-Anwendung für Zeiterfassung und Aufgabenverwaltung (Ersterstellung 2015). Das System basierte auf .NET Framework 4.7 mit ASP.NET MVC 5 und Web API 2 im Backend, kombiniert mit einer AngularJS 1.4 Single-Page-Application im Frontend. Die Echtzeitkommunikation lief über SignalR 2.4, die Datenhaltung über Entity Framework 6.3 gegen MS-SQL Server.
Architektur auf einen Blick
Die Backend-Solution umfasste 10 C#-Projekte mit 151 Klassen und rund 20.300 Zeilen Code. Besonders charakteristisch: 23 SignalR Hubs – nahezu jede Entität hatte einen eigenen Hub mit standardisierten CRUD-Operationen über eine generische Basisklasse. Sämtliche Datenbankzugriffe liefen über eine einzige Repository-Klasse TWRepository mit 29 öffentlichen Methoden – ein klassisches God-Object-Antipattern.
Das Frontend war als AngularJS-SPA mit 49 Routen, 88 HTML-Templates und rund 16.200 Zeilen JavaScript umgesetzt. Ein separater Windows Service mit Quartz.NET erledigte zeitgesteuerte Aufgaben.
Gesamtkomplexität
| Metrik | Wert |
|---|---|
| C#-Projekte in der Solution | 10 |
| C#-Klassen | 151 |
| Entity-/Model-Klassen | 23 |
| Web API Controller / SignalR Hubs | 12 / 23 |
| Angular Controller / Services / Directives | 44 / 86 / 34 |
| NuGet-Abhängigkeiten (unique) | 65 |
| Codezeilen Backend (C#) | ~20.300 |
| Codezeilen Frontend (JS + HTML) | ~32.000 |
| Codezeilen gesamt | ~52.300 |
Technische Schulden – die Greatest Hits
Wer das Repository öffnete, stolperte über eine beeindruckende Sammlung technischer Schulden – jede einzelne mit dem untrüglichen Geruch von „das war damals eine gute Idee":
- Keine automatisierten Tests. Keinerlei Unit- oder Integrationstests. Jede Änderung erforderte manuelles Testen – bei 52.000 Zeilen Code ein beachtliches Glücksspiel.
- Veralteter Frontend-Stack. AngularJS 1.4 hatte bereits im Januar 2022 sein End-of-Life erreicht. Zusammen mit jQuery 2.1 und Bootstrap 3 ein Trio, das keine Sicherheitsupdates mehr sah.
- 13 proprietäre Evanto.Common-NuGet-Pakete bildeten das Fundament der Anwendung – von der Repository-Basisklasse über Authentifizierung bis zur SignalR-Infrastruktur. Eine enge Kopplung, die jede Modernisierung zur Großbaustelle machte.
- Windows-Bindung. Das .NET Framework 4.7 ließ weder Containerisierung noch Cross-Platform-Deployment zu. Konfiguration lief über Web.config-Transformationen – umständlich und fehleranfällig.
- Keine Datenbankmigrationen. Das Schema existierte nur implizit im DbContext. Reproduzierbare Bereitstellung? Eher Wunschdenken.
Vorgehensweise
Die Migration folgte einem bewusst sequenziellen Ablauf in elf Schritten. Das Grundprinzip: Zuerst das Backend vollständig migrieren, dann das Frontend nur soweit anpassen, dass es mit dem neuen Backend kommunizieren kann, und abschließend die JavaScript-Abhängigkeiten aktualisieren. Jeder Schritt wurde als eigenständiger Prompt an Claude Code formuliert – die wörtlichen Prompts sind im Folgenden als Blockquotes dokumentiert.
1. Projektkontext etablieren mit CLAUDE.md
Bevor der Agent produktiv arbeiten kann, braucht er ein Verständnis der bestehenden Codebasis. Dafür setzten wir das Custom Command /create-rules ein – eine erweiterte Variante des eingebauten /init-Befehls. Das Command analysiert automatisch den Tech Stack, erkennt Projekttyp und Verzeichnisstruktur, extrahiert Namenskonventionen aus dem bestehenden Code und generiert daraus eine CLAUDE.md-Datei im Projektstamm.
Dieser Schritt steht bewusst am Anfang, weil die Qualität aller nachfolgenden Planungen und Implementierungen direkt vom Projektverständnis des Agenten abhängt.
2. Migrationsplan erstellen
Im zweiten Schritt beauftragten wir Claude Code im /plan Modus mit einem detaillierten Migrationsplan. Die zentrale strategische Entscheidung: Backend zuerst, den Windows Service zunächst ausklammern, das AngularJS-Frontend nur soweit anfassen, wie es für die SignalR-Anbindung nötig ist. Die proprietären Evanto.Common-Bibliotheken sollten weitestgehend eliminiert werden.
The application has basically three parts, classic .NET 4.7 backend, scheduler and AngularJS frontend. Please create a detailed plan how to migrate the backend to latest .NET core 10 framework. Don't touch scheduler in first step and the AngularJS UI only as far that it is able to connect to the migrated backend (mostly done via SignalR web sockets connection).
Clarify if all needed dependencies (external libraries) can be migrated too. If not, research alternative solutions. Ask questions if there are things to clarify or implementation options so that we are finally on same track. The source for the Evanto.Common.* libraries is in folder ./common/lib. Basically I do want to eliminate as much as possible of them. Please migrate the absolutely necessary parts to project specific libraries in a ./lib folder. Split the migration in multiple steps if it is to complex to be handled in one step.
Warum dieser Prompt funktioniert: Er gibt klare Leitplanken (Backend zuerst, Scheduler ausklammern), benennt explizit das Ziel für die proprietären Bibliotheken, fordert Rückfragen bei Unklarheiten ein und erlaubt dem Agent, die Komplexität selbst einzuschätzen und bei Bedarf aufzuteilen. Claude Code erstellte daraufhin einen mehrstufigen Plan, identifizierte nicht migrierbare Abhängigkeiten mit Alternativvorschlägen und stellte Rückfragen zu Implementierungsoptionen.
3. Backend-Migration durchführen
Die Ausführung des Migrationsplans lief vollständig autonom ab – 75 Minuten ohne eine einzige Unterbrechung oder Rückfrage auf einem Mac M4 Pro. Claude Code migrierte in dieser Zeit die gesamte Backend-Codebasis von .NET Framework 4.7 auf .NET 10.0, portierte die SignalR-Hubs auf ASP.NET Core SignalR, ersetzte die Evanto.Common-Bibliotheken durch projektspezifische Implementierungen und passte die Frontend-seitige SignalR-Anbindung an.
4. Migrationsreport erstellen und validieren
Nach Abschluss forderten wir einen detaillierten Report über den aktuellen Status an. Dieser Schritt dient der Validierung: Welche Teile wurden erfolgreich migriert, welche offenen Punkte gibt es? Ein konkretes Beispiel: Das Quellprojekt verwendete zwei Connection Strings (Anwendungsdatenbank + Authentifizierung), das migrierte Projekt nur noch einen.
Please write a detailed report about the execution of last plan (migration from .NET 4.7 to .NET core). Check open issues and current status, e.g. in user management (source project has two connection strings for app and authentication, target project only one for app database, whats with the authentication?).
5. Modernisierung und Best Practices
Mit dem funktionierenden Backend als Grundlage zogen wir in einer Serie von gezielten Prompts aktuelle .NET Best Practices nach. Jeder Prompt adressierte ein spezifisches Thema:
Central Package Management – Directory.Packages.props, Directory.Build.props und global.json für zentralisierte Versionsverwaltung:
Please introduce a centralized management via introducing Directory.Packages.props, Directory.Build.props, and global.json to enable easier management.
Package Updates und SLNX-Format – Aktualisierung aller NuGet-Pakete und Umstellung auf das moderne Solution-Format:
Please update all packages to latest versions but no preview versions. Verify with building solution. Please convert the .NET solution file from SLN to SLNX format and verify build.
Containerisierung und CI/CD – Dockerfile und GitLab-CI-Pipeline:
Please create me now a Dockerfile and a .gitlab-ci file in root ./ for ./src/TimeWizard.Web website project. Take EXISTING_PROJECT as reference.
E-Mail-Versand mit Coravel Mailables – Migration auf das Coravel-Mailable-Pattern, mit einem bestehenden Projekt als Referenz:
Please create me a plan to migrate the email sending in the ./src project to Coravel Mailables. Please identify first all places where mails are sent and update then to Coravel Mailables. See following project for reference: EXISTING_PROJECT
Konfiguration über Environment-Variablen – .env-basierte Konfiguration für sensitive Daten:
I do want to support configuration by environment variables via an .env file to avoid storing sensitive credentials like connection string and passwords in appsettings.json. Please create me a suitable .env file and adapt configuration loading in Program.cs. Modify also .gitignore to avoid storing the .env file in GIT.
6. Backend-Test
Da das Projekt über keinerlei automatisierte Tests verfügte, validierten wir das migrierte Backend durch manuelles Testen. Das einzige unmittelbare Problem: Die PDF-Generierung. Die Originalanwendung verwendete Windows-Systemfonts, die unter macOS und in Linux-Containern schlicht nicht existieren. Ein typisches Migrationsproblem beim Wechsel zu Cross-Platform .NET. Die Lösung – ein eigener PdfSharp FontResolver, der Schriften aus eingebetteten Ressourcen auflöst – generierte Claude Code automatisch, nachdem wir die Fehlermeldung aus dem Anwendungslog als Prompt übergeben hatten.
7. AngularJS-Upgrade
Für die Frontend-Modernisierung wählten wir bewusst ein dreistufiges Vorgehen: Research → Plan → Execute. Im ersten Schritt sollte Claude Code ermitteln, auf welche AngularJS-Version ein gefahrloses Upgrade möglich ist:
The project contains an AngularJS 1.4.x frontend. Latest AngularJS version is 1.8.4. Please make a careful research how we can update AngularJS to a higher 1.x.x version without breaking the JavaScript Dependencies.
Das Ergebnis: Version 1.8.3 ist die letzte tatsächlich verfügbare Release (1.8.4 existiert nicht als vollständiges Release). Claude Code erstellte daraufhin einen Upgrade-Plan und führte diesen nach Freigabe aus.
8. jQuery und weitere JavaScript-Abhängigkeiten
Nach dem gleichen Research → Plan → Execute-Muster aktualisierten wir die übrigen Frontend-Abhängigkeiten. Den größten Sprung machte jQuery von 2.1.4 auf 3.7.1. Das dreistufige Vorgehen hat sich als zuverlässiges Pattern für Upgrades über mehrere Major-Versionen hinweg bewährt, weil der Agent vor der Ausführung Breaking Changes identifiziert und im Plan berücksichtigt.
9. CLAUDE.md neu generieren
Nach Abschluss aller Migrationsschritte generierten wir die CLAUDE.md erneut mit /create-rules. Dieser Schritt ist notwendig, weil sich der Projektstand grundlegend verändert hat: neues Framework, neue Projektstruktur, andere Abhängigkeiten. Damit der Agent bei den folgenden Frontend-Fixes mit aktuellem Kontext arbeitet, muss die CLAUDE.md den migrierten Stand widerspiegeln.
10. Frontend-Test und Fehlerbehebung
Nach den JavaScript-Upgrades über mehrere Major-Versionen war mit Regressionen zu rechnen. Bei auftretenden Problemen standen zwei Wege zur Verfügung: Screenshots und Console Logs als Prompt übergeben – oder, deutlich effizienter, dem Agent die URL der laufenden Anwendung mitteilen und ihn den Fehler selbst untersuchen lassen. Für letzteres kamen zwei Browser-Automation-Tools zum Einsatz: das claude-in-chrome Plugin und Playwright MCP.
Insgesamt mussten rund 10 UI-Probleme behoben werden. Der Zeitbedarf lag bei 90 Minuten. Eine wichtige Erkenntnis: Das Auslesen der Browser-Konsole und die Behebung von JavaScript-Fehlern gelingt mit Playwright zuverlässiger und schneller als mit claude-in-chrome.
11. README.md als Onboarding-Guide
Als Abschluss generierte Claude Code eine entwicklerorientierte README.md, die als Einstiegspunkt für neue Entwickler Setup, Konfiguration und Architekturentscheidungen dokumentiert.
Create a user focused README.md as onboarding guide especially for new developers joining the TimeWizard project.
Timeline-Übersicht
| Schritt | Beschreibung | Dauer | Modus |
|---|---|---|---|
| 1 | CLAUDE.md generieren | ~5 Min | Autonom |
| 2 | Migrationsplan erstellen | ~15 Min | Interaktiv |
| 3 | Backend-Migration | ~75 Min | Autonom |
| 4 | Migrationsreport | ~10 Min | Autonom + Review |
| 5 | Modernisierung & Best Practices | ~30 Min | Serie von Prompts |
| 6 | Backend-Test | ~20 Min | Manuell + Prompt |
| 7–8 | AngularJS + JS-Upgrades | ~30 Min | Research → Execute |
| 9 | CLAUDE.md neu generieren | ~5 Min | Autonom |
| 10 | Frontend-Test & Fixes | ~90 Min | Manuell + Agent |
| 11 | README.md generieren | ~5 Min | Autonom |
| Gesamt | ~4–5h | < 0,5 MT |
Ergebnis
Key Metrics
52.300 → 36.300 LOC (−31 %) | 65 → 10 NuGet-Pakete | Windows-only → Cross-Platform | Aufwand: <0,5 MT vs. geschätzt 2–3 MT manuell
Vorher/Nachher im Detail
| Metrik | Vorher | Nachher | Delta |
|---|---|---|---|
| C#-Klassen / Dateien | 151 / 165 | 158 / 172 | +7 |
| Entity-/Model-Klassen | 23 | 18 | −5 |
| ViewModel-Klassen | 55 | 63 | +8 |
| Web API Controller | 12 | 11 | −1 |
| SignalR Hubs | 23 | 24 | +1 |
| NuGet-Abhängigkeiten (unique) | 65 | 10 | −55 |
| Codezeilen Backend (C#) | ~20.300 | ~12.800 | −37 % |
| Codezeilen Frontend (JS + HTML) | ~32.000 | ~23.500 | −27 % |
| Codezeilen gesamt | ~52.300 | ~36.300 | −31 % |
Was wir gewonnen haben
Die Codebasis schrumpfte um 31 % bei identischer Funktionalität – hauptsächlich durch die Eliminierung der proprietären Bibliotheken und die schlankeren Patterns von ASP.NET Core. Die Anwendung läuft nun plattformunabhängig in Linux-Containern auf unserem RKE2-Cluster. Autofac wurde durch den integrierten Microsoft-DI-Container ersetzt, der E-Mail-Versand auf Coravel Mailables migriert, und die Konfiguration nutzt .env-Dateien statt Web.config-Transformationen. Die Frontend-Sicherheitslücken (jQuery XSS, AngularJS Prototype Pollution) sind durch die Updates auf aktuelle Versionen geschlossen.
Was bewusst offen blieb
Nicht jede technische Schuld wurde adressiert – das war eine bewusste Scope-Entscheidung:
- Keine automatisierten Tests. Die Validierung erfolgt weiterhin manuell. Bei einer Anwendung, die voraussichtlich nicht mehr aktiv weiterentwickelt wird, war der ROI für eine Testabdeckung nicht gegeben.
- AngularJS bleibt. Das Frontend wurde auf 1.8.3 aktualisiert, aber nicht auf ein modernes Framework migriert. Die hohe Komplexität durch zahlreiche Zusatzkomponenten macht eine vollautomatische Migration unrealistisch.
- Kein Scheduler. Der Windows Service für Fälligkeitsbenachrichtigungen wurde entfernt, aber noch nicht durch Coravel Scheduler ersetzt.
Challenges & Lessons Learned
Proprietäre Bibliotheksabhängigkeiten
Die größte Herausforderung war die Ablösung der 13 internen Evanto.Common-NuGet-Pakete. Diese Bibliotheken waren als gemeinsame Basis für mehrere Anwendungen konzipiert und entsprechend eng verwoben – von der Repository-Basisklasse über Authentifizierung bis zur SignalR-Infrastruktur. Claude Code musste die relevanten Teile identifizieren, in projektspezifische Bibliotheken extrahieren und sämtliche Referenzen anpassen. Die Entscheidung, diese Abhängigkeiten komplett aufzulösen statt sie mitzumigrieren, erhöhte den initialen Aufwand, eliminiert aber langfristig eine wesentliche Wartungslast.
Lesson Learned: Proprietäre Bibliotheksabhängigkeiten sind für einen Coding Agent keine Blackbox – vorausgesetzt, der Quellcode liegt vor. Den Pfad zum Quellcode explizit im Prompt anzugeben war entscheidend.
Plattformspezifische PDF-Probleme
Die Originalanwendung setzte für PDFsharp/MigraDoc auf Windows-Systemfonts, die unter macOS und in Linux-Containern nicht verfügbar sind. Dieses Problem wurde erst beim manuellen Test sichtbar. Der FontResolver war dann allerdings eine Sache von einem Prompt mit der Fehlermeldung.
Lesson Learned: Plattformspezifische Hürden beim Wechsel von Windows-.NET lassen sich vorab schwer antizipieren. Ein manueller Testlauf nach der Backend-Migration ist unerlässlich.
Kaskadierende JavaScript-Upgrades
AngularJS 1.4 → 1.8.3 und jQuery 2.1 → 3.7.1 über mehrere Major-Versionen hinweg zogen rund 10 UI-Probleme nach sich. Die Identifikation und Behebung dieser Regressionen war der zeitaufwendigste manuelle Anteil der Migration (90 Minuten), wurde jedoch effektiv durch Playwright MCP unterstützt.
Lesson Learned: Das dreistufige Research → Plan → Execute-Muster ist bei Multi-Major-Upgrades Gold wert. Der Agent identifiziert Breaking Changes vor der Ausführung und plant entsprechend.
Fehlende Testabdeckung
Keinerlei Tests im Originalprojekt bedeutete: Vollständig manuelle Validierung nach jedem Schritt. In einem Projekt mit bestehender Testabdeckung hätte der Agent die Tests nach jeder Änderung automatisch ausführen und Probleme früher erkennen können.
Lesson Learned: Tests sind nicht nur für Menschen – sie sind der effektivste Feedback-Loop für Coding Agents.
Fazit & Einordnung
Aufwand und Kosten
Die gesamte Migration wurde in weniger als einem halben Manntag abgeschlossen (siehe Timeline oben). Bei rein manueller Durchführung wären mindestens 2 bis 3 Manntage realistisch gewesen – konservativ geschätzt, da allein das Verstehen und Umschreiben der proprietären Bibliotheksabhängigkeiten erheblichen Analyseaufwand erfordert hätte.
Die API-Kosten für die Claude Code Nutzung lagen im Bereich von ca. 30–40 € für die gesamte Migration. Gemessen an der eingesparten Arbeitszeit – selbst bei konservativer Kalkulation – ein hervorragender ROI.
Übertragbare Patterns
Drei Patterns haben sich als projektübergreifend anwendbar erwiesen:
Research → Plan → Execute. Besonders bei Upgrades über mehrere Major-Versionen. Der Agent recherchiert Breaking Changes, erstellt einen konkreten Plan und führt diesen erst nach Freigabe aus. Das reduziert das Risiko von Fehlentscheidungen deutlich gegenüber einem direkten „mach mal"-Prompt.
CLAUDE.md als Steuerungsinstrument. Einmal zu Beginn generiert, um dem Agenten den Ist-Zustand zu vermitteln, und ein zweites Mal nach Abschluss der Migration, um den neuen Projektstand für alle Folgearbeiten festzuhalten.
Gezielte Prompts statt Mega-Prompt. Die Modernisierung (Schritt 5) zeigt: Eine Serie fokussierter Prompts – jeder mit einem klar abgegrenzten Thema – liefert bessere Ergebnisse als ein einzelner Prompt, der alles auf einmal erledigen soll.
Grenzen des Ansatzes
Die Migration zeigt auch, wo agentengestützte Modernisierung aktuell an ihre Grenzen stößt. Das AngularJS-Frontend wurde bewusst nicht auf ein modernes Framework migriert – die fehlende Komponentenarchitektur von AngularJS und die zahlreichen Zusatzkomponenten machen eine vollautomatische Migration unrealistisch. Ebenso wurden weder automatisierte Tests noch Datenbankmigrationen eingeführt; beides hätte den Scope deutlich erweitert und den Zeitvorteil relativiert.
Für wen eignet sich dieser Ansatz?
Besonders für Projekte, bei denen der manuelle Migrationsaufwand bisher als zu hoch eingeschätzt wurde und die Migration deshalb immer wieder aufgeschoben wurde – genau wie es bei TimeWizard der Fall war. Die Kombination aus strukturierter Planung durch den Agenten und gezielter manueller Validierung ermöglicht es, auch umfangreiche Legacy-Migrationen mit vertretbarem Aufwand durchzuführen.
Die Voraussetzung: Der Entwickler muss das Zielsystem verstehen und die Ergebnisse des Agenten kritisch bewerten können. Der Coding Agent ersetzt nicht die fachliche Kompetenz – er beschleunigt die Umsetzung.
Referenzen
- Claude Code Dokumentation
- Pragmatischer Claude Code Einsatz für C# Entwickler auf Mac – Unser Artikel zum grundlegenden Claude Code Setup für .NET-Entwicklung
- Coravel Mailables Dokumentation
- Playwright MCP Server
- Claude in Chrome
- Context Engineering (Colin Medin)
- PDFsharp/MigraDoc
Über uns
Ein erfahrenes Entwicklerteam, das mit Leib und Seele Software erstellt.

Letzte Blogeinträge
Pragmatischer Claude Code Einsatz für C# Entwickler auf Mac
KI im Büroalltag: 6 Quick Wins, die Sie sofort umsetzen können
Nützliche Verweise
Kontaktdaten
Brunnstr. 25,
Regensburg
+49 (941) 94592-0
+49 (941) 94592-22