awesome-core 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,587 @@
1
+ Metadata-Version: 2.4
2
+ Name: awesome-core
3
+ Version: 2.0.0
4
+ Summary: Offline-first catalog of tools from GitHub awesome lists, exposed as a read-only MCP server (stdio). Pure stdlib core, no network, no API keys.
5
+ Author: Arkadiusz Słowik
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/twojlogin/awesome-core
8
+ Project-URL: Repository, https://github.com/twojlogin/awesome-core
9
+ Project-URL: Issues, https://github.com/twojlogin/awesome-core/issues
10
+ Keywords: mcp,model-context-protocol,awesome-list,offline,search,cli,sqlite
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Topic :: Utilities
14
+ Requires-Python: >=3.8
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Dynamic: license-file
18
+
19
+ # 🔥 Awesome Core
20
+
21
+ ## Czym to jest, w jednym zdaniu
22
+
23
+ **Ściąga wszystkie awesome listy z GitHuba do jednego katalogu na Twoim dysku
24
+ i pozwala szybko znaleźć narzędzie — po nazwie, języku, systemie albo temacie —
25
+ całkowicie bez internetu.**
26
+
27
+ Na przykład chcesz „coś do OSINT-a działające pod Windows". Wpisujesz:
28
+
29
+ ```bash
30
+ ./awesome search osint --os windows
31
+ ```
32
+
33
+ i dostajesz narzędzia z kilku różnych awesome list naraz, posortowane tak, że
34
+ na górze są te, które **niezależni kuratorzy wskazali w wielu listach**
35
+ (a nie tylko te z jednej głośnej listy).
36
+
37
+ > **Filtry łączy AND, więc kumulują się szybko.** `--os windows --lang PowerShell`
38
+ > zostawia z „osint" **jedno** narzędzie — i to nie to, czego szukałeś, tylko
39
+ > skrypt PowerShell, który akurat też nazywa się „Sherlock". Program wie, że
40
+ > filtr jest za wąski, i mówi wprost, który odpuścić:
41
+ >
42
+ > ```
43
+ > Uwaga: 2 filtry łączy AND i zostawiły 1 wynik(ów).
44
+ > bez lang=PowerShell → 8 wyników
45
+ > ```
46
+ >
47
+ > Zasada: dodawaj filtr tylko wtedy, gdy wyników jest więcej niż kilka.
48
+
49
+ ---
50
+
51
+ ## Jeśli nie masz czasu — trzy komendy
52
+
53
+ ```bash
54
+ ./awesome start # 1. wszystko robi za Ciebie (pobiera, buduje, gotowe)
55
+ ./awesome search nmap
56
+ ./awesome web # i otwiera przeglądarkę
57
+ ```
58
+
59
+ `./awesome start` mówi w każdym kroku, co robi i ile to potrwa. Nic działa się
60
+ samo w tle — zawsze widzisz postęp.
61
+
62
+ ---
63
+
64
+ ## Co musisz mieć zanim zaczniesz
65
+
66
+ **Jedna rzecz: Python 3.8 lub nowszy.** To wszystko.
67
+
68
+ | Potrzebujesz | Po co | Sprawdzenie |
69
+ |---|---|---|
70
+ | **Python 3.8+** | program — jedyna zależność | `python3 --version` |
71
+
72
+ **Nie potrzebujesz** jq, curl, GitHub CLI ani samodzielnego `python -m venv`:
73
+
74
+ - pobieranie list działa przez zwykły HTTPS (`core/api.py`) — bez `gh` jest
75
+ wolniej, bo GitHub limituje wyszukiwanie do 10 zapytań na minutę, ale działa;
76
+ - Flask do web UI instaluje się sam przy pierwszym `./awesome web`;
77
+ - program sam mówi, gdy brakuje czegoś (`./awesome doctor`).
78
+
79
+ Jeśli masz `gh` i się zalogujesz (`gh auth login`), wszystko idzie 30× szybciej
80
+ i `enrich` w ogóle się odblokuje. Ale to przyspieszenie, nie warunek.
81
+
82
+ Instalacja na Linuksie:
83
+
84
+ ```bash
85
+ sudo apt install python3 # albo: sudo dnf install python3
86
+ ```
87
+
88
+ Opcjonalnie, dla 30× szybszego pobierania i metadanych narzędzi:
89
+
90
+ ```bash
91
+ gh auth login # GitHub CLI, jednorazowo
92
+ ```
93
+
94
+ **Windows działa bez basha.** W katalogu jest `awesome.cmd`, więc w PowerShellu
95
+ albo po podwójnym kliknięciu piszesz po prostu:
96
+
97
+ ```powershell
98
+ awesome.cmd start
99
+ awesome.cmd web
100
+ ```
101
+
102
+ `download.sh` został, ale to już tylko nakładka wywołująca Pythona — w nim nie
103
+ ma już ani `jq`, ani `curl`, ani pętli w shellu.
104
+
105
+ W PowerShellu odpowiedniki reszty komend:
106
+
107
+ ```powershell
108
+ gh auth login # potem reszta jak w Linuxie
109
+ .\venv\Scripts\Activate.ps1 # aktywacja venv
110
+ .\awesome web
111
+ ```
112
+
113
+ Flask do web UI instaluje się **sam**, przy pierwszym `./awesome web`:
114
+
115
+ ```
116
+ Web UI potrzebuje Flaska. Przygotowuję środowisko (requirements.txt):
117
+ Tworzę venv…
118
+ Aktualizuję pip…
119
+ Instaluję z requirements.txt…
120
+ Gotowe. Od teraz web używa venv/.
121
+ ```
122
+
123
+ Jeśli z jakiegoś powodu to się nie uda (brak sieci, proxy), program wypisze
124
+ instrukcję ręczną — ale nie musisz jej pamiętać na co dzień.
125
+
126
+ **Nie musisz** znać SQL, programować, nic konfigurować w środku i **nie musisz**
127
+ nic aktualizować automatycznie. Jak coś nie działa — `./awesome status` powie
128
+ Ci, co dokładnie odpalić.
129
+
130
+ ---
131
+
132
+ ## Pierwsze uruchomienie, krok po kroku
133
+
134
+ ### `./awesome start`
135
+
136
+ Program sprawdza, czy masz wszystko, potem:
137
+
138
+ | Krok | Co robi | Ile trwa |
139
+ |---|---|---|
140
+ | 1 | pobiera README awesome list z GitHuba (pomija to, co już masz) | 10–25 min |
141
+ | 2 | wyciąga z nich narzędzia do bazy | ~2 min |
142
+ | 3 | dociąga gwiazdki i języki list | ~1 min |
143
+ | 4 | **włącza Web UI** i czeka | — |
144
+
145
+ **Jeśli baza już jest zbudowana, `start` nie pobiera nic od nowa.** Wypisuje
146
+ liczbę narzędzi i od razu włącza interfejs. Przebudowa wymaga świadomej decyzji:
147
+
148
+ ```bash
149
+ ./awesome start --rebuild # kasuje bazę i buduje od nowa (~2 min)
150
+ ./awesome refresh # dociąga brakujące dane i przebudowuje
151
+ ```
152
+
153
+ Dzięki temu przypadkowe `./awesome start` nie kasuje Ci 2 minuty pracy.
154
+
155
+ **Uwaga, uczciwie:** `start` nie odpytuje GitHuba o repozytoria samych
156
+ narzędzi. Ranking od razu działa (na zgodzie kuratorów), ale gwiazdka przy
157
+ narzędziu to na razie szacunek z listy, nie prawdziwa liczba. Jedna komenda
158
+ to naprawia:
159
+
160
+ ```bash
161
+ ./awesome enrich # 30–60 min, odpytuje ~35 tys. repozytoriów
162
+ ./awesome build # ~2 min, żeby gwiazdki wsiąkły do rankingu
163
+ ```
164
+
165
+ Albo jednym poleceniem od zera:
166
+
167
+ ```bash
168
+ ./awesome start --full # download → build → backfill → enrich → build
169
+ ```
170
+
171
+ Robisz to raz. Przerwać można w każdej chwili (Ctrl+C) — postęp jest zapisywany
172
+ i odpalanie komendy drugi raz jedzie dalej. Bez zalogowania do GitHuba `enrich`
173
+ odmawia z wyjaśnieniem zamiast udawać, że zrobił swoją robotę.
174
+
175
+ Jeśli masz mało czasu, krok 1 możesz pominąć i nadrobić później:
176
+
177
+ ```bash
178
+ ./awesome start --skip-download # szybka ścieżka: buduje z tego, co już jest
179
+ ```
180
+
181
+ ### Codzienne użycie
182
+
183
+ ```bash
184
+ ./awesome search "port scanner" # szukaj po ludzku
185
+ ./awesome search osint --lang Python # ...tylko Python
186
+ ./awesome search "active directory" --os windows # ...tylko pod Windowsa
187
+ ./awesome langs # co jest w bazie (języki)
188
+ ./awesome platforms # systemy: Windows, Linux, Docker...
189
+ ./awesome domains # tematy: osint, security, network...
190
+ ./awesome why nmap # skąd ten wynik — punkt po punkcie
191
+ ./awesome mentions nmap # w ilu listach jest to narzędzie
192
+ ./awesome audit # czy katalog nie jest zatruty fałszywymi listami
193
+ ./awesome audit sindresorhus/awesome # audyt jednego repozytorium
194
+ ./awesome lists # najlepsze listy
195
+ ./awesome info nmap # dane + komenda instalacji
196
+ ./awesome install nmap # zainstaluj (git clone)
197
+ ```
198
+
199
+ ### Twoja własna lista
200
+
201
+ Jak coś znajdziesz i działa — włóż to od razu na swoją listę, a na końcu
202
+ wklej gotowy Markdown:
203
+
204
+ ```bash
205
+ ./awesome shortlist add nmap --note "do skanowania sieci"
206
+ ./awesome shortlist # co jest na liście
207
+ ./awesome shortlist emit --title "Moja lista OSINT" --group domain
208
+ ./awesome shortlist emit --out moja-lista.md # zapisz do pliku
209
+ ```
210
+
211
+ W web UI jest to samo: przycisk **☆ Do mojej listy** na stronie narzędzia,
212
+ lista i Markdown pod linkiem *Moja lista* w menu. W TUI klawisz `k`.
213
+
214
+ Osobno istnieje `watch` — lista **repozytoriów list**, które chcesz śledzić
215
+ (nowe narzędzia w ulubionej liście), a nie lista narzędzi:
216
+
217
+ ```bash
218
+ ./awesome watch add sindresorhus/awesome
219
+ ./awesome watch check # co doszło od ostatniego sprawdzenia
220
+ ```
221
+
222
+ Obie listy są lokalne i żadna nie odpytuje się sama w tle.
223
+
224
+ ### TUI — klawisze
225
+
226
+ ```text
227
+ / szukaj l następny język o następna platforma
228
+ d następna domena s zmień sortowanie a wyczyść filtry
229
+ g ukryte perełki u niedoceniane Enter szczegóły
230
+ k do mojej listy i instaluj ? pomoc
231
+ q wyjście
232
+ ```
233
+
234
+ ### Cztery interfejsy, ten sam katalog
235
+
236
+ ```bash
237
+ ./awesome # terminal — najszybszy do szybkiego szukania
238
+ ./awesome tui # terminal, ale interaktywnie (strzałki, filtry)
239
+ ./awesome web # przeglądarka (port wypisuje na ekranie)
240
+ ./awesome help # wszystkie komendy
241
+ ```
242
+
243
+ ---
244
+
245
+ ## Codzienna pielęgnacja (nic nie leci samo)
246
+
247
+ ```bash
248
+ ./awesome status # co jest w bazie, kiedy ostatnio odświeżone, czego brakuje
249
+ ./awesome refresh # pobierz nowe listy → metadane → przebuduj bazę
250
+ ```
251
+
252
+ `./awesome status` po odświeżeniu podpowiada dokładną komendę, np.
253
+ `./awesome enrich`. To samo w przeglądarce: strona `/refresh`
254
+ z czterema przyciskami. Żadnych cronów, daemonów ani procesów w tle.
255
+
256
+ **Ważne przy liczbach:** status nie mówi „X narzędzi bez gwiazdek", tylko ile
257
+ **repozytoriów zostało do odpytania**. Różnica jest ogromna, bo kilka narzędzi
258
+ często wskazuje na to samo repo, a linki poza GitHubem (artykuły, filmy,
259
+ dokumentacja) **nie mają i nigdy nie będą miały gwiazdek** — nie licz ich
260
+ jako brakującej pracy.
261
+
262
+ ---
263
+
264
+ ---
265
+
266
+ ## Co jest w środku
267
+
268
+ <!-- STAN: te liczby są zależne od pobranych list — nie ma tu sztywnych
269
+ wartości. Sprawdź aktualne: ./awesome status -->
270
+ | | |
271
+ |---|---|
272
+ | narzędzi w bazie | zależne od pobranych list |
273
+ | źródeł (repozytoriów) | zależne od pobranych list |
274
+
275
+ Aktualne liczby zawsze sprawdzisz: `./awesome status`.
276
+
277
+ ---
278
+
279
+ **Uczciwa uwaga:** nie ma tu żadnego AI. Żadne modele językowe nie wybierają,
280
+ nie oceniają ani nie rankują narzędzi. To zwykły Python, który parsuje README
281
+ z list GitHuba i liczy rzeczy na surowo. Jeśli liczby w README różnią się od
282
+ bazy — ktoś zapomniał odświeżyć blok STAN. Zrób `./awesome status` i popraw.
283
+
284
+ ## Podłącz agenta AI (MCP) — lokalnie, bez kluczy API
285
+
286
+ Katalog można dać do dyspozycji lokalnemu agentowi (Claude, Cursor, cokolwiek
287
+ mówi „Model Context Protocol”) jako źródło narzędzi. Agent dostaje ranking
288
+ oparty o zgodę niezależnych kuratorów, a nie o to, co jest najczęściej
289
+ wypisane w jednym README.
290
+
291
+ ```bash
292
+ ./awesome mcp --demo # podgląd: zobaczysz całą wymianę JSON-RPC bez agenta
293
+ ./awesome mcp # serwer czeka na stdin (tak to działa w praktyce)
294
+ ```
295
+
296
+ Serwer daje 5 narzędzi: `search_tools` (szukanie z filtrami),
297
+ `find_undiscovered_tools` (niedoceniane i ukryte perełki), `explain_tool`
298
+ (uzasadnienie rankingu: z jakich list, ile punktów, co ważyło),
299
+ `lists_with_tool` (wszystkie listy + oznaczone kopie) i `catalog_facets`
300
+ (co jest w bazie: języki, platformy, domeny).
301
+
302
+ Wpisz to do konfiguracji klienta, np. `claude_desktop_config.json`:
303
+
304
+ ```json
305
+ {
306
+ "mcpServers": {
307
+ "awesome-core": {
308
+ "command": "/pełna/ścieżka/do/awesome-core/awesome",
309
+ "args": ["mcp"]
310
+ }
311
+ }
312
+ }
313
+ ```
314
+
315
+ Co warto wiedzieć:
316
+
317
+ - **Nic nie wychodzi do sieci.** Zero kluczy API, zero kont, tylko odczyt
318
+ lokalnej bazy SQLite. Serwer nie ma narzędzi z efektem ubocznym.
319
+ - **Start jest natychmiastowy** — baza jest już zbudowana, serwer tylko czyta.
320
+ - Wyniki to zwykły tekst z liczbami (gwiazdki, liczba niezależnych list, score),
321
+ więc agent może je cytować i porównywać.
322
+ - Protokół jest czystym JSON-RPC 2.0 po stdin/stdout; logi idą na stderr,
323
+ żeby nie psuły kanału.
324
+
325
+ ---
326
+
327
+ ## Skąd to wszystko pochodzi — i czy mi szkodzi
328
+
329
+ Pytanie, które powinien zadać każdy: *co jeśli ktoś wrzuci złośliwą listę?*
330
+
331
+ **Skąd listy:** `download.sh` pyta publiczne API GitHuba o repozytoria
332
+ oznaczone `topic:awesome-list` (plus `topic:awesome` i `topic:curated-list`
333
+ w trybie `--wide`), posortowane po gwiazdkach. Nic więcej — żadnych
334
+ „polecanych" repozytoriów, żadnych losowych adresów.
335
+
336
+ **Nic z obcego repozytorium nigdy nie jest wykonywane:**
337
+
338
+ - README jest **danymi**. Parser wyciąga z niego linki regexem i tyle.
339
+ Nie ma miejsca, w którym treść README trafiłaby do `eval`, `exec`,
340
+ `shell=True` czy któregokolwiek wywołania systemowego.
341
+ - `awesome install` robi dokładnie `git clone --depth 1`. Git nie uruchamia
342
+ kodu z zdalnego repozytorium (żadnych hooków).
343
+ - Przeglądarka escapuje HTML, a renderer Markdown w `core/md.py` też —
344
+ `<script>` w opisie wychodzi jako tekst, nie jako tag.
345
+
346
+ **Jedyny realny wektor: opisy trafiające do kontekstu modelu.** Serwer MCP
347
+ zamienia opisy narzędzi w tekst, który czyta agent. Opis napisał ktoś
348
+ nieznany, w repozytorium niesprawdzonym. Dlatego:
349
+
350
+ - Opisy przechodzą przez `core/untrusted.py`, które wycina instrukcje
351
+ wyglądające na polecenia, znaczniki ról (`system:`, `assistant:`), tagi
352
+ HTML, `curl … | sh` i `rm -rf` — zostawiając przy tym znacznik
353
+ `[odfiltrowano: …]`, żeby dało się zauważyć.
354
+ - `initialize` w MCP mówi agentowi wprost: to treść trzecia, nie rozkazy.
355
+ - Sprawdź sam, kiedy chcesz:
356
+
357
+ ```bash
358
+ ./awesome untrusted
359
+ ```
360
+
361
+ Stan na dziś: **0 wykrytych ataków** w 186 861 narzędziach (3 trafienia to
362
+ fałszywe alarmy — `rimraf` ma w opisie „like rm -rf", a `safety-net` to
363
+ narzędzie, które `rm -rf` blokuje). Ciekawa ironia: katalog zawiera trzy
364
+ narzędzia do obrony przed dokładnie tym problemem (`nvidia/skillspector`,
365
+ `vaporif/parry-guard`, `safety-net`).
366
+
367
+ Czego **nie** obiecuję: skaner łapie znane wzorce, nie jest dowodem
368
+ niezawodności. Dlatego traktuj opisy jako dane, a nie polecenia.
369
+
370
+ ---
371
+
372
+ ## Zasada: rdzeń bez AI
373
+
374
+ Właściciel projektu dopuścił MCP, ale nie chce sztucznej inteligencji
375
+ wszędzie — szczególnie nie w narzędziu, które miało być lokalne. Zapisuję to,
376
+ bo obietnica bez pilnowania wyparuje się przy pierwszym refaktorze:
377
+
378
+ | Warstwa | AI? | Sieć? |
379
+ |---|---|---|
380
+ | parser, baza, ranking, kopie, shortlist, TUI, web | **nie** | **nie** — czyste odczyty z `data/awesome.db` |
381
+ | `core/mcp.py` (adapter dla agentów) | tak, poza procesem | nie — JSON-RPC po stdio |
382
+ | `download`, `enrich`, `backfill`, `validate`, `install` | nie | tak, tylko na wyraźne polecenie |
383
+
384
+ Z tego wynika reszta decyzji:
385
+
386
+ - **Cała zależność zewnętrzna to `flask`** (web UI). Rdzeń to czysty stdlib.
387
+ - **Zero modeli, embeddingów, sieci neuronowych czy LLM w rankingu.** Sortowanie
388
+ to jawna arytmetyka (`core/scoring.py`), którą da się wypisać i podważyć.
389
+ - **Ranking nie zależy od usługi firmy trzeciej.** Nikt nie może Ci podsunąć
390
+ wyników ani zobaczyć, czego szukałeś.
391
+ - **MCP jest adapterem na brzegu**, nie logiki w środku. Możesz go wywalić
392
+ i nic nie przestanie działać.
393
+ - Test `test_no_ai_in_core` pilnuje tego mechanicznie: rdzeń nie zaimportuje
394
+ biblioteki AI ani sieciowej modułu bez zgody, a jedynym plikiem znającym
395
+ protokół MCP jest `core/mcp.py`.
396
+
397
+ ---
398
+
399
+ ## Czy katalog można zatruć — i co z tym robimy
400
+
401
+ Katalog powstaje z **cudzych repozytoriów**. To znaczy, że ktoś może celowo
402
+ wstawić fałszywą listę, która zbiera wejścia, a jej „narzędzia" prowadzą do
403
+ podszywanych domen albo do szkodliwego kodu. **Czy to się zdarzyło?**
404
+
405
+ ```bash
406
+ ./awesome audit
407
+ ```
408
+
409
+ Stan na dziś (6 października 2026, 1 032 listy, 186 861 narzędzi): **7 list
410
+ warte obejrzenia, 1 podejrzany link**. Zero potwierdzonych ataków.
411
+
412
+ Co sygnał ma złapać:
413
+
414
+ | Sygnał | Dlaczego podejrzane |
415
+ |---|---|
416
+ | dużo narzędzi przy **0 gwiazdek** | twórca dopiero zaczął — nie ma reputacji do stracenia |
417
+ | **jeden właściciel** dla wielu linków | to nie katalog, tylko linki do jednego projektu |
418
+ | dużo **martwych linków** | farma linków, nie treść |
419
+ | niedawno utworzone repo + dużo narzędzi | kampania, nie dorobek |
420
+ | **klon** innej listy | kopiowanie zamiast budowania |
421
+ | link typu `github.com@evil.tld`, `githvb.com`, adres IP, punycode | podszywanie domeny |
422
+
423
+ Przykładowe trafienie z naszej bazy: `laoma2053/awesome-zhuiju-free` — 25 narzędzi,
424
+ **0 gwiazdek**, brak opisu, żaden link nie potwierdzony przez inną listę.
425
+
426
+ Czego **nie** robimy i dlaczego warto to wiedzieć:
427
+
428
+ - **To nie jest skaner złośliwego oprogramowania.** Nie rozpoznajemy droppera
429
+ w repozytorium ani złośliwego kodu w kodzie narzędzia. Nie obiecujemy, że
430
+ przepuścimy wszystko.
431
+ - **Sygnały nie są wyrokiem.** Flag oznacza „obejrzyć ręcznie", nie „złośliwe".
432
+ Trzy z siedmiu trafień okazały się uczciwymi, choć dziwnymi listami.
433
+ - **Ranking już się przed tym broni**: narzędzie potrzebuje zgody co najmniej
434
+ dwóch niezależnych list, a kopie list nie liczą się do tej zgody. Jedna
435
+ nowa fałszywa lista nie wypchnie niczego na szczyt.
436
+ - **`awesome install` to tylko `git clone`.** Nie uruchamia skryptów, nie pyta
437
+ o hasło do Twojego GitHuba, nie wykonuje kodu zdalnego repozytorium. Ale
438
+ potem **to Ty** decydujesz, co z tym kodem zrobisz — i tego program nie
439
+ kontroluje.
440
+ - **Opisy z obcych list trafiają do kontekstu modelu przez MCP**, więc są
441
+ przepuszczane przez `core/untrusted.py` (patrz sekcja o bezpieczeństwie).
442
+
443
+ Najprostsza zasada: narzędzie z jednej nowej listy, o którym nigdy nie
444
+ słyszałeś, to znak sprawdzenia — nie polecenia instalacji.
445
+
446
+ ---
447
+
448
+ ## Czego nie wiem — słowniczek
449
+
450
+ | Słowo | Co to znaczy |
451
+ |---|---|
452
+ | **awesome list** | lista linków do narzędzi prowadzona na GitHubie (np. `sindresorhus/awesome`) |
453
+ | **baza (SQLite)** | jeden plik `data/awesome.db` z całym katalogiem; zwykły plik, możesz go skasować i przebudować. Kasowanie i wstawianie idą w jednej transakcji, więc przerwany build zostawia poprzednią bazę, a nie pustą |
454
+ | **FTS5** | wbudowany w SQLite szybki indeks tekstowy — dzięki niemu szukanie trwa milisekundy |
455
+ | **metadane listy** | gwiazdki, język, opis listy z GitHuba |
456
+ | **metadane narzędzia** | gwiazdki, język i czy żyje repozytorium **samego narzędzia** |
457
+ | **consensus (zgoda)** | narzędzie wskazane przez ilu **różnych** autorów list — nasz główny ranking |
458
+ | **jakość listy** | 0–1: czy lista ma opisy, czy duplikaty, czy jej linki żyją, czy jest aktualna |
459
+ | **score** | punkty narzędzia (0–100) z tych wszystkich sygnałów |
460
+
461
+ **Program niczego nie rekomenduje.** Nie ma w nim „polecam", „najlepszy wybór"
462
+ ani LLM, który podpowiada narzędzia. Jest za to: policzone liczby (zgoda
463
+ niezależnych kuratorów, gwiazdki, jakość listy, z jakich list narzędzie
464
+ pochodzi) i filtry o jawnych kryteriach. Wybór zostaje po Twojej stronie —
465
+ dlatego wszystko, co program mówi, da się sprawdzić liczbą.
466
+ | **backfill** | dociąganie brakujących metadanych list |
467
+ | **enrich** | sprawdzanie repozytoriów narzędzi (batch po 50 na zapytanie do API) |
468
+ | **build** | przebudowa bazy z lokalnych plików README (~2 min) |
469
+ | **fasetka** | klikalny filtr boczny, np. „język: Python” |
470
+
471
+ ---
472
+
473
+ ## Licencja
474
+
475
+ MIT — `LICENSE` w katalogu. Kod jest mój, ale **nazwy, linki i krótkie opisy
476
+ narzędzi pochodzą z cudzych awesome list** i należą do ich autorów. W bazie
477
+ są tylko adresy i nazwy repozytoriów (fakty, nie czyjeś treści), a same
478
+ README nie są dołączane do repo — pobierasz je na swój dysk przez
479
+ `./download.sh`.
480
+
481
+ ## Znane ograniczenia (uczciwie)
482
+
483
+ **Ranking czyta to, co napisał autor — nie kod.** Nazwa, opis, gwiazdki,
484
+ tematy, README: wszystko to można napisać dowolnie i wszystko wchodzi do
485
+ score. Program **nigdy nie zagląda do kodu repozytorium**, więc nie odróżnia
486
+ narzędzia od kolekcji skryptów o tej samej nazwie ani oryginału od kopii.
487
+
488
+ Mierzalny skutek: `awesome selfcheck` sprawdza 15 znanych narzędzi
489
+ (nazwa → właściwe repozytorium) i zwykle trafia **13/15 na pozycji #1**.
490
+ Dwie porażki to zawsze ten sam mechanizm — repozytorium fanowskie, które
491
+ powtarza nazwę narzędzia w opisie, wyprzedza oryginał.
492
+
493
+ ```bash
494
+ ./awesome selfcheck
495
+ ```
496
+
497
+ To jest granica tego podejścia, nie do poprawienia strojeniem wag: do jej
498
+ przekroczenia trzeba by patrzeć na zawartość repozytorium (importy, pliki
499
+ wejściowe, tagi wydań), a to osobny projekt. Świadomie tego nie udaję.
500
+
501
+ **Mniej poważne, ale też powiedziane:**
502
+ - 91% narzędzi występuje w jednej liście, więc dla nich „zgoda kuratorów"
503
+ wynosi zero — teza działa na głowie katalogu, nie na ogonie
504
+ - 75 571 wpisów to linki poza GitHubem (artykuły, filmy, dokumentacja):
505
+ nigdy nie dostaną gwiazdek i nie są narzędziami
506
+
507
+ * **Wyszukiwarka GitHuba oddaje maks. 1000 wyników na jedno zapytanie.**
508
+ Dlatego pobieranie używa kilku zapytań naraz (`--wide`) i skaluje wyniki.
509
+ * **Prawdziwy język narzędzia** znamy tylko dla repozytoriów sprawdzonych przez
510
+ `./awesome enrich`. Reszta zgadywana jest z adresu i opisu — stąd `?` tam,
511
+ gdzie nie wiadomo. Ranking celowo nie ufa temu zgadywaniu.
512
+ * **Linki poza GitHubem** sprawdzamy tylko na żądanie:
513
+ `./awesome validate --non-github --limit 500`.
514
+ * **Nie sprawdzamy, czy narzędzie jest bezpieczne.** Sygnały przy repozytoriach
515
+ (archiwalne, dawno nieaktualizowane) to wskazówki do sprawdzenia, nie etykieta.
516
+ Przeczytaj kod i release'y, zanim cokolwiek zainstalujesz.
517
+
518
+ ---
519
+
520
+ ## Dla tych, którzy chcą wejść głębiej
521
+
522
+ <details>
523
+ <summary>Struktura projektu</summary>
524
+
525
+ ```
526
+ awesome # wygodny wrapper: ./awesome <komenda>
527
+ download.sh # pobieranie README list z GitHuba (bash + gh + jq)
528
+ extract_tools.py # budowa bazy z lokalnych README
529
+ data/awesome.db # baza SQLite (generowana, w .gitignore)
530
+ offline-db/ # pobrane README list (generowane, w .gitignore)
531
+
532
+ core/store.py # schemat bazy, migracje, zapis metadanych
533
+ core/parser.py # wyciąganie narzędzi z markdown (listy i tabele)
534
+ core/langmap.py # język / platforma / domena / czyszczenie URL-i
535
+ core/scoring.py # consensus, jakość listy, ranking
536
+ core/aliases.py # synonimy („port scanner” → nmap, masscan…)
537
+ core/md.py # własny renderer Markdown → HTML (bez CDN)
538
+ core/builder.py # orkiestracja builda
539
+ core/backfill.py # metadane list
540
+ core/enrich.py # metadane repozytoriów narzędzi
541
+ core/status.py # stan danych i plan odświeżenia
542
+ core/tools_db.py # zapytania (search, fasetki, ranking)
543
+ core/database.py # zapytania po listach/repozytoriach
544
+ core/curator.py # kolekcje + instalacja
545
+ core/validator.py # weryfikacja linków
546
+ core/trust.py # sygnały ryzyka przy repozytoriach
547
+ cli/awesome_cli.py # CLI
548
+ cli/tui.py # TUI (curses)
549
+ web/app.py # Flask UI
550
+ web/templates/ # szablony Jinja2
551
+ tests/smoke_test.py # 106 testy (CI)
552
+ ```
553
+
554
+ </details>
555
+
556
+ <details>
557
+ <summary>Jak liczymy ranking</summary>
558
+
559
+ `score` (0–100) to świadoma korekta nad „sortuj po gwiazdkach listy”:
560
+
561
+ | Składowa | Waga | Znaczenie |
562
+ |---|---|---|
563
+ | `consensus` | 0.28 | w ilu **niezależnych** listach jest narzędzie × jakość tych list |
564
+ | `own_stars` | 0.22 | gwiazdki **samego narzędzia** (z API), nie listy |
565
+ | `quality` | 0.14 | jakość listy: opisy, unikalność, żywe linki, świeżość, rozmiar |
566
+ | `alive` | 0.14 | link sprawdzony i żywy |
567
+ | `desc` | 0.10 | ma sensowny opis |
568
+ | `list_stars` | 0.06 | gwiazdki listy (słaby sygnał) |
569
+ | `known` | 0.06 | mamy metadane narzędzia z API |
570
+
571
+ Dodatkowo `underrated` (dobra jakość, mało gwiazdek) i `hidden_gem` (mało list,
572
+ wysoki score). `./awesome why <nazwa>` pokazuje rozkład punktów.
573
+
574
+ </details>
575
+
576
+ <details>
577
+ <summary>Wymagania i licencja</summary>
578
+
579
+ * Python 3.8+ (SQLite z FTS5; bez FTS5 działa fallback na LIKE)
580
+ * Flask ≥ 3.0 — tylko dla web UI
581
+ * `gh`, `jq`, `curl` — tylko do pobierania i enrichmentu
582
+ * `curses` z biblioteki standardowej — tylko dla TUI
583
+
584
+ MIT — używaj, zmieniaj, dziel się.
585
+ Autor: **Arkadiusz Słowik** — [@twojlogin](https://github.com/twojlogin)
586
+
587
+ </details>
@@ -0,0 +1,33 @@
1
+ awesome_core-2.0.0.dist-info/licenses/LICENSE,sha256=otBwht3mJ1u0kxyI-tUPAPXjGpo34AZjZ0lxvomhO_8,1061
2
+ core/__init__.py,sha256=VjE4x2psjrINSAaRLbZqS6vuoke53N9X_HmqcFOarYI,50
3
+ core/aliases.py,sha256=a3TcOGo7gG3ee1EPTN3rqEBQHW1MYCimIEdV7mJznUI,7759
4
+ core/api.py,sha256=-U67VsQT2h0qHt0v_Va9V89AjZL2jjKCQum01gUaTLU,6001
5
+ core/backfill.py,sha256=TKXt5F_RXHvjuJqNMHZ8j4DuIuij-_tfix5IxmoTv4g,8347
6
+ core/bootstrap.py,sha256=1RWQjuvpraK5Izp1TPWULWqT8ZGw_R5N-7_D3nelIpE,3953
7
+ core/builder.py,sha256=6guHkeu-pmAJN84Dt9dqx4J3roqXqPTNvxI9nwk-qEw,19892
8
+ core/clones.py,sha256=LhwEPMWbrTc7vuRvVsU_HiknoEyLx5v-9uC0PZbVq2s,6286
9
+ core/curator.py,sha256=LHrfZymI6vvG0XXX9DZQ6emYH5CB1_llACC7NvNlNng,8736
10
+ core/database.py,sha256=TAydogfMIM-B1E72BxJqC2SuaHhoQxCack-19PHU4Cg,6388
11
+ core/doctor.py,sha256=lYkcX47iDKkvgJ4jAYDCOxnGbGGDy3M3aXKEx41NEKg,4625
12
+ core/enrich.py,sha256=j60vUKRyTFW0w8swHwcU5oyW20KZXcX6-P6AEbX5URY,11878
13
+ core/fetcher.py,sha256=LfrCUPetJD6xUrWPNzMOI793Nggqrcq9vsklykwuyII,7867
14
+ core/langmap.py,sha256=qqoIWtjdUrLwZMBzWRPCwAVIjMYShc_3GmFTNYCK79Q,26233
15
+ core/mcp.py,sha256=oE1fIOF3QEBozrhrmMb86teKc8YDuo-_2FkFm164_8U,19272
16
+ core/md.py,sha256=VJBBSr4pS7JJn9ekmviasX8YcsOZR73LeXWR5c_EVsA,15345
17
+ core/parser.py,sha256=d4TGNxmmBDF5hxACXzrZ0Y43fw1pzVU-xX69q1HLBCo,8525
18
+ core/poisoning.py,sha256=qHXpYE-lvLD1tLm8aBOuCVQqBKcks0CzQg7lZvYHJkU,7899
19
+ core/scoring.py,sha256=pUQpVVUy9-u-PIAs9gISSeWLB2uTxxXlscLaT-ysGGI,6128
20
+ core/selfcheck.py,sha256=PU5dgdMTfA8IPjUAuzG48Fovf8TPuM9h3AgQasVtzCU,2217
21
+ core/shortlist.py,sha256=xtTIn6pCNJw20iWLr3P5jUt0YwMG0J2MWLfYJs7SbX0,6265
22
+ core/status.py,sha256=hPs2r6JH7J9TVgX6UFro6mitFmRy1NGZPSHj2VIiR7g,7168
23
+ core/store.py,sha256=H7_pPQbVCEF7QDooTHwoPwyPDAMza57eaCsjqgTMzuc,17638
24
+ core/tools_db.py,sha256=hJm_eGAspMJo0br_FkW9lBrE1v3mawXmQXjI9Z_BSFE,30813
25
+ core/trust.py,sha256=hxrGgT_L2AGoJZss-x0siP4OO1g3Wm7FRTph6zRJrLY,4383
26
+ core/untrusted.py,sha256=dU7SDYTbAMjTMZ_MAonkM_HT0vzzRNdkJfPKpr4hNFc,4148
27
+ core/validator.py,sha256=p49ARubiIuctThdiRfMfkyxs9MutYNQ5o9IRKSmP5S0,5470
28
+ core/watcher.py,sha256=reJAKSHy2LcB-NZT5XHPS7W9fpGkOZ9Gi7m5sYru2bw,3108
29
+ awesome_core-2.0.0.dist-info/METADATA,sha256=ybqh-TRlHV3IidFn7KbrM_nhZiFHL2kUExYb9xBbhhw,23842
30
+ awesome_core-2.0.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
31
+ awesome_core-2.0.0.dist-info/entry_points.txt,sha256=XEK3KPcHGt_Fd_6qx1SftInuwuUhoveFFjD8R8WO9LY,47
32
+ awesome_core-2.0.0.dist-info/top_level.txt,sha256=0ebp8k35dOTHVwbY3UcokRsjC7cWLN_iaJ70tIcmODU,5
33
+ awesome_core-2.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ awesome-core = core.mcp:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Arek
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ core
core/__init__.py ADDED
@@ -0,0 +1 @@
1
+ from core.database import AwesomeDB # noqa: F401