CLI — interfejs wiersza poleceń#
KSeFka dostarcza CLI (ksefka) do zarządzania fakturami, kontrahentami i danymi bezpośrednio z terminala lub skryptów. Większość komend wymaga licencji PRO (bez niej działają m.in. status, authorize i lista produktów). Każda instalacja ma 30 dni okresu próbnego, wspólnego z aplikacją i MCP; rusza przy pierwszym uruchomieniu aplikacji albo pierwszej komendzie CLI.
Instalacja#
CLI jest dołączone do instalatora KSeFka, ale nie włącza się samo. Otwórz Ustawienia → CLI i kliknij "Zainstaluj CLI" — dopiero wtedy polecenie ksefka pojawia się w terminalu. Na Windows instalator aplikacji dodaje katalog instalacji do zmiennej PATH, więc nic więcej nie trzeba ustawiać.
Kolejne wersje CLI aplikacja podmienia sama, o ile CLI jest już zainstalowane.
Weryfikacja instalacji:
ksefka --version
Opcje globalne#
| Opcja | Opis |
|---|---|
--env <środowisko> | Środowisko KSeF: test, demo, production (domyślnie: środowisko wybrane ostatnio w aplikacji) |
--company-id <ID> | ID firmy, gdy masz w aplikacji kilka firm (domyślnie: firma aktywna w aplikacji) |
--help | Wyświetl pomoc dla komendy |
Jak znaleźć pomoc#
Każda komenda ma wbudowaną dokumentację:
ksefka --help # lista wszystkich komend ksefka <komenda> --help # szczegóły konkretnej komendy
Komendy#
| Komenda | Opis |
|---|---|
| Faktury | |
list-invoices | Lista faktur z filtrowaniem |
get-invoice | Szczegóły faktury z pozycjami |
create-invoice | Utwórz fakturę z pliku JSON lub stdin |
finalize-invoice | Przenieś fakturę roboczą do stanu "gotowa do wysłania" |
unfinalize-invoice | Cofnij finalizację faktury do wersji roboczej |
copy-invoice | Skopiuj fakturę jako nowy szkic z dzisiejszą datą |
open-invoice | Otwórz fakturę w aplikacji desktopowej |
export-invoice | Zapisz fakturę jako PDF i/lub XML |
mark-invoice-paid | Oznacz fakturę jako zapłaconą |
mark-unpaid | Cofnij oznaczenie zapłaty |
generate-payment-file | Wygeneruj plik przelewów (Elixir-0) dla faktur otrzymanych — PRO, 1 darmowy eksport |
| Pro-formy | |
list-proformas | Lista pro-form |
get-proforma | Szczegóły pro-formy i faktury, która z niej powstała |
create-proforma | Utwórz pro-formę z pliku JSON lub stdin |
convert-proforma | Po wpłacie zamień oczekującą pro-formę na fakturę VAT albo zaliczkową |
cancel-proforma | Anuluj pro-formę |
| Faktury cykliczne | |
list-recurring | Lista harmonogramów |
get-recurring | Szczegóły harmonogramu |
pause-recurring | Wstrzymaj harmonogram |
resume-recurring | Wznów harmonogram |
delete-recurring | Usuń harmonogram |
generate-recurring | Wystaw fakturę z harmonogramu teraz |
process-recurring | Wystaw wszystkie zaległe faktury cykliczne |
| Kontrahenci | |
list-contractors | Lista kontrahentów z wyszukiwaniem |
get-contractor | Szczegóły kontrahenta |
create-contractor | Dodaj kontrahenta z pliku JSON lub stdin |
update-contractor | Zaktualizuj dane kontrahenta |
delete-contractor | Usuń (dezaktywuj) kontrahenta |
| Produkty | |
list-products | Lista produktów/usług z katalogu |
get-product | Szczegóły produktu |
create-product | Dodaj produkt do katalogu — flagi --vat-exemption-reason-type i --vat-exemption-reason zapisują podstawę zwolnienia przy stawce zw.; dostępne też w update-product |
update-product | Zmień produkt: podane pola zastępują obecne |
delete-product | Usuń produkt z katalogu (zostaje w historii faktur, znika z list) |
| Raporty | |
monthly-summary | Podsumowanie miesięczne (przychody/koszty) |
dashboard-stats | Statystyki bieżącego miesiąca |
list-templates | Lista szablonów faktur |
| Inne | |
status | Aktywne środowisko, firma i liczba faktur |
ksef-authorize | Zapisz token KSeF firmy |
authorize | Aktywuj licencję PRO tokenem |
mcp | Uruchom serwer MCP (stdio) |
serve | Praca w tle bez okna aplikacji (PRO), opis niżej |
sync | Synchronizacja z KSeF teraz, przez demona pracy w tle (PRO) |
send | Wysyłka do KSeF teraz, przez demona pracy w tle (PRO) |
daemon start|stop|status|login-start | Uruchomienie, zatrzymanie i stan demona pracy w tle, start po zalogowaniu |
Większość komend nazywa się tak jak narzędzia serwera MCP, z łącznikiem zamiast podkreślnika (list-invoices to list_invoices). Dawne nazwy nadal działają w tym wydaniu, ale w następnym znikną: zamiast summary użyj monthly-summary, zamiast dashboard — dashboard-stats, zamiast export — export-invoice, zamiast mark-paid — mark-invoice-paid, zamiast payment-file — generate-payment-file, a zamiast proforma list i pozostałych akcji pro-form — list-proformas, get-proforma, create-proforma, convert-proforma i cancel-proforma.
Praca w tle#
Z KSeF rozmawia jeden proces w tle: ksefka serve, dalej nazywany demonem. Otwarta aplikacja uruchamia go sama. Z terminala zlecasz mu pracę komendami sync i send, a uruchamiasz i zatrzymujesz go komendą daemon. Gdy demon nie działa, komendy nie pobierają faktur z KSeF i nic do niego nie wysyłają, chyba że dodasz --local.
Sterowanie z terminala#
ksefka synczleca synchronizację aktywnej firmy (albo firmy z--company-id) i od razu wraca. Z--waitczeka na koniec, najwyżej 15 minut, i wypisuje wynik: nowe i zaktualizowane faktury oraz ostrzeżenia.ksefka send --invoice-id 42wysyła jedną fakturę (szkic albo zatwierdzoną) i czeka na status z KSeF. Bez--invoice-idzleca wysyłkę wszystkich zatwierdzonych faktur firmy i od razu wraca; wynik zobaczysz na liście faktur.--localprzysyncisendwykonuje pracę w procesie komendy, bez demona, i zawsze czeka na wynik. Gdy firmę obsługuje w tej chwili inny proces,synckończy się komunikatem "Trwa synchronizacja w tle", wysyłka jednej faktury czeka na niego do minuty, a kolejka nie rusza i komenda to zgłasza.ksefka daemon starturuchamia demona w tle dla środowiska z--env(albo ostatnio wybranego w aplikacji) i wraca, gdy demon odpowiada. Gdy demon już działa, komenda zgłasza to i niczego nie zmienia.ksefka daemon stopzatrzymuje demona; ten najpierw kończy bieżący przebieg, najwyżej 30 sekund. Demona uruchomionego przez otwartą aplikację zatrzymasz w aplikacji: Ustawienia → KSeF → Praca w tle.ksefka daemon statuswypisuje stan demona: wersję, PID, środowisko, firmy z czasem ostatniej synchronizacji i blokadą po limicie zapytań KSeF.
sync, send, daemon start i daemon login-start on wymagają licencji PRO albo okresu próbnego; daemon status, daemon stop i pozostałe akcje login-start działają bez niej. Gdy demon nie działa, sync, send i daemon status kończą się kodem 4. sync i send dają kod 4 także wtedy, gdy demon działa na innym środowisku niż komenda, bo identyfikatory firm i faktur pochodzą z innej bazy; daemon status pokazuje wtedy demona z jego środowiskiem. Kodem 3 kończą się, po wypisaniu wyniku i krótkiego podsumowania na stderr: sync, gdy części faktur nie pobrał (lista w polu failures), send, gdy KSeF odrzucił fakturę, i send --local, gdy część kolejki się nie wysłała.
$ ksefka sync --wait
{
"data": {
"new_invoices": 3,
"updated_invoices": 1,
"skipped_duplicates": 0,
"failed_invoices": 0,
"warnings": [],
"failures": [],
"ksef_floor_reached": false,
"authenticated": true
}
}
$ ksefka send --invoice-id 42
{
"data": {
"ksef_status": "accepted",
"ksef_reference_number": "20261101-EE-1A2B3C4D5E-6F",
"ksef_number": "5260250995-20261101-0100A1B2C3D4-E5",
"error": null,
"upo_warning": null
}
}
$ ksefka sync
{
"error": "Demon nie działa. Uruchom: ksefka daemon start albo użyj --local"
}
$ echo $?
4Jak działa demon#
ksefka serve wykonuje bez okna aplikacji tę samą pracę co otwarta KSeFka: synchronizuje faktury z KSeF wszystkich firm z włączoną pracą w tle, wysyła faktury gotowe do wysłania, generuje faktury cykliczne i sprawdza kontrahentów na białej liście VAT. Działa do zamknięcia przez Ctrl+C albo sygnał SIGTERM. Uruchomione z ręki wymaga licencji PRO albo okresu próbnego; otwarta aplikacja uruchamia je sama, bez licencji (niżej).
- Środowisko KSeF ustala się przy starcie: z opcji
--envalbo z ostatniego wyboru w aplikacji. Po zmianie środowiska w aplikacji działającyservena poprzednim środowisku (także uruchomiony z ręki) zostaje zatrzymany, a aplikacja uruchamia własny proces na nowym. - Na jednym katalogu danych może działać jeden
serve. Drugi kończy się od razu kodem5i podaje PID działającego. - Otwarta aplikacja sama uruchamia
serve --follow-parent(swój PID) i w nim wykonuje pracę w tle; taki proces kończy się razem z oknem, a po awarii aplikacja uruchamia go ponownie. Gdy zastanieserveuruchomione z ręki w tej samej wersji i na tym samym środowisku, podłącza się do niego i nie zatrzymuje go przy wyjściu; inną wersję albo inne środowisko zatrzymuje i uruchamia własny proces. Gdy aplikacja jest połączona zserve, "Synchronizuj teraz" i wysyłka z karty faktury też idą przez niego. ZmiennaKSEFKA_NO_DAEMON=1przy starcie aplikacji wyłącza ten mechanizm i przywraca pracę w tle w procesie aplikacji; to samo robi tryb awaryjny w Ustawienia → KSeF → Praca w tle, gdzie też zatrzymasz i uruchomisz proces oraz wybierzesz (PRO), czy ma pracować po zamknięciu okna. - Log trafia do pliku
daemon.logw katalogu logów (macOS:~/Library/Logs/pl.nod.ksefka, Windows:%LOCALAPPDATA%\pl.nod.ksefka\logs, Linux:~/.local/share/pl.nod.ksefka/logs). Po 5 MB plik przechodzi do archiwum; zostają trzy archiwa.
Działającym serve sterujesz przez HTTP na 127.0.0.1. Port i token są w pliku daemon.json w katalogu danych, który może czytać tylko jego właściciel. Każde zapytanie musi mieć nagłówek Authorization: Bearer <token>; bez niego odpowiedź to 401.
GET /status: wersja, PID, środowisko, firmy z punktem, do którego doszła synchronizacja, i blokadą po limicie KSeF.POST /sync-now: synchronizacja wszystkich firm albo jednej ({"company_id": 1}) poza harmonogramem. Gdy firmę synchronizuje w tej chwili aplikacja, zlecenie czeka i rusza w jednym z kolejnych przebiegów (co minutę).POST /send-now: wysyłka faktur gotowych do wysłania wszystkich firm, jednej firmy ({"company_id": 1}) albo jednej faktury ({"invoice_id": 42}). Przy jednej fakturze odpowiedź zawiera wynik wysyłki.POST /shutdown: zamknięcie, jak po SIGTERM.GET /events: strumień zdarzeń (Server-Sent Events), np. koniec synchronizacji albo zmiana statusu faktury.
Odpowiedź 409 znaczy, że praca w tle nie obsługuje firmy podanej w zleceniu albo, przy zleceniu bez firmy i bez faktury, żadnej firmy. Praca w tle obsługuje firmę, która ma dane logowania KSeF, włączoną pracę w tle i nie ma zapisanego błędu danych logowania.
Gdy KSeF zablokował NIP firmy po przekroczeniu limitu zapytań, sync-now dla tej firmy i send-now jej faktury odpowiadają 429 z polem retry_after_secs.
# macOS; jq odczytuje port i token z daemon.json DIR=~/Library/Application\ Support/pl.nod.ksefka PORT=$(jq -r .port "$DIR/daemon.json") TOKEN=$(jq -r .token "$DIR/daemon.json") curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:$PORT/status curl -s -X POST -H "Authorization: Bearer $TOKEN" http://127.0.0.1:$PORT/sync-now
Start po zalogowaniu#
Żeby demon pracował od zalogowania do systemu, bez otwierania aplikacji, wykonaj ksefka daemon login-start on. Komenda instaluje wpis startowy w menedżerze usług użytkownika (bez uprawnień administratora), przestawia pracę w tle na tryb "zawsze" i wymaga licencji PRO albo okresu próbnego. Na macOS i Linuksie demon rusza od razu (chyba że działa już demon aplikacji), na Windows przy następnym logowaniu. Demon pracuje na środowisku ostatnio wybranym w aplikacji, więc on odmawia, gdy --env wskazuje inne. To samo robi wybór trybu "Zawsze, od zalogowania do systemu" w Ustawienia → KSeF → Praca w tle. W tym trybie aplikacja przy każdym uruchomieniu sprawdza wpis i naprawia go, np. po przeniesieniu aplikacji do innego folderu.
ksefka daemon login-start offusuwa wpis i przywraca tryb "tylko gdy aplikacja jest otwarta" w każdym środowisku, które miało tryb "zawsze". Na macOS i Linuksie zatrzymuje też demona uruchomionego ze wpisu. Na Windows taki demon działa do wylogowania; zatrzymasz go komendąksefka daemon stop.ksefka daemon login-start statuswypisuje, czy wpis istnieje, gdzie leży i czy uruchamia zainstalowane CLI.ksefka daemon login-start --printwypisuje treść wpisu dla tego systemu bez instalowania, a z--platform macos|linux|windowsdla innego.- Wpis uruchamia CLI z "Zainstaluj CLI":
~/.local/bin/ksefka, na Windowsksefka.exew katalogu aplikacji. Po przeniesieniu aplikacji albo instalacji z obrazu dysku zainstaluj CLI ponownie w Ustawieniach aplikacji, która leży już na swoim miejscu, a potem włącz start po zalogowaniu. - Komenda odmawia, gdy KSeFka leży na obrazie dysku albo w tymczasowej kopii (przenieś ją do folderu Programy, otwórz stamtąd i zainstaluj CLI w Ustawieniach), oraz gdy Linux nie ma usług użytkownika systemd, np. w WSL bez
systemd=true. Wtedy uruchamiaj demona sam:ksefka daemon start. - Bez licencji PRO i okresu próbnego demon ze wpisu kończy się kodem
6i zapisuje przyczynę wdaemon.log. Licencję sprawdza też co 5 minut, więc po końcu okresu próbnego albo unieważnieniu licencji kończy pracę tak samo. Do następnego logowania już nie wraca. Gdy pliku ustawień nie da się odczytać albo token licencji jest nieprawidłowy, demon nie startuje (kod1), a działający pracuje dalej. Na Linuksie systemd uruchamia go ponownie po każdym wyjściu z kodem innym niż0,5i6, najwcześniej po minucie. Na macOS launchd robi to tylko po awarii, a Windows wcale: po kodzie1demon wraca przy następnym logowaniu. - Otwarta aplikacja w tej samej wersji i na tym samym środowisku podłącza się do demona i nie zatrzymuje go przy wyjściu. Aplikacja w innej wersji albo na innym środowisku zatrzymuje go i uruchamia własny proces. Demon ze wpisu wraca wtedy przy następnym logowaniu, a do tego czasu pracę po zamknięciu okna wyznacza tryb wybrany w aplikacji.
macOS: plik ~/Library/LaunchAgents/pl.nod.ksefka.daemon.plist, który włącza launchctl bootstrap gui/$(id -u) <plik>. launchd nie rozwija ~, więc ścieżka do CLI jest pełna. W szablonach wpisz swoją nazwę użytkownika zamiast NAZWA_UZYTKOWNIKA albo wygeneruj wpis dla siebie komendą ksefka daemon login-start --print.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>pl.nod.ksefka.daemon</string>
<key>ProgramArguments</key>
<array>
<string>/Users/NAZWA_UZYTKOWNIKA/.local/bin/ksefka</string>
<string>serve</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<dict>
<key>Crashed</key>
<true/>
</dict>
<key>ThrottleInterval</key>
<integer>60</integer>
<key>ProcessType</key>
<string>Background</string>
</dict>
</plist>Linux: plik ~/.config/systemd/user/ksefka-daemon.service, który włącza systemctl --user enable --now ksefka-daemon.service. Usługa użytkownika kończy się przy wylogowaniu; żeby działała dalej, wykonaj loginctl enable-linger $USER.
[Unit] Description=KSeFka - praca w tle (synchronizacja z KSeF) After=network-online.target [Service] ExecStart="/home/NAZWA_UZYTKOWNIKA/.local/bin/ksefka" serve Restart=on-failure RestartSec=60 # 5: demon już działa (np. pod aplikacją), 6: licencja nie pozwala na pracę w tle RestartPreventExitStatus=5 6 [Install] WantedBy=default.target
Windows: wartość KSeFkaDaemon w kluczu HKCU\Software\Microsoft\Windows\CurrentVersion\Run. conhost --headless uruchamia demona bez okna konsoli.
conhost.exe --headless "C:\Users\NAZWA_UZYTKOWNIKA\AppData\Local\KSeFka\ksefka.exe" serve
- Token KSeF zapisany w KSeFce jest zaszyfrowany kluczem związanym z komputerem. Demon na innej maszynie (serwer, NAS) z kopią bazy nie odczyta go; wykonaj tam
ksefka ksef-authorize <token>. Uruchamianie demona na innej maszynie niż aplikacja opisujemy tylko tutaj i nie obejmuje go pomoc techniczna. - Baza działa w trybie WAL: kopia samych plików
.dbprzy działającej aplikacji albo demonie może być niepełna. Kopiuj razem z plikami-wali-shmalbo przy zamkniętej aplikacji i zatrzymanym demonie (ksefka daemon stop). Kopię bez tych zastrzeżeń zrobisz w aplikacji: Ustawienia → Import / Eksport → Pełny backup danych.
Wejście JSON#
Komendy tworzące obiekty (np. create-invoice, create-contractor) przyjmują dane jako:
# z pliku ksefka create-invoice --from-json faktura.json # ze stdin (pipe) cat faktura.json | ksefka create-invoice --from-json - # lub przekierowanie ksefka create-invoice --from-json - < faktura.json
Strukturę JSON znajdziesz w pomocy komendy: ksefka create-invoice --help.
Kody wyjścia#
Komendy zwracają wynik jako JSON na stdout, w polu data. Skrypt rozpoznaje, co się stało, po kodzie wyjścia:
0— komenda wykonała pracę w całości1— komenda nie wykonała pracy; na stdout zamiastdatajest{ "error": "..." }2— błędne wywołanie (nieznana flaga, brak argumentu); opis na stderr, nic na stdout3— komenda wykonała część pracy. Wynik jest na stdout jak przy kodzie 0. Tak kończą sięsyncisendopisane w sekcji "Praca w tle" orazprocess-recurring, gdy choć jeden harmonogram został bez faktury:datazawiera wynik każdego harmonogramu, obok są licznikigenerated_countifailed_count, a stderr wymienia nieudane harmonogramy z powodem.4— demon nie działa (sync,send,daemon status) albo działa na innym środowisku (sync,send)5—servejuż działa na tym katalogu danych6— brak licencji PRO i okresu próbnego przy pracy w tle bez okna:servebez--follow-parentprzy starcie albo gdy licencja przestanie pozwalać (koniec okresu próbnego, unieważnienie),serve --follow-parentpo zamknięciu aplikacji w trybie pracy po zamknięciu okna
# cron: alarm, gdy process-recurring nie wykonał pracy albo któryś harmonogram został bez faktury ksefka process-recurring > /tmp/cykliczne.json || echo "process-recurring: kod $?" | mail -s "KSeFka" ja@firma.pl