Od 2026 roku każda polska faktura B2B musi przejść przez KSeF: zostać zaszyfrowana, przesłana przez sesyjne API i odebrana z numerem referencyjnym. Brzmi skomplikowanie, bo jest skomplikowane. ksef-cli chowa całą tę złożoność za prostymi komendami.
Podajesz XML - albo nawet skan PDF — a narzędzie zajmuje się resztą: uwierzytelnianiem RSA-OAEP, szyfrowaniem sesji AES-256-CBC, budowaniem FA(3) XML, wysyłką i pollingiem statusu. Jeśli PDF jest nieczytelny dla parsera, wchodzi Claude AI i wyciąga pola faktury multimodalnie.
Projekt jest też w pełni przystosowany do użycia przez agentów AI: każda kluczowa komenda obsługuje flagę --json z czystym JSON-em na stdout i ustrukturyzowanymi błędami na stderr. Dołączony skill dla Claude Code pozwala agentowi natychmiast nauczyć się całego API narzędzia — bez dokumentacji, bez zgadywania.
git clone https://github.com/ArturSkowronski/ksef-cli
cd ksef-cli
pip install -e ".[dev]"Wymagany Python 3.11+.
Dla ekstrakcji wspomaganej AI, ustaw klucz Anthropic:
export ANTHROPIC_API_KEY=sk-ant-...Zapisz dane uwierzytelniające raz:
ksef config set --nip 1234567890 --token <TWÓJ_TOKEN_KSEF>Zaloguj się (przeprowadza pełny flow challenge/response KSeF i zapisuje token sesji):
ksef auth loginGotowe. Wyślij pierwszą fakturę:
ksef invoice send faktura.xmlTo wszystko. ksef-cli otwiera zaszyfrowaną sesję, przesyła fakturę, zamyka sesję i czeka na potwierdzenie z KSeF. Dostajesz numer referencyjny KSeF gdy wszystko się zakończy.
KSeF używa wieloetapowego flow: challenge → zaszyfrowany token RSA → token dostępu + token odświeżania. ksef-cli obsługuje to transparentnie.
ksef auth login # pełny flow, zapisuje sesję
ksef auth status # pokaż wygaśnięcie sesji i tokeny
ksef auth refresh # odśwież token dostępu
ksef auth logout # wyczyść lokalne tokeny sesjiSesje wygasają po około godzinie. Token odświeżania jest ważny 24 godziny. Użyj ksef auth refresh żeby przedłużyć sesję bez ponownego podawania danych.
ksef invoice send faktura.pdfNarzędzie wyciąga pola faktury z PDF, buduje XML zgodny z FA(3) i wysyła go. Jeśli parser heurystyczny nie jest pewny (poniżej 50%), przełącza się na analizę multimodalną Claude AI. Przy niskim poziomie pewności zobaczysz ostrzeżenie — sprawdź wygenerowany XML przed wysłaniem.
ksef invoice send faktura.xml # wyślij i czekaj na przetworzenie
ksef invoice send faktura.xml --no-wait # wyślij bez czekaniaKonwertuj do XML bez wysyłania:
ksef invoice generate faktura.pdf --out faktura.xml
ksef invoice generate faktura.pdf # wypisz na stdoutksef invoice status <numer-referencyjny> # sprawdź status
ksef invoice get <numer-ksef> --out faktura.xml # pobierz XML
ksef invoice get <numer-ksef> --pdf --out faktura.pdf # wyrenderuj jako PDFksef invoice list # bieżący miesiąc
ksef invoice list --date-from 2024-01-01 --date-to 2024-01-31
ksef invoice list --received # faktury do Ciebie
ksef invoice list --seller-nip 9876543210 # filtruj po sprzedawcyKażda kluczowa komenda obsługuje flagę --json. Żadnego Rich markup, żadnych interaktywnych promptów — tylko czysty JSON na stdout i {"error": "..."} na stderr z niezerowym exit code przy błędzie.
# Sprawdź sesję przed jakąkolwiek operacją
ksef auth status --json
# → {"nip": "1234567890", "environment": "PRD", "sessionActive": true, "expiresIn": 3542, "expiry": "..."}
# Lista faktur
ksef invoice list --json
# → {"invoices": [{"ksefNumber": "...", "invoiceNumber": "...", "buyer": "Acme Sp. z o.o.", "netAmount": "1000.00", ...}]}
# Wyślij i odbierz numer KSeF
ksef invoice send faktura.xml --json
# → {"invoiceRef": "...", "ksefNumber": "KSeF/123/2024", "processingCode": 200}
# Wysyłka nieblokująca
ksef invoice send faktura.xml --no-wait --json
# → {"invoiceRef": "...", "ksefNumber": null, "processingCode": null}W katalogu skills/ksef-cli/ znajduje się skill dla agentów Claude Code. Po załadowaniu agent wie jak sprawdzić sesję, wywołać każdą komendę, sparsować odpowiedź JSON i obsłużyć błędy — bez żadnego zgadywania.
Żeby udostępnić skill lokalnie:
ln -s $(pwd)/skills/ksef-cli ~/.claude/skills/ksef-cliksef config set --nip 1234567890 --token <TOKEN>
ksef config set --environment TEST # PRD (domyślnie) | TEST | DEMO
ksef config show # tokeny są maskowaneKonfiguracja przechowywana w ~/.ksef/config.toml z uprawnieniami 600. Dane uwierzytelniające nigdy nie pojawiają się w logach ani w outputcie.
KSeF v2 wymaga przesyłania faktur wewnątrz zaszyfrowanej sesji:
- Pobierz certyfikat klucza publicznego KSeF
- Wygeneruj świeży klucz AES-256 + wektor inicjalizacyjny
- Zaszyfruj klucz AES algorytmem RSA-OAEP kluczem publicznym KSeF
- Otwórz sesję (
POST /sessions/online) z zaszyfrowanym kluczem - Zaszyfruj XML faktury algorytmem AES-256-CBC
- Prześlij zaszyfrowaną fakturę w ramach sesji
- Zamknij sesję
- Czekaj na status przetworzenia (kod 200 = zaakceptowano)
ksef-cli przeprowadza cały ten flow automatycznie. Ty dostarczasz tylko XML (albo PDF).
pip install -e ".[dev]"
pytest tests/ -v # 55 testówksef/
├── main.py # punkt wejścia CLI (Typer)
├── config.py # konfiguracja (~/.ksef/config.toml)
├── client.py # klient HTTP KSeF API (httpx)
├── auth.py # komendy auth + szyfrowanie RSA-OAEP
├── invoice.py # komendy faktur
├── crypto.py # pomocniki AES-256-CBC + RSA-OAEP
├── extractor.py # PDF/obraz → InvoiceData (pdfplumber + Claude)
├── xml_builder.py # InvoiceData → XML FA(3)
├── models.py # modele Pydantic
├── pdf_renderer.py # XML → PDF
└── tui.py # interaktywny dashboard TUI
skills/ksef-cli/SKILL.md # skill dla agentów Claude Code
MIT
