Stary kod na nowym stosie. Z dowodem, że liczy tak samo.

code-modernization to oficjalny plugin Anthropic do Claude Code. Tu znajdziesz: kiedy go użyć, jak go zainstalować, które komendy uruchomić po kolei i co sprawdzić przy każdej decyzji. Na koniec dwa przykłady: Xbase++ i C++Builder.

Autor: · Ostatnia aktualizacja:

1 komenda na start /code-modernization:modernize
Tylko do odczytu stary kod nie jest edytowany
Werdykt ze skryptu stary i nowy kod na tych samych danych

Kiedy go użyć, a kiedy wystarczy zwykły prompt.

Nikt nie wie, jak to działa Tryb „Understand it first”
Brak dokumentacji, autor odszedł, każdy boi się zmian. Dostajesz ocenę, mapę, reguły biznesowe i plan, a kod zostaje nietknięty. Od tego warto zacząć, jeśli nie wiesz, co dalej: ocena sama poleci jedną z dróg poniżej.
Stara wersja tego samego stosu uplift
.NET Framework 4.8 na .NET 8, Java 8 na 17, Spring Boot 2 na 3, Python 2 na 3. Kod zostaje, poprawiasz tylko to, co psuje nowa wersja. Dowód: ten sam zestaw testów przechodzi na obu wersjach.
Stary język transform
Xbase++, C++Builder, Delphi, COBOL, PHP 5 na C#, Javę, Pythona albo Rust. Przepisujesz moduł po module, a stary system w tym czasie dalej pracuje.
Stara architektura reimagine
Monolit na REST API z osobnym frontem albo kilka usług. Najpierw specyfikacja wyciągnięta z kodu i zatwierdzona architektura, potem szkielety usług z testami akceptacyjnymi.
Kiedy nie Zwykły Claude Code wystarczy
Skrypt na kilkaset linii przepiszesz szybciej zwykłym promptem. Przeniesienie aplikacji bez zmian na nowy serwer albo zakup gotowego produktu nie zmieniają kodu, więc nie ma czego budować.

Dlaczego plugin, a nie „przepisz to na C#”

  • Zwykły prompt nie ma kontroli. Model przepisuje to, co zrozumiał, a testy pisze ten sam model. Nikt nie sprawdza, czy nowy kod liczy jak stary.
  • Plugin wyciąga reguły z dowodem. Każda reguła biznesowa ma cytat plik:linia, sprawdza ją drugi agent, a podejrzane zatwierdza człowiek.
  • Nic nie powstaje bez zgody. Plan musi zostać podpisany, zanim cokolwiek zostanie zbudowane, a testy każdego modułu zatwierdzasz przed napisaniem kodu.
  • Dowód liczy skrypt, nie model. Stary i nowy kod dostają te same dane, skrypt porównuje wynik bajt po bajcie. Do tego co najmniej 10 nowych wejść i celowa usterka, która musi zaczerwienić testy.
  • Stan zostaje w plikach. Kolejne komendy czytają analysis/, a nie rozmowę. Druga osoba albo nowa sesja ruszy dalej od modernize-status.

Instalacja i pierwsze uruchomienie.

Potrzebujesz Claude Code i Pythona 3.8+ dostępnego jako python3. Opcjonalnie: scc albo cloc do metryk. Najmocniejszy dowód dostaniesz, gdy na tej samej maszynie da się zbudować i uruchomić stary program.

1. Osobny katalog roboczy

Nie pracuj w repozytorium starego kodu. Plugin podłączy je dowiązaniem.

mkdir ~/modernizacja && cd ~/modernizacja

2. Stary kod tylko do odczytu

W .claude/settings.json katalogu roboczego:

{
  "permissions": {
    "allow": ["Read(**)", "Edit(analysis/**)", "Edit(modernized/**)"],
    "deny": ["Edit(/legacy/**)", "Edit(//Users/ja/legacy/faktury/**)"],
    "additionalDirectories": ["/Users/ja/legacy/faktury"]
  }
}

Pierwszy deny blokuje dowiązanie legacy/, drugi prawdziwą ścieżkę kodu (reguła pasuje do ścieżki dowiązania, nie do celu). preflight sprawdzi, czy reguła jest.

3. Instalacja pluginu

claude
/plugin marketplace add anthropics/claude-plugins-official
/plugin install code-modernization@claude-plugins-official

4. Start

/code-modernization:modernize faktury --source /Users/ja/legacy/faktury

Plugin policzy język i rozmiar kodu, a potem zada dwa pytania w okienkach:

  • Co chcesz zrobić? Nowsza wersja tego samego stosu / inny język moduł po module / nowa architektura / najpierw zrozumieć.
  • Co musi zostać prawdą? Stary system działa w trakcie / zachowanie 1:1 razem z dziwactwami / poprawiamy znane błędy / najpierw przegląd bezpieczeństwa.

Przy przebudowie dopyta jeszcze, w co system ma się zmienić. Odpowiedzi trafią do analysis/faktury/INTENT.md, a na ekranie zobaczysz dokładną komendę preflight z wypełnionymi argumentami i pytanie, czy ją uruchomić.

Ściąga: komenda, kiedy, co dostajesz.

Wszystkie komendy mają prefiks /code-modernization:. Każda kończy się linią z następnym krokiem i odświeża analysis/<nazwa>/REPORT.html (jedna strona ze stanem prac, działa offline). Czasy według README, dla systemów rzędu dziesiątek tysięcy linii.

KomendaKiedyCo dostajeszCzas
modernize <nazwa> --source <ścieżka>Zawsze na start (argumenty opcjonalne)INTENT.md, gotowa następna komenda1 min
modernize-preflight <nazwa> [stos] [--source ścieżka]Pierwszy krokPREFLIGHT.md: 5 odpowiedzi, próbny build, brakujące źródła3–4 min
modernize-assess <nazwa>Co to za systemASSESSMENT.md: rozmiar, złożoność, dług, bezpieczeństwo, rekomendowana droga5–8 min
modernize-assess --portfolio <katalog>Kilka systemów narazRanking systemów na jednej stronie—
modernize-map <nazwa>Jak to jest zbudowaneTOPOLOGY.html: zależności, przepływ danych, punkty wejścia5–15 min
modernize-extract-rules <nazwa> [moduły]Przed przepisaniemBUSINESS_RULES.md: karty Given/When/Then z plik:linia5–15 min
modernize-review <nazwa> [flagged|p0|all]Gdy są oflagowane regułyRULE_REVIEWS.json: Twoje werdyktyTwój czas
modernize-brief <nazwa> [stos]Przed budowąMODERNIZATION_BRIEF.md: fazy, architektura, blok zatwierdzeniaok. 5 min
modernize-uplift <nazwa> [z] [do]Nowsza wersja tego samego stosuKatalog zmian, pilot, playbook, reszta partiamipilot ok. 15 min
modernize-transform <nazwa> [moduł] [stos]Inny język, moduł po modulemodernized/<nazwa>/<moduł>/, testy, EQUIVALENCE.json15–30 min
modernize-reimagine <nazwa> [wizja]Nowa architekturaSpecyfikacja, architektura, szkielety usług z testami—
modernize-verify <nazwa> [moduł]Po każdej budowieVERIFICATION.md: werdykt na moduł—
modernize-harden <nazwa>Przegląd bezpieczeństwaSECURITY_FINDINGS.md i łatka do przejrzenia—
modernize-status <nazwa>Gdy nie wiesz, co dalejPostęp, co jest nieaktualne, komenda do wklejeniasekundy

Typowa kolejność przy przepisaniu: modernize → preflight → assess → map → extract-rules → review → brief → transform → verify. Podbicie wersji może pominąć reguły: preflight → assess → uplift → verify. Przy „najpierw zrozumieć” kończysz na brief.

Co robisz Ty: sześć decyzji i co sprawdzić przy każdej.

Plugin nigdy nie decyduje w tych miejscach za Ciebie. Każda decyzja to konkretny plik do przeczytania albo okienko z pytaniem.

1 · preflight Okienka z 5 pytaniami → PREFLIGHT.md
Czy to cały system, czy wycinek (i kto z zewnątrz z niego korzysta)? Czy da się tu zbudować i odpalić testy? Czy jest nietypowy build: wewnętrzne repozytorium paczek, generator kodu? Czy ktoś już próbował i co poszło źle? Czego nie wolno ruszać? Na każde pytanie można odpowiedzieć „nie wiem”.
2 · review BUSINESS_RULES.md → RULE_REVIEWS.json
Dostajesz w okienkach reguły P0 z podejrzeniem błędu, pytaniem do eksperta albo niską pewnością, po cztery naraz, z cytatem kodu. Oceniasz, czy reguła jest poprawna. Regułę oznaczoną jako błędną plan pokaże jako otwarte pytanie, a testy nie przyjmą jej za wzorzec.
3 · brief MODERNIZATION_BRIEF.md, sekcja 8
Czytasz cel, architekturę docelową (diagram C4), fazy i otwarte pytania z sekcji 7. Zatwierdzasz w bloku Approved by / Date / Approval covers: Phase 1 only | Full plan. Brak sprzeciwu to nie zgoda. Zmieniając brief, sterujesz budową.
4 · transform Plan modułu i plik testów
Przed kodem dostajesz plan modułu, a potem plik testów charakteryzujących z numerami reguł w nazwach. Sprawdź, czy testy obejmują reguły P0 tego modułu. Dopiero po Twojej zgodzie powstaje kod.
5 · verify fresh-cases.json, BASELINE.md, VERIFICATION.md
Każdą różnicę między starym a nowym kodem akceptujesz sam, z powodem: approvedInputs w fresh-cases.json albo tabela „Approved differences” w BASELINE.md. Werdykt PROVEN to dowód, a nie zgoda: VERIFICATION.md podpisuje osoba z imienia i nazwiska.
6 · harden SECURITY_FINDINGS.md i łatka
Przegląd bezpieczeństwa starego systemu (OWASP, CWE, podatne zależności, sekrety). Łatkę wdraża inżynier bezpieczeństwa, nie plugin. Usunięcie danych logowania trafia do osobnej łatki poza gitem.

Prezentacja szkoleniowa.

21 slajdów, około 30 minut. Na slajdach kilka słów, pod podglądem fakty do opowiedzenia. Pełny ekran to widok na projektor. Widok prelegenta otwiera drugie okno z notatkami, następnym slajdem i zegarem. Oba okna przełączają się razem.

Akademia SZRON

Stary kod.

1 / 21

Do opowiedzenia

  • Temat: plugin code-modernization do Claude Code. Autor: Anthropic, oficjalny katalog wtyczek, wersja 1.0.0 z października 2026.
  • Plan: gdzie go użyć, dlaczego zamiast zwykłego promptu, instalacja, komendy po kolei, decyzje człowieka, dwa przykłady (Xbase++ i C++Builder).

    Sterowanie: strzałki, spacja, Page Up/Down (pilot do prezentacji), Home/End. N pokazuje notatki na pełnym ekranie, gdy masz jeden monitor.

    Przykład 1: faktury z Xbase++ na .NET 10.

    Scenariusz szkoleniowy, nie wdrożenie u klienta. Program do faktur z końca lat 90.: Xbase++, pliki DBF z indeksami, ekrany @ SAY/GET, wydruki na drukarkę igłową.

    Co Stos docelowy
    ASP.NET Core na .NET 10, PostgreSQL, front w React z TypeScriptem.
    Dlaczego Ten stos, a nie inny
    Typ decimal liczy pieniądze bez błędów binarnych, .NET 10 ma wsparcie LTS do listopada 2028, a programistów C# łatwo znaleźć. Przeglądarka zamiast terminala znosi instalację na każdym stanowisku.
    Jak Droga i pierwszy moduł
    transform, czyli moduł po module, podczas gdy stary program dalej wystawia faktury. Pierwszy moduł: wyliczenie i wydruk faktury, bo ma jasne wejście (pozycje) i wyjście (kwoty, wydruk).
    Gdzie Stary program do porównań
    Xbase++ działa na Windows. Maszyna wirtualna z działającym programem pozwala porównywać na żywo i dojść do PROVEN. Bez niej zostają nagrane wydruki i najwyżej PARTLY PROVEN.
    Alternatywa Zostajemy na Xbase++
    Producent ma własną ścieżkę z DBF na SQL (dokumentacja Alaska Software). Wtedy wybierasz uplift.

    Komendy

    /code-modernization:modernize faktury --source /Users/ja/legacy/faktury
    /code-modernization:modernize-preflight faktury "C# .NET 10" --source /Users/ja/legacy/faktury
    /code-modernization:modernize-assess faktury
    /code-modernization:modernize-map faktury
    /code-modernization:modernize-extract-rules faktury
    /code-modernization:modernize-review faktury
    /code-modernization:modernize-brief faktury "C# .NET 10, ASP.NET Core, PostgreSQL, React"
    /code-modernization:modernize-transform faktury wydruk-faktury "C# .NET 10"
    /code-modernization:modernize-verify faktury wydruk-faktury
    Przed Xbase++ · FAKTURY.PRG
    PROCEDURE ZapiszFakture()
       LOCAL nNetto := 0, nVat
       SELECT POZYCJE
       SET FILTER TO POZYCJE->ID_FAKT == FAKTURY->ID
       GO TOP
       DO WHILE ! EOF()
          nNetto += ROUND( POZYCJE->ILOSC * POZYCJE->CENA, 2 )
          SKIP
       ENDDO
       nVat := ROUND( nNetto * 0.23, 2 )   // stawka w kodzie
       SELECT FAKTURY
       REPLACE NETTO WITH nNetto, VAT WITH nVat
       COMMIT
    RETURN
    Po C# · .NET 10
    // RULE-007: VAT od sumy netto, nie od pozycji
    public static Totals Compute(
        IReadOnlyList<Line> lines, decimal vatRate)
    {
        var net = lines.Sum(l => Money(l.Qty * l.Price));
        return new Totals(net, Money(net * vatRate));
    }
    
    // ROUND() w Xbase++ zaokrągla połówkę od zera,
    // Math.Round w .NET domyślnie do parzystej
    static decimal Money(decimal v) =>
        Math.Round(v, 2, MidpointRounding.AwayFromZero);

    Karta reguły z BUSINESS_RULES.md

    ### RULE-007: VAT liczony od sumy netto faktury
    Priorytet: P0 · Źródło: FAKTURY.PRG:41–52
    Given faktura z pozycjami 3 × 33,33 zł netto, stawka 23%
    When  program zapisuje fakturę
    Then  netto = 99,99 zł, VAT = 23,00 zł
    And   VAT nie jest sumą VAT-ów pozycji (3 × 7,67 = 23,01 zł)

    Co wyłapie dowód

    Zaokrąglanie 0,125 → 0,13 albo 0,12
    ROUND() w Xbase++ zaokrągla połówkę od zera, Math.Round w .NET domyślnie do parzystej. Poprawka to jeden parametr: MidpointRounding.AwayFromZero.
    Usunięte rekordy SET DELETED ON
    DELETE w DBF tylko oznacza rekord, usuwa go dopiero PACK. Naiwny import do PostgreSQL wskrzesza anulowane faktury.
    Daty SET EPOCH, puste daty
    Dwucyfrowe lata rozwijane według SET EPOCH, puste pole daty zamiast NULL.
    Polskie znaki CP852, sortowanie
    Dane w CP852 (albo Mazovii, jeśli pamiętają Clippera), indeksy sortujące po bajtach: „Ł” za „Z”. Utrzymanie albo zmianę tego zachowania zatwierdza się w review.

    Przykład 2: stanowisko ważenia z C++Buildera na Rust i Tauri.

    Też scenariusz szkoleniowy. Aplikacja VCL na hali: timer co sekundę czyta wagę z portu RS-232, liczy wartość towaru, zapisuje ważenie do Firebirda i drukuje etykietę z QuickReport. Cała logika siedzi w obsłudze zdarzeń formularza.

    Co Stos docelowy
    Rdzeń w Rust (port szeregowy, logika, kwoty w rust_decimal), okno w Tauri 2 z interfejsem w TypeScripcie, PostgreSQL w centrali.
    Dlaczego Ten stos, a nie inny
    Logika ważenia staje się biblioteką, którą da się przetestować bez wagi i bez okna. Jeden mały instalator zamiast runtime'u VCL i sterowników bazy na każdym stanowisku.
    Jak Droga i pierwszy moduł
    transform. Pierwszy moduł: parsowanie ramki i wyliczenie wartości, bo da się je porównać na nagranych danych. Ekran i wydruk w kolejnych fazach.
    Gdzie Stary program do porównań
    Maszyna wirtualna z Windows, a zamiast wagi plik z ramkami nagranymi raz z prawdziwego urządzenia, łącznie z uszkodzonymi i niestabilnymi odczytami. Etykiety porównuje się jako dane przekazane do wydruku, nie jako piksele.
    Alternatywa Zostajemy na C++Builderze
    Uplift do aktualnego RAD Studio (BDE na FireDAC, AnsiString na Unicode) przez modernize-uplift. Embarcadero ma do tego własne centrum migracji.

    Komendy

    /code-modernization:modernize waga --source /Users/ja/legacy/waga
    /code-modernization:modernize-preflight waga "Rust, Tauri 2" --source /Users/ja/legacy/waga
    /code-modernization:modernize-assess waga
    /code-modernization:modernize-map waga
    /code-modernization:modernize-extract-rules waga
    /code-modernization:modernize-review waga
    /code-modernization:modernize-brief waga "Rust, Tauri 2, PostgreSQL"
    /code-modernization:modernize-transform waga wazenie "Rust"
    /code-modernization:modernize-verify waga wazenie
    Przed C++Builder · WagaForm.cpp
    void __fastcall TWagaForm::Timer1Timer(TObject *Sender)
    {
        AnsiString r = ComPort1->ReadStr(); // "ST,GS,+0012.345kg"
        if (r.Pos("ST") != 1) return;       // tylko stabilny odczyt
        // działa, bo FormCreate ustawia DecimalSeparator = '.'
        double kg = StrToFloat(r.SubString(7, 9));
        double cena = Query1->FieldByName("CENA_KG")->AsFloat;
        double wartosc = RoundTo(kg * cena, -2);
        ZapiszWazenie(kg, wartosc);
        QuickRep1->Print();
    }
    Po Rust · waga-core
    use rust_decimal::{Decimal, RoundingStrategy};
    
    /// Tylko stabilny odczyt: "ST,GS,+0012.345kg"
    pub fn kg_z_ramki(r: &str) -> Option<Decimal> {
        let r = r.strip_prefix("ST,")?;
        r.get(3..12)?.trim_start_matches('+').parse().ok()
    }
    
    /// RoundTo z RTL: połówka do parzystej
    pub fn wartosc(kg: Decimal, cena: Decimal) -> Decimal {
        (kg * cena).round_dp_with_strategy(
            2, RoundingStrategy::MidpointNearestEven)
    }
    Zaokrąglanie bankierskie RoundTo(2.5, 0) = 2
    RoundTo zaokrągla połówki do parzystej, a f64::round w Rust od zera. Odwrotnie niż w przykładzie 1. Poprawka: MidpointNearestEven w rust_decimal.
    Ukryta globalna reguła DecimalSeparator
    Parsowanie ramki działa tylko dlatego, że FormCreate ustawia kropkę jako separator dziesiętny. Na polskich ustawieniach Windows bez tej linii każdy odczyt kończy się wyjątkiem.
    Daty i teksty TDateTime, AnsiString
    TDateTime to liczba dni od 30.12.1899 zapisana jako double. Teksty AnsiString są w Windows-1250. Test na granicy: ważenie o północy.

    Koszt i pułapki.

    Limit planu 50–200 agentów
    Tyle odpalał w testach najcięższy krok, extract-rules. Każdy krok z wieloma agentami mówi przed startem, ilu uruchomi, a przy dużym przebiegu pyta o zgodę. Zaczynaj od jednego modułu.
    Reguły nie są deterministyczne Wyciąga je model
    Dwa przebiegi mogą znaleźć inne reguły. BUSINESS_RULES.md przeglądasz jak każdy inny tekst, nie traktujesz go jak wyniku kompilacji.
    Git Plugin niczego nie commituje
    analysis/ i modernized/ commitujesz sam. Kopia robocza przy uplift ma własną lokalną historię, żeby różnica była czytelna.
    Skrypty i CI claude -p
    Sesja bez okna przestaje czekać na pracę w tle po 10 minutach. Ustaw CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS=0, żeby długie kroki zdążyły się skończyć.
    Sekrety Maskowane w raportach
    Znalezione klucze trafiają do raportów jako AKIA****, pełne wartości tylko do SECRETS.local.md poza gitem.
    Telemetria Same liczby
    Plugin wysyła tylko liczby (bez kodu, nazw i ścieżek). Wyłączysz ją przez CODE_MODERNIZATION_TELEMETRY=0.

    Macie program, którego nikt nie chce ruszać?

    Zaczynamy od jednego modułu: ocena, reguły, plan i pilot z dowodem równoważności na Waszym kodzie. Krótka rozmowa wystarczy, żeby sprawdzić, czy ma to u Was sens. Odpowiadamy w 24 h.