fixos 2.2.41__tar.gz → 2.2.46__tar.gz

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.
Files changed (178) hide show
  1. {fixos-2.2.41 → fixos-2.2.46}/CHANGELOG.md +52 -0
  2. {fixos-2.2.41 → fixos-2.2.46}/PKG-INFO +47 -16
  3. {fixos-2.2.41 → fixos-2.2.46}/README.md +46 -15
  4. {fixos-2.2.41 → fixos-2.2.46}/fixos/__init__.py +1 -1
  5. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/cleanup_cmd.py +231 -17
  6. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/main.py +17 -1
  7. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/service_cleanup.py +574 -7
  8. {fixos-2.2.41 → fixos-2.2.46}/fixos.egg-info/PKG-INFO +47 -16
  9. {fixos-2.2.41 → fixos-2.2.46}/pyproject.toml +1 -1
  10. {fixos-2.2.41 → fixos-2.2.46}/setup.py +1 -1
  11. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_cleanup_cmd.py +195 -0
  12. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_service_cleanup.py +220 -0
  13. {fixos-2.2.41 → fixos-2.2.46}/.env.example +0 -0
  14. {fixos-2.2.41 → fixos-2.2.46}/LICENSE +0 -0
  15. {fixos-2.2.41 → fixos-2.2.46}/MANIFEST.in +0 -0
  16. {fixos-2.2.41 → fixos-2.2.46}/docker/README.md +0 -0
  17. {fixos-2.2.41 → fixos-2.2.46}/docker/TEST_RESULTS.md +0 -0
  18. {fixos-2.2.41 → fixos-2.2.46}/docker/TEST_RESULTS_V2.md +0 -0
  19. {fixos-2.2.41 → fixos-2.2.46}/docker/alpine/Dockerfile +0 -0
  20. {fixos-2.2.41 → fixos-2.2.46}/docker/arch/Dockerfile +0 -0
  21. {fixos-2.2.41 → fixos-2.2.46}/docker/base/Dockerfile +0 -0
  22. {fixos-2.2.41 → fixos-2.2.46}/docker/broken-audio/Dockerfile +0 -0
  23. {fixos-2.2.41 → fixos-2.2.46}/docker/broken-full/Dockerfile +0 -0
  24. {fixos-2.2.41 → fixos-2.2.46}/docker/broken-network/Dockerfile +0 -0
  25. {fixos-2.2.41 → fixos-2.2.46}/docker/broken-thumbnails/Dockerfile +0 -0
  26. {fixos-2.2.41 → fixos-2.2.46}/docker/debian/Dockerfile +0 -0
  27. {fixos-2.2.41 → fixos-2.2.46}/docker/docker-compose.multi-system.yml +0 -0
  28. {fixos-2.2.41 → fixos-2.2.46}/docker/docker-compose.yml +0 -0
  29. {fixos-2.2.41 → fixos-2.2.46}/docker/fedora/Dockerfile +0 -0
  30. {fixos-2.2.41 → fixos-2.2.46}/docker/test-multi-system.sh +0 -0
  31. {fixos-2.2.41 → fixos-2.2.46}/docker/test-scenarios.sh +0 -0
  32. {fixos-2.2.41 → fixos-2.2.46}/docker/ubuntu/Dockerfile +0 -0
  33. {fixos-2.2.41 → fixos-2.2.46}/docker/validate-scenario.py +0 -0
  34. {fixos-2.2.41 → fixos-2.2.46}/docs/examples/advanced_usage.py +0 -0
  35. {fixos-2.2.41 → fixos-2.2.46}/docs/examples/quickstart.py +0 -0
  36. {fixos-2.2.41 → fixos-2.2.46}/fixos/__main__.py +0 -0
  37. {fixos-2.2.41 → fixos-2.2.46}/fixos/agent/__init__.py +0 -0
  38. {fixos-2.2.41 → fixos-2.2.46}/fixos/agent/autonomous.py +0 -0
  39. {fixos-2.2.41 → fixos-2.2.46}/fixos/agent/autonomous_session.py +0 -0
  40. {fixos-2.2.41 → fixos-2.2.46}/fixos/agent/hitl.py +0 -0
  41. {fixos-2.2.41 → fixos-2.2.46}/fixos/agent/hitl_session.py +0 -0
  42. {fixos-2.2.41 → fixos-2.2.46}/fixos/agent/session_core.py +0 -0
  43. {fixos-2.2.41 → fixos-2.2.46}/fixos/agent/session_handlers.py +0 -0
  44. {fixos-2.2.41 → fixos-2.2.46}/fixos/agent/session_io.py +0 -0
  45. {fixos-2.2.41 → fixos-2.2.46}/fixos/anonymizer.py +0 -0
  46. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/__init__.py +0 -0
  47. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/_cleanup_flatpak.py +0 -0
  48. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/_cleanup_home.py +0 -0
  49. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/_cleanup_snap.py +0 -0
  50. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/_cleanup_system.py +0 -0
  51. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/_cleanup_utils.py +0 -0
  52. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/ask_cmd.py +0 -0
  53. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/config_cmd.py +0 -0
  54. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/features_cmd.py +0 -0
  55. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/fix_cmd.py +0 -0
  56. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/history_cmd.py +0 -0
  57. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/orchestrate_cmd.py +0 -0
  58. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/output_formatter.py +0 -0
  59. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/profile_cmd.py +0 -0
  60. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/projects_cmd.py +0 -0
  61. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/provider_cmd.py +0 -0
  62. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/quick_cmd.py +0 -0
  63. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/quickfix_cmd.py +0 -0
  64. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/report_cmd.py +0 -0
  65. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/rollback_cmd.py +0 -0
  66. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/scan_cmd.py +0 -0
  67. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/shared.py +0 -0
  68. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/token_cmd.py +0 -0
  69. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli/watch_cmd.py +0 -0
  70. {fixos-2.2.41 → fixos-2.2.46}/fixos/cli.py +0 -0
  71. {fixos-2.2.41 → fixos-2.2.46}/fixos/config.py +0 -0
  72. {fixos-2.2.41 → fixos-2.2.46}/fixos/config_interactive.py +0 -0
  73. {fixos-2.2.41 → fixos-2.2.46}/fixos/constants.py +0 -0
  74. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/__init__.py +0 -0
  75. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/_flatpak_analysis_mixin.py +0 -0
  76. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/_flatpak_execution_mixin.py +0 -0
  77. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/_flatpak_recommendations_mixin.py +0 -0
  78. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/_storage_container_mixin.py +0 -0
  79. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/_storage_system_mixin.py +0 -0
  80. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/_storage_user_mixin.py +0 -0
  81. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/cache_discovery.py +0 -0
  82. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/checks/__init__.py +0 -0
  83. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/checks/_shared.py +0 -0
  84. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/checks/audio.py +0 -0
  85. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/checks/file_analysis.py +0 -0
  86. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/checks/hardware.py +0 -0
  87. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/checks/packages.py +0 -0
  88. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/checks/resources.py +0 -0
  89. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/checks/security.py +0 -0
  90. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/checks/storage_optimization.py +0 -0
  91. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/checks/system_core.py +0 -0
  92. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/checks/thumbnails.py +0 -0
  93. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/dev_project_analyzer.py +0 -0
  94. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/disk_analyzer.py +0 -0
  95. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/flatpak_analyzer.py +0 -0
  96. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/project_scanner.py +0 -0
  97. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/quick_snapshot.py +0 -0
  98. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/service_details.py +0 -0
  99. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/service_scanner.py +0 -0
  100. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/storage_analyzer.py +0 -0
  101. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/system_checks.py +0 -0
  102. {fixos-2.2.41 → fixos-2.2.46}/fixos/diagnostics/utils.py +0 -0
  103. {fixos-2.2.41 → fixos-2.2.46}/fixos/features/__init__.py +0 -0
  104. {fixos-2.2.41 → fixos-2.2.46}/fixos/features/auditor.py +0 -0
  105. {fixos-2.2.41 → fixos-2.2.46}/fixos/features/catalog.py +0 -0
  106. {fixos-2.2.41 → fixos-2.2.46}/fixos/features/installer.py +0 -0
  107. {fixos-2.2.41 → fixos-2.2.46}/fixos/features/profiles.py +0 -0
  108. {fixos-2.2.41 → fixos-2.2.46}/fixos/features/renderer.py +0 -0
  109. {fixos-2.2.41 → fixos-2.2.46}/fixos/fixes/__init__.py +0 -0
  110. {fixos-2.2.41 → fixos-2.2.46}/fixos/interactive/__init__.py +0 -0
  111. {fixos-2.2.41 → fixos-2.2.46}/fixos/interactive/cleanup_planner.py +0 -0
  112. {fixos-2.2.41 → fixos-2.2.46}/fixos/llm_shell.py +0 -0
  113. {fixos-2.2.41 → fixos-2.2.46}/fixos/orchestrator/__init__.py +0 -0
  114. {fixos-2.2.41 → fixos-2.2.46}/fixos/orchestrator/executor.py +0 -0
  115. {fixos-2.2.41 → fixos-2.2.46}/fixos/orchestrator/graph.py +0 -0
  116. {fixos-2.2.41 → fixos-2.2.46}/fixos/orchestrator/orchestrator.py +0 -0
  117. {fixos-2.2.41 → fixos-2.2.46}/fixos/orchestrator/rollback.py +0 -0
  118. {fixos-2.2.41 → fixos-2.2.46}/fixos/platform_utils.py +0 -0
  119. {fixos-2.2.41 → fixos-2.2.46}/fixos/plugins/__init__.py +0 -0
  120. {fixos-2.2.41 → fixos-2.2.46}/fixos/plugins/base.py +0 -0
  121. {fixos-2.2.41 → fixos-2.2.46}/fixos/plugins/builtin/__init__.py +0 -0
  122. {fixos-2.2.41 → fixos-2.2.46}/fixos/plugins/builtin/audio.py +0 -0
  123. {fixos-2.2.41 → fixos-2.2.46}/fixos/plugins/builtin/disk.py +0 -0
  124. {fixos-2.2.41 → fixos-2.2.46}/fixos/plugins/builtin/hardware.py +0 -0
  125. {fixos-2.2.41 → fixos-2.2.46}/fixos/plugins/builtin/resources.py +0 -0
  126. {fixos-2.2.41 → fixos-2.2.46}/fixos/plugins/builtin/security.py +0 -0
  127. {fixos-2.2.41 → fixos-2.2.46}/fixos/plugins/builtin/thumbnails.py +0 -0
  128. {fixos-2.2.41 → fixos-2.2.46}/fixos/plugins/registry.py +0 -0
  129. {fixos-2.2.41 → fixos-2.2.46}/fixos/profiles/__init__.py +0 -0
  130. {fixos-2.2.41 → fixos-2.2.46}/fixos/providers/__init__.py +0 -0
  131. {fixos-2.2.41 → fixos-2.2.46}/fixos/providers/llm.py +0 -0
  132. {fixos-2.2.41 → fixos-2.2.46}/fixos/providers/llm_analyzer.py +0 -0
  133. {fixos-2.2.41 → fixos-2.2.46}/fixos/providers/schemas.py +0 -0
  134. {fixos-2.2.41 → fixos-2.2.46}/fixos/system_checks.py +0 -0
  135. {fixos-2.2.41 → fixos-2.2.46}/fixos/utils/__init__.py +0 -0
  136. {fixos-2.2.41 → fixos-2.2.46}/fixos/utils/anonymizer.py +0 -0
  137. {fixos-2.2.41 → fixos-2.2.46}/fixos/utils/terminal.py +0 -0
  138. {fixos-2.2.41 → fixos-2.2.46}/fixos/utils/timeout.py +0 -0
  139. {fixos-2.2.41 → fixos-2.2.46}/fixos/utils/web_search.py +0 -0
  140. {fixos-2.2.41 → fixos-2.2.46}/fixos/watch.py +0 -0
  141. {fixos-2.2.41 → fixos-2.2.46}/fixos.egg-info/SOURCES.txt +0 -0
  142. {fixos-2.2.41 → fixos-2.2.46}/fixos.egg-info/dependency_links.txt +0 -0
  143. {fixos-2.2.41 → fixos-2.2.46}/fixos.egg-info/entry_points.txt +0 -0
  144. {fixos-2.2.41 → fixos-2.2.46}/fixos.egg-info/requires.txt +0 -0
  145. {fixos-2.2.41 → fixos-2.2.46}/fixos.egg-info/top_level.txt +0 -0
  146. {fixos-2.2.41 → fixos-2.2.46}/pytest.ini +0 -0
  147. {fixos-2.2.41 → fixos-2.2.46}/requirements-dev.txt +0 -0
  148. {fixos-2.2.41 → fixos-2.2.46}/requirements.txt +0 -0
  149. {fixos-2.2.41 → fixos-2.2.46}/scripts/pyqual-calibrate.py +0 -0
  150. {fixos-2.2.41 → fixos-2.2.46}/setup.cfg +0 -0
  151. {fixos-2.2.41 → fixos-2.2.46}/tests/__init__.py +0 -0
  152. {fixos-2.2.41 → fixos-2.2.46}/tests/conftest.py +0 -0
  153. {fixos-2.2.41 → fixos-2.2.46}/tests/e2e/__init__.py +0 -0
  154. {fixos-2.2.41 → fixos-2.2.46}/tests/e2e/test_anonymization_layers.py +0 -0
  155. {fixos-2.2.41 → fixos-2.2.46}/tests/e2e/test_audio_broken.py +0 -0
  156. {fixos-2.2.41 → fixos-2.2.46}/tests/e2e/test_cli.py +0 -0
  157. {fixos-2.2.41 → fixos-2.2.46}/tests/e2e/test_diagnostics_integration.py +0 -0
  158. {fixos-2.2.41 → fixos-2.2.46}/tests/e2e/test_executor.py +0 -0
  159. {fixos-2.2.41 → fixos-2.2.46}/tests/e2e/test_multi_system.py +0 -0
  160. {fixos-2.2.41 → fixos-2.2.46}/tests/e2e/test_network_broken.py +0 -0
  161. {fixos-2.2.41 → fixos-2.2.46}/tests/e2e/test_thumbnails_broken.py +0 -0
  162. {fixos-2.2.41 → fixos-2.2.46}/tests/test_fixos.py +0 -0
  163. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/__init__.py +0 -0
  164. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_anonymizer.py +0 -0
  165. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_cache_discovery.py +0 -0
  166. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_core.py +0 -0
  167. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_dev_project_analyzer.py +0 -0
  168. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_executor.py +0 -0
  169. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_llm_provider.py +0 -0
  170. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_orchestrator.py +0 -0
  171. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_project_scanner.py +0 -0
  172. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_projects_cmd.py +0 -0
  173. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_quick_cmd.py +0 -0
  174. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_quick_snapshot.py +0 -0
  175. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_resources_quick.py +0 -0
  176. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_security_quick.py +0 -0
  177. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_service_scanner.py +0 -0
  178. {fixos-2.2.41 → fixos-2.2.46}/tests/unit/test_system_checks_parallel.py +0 -0
@@ -2,6 +2,19 @@
2
2
 
3
3
  ### Added
4
4
 
5
+ - `fixos cleanup --docker-old [--days N]` oraz `-c docker-old`: usuwa wyłącznie
6
+ nieużywane obrazy Docker i build cache starsze niż N dni (domyślnie 30);
7
+ bez wolumenów i bez obrazów używanych przez kontenery.
8
+ - `fixos cleanup --ollama-old [--days N]` oraz `-c ollama-old`: usuwa modele
9
+ Ollama niezmieniane od N dni (domyślnie 90), z pominięciem modeli
10
+ aktualnie załadowanych (`/api/ps`).
11
+ - Opcja interaktywna **[1] Wszystkie bezpieczne** obejmuje teraz także:
12
+ - **Docker (nieużywane obrazy)** — pełną pulę unused (zgodną z RECLAIMABLE
13
+ Images+Build Cache), bez filtra wieku,
14
+ - **Ollama (modele >90 dni)** — gdy takie modele istnieją.
15
+ - Pomiar zwolnionego miejsca Dockera przez `docker system df` przed/po oraz
16
+ parsowanie `Total reclaimed space`; ostrzeżenie przy 0.00 GB mimo sukcesu
17
+ komendy; przypomnienie, że listy po `[1]` pochodzą ze skanu sprzed cleanup.
5
18
  - `fixos quick`: ograniczona czasowo analiza heurystyczna bez LLM, która od razu
6
19
  pokazuje presję CPU/RAM/dysku i maksymalny rozmiar jawnie odtwarzalnych cache.
7
20
  - Lokalna historia szybkich próbek z porównaniem ostatnich godzin i bieżącego
@@ -14,6 +27,9 @@
14
27
 
15
28
  ### Changed
16
29
 
30
+ - Dokumentacja README / getting-started / architecture opisuje model trzech
31
+ poziomów ryzyka z nowymi flagami `--docker-old` / `--ollama-old` i różnicą
32
+ między reclaimable a filtrem wieku.
17
33
  - Zakończone elementy historycznych roadmap zostały przeniesione z TODO do
18
34
  changelogu: modułowy pakiet CLI, klasowe sesje HITL, wspólny
19
35
  `SessionTimeout`, plugin registry, structured output LLM, rollback, profile
@@ -24,6 +40,9 @@
24
40
 
25
41
  ### Fixed
26
42
 
43
+ - Szacunek Dockera w opcji `[1]` nie obiecuje już całej puli RECLAIMABLE przy
44
+ filtrze `until=30d` (świeże unused images nie były kasowane, a UI pokazywało
45
+ 0.00 GB).
27
46
  - Zablokowano zbiorcze kasowanie chronionych danych LM Studio, Hugging Face,
28
47
  Podman/containerd, Jupyter, Minikube, AppImage, VirtualBox, VMware oraz
29
48
  rozszerzeń VS Code/Cursor. Takie wpisy pokazują teraz wyłącznie bezpieczny
@@ -51,6 +70,39 @@
51
70
  rekurencyjnych skanów `/` oraz `/home` z szybkich kontroli.
52
71
  - Czyszczenie cache JetBrains trafia w aktualną ścieżkę i wymaga zamknięcia IDE.
53
72
 
73
+ ## [2.2.46] - 2026-08-07
74
+
75
+ ### Docs
76
+ - Update CHANGELOG.md
77
+ - Update README.md
78
+ - Update docs/architecture.md
79
+ - Update docs/getting-started.md
80
+
81
+ ### Test
82
+ - Update tests/unit/test_service_cleanup.py
83
+
84
+ ### Other
85
+ - Update fixos/cli/cleanup_cmd.py
86
+ - Update fixos/diagnostics/service_cleanup.py
87
+ - Update project/planfile-tickets.yaml
88
+
89
+ ## [2.2.45] - 2026-08-07
90
+
91
+ ### Docs
92
+ - Update README.md
93
+
94
+ ### Test
95
+ - Update tests/unit/test_cleanup_cmd.py
96
+ - Update tests/unit/test_service_cleanup.py
97
+
98
+ ### Other
99
+ - Update VERSION
100
+ - Update fixos/__init__.py
101
+ - Update fixos/cli/cleanup_cmd.py
102
+ - Update fixos/cli/main.py
103
+ - Update fixos/diagnostics/service_cleanup.py
104
+ - Update uv.lock
105
+
54
106
  ## [2.2.41] - 2026-07-23
55
107
 
56
108
  ### Docs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fixos
3
- Version: 2.2.41
3
+ Version: 2.2.46
4
4
  Summary: AI-powered Linux/Windows diagnostics and repair – audio, hardware, system issues
5
5
  Home-page: https://github.com/wronai/fixos
6
6
  Author: fixos contributors
@@ -63,13 +63,13 @@ AI-powered OS Diagnostics
63
63
 
64
64
  ## AI Cost Tracking
65
65
 
66
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-2.2.41-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
67
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$4.87-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-39.1h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
66
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-2.2.46-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
67
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$4.84-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-40.6h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
68
68
 
69
- - 🤖 **LLM usage:** $4.8653 (149 commits)
70
- - 👤 **Human dev:** ~$3913 (39.1h @ $100/h, 30min dedup)
69
+ - 🤖 **LLM usage:** $4.8388 (151 commits)
70
+ - 👤 **Human dev:** ~$4059 (40.6h @ $100/h, 30min dedup)
71
71
 
72
- Generated on 2026-07-23 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
72
+ Generated on 2026-08-07 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
73
73
 
74
74
  ---
75
75
 
@@ -118,6 +118,8 @@ fixos quick --deep – szybki wynik, potem pełny skan danych usług
118
118
  fixos fix – diagnoza + sesja naprawcza z AI (HITL)
119
119
  fixos scan – diagnostyka systemu bez AI
120
120
  fixos cleanup – skanuj i czyść dane usług (Docker, npm, pip, ...)
121
+ fixos cleanup --docker-old – nieużywane obrazy Docker starsze niż N dni (--days)
122
+ fixos cleanup --ollama-old – modele Ollama niezmieniane od N dni (domyślnie 90)
121
123
  fixos cleanup --full – pełny audit systemu + dev projects
122
124
  fixos projects – skanuj projekty dev (venv, node_modules, ~/github/*/*)
123
125
  fixos orchestrate – zaawansowana orkiestracja (graf problemów DAG)
@@ -153,6 +155,17 @@ fixos fix --disc
153
155
  # Pełny audit systemu (DNF, Docker, Flatpak, dev projects)
154
156
  fixos cleanup --full --dry-run
155
157
 
158
+ # Podgląd usług + interaktywne czyszczenie (opcja [1] = wszystkie bezpieczne)
159
+ fixos cleanup --list
160
+ fixos cleanup --dry-run # tylko gdy -c / --docker-old / --ollama-old
161
+ fixos cleanup
162
+
163
+ # Nieużywane obrazy Docker starsze niż 30 dni (filtr wieku; może zwolnić mniej niż RECLAIMABLE)
164
+ fixos cleanup --docker-old --days 30 --dry-run
165
+
166
+ # Modele Ollama niezmieniane od 90+ dni (pomija uruchomione)
167
+ fixos cleanup --ollama-old --days 90 --dry-run
168
+
156
169
  # Usuń tylko foldery venv z projektów
157
170
  fixos cleanup --full
158
171
  > type:venv
@@ -259,20 +272,38 @@ Tryb DRY-RUN - żadne akcje nie zostaną wykonane
259
272
 
260
273
  Każda znaleziona usługa jest klasyfikowana do jednej z trzech grup:
261
274
 
262
- - **bezpieczne** – cache do odtworzenia jednym poleceniem (pip/npm/cargo/conda/nix/brew...).
263
- Tylko tę grupę można usunąć automatycznie opcją „wszystkie”.
275
+ - **bezpieczne** – cache do odtworzenia jednym poleceniem (pip/npm/cargo/conda/nix/brew...)
276
+ oraz ograniczone, jawnie bezpieczne akcje wiekowe / reclaimable:
277
+ - **Docker (nieużywane obrazy)** — wszystkie unused images + build cache
278
+ (bez wolumenów, bez obrazów podpiętych do kontenerów); odpowiada puli
279
+ `RECLAIMABLE` Images+Build Cache,
280
+ - **Ollama (modele >90 dni)** — modele niezmieniane od 90+ dni; pomija
281
+ modele aktualnie załadowane w pamięci.
282
+ Tylko tę grupę usuwa opcja **[1] Wszystkie bezpieczne**.
264
283
  - **do rozważenia** – reinstalowalne aplikacje, dane długo nieużywane, nierozpoznane
265
284
  foldery (JetBrains, Snap, Flatpak) – pokazywane z komendą i wymagają
266
285
  osobnego, świadomego potwierdzenia.
267
286
  - **chronione lub mieszane** – realne dane aplikacji albo magazyny łączące dane aktywne
268
- z cache (Ollama, LM Studio, HuggingFace hub, Docker/Podman/containerd, cała biblioteka
269
- Steam, `.cursor/extensions`/`.vscode/extensions`
270
- – zainstalowane rozszerzenia edytora, nie ich cache). Osobna sekcja z ostrzeżeniem;
271
- zbiorcze kasowanie modeli, klastrów, maszyn wirtualnych, rozszerzeń i
272
- wolumenów jest wyłączone. Docker pokazuje osobno `SIZE` i `RECLAIMABLE`;
273
- domyślne czyszczenie ogranicza się do starego cache buildów. Raportowane
274
- `RECLAIMABLE` jest górną informacją z Dockera — filtr starszy niż 7 dni może
275
- faktycznie zwolnić znacznie mniej.
287
+ z cache (cały sklep Ollama/LM Studio/HuggingFace, cały Docker z wolumenami,
288
+ Steam, `.cursor/extensions`/`.vscode/extensions`). Osobna sekcja z ostrzeżeniem;
289
+ zbiorcze kasowanie modeli „na ślepo”, klastrów, maszyn wirtualnych, rozszerzeń i
290
+ wolumenów jest wyłączone.
291
+
292
+ Dedykowane flagi (też dostępne jako `-c docker-old` / `-c ollama-old`):
293
+
294
+ ```bash
295
+ fixos cleanup --docker-old --days 30 --dry-run # tylko unused starsze niż N dni
296
+ fixos cleanup --ollama-old --days 90 --dry-run # modele niezmieniane od N dni
297
+ ```
298
+
299
+ `RECLAIMABLE` Dockera obejmuje też świeże unused images. Filtr `--docker-old`
300
+ (domyślnie 30 dni) może więc zwolnić **znacznie mniej** niż szacunek całej puli —
301
+ dlatego opcja `[1]` używa prune **wszystkich** nieużywanych obrazów, a
302
+ `--docker-old` zostaje dla świadomego cięcia po wieku. Domyślne
303
+ `fixos cleanup -c docker` nadal ogranicza się do cache buildów >7 dni.
304
+
305
+ Po wykonaniu opcji `[1]` listy „do rozważenia / chronione” pochodzą ze skanu
306
+ sprzed czyszczenia — uruchom ponownie `fixos cleanup --list`, by zobaczyć stan.
276
307
 
277
308
  Opcja „Wybierz pojedyncze” przechodzi kolejno przez wszystkie znalezione
278
309
  usługi w tych trzech grupach. Dla pozycji bez bezpiecznej operacji zbiorczej
@@ -19,13 +19,13 @@ AI-powered OS Diagnostics
19
19
 
20
20
  ## AI Cost Tracking
21
21
 
22
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-2.2.41-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
23
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$4.87-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-39.1h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
22
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-2.2.46-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
23
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$4.84-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-40.6h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
24
24
 
25
- - 🤖 **LLM usage:** $4.8653 (149 commits)
26
- - 👤 **Human dev:** ~$3913 (39.1h @ $100/h, 30min dedup)
25
+ - 🤖 **LLM usage:** $4.8388 (151 commits)
26
+ - 👤 **Human dev:** ~$4059 (40.6h @ $100/h, 30min dedup)
27
27
 
28
- Generated on 2026-07-23 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
28
+ Generated on 2026-08-07 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
29
29
 
30
30
  ---
31
31
 
@@ -74,6 +74,8 @@ fixos quick --deep – szybki wynik, potem pełny skan danych usług
74
74
  fixos fix – diagnoza + sesja naprawcza z AI (HITL)
75
75
  fixos scan – diagnostyka systemu bez AI
76
76
  fixos cleanup – skanuj i czyść dane usług (Docker, npm, pip, ...)
77
+ fixos cleanup --docker-old – nieużywane obrazy Docker starsze niż N dni (--days)
78
+ fixos cleanup --ollama-old – modele Ollama niezmieniane od N dni (domyślnie 90)
77
79
  fixos cleanup --full – pełny audit systemu + dev projects
78
80
  fixos projects – skanuj projekty dev (venv, node_modules, ~/github/*/*)
79
81
  fixos orchestrate – zaawansowana orkiestracja (graf problemów DAG)
@@ -109,6 +111,17 @@ fixos fix --disc
109
111
  # Pełny audit systemu (DNF, Docker, Flatpak, dev projects)
110
112
  fixos cleanup --full --dry-run
111
113
 
114
+ # Podgląd usług + interaktywne czyszczenie (opcja [1] = wszystkie bezpieczne)
115
+ fixos cleanup --list
116
+ fixos cleanup --dry-run # tylko gdy -c / --docker-old / --ollama-old
117
+ fixos cleanup
118
+
119
+ # Nieużywane obrazy Docker starsze niż 30 dni (filtr wieku; może zwolnić mniej niż RECLAIMABLE)
120
+ fixos cleanup --docker-old --days 30 --dry-run
121
+
122
+ # Modele Ollama niezmieniane od 90+ dni (pomija uruchomione)
123
+ fixos cleanup --ollama-old --days 90 --dry-run
124
+
112
125
  # Usuń tylko foldery venv z projektów
113
126
  fixos cleanup --full
114
127
  > type:venv
@@ -215,20 +228,38 @@ Tryb DRY-RUN - żadne akcje nie zostaną wykonane
215
228
 
216
229
  Każda znaleziona usługa jest klasyfikowana do jednej z trzech grup:
217
230
 
218
- - **bezpieczne** – cache do odtworzenia jednym poleceniem (pip/npm/cargo/conda/nix/brew...).
219
- Tylko tę grupę można usunąć automatycznie opcją „wszystkie”.
231
+ - **bezpieczne** – cache do odtworzenia jednym poleceniem (pip/npm/cargo/conda/nix/brew...)
232
+ oraz ograniczone, jawnie bezpieczne akcje wiekowe / reclaimable:
233
+ - **Docker (nieużywane obrazy)** — wszystkie unused images + build cache
234
+ (bez wolumenów, bez obrazów podpiętych do kontenerów); odpowiada puli
235
+ `RECLAIMABLE` Images+Build Cache,
236
+ - **Ollama (modele >90 dni)** — modele niezmieniane od 90+ dni; pomija
237
+ modele aktualnie załadowane w pamięci.
238
+ Tylko tę grupę usuwa opcja **[1] Wszystkie bezpieczne**.
220
239
  - **do rozważenia** – reinstalowalne aplikacje, dane długo nieużywane, nierozpoznane
221
240
  foldery (JetBrains, Snap, Flatpak) – pokazywane z komendą i wymagają
222
241
  osobnego, świadomego potwierdzenia.
223
242
  - **chronione lub mieszane** – realne dane aplikacji albo magazyny łączące dane aktywne
224
- z cache (Ollama, LM Studio, HuggingFace hub, Docker/Podman/containerd, cała biblioteka
225
- Steam, `.cursor/extensions`/`.vscode/extensions`
226
- – zainstalowane rozszerzenia edytora, nie ich cache). Osobna sekcja z ostrzeżeniem;
227
- zbiorcze kasowanie modeli, klastrów, maszyn wirtualnych, rozszerzeń i
228
- wolumenów jest wyłączone. Docker pokazuje osobno `SIZE` i `RECLAIMABLE`;
229
- domyślne czyszczenie ogranicza się do starego cache buildów. Raportowane
230
- `RECLAIMABLE` jest górną informacją z Dockera — filtr starszy niż 7 dni może
231
- faktycznie zwolnić znacznie mniej.
243
+ z cache (cały sklep Ollama/LM Studio/HuggingFace, cały Docker z wolumenami,
244
+ Steam, `.cursor/extensions`/`.vscode/extensions`). Osobna sekcja z ostrzeżeniem;
245
+ zbiorcze kasowanie modeli „na ślepo”, klastrów, maszyn wirtualnych, rozszerzeń i
246
+ wolumenów jest wyłączone.
247
+
248
+ Dedykowane flagi (też dostępne jako `-c docker-old` / `-c ollama-old`):
249
+
250
+ ```bash
251
+ fixos cleanup --docker-old --days 30 --dry-run # tylko unused starsze niż N dni
252
+ fixos cleanup --ollama-old --days 90 --dry-run # modele niezmieniane od N dni
253
+ ```
254
+
255
+ `RECLAIMABLE` Dockera obejmuje też świeże unused images. Filtr `--docker-old`
256
+ (domyślnie 30 dni) może więc zwolnić **znacznie mniej** niż szacunek całej puli —
257
+ dlatego opcja `[1]` używa prune **wszystkich** nieużywanych obrazów, a
258
+ `--docker-old` zostaje dla świadomego cięcia po wieku. Domyślne
259
+ `fixos cleanup -c docker` nadal ogranicza się do cache buildów >7 dni.
260
+
261
+ Po wykonaniu opcji `[1]` listy „do rozważenia / chronione” pochodzą ze skanu
262
+ sprzed czyszczenia — uruchom ponownie `fixos cleanup --list`, by zobaczyć stan.
232
263
 
233
264
  Opcja „Wybierz pojedyncze” przechodzi kolejno przez wszystkie znalezione
234
265
  usługi w tych trzech grupach. Dla pozycji bez bezpiecznej operacji zbiorczej
@@ -1,3 +1,3 @@
1
1
  """fixos – AI-powered Linux/Windows diagnostics and repair."""
2
2
 
3
- __version__ = "2.2.41"
3
+ __version__ = "2.2.46"
@@ -17,6 +17,11 @@ from fixos.constants import DEFAULT_CLEANUP_THRESHOLD_MB
17
17
  # Re-export public symbols used by fixos.cli (backward-compat)
18
18
  from fixos.cli._cleanup_flatpak import _cleanup_flatpak_detailed # noqa: F401
19
19
  from fixos.cli._cleanup_system import _cleanup_full_system
20
+ from fixos.diagnostics.service_cleanup import (
21
+ DEFAULT_DOCKER_OLD_UNUSED_DAYS,
22
+ DEFAULT_OLLAMA_OLD_UNUSED_DAYS,
23
+ ServiceCleaner,
24
+ )
20
25
 
21
26
 
22
27
  # ── Service display helpers ───────────────────────────────────────────────
@@ -129,21 +134,53 @@ def _error_message(result: dict) -> str:
129
134
  return "nieznany błąd"
130
135
 
131
136
 
137
+ def _execute_planned_cleanup(scanner, svc: dict, *, dry_run: bool = False) -> dict:
138
+ """Run a planned cleanup entry (including age-bounded docker/ollama actions)."""
139
+ kind = svc.get("cleanup_kind")
140
+ cleaner = ServiceCleaner(scanner)
141
+ if kind == "ollama-old":
142
+ return cleaner.cleanup_ollama_old_unused(
143
+ days=int(svc.get("days") or DEFAULT_OLLAMA_OLD_UNUSED_DAYS),
144
+ dry_run=dry_run,
145
+ )
146
+ if kind == "docker-unused":
147
+ return cleaner.cleanup_docker_unused(dry_run=dry_run)
148
+ if kind == "docker-old":
149
+ return cleaner.cleanup_docker_old_unused(
150
+ days=int(svc.get("days") or DEFAULT_DOCKER_OLD_UNUSED_DAYS),
151
+ dry_run=dry_run,
152
+ )
153
+ return scanner.cleanup_service(
154
+ svc["service_type"],
155
+ dry_run=dry_run,
156
+ planned_service=svc,
157
+ )
158
+
159
+
132
160
  def _execute_safe_cleanup(services: list, scanner) -> float:
133
161
  """Execute cleanup for safe-to-remove services. Returns total space freed in GB."""
134
162
  total_freed = 0.0
135
163
  for svc in services:
136
- svc_type = svc["service_type"]
137
- click.echo(f"Czyszczenie {svc_type}...")
138
- result = scanner.cleanup_service(
139
- svc_type,
140
- dry_run=False,
141
- planned_service=svc,
142
- )
164
+ click.echo(f"Czyszczenie {svc.get('name') or svc['service_type']}...")
165
+ result = _execute_planned_cleanup(scanner, svc, dry_run=False)
143
166
  if result["success"]:
144
- freed = result.get("space_freed_gb", 0)
167
+ freed = float(result.get("space_freed_gb", 0) or 0)
145
168
  total_freed += freed
146
- click.echo(click.style(f" Zwolniono {freed:.2f} GB", fg="green"))
169
+ if freed > 0:
170
+ click.echo(click.style(f" Zwolniono {freed:.2f} GB", fg="green"))
171
+ else:
172
+ click.echo(
173
+ click.style(
174
+ " Brak mierzalnej zmiany rozmiaru (0.00 GB) — "
175
+ "komenda zakończyła się OK, ale cache mógł być już pusty "
176
+ "albo filtr wieku nic nie trafił.",
177
+ fg="yellow",
178
+ )
179
+ )
180
+ note = (result.get("output") or result.get("error") or "").strip()
181
+ if note:
182
+ for line in note.splitlines()[:4]:
183
+ click.echo(f" {line}")
147
184
  else:
148
185
  click.echo(click.style(f" Błąd: {_error_message(result)}", fg="red"))
149
186
  return total_freed
@@ -441,6 +478,112 @@ def _cleanup_single_service(
441
478
  click.echo(f"Output: {result['output']}")
442
479
 
443
480
 
481
+ def _cleanup_docker_old_unused(
482
+ scanner, days: int, json_output: bool, dry_run: bool
483
+ ) -> None:
484
+ """Prune unused Docker images (and old build cache) older than N days."""
485
+ cleaner = ServiceCleaner(scanner)
486
+ try:
487
+ result = cleaner.cleanup_docker_old_unused(days=days, dry_run=dry_run)
488
+ except ValueError as exc:
489
+ click.echo(click.style(f"Błąd: {exc}", fg="red"))
490
+ return
491
+
492
+ if json_output:
493
+ import json
494
+
495
+ click.echo(json.dumps(result, indent=2, default=str))
496
+ return
497
+
498
+ click.echo(
499
+ click.style(
500
+ f"Docker — nieużywane obrazy starsze niż {days} dni",
501
+ fg="yellow",
502
+ )
503
+ )
504
+ click.echo(f" Komenda: {result.get('command')}")
505
+ if dry_run:
506
+ click.echo(click.style("[TRYB DRY-RUN] - brak faktycznych zmian", fg="cyan"))
507
+
508
+ if result.get("success"):
509
+ if dry_run:
510
+ click.echo(click.style("Symulacja zakończona", fg="green"))
511
+ if result.get("output"):
512
+ for line in str(result["output"]).splitlines():
513
+ click.echo(f" {line}")
514
+ if result.get("estimated_max_gb", 0) > 0:
515
+ click.echo(
516
+ f" Szacowane maksimum (Images+Build Cache reclaimable): "
517
+ f"{result['estimated_max_gb']:.2f} GB "
518
+ f"(filtr until zwykle usunie mniej)"
519
+ )
520
+ else:
521
+ click.echo(click.style("Zakończono czyszczenie docker-old", fg="green"))
522
+ if result.get("space_freed_gb", 0) > 0:
523
+ click.echo(f" Zwolniono: {result['space_freed_gb']:.2f} GB")
524
+ elif result.get("output"):
525
+ click.echo(f" {result['output'].strip()[:500]}")
526
+ else:
527
+ click.echo(click.style(f"Błąd: {_error_message(result)}", fg="red"))
528
+ if result.get("output"):
529
+ click.echo(f"Output: {result['output']}")
530
+
531
+
532
+ def _cleanup_ollama_old_unused(
533
+ scanner, days: int, json_output: bool, dry_run: bool
534
+ ) -> None:
535
+ """Remove Ollama models not modified for more than N days."""
536
+ cleaner = ServiceCleaner(scanner)
537
+ try:
538
+ result = cleaner.cleanup_ollama_old_unused(days=days, dry_run=dry_run)
539
+ except ValueError as exc:
540
+ click.echo(click.style(f"Błąd: {exc}", fg="red"))
541
+ return
542
+
543
+ if json_output:
544
+ import json
545
+
546
+ click.echo(json.dumps(result, indent=2, default=str))
547
+ return
548
+
549
+ click.echo(
550
+ click.style(
551
+ f"Ollama — modele niezmieniane od {days}+ dni",
552
+ fg="yellow",
553
+ )
554
+ )
555
+ if result.get("command"):
556
+ click.echo(f" Komenda: {result['command']}")
557
+ if dry_run:
558
+ click.echo(click.style("[TRYB DRY-RUN] - brak faktycznych zmian", fg="cyan"))
559
+
560
+ if result.get("success"):
561
+ if dry_run:
562
+ click.echo(click.style("Symulacja zakończona", fg="green"))
563
+ if result.get("output"):
564
+ for line in str(result["output"]).splitlines():
565
+ click.echo(f" {line}")
566
+ if result.get("estimated_max_gb", 0) > 0:
567
+ click.echo(
568
+ f" Szacowane zwolnienie: {result['estimated_max_gb']:.2f} GB"
569
+ )
570
+ if result.get("skipped_running"):
571
+ click.echo(
572
+ " Pominięto uruchomione: "
573
+ + ", ".join(result["skipped_running"])
574
+ )
575
+ else:
576
+ click.echo(click.style("Zakończono czyszczenie ollama-old", fg="green"))
577
+ if result.get("space_freed_gb", 0) > 0:
578
+ click.echo(f" Zwolniono: {result['space_freed_gb']:.2f} GB")
579
+ if result.get("output"):
580
+ click.echo(f" {result['output'].strip()[:500]}")
581
+ else:
582
+ click.echo(click.style(f"Błąd: {_error_message(result)}", fg="red"))
583
+ if result.get("output"):
584
+ click.echo(f"Output: {result['output']}")
585
+
586
+
444
587
  # ── Interactive cleanup orchestration ─────────────────────────────────────
445
588
 
446
589
 
@@ -540,11 +683,7 @@ def _execute_individual_cleanup(services: list, scanner) -> float:
540
683
  continue
541
684
 
542
685
  click.echo(f"Czyszczenie {svc['name']}...")
543
- result = scanner.cleanup_service(
544
- svc["service_type"],
545
- dry_run=False,
546
- planned_service=svc,
547
- )
686
+ result = _execute_planned_cleanup(scanner, svc, dry_run=False)
548
687
  if result["success"]:
549
688
  freed = float(result.get("space_freed_gb", 0))
550
689
  total_freed += freed
@@ -570,6 +709,14 @@ def _run_interactive_cleanup(plan: dict, list_only: bool, scanner) -> None:
570
709
  return
571
710
  if selected:
572
711
  _execute_safe_cleanup(selected, scanner)
712
+ click.echo()
713
+ click.echo(
714
+ click.style(
715
+ "Uwaga: listy poniżej pochodzą ze skanu sprzed czyszczenia — "
716
+ "uruchom ponownie `fixos cleanup --list`, by zobaczyć aktualny stan.",
717
+ fg="cyan",
718
+ )
719
+ )
573
720
  elif mode == "none":
574
721
  click.echo(click.style("Pominięto czyszczenie.", fg="yellow"))
575
722
  if plan["requires_review"] and not list_only:
@@ -602,7 +749,37 @@ def _run_interactive_cleanup(plan: dict, list_only: bool, scanner) -> None:
602
749
  "--cleanup",
603
750
  "-c",
604
751
  default=None,
605
- help="Wyczyść konkretną usługę (docker, ollama, npm, ...)",
752
+ help="Wyczyść konkretną usługę (docker, docker-old, ollama-old, ollama, npm, ...)",
753
+ )
754
+ @click.option(
755
+ "--docker-old",
756
+ "docker_old",
757
+ is_flag=True,
758
+ default=False,
759
+ help=(
760
+ "Usuń nieużywane obrazy Docker (i stary build cache) starsze niż --days "
761
+ f"(domyślnie {DEFAULT_DOCKER_OLD_UNUSED_DAYS}); nie rusza wolumenów ani obrazów w użyciu"
762
+ ),
763
+ )
764
+ @click.option(
765
+ "--ollama-old",
766
+ "ollama_old",
767
+ is_flag=True,
768
+ default=False,
769
+ help=(
770
+ "Usuń modele Ollama niezmieniane od --days dni "
771
+ f"(domyślnie {DEFAULT_OLLAMA_OLD_UNUSED_DAYS}); pomija modele aktualnie uruchomione"
772
+ ),
773
+ )
774
+ @click.option(
775
+ "--days",
776
+ default=None,
777
+ type=int,
778
+ help=(
779
+ "Wiek w dniach dla --docker-old "
780
+ f"(domyślnie {DEFAULT_DOCKER_OLD_UNUSED_DAYS}) lub --ollama-old "
781
+ f"(domyślnie {DEFAULT_OLLAMA_OLD_UNUSED_DAYS})"
782
+ ),
606
783
  )
607
784
  @click.option(
608
785
  "--dry-run",
@@ -626,7 +803,16 @@ def _run_interactive_cleanup(plan: dict, list_only: bool, scanner) -> None:
626
803
  help="Pełna analiza systemu (DNF, kernels, logs, Docker, cache)",
627
804
  )
628
805
  def cleanup_services(
629
- threshold, services, json_output, cleanup, dry_run, list_only, full_analysis
806
+ threshold,
807
+ services,
808
+ json_output,
809
+ cleanup,
810
+ docker_old,
811
+ ollama_old,
812
+ days,
813
+ dry_run,
814
+ list_only,
815
+ full_analysis,
630
816
  ) -> None:
631
817
  """
632
818
  Skanuje i czyści dane usług przekraczające próg.
@@ -643,7 +829,12 @@ def cleanup_services(
643
829
  fixos cleanup -t 1000 # próg 1000MB (1GB)
644
830
  fixos cleanup -s docker,ollama # tylko Docker i Ollama
645
831
  fixos cleanup --list # tylko lista, bez czyszczenia
646
- fixos cleanup -c docker --dry-run # symulacja czyszczenia Dockera
832
+ fixos cleanup -c docker --dry-run # tylko cache buildów >7 dni
833
+ fixos cleanup --docker-old --days 30 --dry-run
834
+ # nieużywane obrazy (+ cache) starsze niż 30 dni
835
+ fixos cleanup --ollama-old --days 90 --dry-run
836
+ # modele Ollama niezmieniane od 90+ dni
837
+ fixos cleanup -c ollama-old
647
838
  fixos cleanup --full # pełna analiza systemu
648
839
  """
649
840
  if full_analysis:
@@ -652,6 +843,29 @@ def cleanup_services(
652
843
 
653
844
  scanner = ServiceDataScanner(threshold_mb=threshold)
654
845
 
846
+ want_docker_old = docker_old or (cleanup == "docker-old")
847
+ want_ollama_old = ollama_old or (cleanup == "ollama-old")
848
+ if want_docker_old and want_ollama_old:
849
+ click.echo(
850
+ click.style(
851
+ "Wybierz jedno: --docker-old albo --ollama-old (nie oba naraz).",
852
+ fg="red",
853
+ )
854
+ )
855
+ return
856
+ if want_docker_old:
857
+ effective_days = (
858
+ days if days is not None else DEFAULT_DOCKER_OLD_UNUSED_DAYS
859
+ )
860
+ _cleanup_docker_old_unused(scanner, effective_days, json_output, dry_run)
861
+ return
862
+ if want_ollama_old:
863
+ effective_days = (
864
+ days if days is not None else DEFAULT_OLLAMA_OLD_UNUSED_DAYS
865
+ )
866
+ _cleanup_ollama_old_unused(scanner, effective_days, json_output, dry_run)
867
+ return
868
+
655
869
  if cleanup:
656
870
  if cleanup == "flatpak":
657
871
  _cleanup_flatpak_detailed(scanner, json_output, dry_run)
@@ -72,6 +72,16 @@ def _print_welcome() -> None:
72
72
  ("fixos scan", "", "Diagnostyka systemu bez AI"),
73
73
  ("fixos quickfix", "", "Naprawy offline bez API (baza znanych bugów)"),
74
74
  ("fixos cleanup", "", "Skanuj i czyść dane usług (Docker, Ollama)"),
75
+ (
76
+ "fixos cleanup --docker-old",
77
+ "",
78
+ "Usuń nieużywane obrazy Docker starsze niż 30 dni",
79
+ ),
80
+ (
81
+ "fixos cleanup --ollama-old",
82
+ "",
83
+ "Usuń modele Ollama niezmieniane od 90+ dni",
84
+ ),
75
85
  (
76
86
  "fixos projects",
77
87
  "",
@@ -90,7 +100,7 @@ def _print_welcome() -> None:
90
100
  ]
91
101
 
92
102
  for cmd, icon, desc in commands:
93
- cmd_styled = click.style(f"{cmd:<26}", fg="yellow")
103
+ cmd_styled = click.style(f"{cmd:<32}", fg="yellow")
94
104
  click.echo(f" {icon} {cmd_styled} {desc}")
95
105
 
96
106
  click.echo()
@@ -142,6 +152,12 @@ def _print_welcome() -> None:
142
152
  click.echo(
143
153
  f"{click.style(' fixos fix', fg='yellow')} # pełna diagnostyka + naprawa"
144
154
  )
155
+ click.echo(
156
+ f"{click.style(' fixos cleanup --docker-old --dry-run', fg='yellow')} # stare nieużywane obrazy Docker"
157
+ )
158
+ click.echo(
159
+ f"{click.style(' fixos cleanup --ollama-old --dry-run', fg='yellow')} # stare modele Ollama (90+ dni)"
160
+ )
145
161
  click.echo(
146
162
  f"{click.style(' fixos fix --modules security,resources', fg='yellow')} # bezpieczeństwo + zasoby"
147
163
  )