fixos 2.2.37__tar.gz → 2.2.38__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 (171) hide show
  1. {fixos-2.2.37 → fixos-2.2.38}/CHANGELOG.md +23 -0
  2. {fixos-2.2.37 → fixos-2.2.38}/PKG-INFO +91 -6
  3. {fixos-2.2.37 → fixos-2.2.38}/README.md +90 -5
  4. {fixos-2.2.37 → fixos-2.2.38}/fixos/__init__.py +1 -1
  5. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/cleanup_cmd.py +78 -24
  6. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/fix_cmd.py +5 -1
  7. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/main.py +3 -0
  8. fixos-2.2.38/fixos/cli/projects_cmd.py +346 -0
  9. {fixos-2.2.37 → fixos-2.2.38}/fixos/config.py +12 -1
  10. {fixos-2.2.37 → fixos-2.2.38}/fixos/constants.py +6 -0
  11. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/checks/resources.py +8 -6
  12. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/checks/security.py +3 -1
  13. fixos-2.2.38/fixos/diagnostics/project_scanner.py +258 -0
  14. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/service_cleanup.py +76 -13
  15. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/service_scanner.py +107 -15
  16. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/system_checks.py +40 -8
  17. {fixos-2.2.37 → fixos-2.2.38}/fixos/providers/llm.py +95 -12
  18. {fixos-2.2.37 → fixos-2.2.38}/fixos.egg-info/PKG-INFO +91 -6
  19. {fixos-2.2.37 → fixos-2.2.38}/fixos.egg-info/SOURCES.txt +9 -1
  20. {fixos-2.2.37 → fixos-2.2.38}/fixos.egg-info/top_level.txt +1 -0
  21. {fixos-2.2.37 → fixos-2.2.38}/pyproject.toml +1 -1
  22. {fixos-2.2.37 → fixos-2.2.38}/setup.py +1 -1
  23. fixos-2.2.38/tests/unit/test_llm_provider.py +144 -0
  24. fixos-2.2.38/tests/unit/test_project_scanner.py +273 -0
  25. fixos-2.2.38/tests/unit/test_projects_cmd.py +174 -0
  26. fixos-2.2.38/tests/unit/test_resources_quick.py +21 -0
  27. fixos-2.2.38/tests/unit/test_security_quick.py +23 -0
  28. {fixos-2.2.37 → fixos-2.2.38}/tests/unit/test_service_cleanup.py +121 -0
  29. {fixos-2.2.37 → fixos-2.2.38}/tests/unit/test_service_scanner.py +43 -0
  30. fixos-2.2.38/tests/unit/test_system_checks_parallel.py +54 -0
  31. {fixos-2.2.37 → fixos-2.2.38}/.env.example +0 -0
  32. {fixos-2.2.37 → fixos-2.2.38}/LICENSE +0 -0
  33. {fixos-2.2.37 → fixos-2.2.38}/MANIFEST.in +0 -0
  34. {fixos-2.2.37 → fixos-2.2.38}/docker/README.md +0 -0
  35. {fixos-2.2.37 → fixos-2.2.38}/docker/TEST_RESULTS.md +0 -0
  36. {fixos-2.2.37 → fixos-2.2.38}/docker/TEST_RESULTS_V2.md +0 -0
  37. {fixos-2.2.37 → fixos-2.2.38}/docker/alpine/Dockerfile +0 -0
  38. {fixos-2.2.37 → fixos-2.2.38}/docker/arch/Dockerfile +0 -0
  39. {fixos-2.2.37 → fixos-2.2.38}/docker/base/Dockerfile +0 -0
  40. {fixos-2.2.37 → fixos-2.2.38}/docker/broken-audio/Dockerfile +0 -0
  41. {fixos-2.2.37 → fixos-2.2.38}/docker/broken-full/Dockerfile +0 -0
  42. {fixos-2.2.37 → fixos-2.2.38}/docker/broken-network/Dockerfile +0 -0
  43. {fixos-2.2.37 → fixos-2.2.38}/docker/broken-thumbnails/Dockerfile +0 -0
  44. {fixos-2.2.37 → fixos-2.2.38}/docker/debian/Dockerfile +0 -0
  45. {fixos-2.2.37 → fixos-2.2.38}/docker/docker-compose.multi-system.yml +0 -0
  46. {fixos-2.2.37 → fixos-2.2.38}/docker/docker-compose.yml +0 -0
  47. {fixos-2.2.37 → fixos-2.2.38}/docker/fedora/Dockerfile +0 -0
  48. {fixos-2.2.37 → fixos-2.2.38}/docker/test-multi-system.sh +0 -0
  49. {fixos-2.2.37 → fixos-2.2.38}/docker/test-scenarios.sh +0 -0
  50. {fixos-2.2.37 → fixos-2.2.38}/docker/ubuntu/Dockerfile +0 -0
  51. {fixos-2.2.37 → fixos-2.2.38}/docker/validate-scenario.py +0 -0
  52. {fixos-2.2.37 → fixos-2.2.38}/docs/examples/advanced_usage.py +0 -0
  53. {fixos-2.2.37 → fixos-2.2.38}/docs/examples/quickstart.py +0 -0
  54. {fixos-2.2.37 → fixos-2.2.38}/fixos/agent/__init__.py +0 -0
  55. {fixos-2.2.37 → fixos-2.2.38}/fixos/agent/autonomous.py +0 -0
  56. {fixos-2.2.37 → fixos-2.2.38}/fixos/agent/autonomous_session.py +0 -0
  57. {fixos-2.2.37 → fixos-2.2.38}/fixos/agent/hitl.py +0 -0
  58. {fixos-2.2.37 → fixos-2.2.38}/fixos/agent/hitl_session.py +0 -0
  59. {fixos-2.2.37 → fixos-2.2.38}/fixos/agent/session_core.py +0 -0
  60. {fixos-2.2.37 → fixos-2.2.38}/fixos/agent/session_handlers.py +0 -0
  61. {fixos-2.2.37 → fixos-2.2.38}/fixos/agent/session_io.py +0 -0
  62. {fixos-2.2.37 → fixos-2.2.38}/fixos/anonymizer.py +0 -0
  63. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/__init__.py +0 -0
  64. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/_cleanup_flatpak.py +0 -0
  65. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/_cleanup_home.py +0 -0
  66. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/_cleanup_snap.py +0 -0
  67. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/_cleanup_system.py +0 -0
  68. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/_cleanup_utils.py +0 -0
  69. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/ask_cmd.py +0 -0
  70. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/config_cmd.py +0 -0
  71. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/features_cmd.py +0 -0
  72. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/history_cmd.py +0 -0
  73. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/orchestrate_cmd.py +0 -0
  74. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/output_formatter.py +0 -0
  75. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/profile_cmd.py +0 -0
  76. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/provider_cmd.py +0 -0
  77. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/quickfix_cmd.py +0 -0
  78. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/report_cmd.py +0 -0
  79. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/rollback_cmd.py +0 -0
  80. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/scan_cmd.py +0 -0
  81. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/shared.py +0 -0
  82. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/token_cmd.py +0 -0
  83. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli/watch_cmd.py +0 -0
  84. {fixos-2.2.37 → fixos-2.2.38}/fixos/cli.py +0 -0
  85. {fixos-2.2.37 → fixos-2.2.38}/fixos/config_interactive.py +0 -0
  86. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/__init__.py +0 -0
  87. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/_flatpak_analysis_mixin.py +0 -0
  88. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/_flatpak_execution_mixin.py +0 -0
  89. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/_flatpak_recommendations_mixin.py +0 -0
  90. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/_storage_container_mixin.py +0 -0
  91. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/_storage_system_mixin.py +0 -0
  92. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/_storage_user_mixin.py +0 -0
  93. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/cache_discovery.py +0 -0
  94. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/checks/__init__.py +0 -0
  95. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/checks/_shared.py +0 -0
  96. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/checks/audio.py +0 -0
  97. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/checks/file_analysis.py +0 -0
  98. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/checks/hardware.py +0 -0
  99. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/checks/packages.py +0 -0
  100. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/checks/storage_optimization.py +0 -0
  101. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/checks/system_core.py +0 -0
  102. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/checks/thumbnails.py +0 -0
  103. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/dev_project_analyzer.py +0 -0
  104. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/disk_analyzer.py +0 -0
  105. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/flatpak_analyzer.py +0 -0
  106. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/service_details.py +0 -0
  107. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/storage_analyzer.py +0 -0
  108. {fixos-2.2.37 → fixos-2.2.38}/fixos/diagnostics/utils.py +0 -0
  109. {fixos-2.2.37 → fixos-2.2.38}/fixos/features/__init__.py +0 -0
  110. {fixos-2.2.37 → fixos-2.2.38}/fixos/features/auditor.py +0 -0
  111. {fixos-2.2.37 → fixos-2.2.38}/fixos/features/catalog.py +0 -0
  112. {fixos-2.2.37 → fixos-2.2.38}/fixos/features/installer.py +0 -0
  113. {fixos-2.2.37 → fixos-2.2.38}/fixos/features/profiles.py +0 -0
  114. {fixos-2.2.37 → fixos-2.2.38}/fixos/features/renderer.py +0 -0
  115. {fixos-2.2.37 → fixos-2.2.38}/fixos/fixes/__init__.py +0 -0
  116. {fixos-2.2.37 → fixos-2.2.38}/fixos/interactive/__init__.py +0 -0
  117. {fixos-2.2.37 → fixos-2.2.38}/fixos/interactive/cleanup_planner.py +0 -0
  118. {fixos-2.2.37 → fixos-2.2.38}/fixos/llm_shell.py +0 -0
  119. {fixos-2.2.37 → fixos-2.2.38}/fixos/orchestrator/__init__.py +0 -0
  120. {fixos-2.2.37 → fixos-2.2.38}/fixos/orchestrator/executor.py +0 -0
  121. {fixos-2.2.37 → fixos-2.2.38}/fixos/orchestrator/graph.py +0 -0
  122. {fixos-2.2.37 → fixos-2.2.38}/fixos/orchestrator/orchestrator.py +0 -0
  123. {fixos-2.2.37 → fixos-2.2.38}/fixos/orchestrator/rollback.py +0 -0
  124. {fixos-2.2.37 → fixos-2.2.38}/fixos/platform_utils.py +0 -0
  125. {fixos-2.2.37 → fixos-2.2.38}/fixos/plugins/__init__.py +0 -0
  126. {fixos-2.2.37 → fixos-2.2.38}/fixos/plugins/base.py +0 -0
  127. {fixos-2.2.37 → fixos-2.2.38}/fixos/plugins/builtin/__init__.py +0 -0
  128. {fixos-2.2.37 → fixos-2.2.38}/fixos/plugins/builtin/audio.py +0 -0
  129. {fixos-2.2.37 → fixos-2.2.38}/fixos/plugins/builtin/disk.py +0 -0
  130. {fixos-2.2.37 → fixos-2.2.38}/fixos/plugins/builtin/hardware.py +0 -0
  131. {fixos-2.2.37 → fixos-2.2.38}/fixos/plugins/builtin/resources.py +0 -0
  132. {fixos-2.2.37 → fixos-2.2.38}/fixos/plugins/builtin/security.py +0 -0
  133. {fixos-2.2.37 → fixos-2.2.38}/fixos/plugins/builtin/thumbnails.py +0 -0
  134. {fixos-2.2.37 → fixos-2.2.38}/fixos/plugins/registry.py +0 -0
  135. {fixos-2.2.37 → fixos-2.2.38}/fixos/profiles/__init__.py +0 -0
  136. {fixos-2.2.37 → fixos-2.2.38}/fixos/providers/__init__.py +0 -0
  137. {fixos-2.2.37 → fixos-2.2.38}/fixos/providers/llm_analyzer.py +0 -0
  138. {fixos-2.2.37 → fixos-2.2.38}/fixos/providers/schemas.py +0 -0
  139. {fixos-2.2.37 → fixos-2.2.38}/fixos/system_checks.py +0 -0
  140. {fixos-2.2.37 → fixos-2.2.38}/fixos/utils/__init__.py +0 -0
  141. {fixos-2.2.37 → fixos-2.2.38}/fixos/utils/anonymizer.py +0 -0
  142. {fixos-2.2.37 → fixos-2.2.38}/fixos/utils/terminal.py +0 -0
  143. {fixos-2.2.37 → fixos-2.2.38}/fixos/utils/timeout.py +0 -0
  144. {fixos-2.2.37 → fixos-2.2.38}/fixos/utils/web_search.py +0 -0
  145. {fixos-2.2.37 → fixos-2.2.38}/fixos/watch.py +0 -0
  146. {fixos-2.2.37 → fixos-2.2.38}/fixos.egg-info/dependency_links.txt +0 -0
  147. {fixos-2.2.37 → fixos-2.2.38}/fixos.egg-info/entry_points.txt +0 -0
  148. {fixos-2.2.37 → fixos-2.2.38}/fixos.egg-info/requires.txt +0 -0
  149. {fixos-2.2.37 → fixos-2.2.38}/pytest.ini +0 -0
  150. {fixos-2.2.37 → fixos-2.2.38}/requirements-dev.txt +0 -0
  151. {fixos-2.2.37 → fixos-2.2.38}/requirements.txt +0 -0
  152. {fixos-2.2.37 → fixos-2.2.38}/scripts/pyqual-calibrate.py +0 -0
  153. {fixos-2.2.37 → fixos-2.2.38}/setup.cfg +0 -0
  154. {fixos-2.2.37 → fixos-2.2.38}/tests/__init__.py +0 -0
  155. {fixos-2.2.37 → fixos-2.2.38}/tests/conftest.py +0 -0
  156. {fixos-2.2.37 → fixos-2.2.38}/tests/e2e/__init__.py +0 -0
  157. {fixos-2.2.37 → fixos-2.2.38}/tests/e2e/test_anonymization_layers.py +0 -0
  158. {fixos-2.2.37 → fixos-2.2.38}/tests/e2e/test_audio_broken.py +0 -0
  159. {fixos-2.2.37 → fixos-2.2.38}/tests/e2e/test_cli.py +0 -0
  160. {fixos-2.2.37 → fixos-2.2.38}/tests/e2e/test_diagnostics_integration.py +0 -0
  161. {fixos-2.2.37 → fixos-2.2.38}/tests/e2e/test_executor.py +0 -0
  162. {fixos-2.2.37 → fixos-2.2.38}/tests/e2e/test_multi_system.py +0 -0
  163. {fixos-2.2.37 → fixos-2.2.38}/tests/e2e/test_network_broken.py +0 -0
  164. {fixos-2.2.37 → fixos-2.2.38}/tests/e2e/test_thumbnails_broken.py +0 -0
  165. {fixos-2.2.37 → fixos-2.2.38}/tests/test_fixos.py +0 -0
  166. {fixos-2.2.37 → fixos-2.2.38}/tests/unit/__init__.py +0 -0
  167. {fixos-2.2.37 → fixos-2.2.38}/tests/unit/test_anonymizer.py +0 -0
  168. {fixos-2.2.37 → fixos-2.2.38}/tests/unit/test_cache_discovery.py +0 -0
  169. {fixos-2.2.37 → fixos-2.2.38}/tests/unit/test_core.py +0 -0
  170. {fixos-2.2.37 → fixos-2.2.38}/tests/unit/test_executor.py +0 -0
  171. {fixos-2.2.37 → fixos-2.2.38}/tests/unit/test_orchestrator.py +0 -0
@@ -150,6 +150,29 @@ fix(goal): code analysis engine
150
150
  - **refactor(cli):** Usunięto zduplikowany kod ujednolicając funkcje analizy dysku do wspólnego helpera `_run_disk_analysis`.
151
151
  - **refactor(ui):** Usunięto ikony Unicode z CLI i sformatowano wyjście `stderr` oraz standardowego logowania na czysty kod Markdown dla poprawy czytelności w oknach terminalowych.
152
152
 
153
+ ## [2.2.38] - 2026-07-23
154
+
155
+ ### Docs
156
+ - Update README.md
157
+
158
+ ### Test
159
+ - Update tests/unit/test_resources_quick.py
160
+ - Update tests/unit/test_security_quick.py
161
+ - Update tests/unit/test_service_cleanup.py
162
+ - Update tests/unit/test_service_scanner.py
163
+ - Update tests/unit/test_system_checks_parallel.py
164
+
165
+ ### Other
166
+ - Update fixos/cli/cleanup_cmd.py
167
+ - Update fixos/cli/fix_cmd.py
168
+ - Update fixos/diagnostics/checks/resources.py
169
+ - Update fixos/diagnostics/checks/security.py
170
+ - Update fixos/diagnostics/service_cleanup.py
171
+ - Update fixos/diagnostics/service_scanner.py
172
+ - Update fixos/diagnostics/system_checks.py
173
+ - Update img_1.png
174
+ - Update uv.lock
175
+
153
176
  ## [2.2.37] - 2026-07-15
154
177
 
155
178
  ### Docs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fixos
3
- Version: 2.2.37
3
+ Version: 2.2.38
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.37-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.56-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-36.2h-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.38-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.62-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-37.0h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
68
68
 
69
- - 🤖 **LLM usage:** $4.5585 (143 commits)
70
- - 👤 **Human dev:** ~$3616 (36.2h @ $100/h, 30min dedup)
69
+ - 🤖 **LLM usage:** $4.6178 (145 commits)
70
+ - 👤 **Human dev:** ~$3695 (37.0h @ $100/h, 30min dedup)
71
71
 
72
- Generated on 2026-07-15 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
72
+ Generated on 2026-07-23 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
73
73
 
74
74
  ---
75
75
 
@@ -80,6 +80,8 @@ z anonimizacją danych, trybem HITL/Autonomous, grafem problemów i 12 providera
80
80
 
81
81
  ---
82
82
 
83
+ ![img_1.png](img_1.png)
84
+
83
85
  ## 🌍 Cross-Platform Support
84
86
 
85
87
  | System | Package Manager | Audio | Hardware | System |
@@ -114,6 +116,7 @@ fixos fix – diagnoza + sesja naprawcza z AI (HITL)
114
116
  fixos scan – diagnostyka systemu bez AI
115
117
  fixos cleanup – skanuj i czyść dane usług (Docker, npm, pip, ...)
116
118
  fixos cleanup --full – pełny audit systemu + dev projects
119
+ fixos projects – skanuj projekty dev (venv, node_modules, ~/github/*/*)
117
120
  fixos orchestrate – zaawansowana orkiestracja (graf problemów DAG)
118
121
  fixos llm – lista 12 providerów LLM + linki do kluczy API
119
122
  fixos token set KEY – zapisz klucz API do .env (auto-detekcja providera)
@@ -151,6 +154,15 @@ fixos cleanup --full
151
154
  > select
152
155
  > 1,3,5-10
153
156
 
157
+ # Skanuj ~/github/*/* pod kątem venv/.venv, node_modules, cache kompilacji...
158
+ fixos projects
159
+
160
+ # Tylko artefakty nieużywane od >60 dni (bez świeżych venv)
161
+ fixos projects --only-stale
162
+
163
+ # Podgląd bez usuwania
164
+ fixos projects --dry-run
165
+
154
166
  # Napraw audio i thumbnails (HITL – pyta o potwierdzenie)
155
167
  fixos fix --modules audio,thumbnails
156
168
 
@@ -218,6 +230,72 @@ Rekomendacje:
218
230
  Tryb DRY-RUN - żadne akcje nie zostaną wykonane
219
231
  ```
220
232
 
233
+ ### `fixos cleanup` – 3 poziomy ryzyka
234
+
235
+ Każda znaleziona usługa jest klasyfikowana do jednej z trzech grup:
236
+
237
+ - **bezpieczne** – cache do odtworzenia jednym poleceniem (docker/pip/npm/cargo/conda/nix/brew...).
238
+ Jedyna grupa oferowana do automatycznego usunięcia, z menu wyboru: wszystkie / pojedynczo / pomiń.
239
+ - **do rozważenia** – reinstalowalne aplikacje, dane długo nieużywane, nierozpoznane
240
+ foldery (JetBrains, Snap, Flatpak) – pokazywane z podpowiedziami, nigdy nie usuwane automatycznie.
241
+ - **niebezpieczne** – realne dane aplikacji, nie cache (Ollama, LM Studio, HuggingFace hub,
242
+ Docker/Podman/containerd, cała biblioteka Steam, `.cursor/extensions`/`.vscode/extensions`
243
+ – zainstalowane rozszerzenia edytora, nie ich cache). Osobna sekcja z ostrzeżeniem;
244
+ usunięcie pojedynczej usługi (`fixos cleanup -c <usluga>`) wymaga dodatkowego
245
+ potwierdzenia z jawnym opisem ryzyka.
246
+
247
+ ### `fixos projects` – skaner artefaktów w projektach deweloperskich
248
+
249
+ Osobne narzędzie od `fixos cleanup` – zamiast globalnych ścieżek cache (`~/.cache/...`)
250
+ rekurencyjnie skanuje drzewo Twoich projektów (domyślnie `~/github/*/*`, dowolna
251
+ ścieżka przez `--path`) i wykrywa usuwalne artefakty per-projekt: `venv`/`.venv`
252
+ (zweryfikowane po `pyvenv.cfg`, żeby nie trafić na przypadkowy folder o tej
253
+ nazwie), `node_modules`/`.next`/`.turbo` (tylko gdy jest `package.json`),
254
+ `target` (tylko gdy jest `Cargo.toml`), `__pycache__`, `.pytest_cache`,
255
+ `.mypy_cache`, `.ruff_cache`, `.tox`, `.nox`; `dist`/`build` osobno jako
256
+ "do rozważenia" (mogą zawierać coś do opublikowania). Flaguje artefakty
257
+ nieużywane od >60 dni (`--stale-days`) oraz projekty ze zduplikowanymi
258
+ virtualenvami (np. i `venv`, i `.venv` naraz).
259
+
260
+ ```bash
261
+ $ fixos projects --only-stale
262
+
263
+ Skanowanie projektów w /home/tom/github (próg: 50 MB)...
264
+ ════════════════════════════════════════════════════════════
265
+ Znaleziono 91 artefaktów w 68 projektach:
266
+ Całkowity rozmiar: 91.90 GB
267
+ Bezpieczne: 91.10 GB
268
+ Do rozważenia: 0.80 GB
269
+ Nieużywane od >60 dni: 91.90 GB
270
+
271
+ ⚠ 12 projekt(ów) ma więcej niż jeden virtualenv naraz (np. venv + .venv):
272
+ • /home/tom/github/semcod/fixOS
273
+
274
+ streamware/venv - 9.27 GB — nieużywany 216 dni
275
+ Python virtualenv
276
+ Ścieżka: /home/tom/github/stream-ware/streamware/venv
277
+ (bezpieczne)
278
+ ...
279
+
280
+ Co wyczyścić?
281
+ [1] Wszystkie bezpieczne (91.10 GB)
282
+ [2] Tylko dawno nieużywane (91.90 GB, 91 art.)
283
+ [3] Wybierz wg ekosystemu (Python/Node/Rust/...)
284
+ [4] Wybierz wg projektu
285
+ [5] Wybierz pojedyncze artefakty
286
+ [0] Nic — pomiń
287
+ Wybór [1]: 4
288
+
289
+ [1] stream-ware/streamware — 9.27 GB (1 art.)
290
+ [2] prototypowanie/raport — 8.30 GB (1 art.)
291
+ [3] stream-ware/edge — 7.68 GB (1 art.)
292
+ ...
293
+ Numery po przecinku (np. 1,3,5), 'all' dla wszystkich, Enter by pominąć: 1,3
294
+ ```
295
+
296
+ Inne opcje: `--list` (tylko podgląd bez interakcji), `--json`, `--max-depth`,
297
+ `--threshold`.
298
+
221
299
  ---
222
300
 
223
301
  ## 🤖 Dostępni Providerzy LLM (12)
@@ -354,6 +432,13 @@ SHOW_ANONYMIZED_DATA=true # pokaż dane przed wysłaniem
354
432
  ENABLE_WEB_SEARCH=true # fallback do zewnętrznych źródeł
355
433
  SESSION_TIMEOUT=3600 # timeout sesji (1h)
356
434
  SERPAPI_KEY= # opcjonalny – lepsze wyniki wyszukiwania
435
+
436
+ # Opcjonalnie: konkretny model dla danego providera + modele zapasowe.
437
+ # Jeśli główny model zostanie odrzucony przez providera jako nieprawidłowy
438
+ # (błąd 400 "not a valid model ID"), klient automatycznie przechodzi na
439
+ # kolejny z listy – bez żadnej akcji z Twojej strony.
440
+ OPENROUTER_MODEL=openrouter/qwen/qwen3.7-plus
441
+ OPENROUTER_MODEL_FALLBACKS=minimax/minimax-m3,google/gemini-2.5-flash-lite
357
442
  ```
358
443
 
359
444
  ---
@@ -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.37-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.56-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-36.2h-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.38-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.62-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-37.0h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
24
24
 
25
- - 🤖 **LLM usage:** $4.5585 (143 commits)
26
- - 👤 **Human dev:** ~$3616 (36.2h @ $100/h, 30min dedup)
25
+ - 🤖 **LLM usage:** $4.6178 (145 commits)
26
+ - 👤 **Human dev:** ~$3695 (37.0h @ $100/h, 30min dedup)
27
27
 
28
- Generated on 2026-07-15 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
28
+ Generated on 2026-07-23 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
29
29
 
30
30
  ---
31
31
 
@@ -36,6 +36,8 @@ z anonimizacją danych, trybem HITL/Autonomous, grafem problemów i 12 providera
36
36
 
37
37
  ---
38
38
 
39
+ ![img_1.png](img_1.png)
40
+
39
41
  ## 🌍 Cross-Platform Support
40
42
 
41
43
  | System | Package Manager | Audio | Hardware | System |
@@ -70,6 +72,7 @@ fixos fix – diagnoza + sesja naprawcza z AI (HITL)
70
72
  fixos scan – diagnostyka systemu bez AI
71
73
  fixos cleanup – skanuj i czyść dane usług (Docker, npm, pip, ...)
72
74
  fixos cleanup --full – pełny audit systemu + dev projects
75
+ fixos projects – skanuj projekty dev (venv, node_modules, ~/github/*/*)
73
76
  fixos orchestrate – zaawansowana orkiestracja (graf problemów DAG)
74
77
  fixos llm – lista 12 providerów LLM + linki do kluczy API
75
78
  fixos token set KEY – zapisz klucz API do .env (auto-detekcja providera)
@@ -107,6 +110,15 @@ fixos cleanup --full
107
110
  > select
108
111
  > 1,3,5-10
109
112
 
113
+ # Skanuj ~/github/*/* pod kątem venv/.venv, node_modules, cache kompilacji...
114
+ fixos projects
115
+
116
+ # Tylko artefakty nieużywane od >60 dni (bez świeżych venv)
117
+ fixos projects --only-stale
118
+
119
+ # Podgląd bez usuwania
120
+ fixos projects --dry-run
121
+
110
122
  # Napraw audio i thumbnails (HITL – pyta o potwierdzenie)
111
123
  fixos fix --modules audio,thumbnails
112
124
 
@@ -174,6 +186,72 @@ Rekomendacje:
174
186
  Tryb DRY-RUN - żadne akcje nie zostaną wykonane
175
187
  ```
176
188
 
189
+ ### `fixos cleanup` – 3 poziomy ryzyka
190
+
191
+ Każda znaleziona usługa jest klasyfikowana do jednej z trzech grup:
192
+
193
+ - **bezpieczne** – cache do odtworzenia jednym poleceniem (docker/pip/npm/cargo/conda/nix/brew...).
194
+ Jedyna grupa oferowana do automatycznego usunięcia, z menu wyboru: wszystkie / pojedynczo / pomiń.
195
+ - **do rozważenia** – reinstalowalne aplikacje, dane długo nieużywane, nierozpoznane
196
+ foldery (JetBrains, Snap, Flatpak) – pokazywane z podpowiedziami, nigdy nie usuwane automatycznie.
197
+ - **niebezpieczne** – realne dane aplikacji, nie cache (Ollama, LM Studio, HuggingFace hub,
198
+ Docker/Podman/containerd, cała biblioteka Steam, `.cursor/extensions`/`.vscode/extensions`
199
+ – zainstalowane rozszerzenia edytora, nie ich cache). Osobna sekcja z ostrzeżeniem;
200
+ usunięcie pojedynczej usługi (`fixos cleanup -c <usluga>`) wymaga dodatkowego
201
+ potwierdzenia z jawnym opisem ryzyka.
202
+
203
+ ### `fixos projects` – skaner artefaktów w projektach deweloperskich
204
+
205
+ Osobne narzędzie od `fixos cleanup` – zamiast globalnych ścieżek cache (`~/.cache/...`)
206
+ rekurencyjnie skanuje drzewo Twoich projektów (domyślnie `~/github/*/*`, dowolna
207
+ ścieżka przez `--path`) i wykrywa usuwalne artefakty per-projekt: `venv`/`.venv`
208
+ (zweryfikowane po `pyvenv.cfg`, żeby nie trafić na przypadkowy folder o tej
209
+ nazwie), `node_modules`/`.next`/`.turbo` (tylko gdy jest `package.json`),
210
+ `target` (tylko gdy jest `Cargo.toml`), `__pycache__`, `.pytest_cache`,
211
+ `.mypy_cache`, `.ruff_cache`, `.tox`, `.nox`; `dist`/`build` osobno jako
212
+ "do rozważenia" (mogą zawierać coś do opublikowania). Flaguje artefakty
213
+ nieużywane od >60 dni (`--stale-days`) oraz projekty ze zduplikowanymi
214
+ virtualenvami (np. i `venv`, i `.venv` naraz).
215
+
216
+ ```bash
217
+ $ fixos projects --only-stale
218
+
219
+ Skanowanie projektów w /home/tom/github (próg: 50 MB)...
220
+ ════════════════════════════════════════════════════════════
221
+ Znaleziono 91 artefaktów w 68 projektach:
222
+ Całkowity rozmiar: 91.90 GB
223
+ Bezpieczne: 91.10 GB
224
+ Do rozważenia: 0.80 GB
225
+ Nieużywane od >60 dni: 91.90 GB
226
+
227
+ ⚠ 12 projekt(ów) ma więcej niż jeden virtualenv naraz (np. venv + .venv):
228
+ • /home/tom/github/semcod/fixOS
229
+
230
+ streamware/venv - 9.27 GB — nieużywany 216 dni
231
+ Python virtualenv
232
+ Ścieżka: /home/tom/github/stream-ware/streamware/venv
233
+ (bezpieczne)
234
+ ...
235
+
236
+ Co wyczyścić?
237
+ [1] Wszystkie bezpieczne (91.10 GB)
238
+ [2] Tylko dawno nieużywane (91.90 GB, 91 art.)
239
+ [3] Wybierz wg ekosystemu (Python/Node/Rust/...)
240
+ [4] Wybierz wg projektu
241
+ [5] Wybierz pojedyncze artefakty
242
+ [0] Nic — pomiń
243
+ Wybór [1]: 4
244
+
245
+ [1] stream-ware/streamware — 9.27 GB (1 art.)
246
+ [2] prototypowanie/raport — 8.30 GB (1 art.)
247
+ [3] stream-ware/edge — 7.68 GB (1 art.)
248
+ ...
249
+ Numery po przecinku (np. 1,3,5), 'all' dla wszystkich, Enter by pominąć: 1,3
250
+ ```
251
+
252
+ Inne opcje: `--list` (tylko podgląd bez interakcji), `--json`, `--max-depth`,
253
+ `--threshold`.
254
+
177
255
  ---
178
256
 
179
257
  ## 🤖 Dostępni Providerzy LLM (12)
@@ -310,6 +388,13 @@ SHOW_ANONYMIZED_DATA=true # pokaż dane przed wysłaniem
310
388
  ENABLE_WEB_SEARCH=true # fallback do zewnętrznych źródeł
311
389
  SESSION_TIMEOUT=3600 # timeout sesji (1h)
312
390
  SERPAPI_KEY= # opcjonalny – lepsze wyniki wyszukiwania
391
+
392
+ # Opcjonalnie: konkretny model dla danego providera + modele zapasowe.
393
+ # Jeśli główny model zostanie odrzucony przez providera jako nieprawidłowy
394
+ # (błąd 400 "not a valid model ID"), klient automatycznie przechodzi na
395
+ # kolejny z listy – bez żadnej akcji z Twojej strony.
396
+ OPENROUTER_MODEL=openrouter/qwen/qwen3.7-plus
397
+ OPENROUTER_MODEL_FALLBACKS=minimax/minimax-m3,google/gemini-2.5-flash-lite
313
398
  ```
314
399
 
315
400
  ---
@@ -1,3 +1,3 @@
1
1
  """fixos – AI-powered Linux/Windows diagnostics and repair."""
2
2
 
3
- __version__ = "2.2.37"
3
+ __version__ = "2.2.38"
@@ -45,19 +45,27 @@ def _display_cleanup_summary(plan: dict, threshold: int) -> None:
45
45
  )
46
46
  click.echo(
47
47
  click.style(
48
- f" Niebezpieczne (rzeczywiste dane, nie cache): "
48
+ f" Chronione/mieszane (nie do automatycznego usunięcia): "
49
49
  f"{plan.get('dangerous_gb', 0):.2f} GB",
50
50
  fg="red",
51
51
  bold=True,
52
52
  )
53
53
  )
54
+ reclaimable = plan.get("manager_reported_reclaimable_gb", 0)
55
+ if reclaimable:
56
+ click.echo(
57
+ click.style(
58
+ f" Odzyskiwalne wg menedżerów usług: {reclaimable:.2f} GB",
59
+ fg="cyan",
60
+ )
61
+ )
54
62
  click.echo()
55
63
 
56
64
 
57
65
  _RISK_LABELS = {
58
66
  "safe": ("(bezpieczne)", "green"),
59
67
  "review": ("(do rozważenia)", "yellow"),
60
- "dangerous": ("(NIEBEZPIECZNE — realne dane, nie cache)", "red"),
68
+ "dangerous": ("(CHRONIONE — dane rzeczywiste lub mieszane)", "red"),
61
69
  }
62
70
 
63
71
 
@@ -87,7 +95,17 @@ def _display_service_item(svc: dict) -> None:
87
95
  # Show details for specific services
88
96
  if svc.get("details"):
89
97
  if svc["service_type"] == "docker" and svc["details"].get("components"):
90
- click.echo(f" Komponenty: {svc['details']['components']}")
98
+ usage = svc["details"].get("usage", {})
99
+ if usage:
100
+ click.echo(" Docker (łącznie / aktywne / rozmiar / odzyskiwalne):")
101
+ for kind, row in usage.items():
102
+ click.echo(
103
+ f" • {kind}: {row.get('total', 0)} / "
104
+ f"{row.get('active', 0)} / {row.get('size_gb', 0):.2f} GB / "
105
+ f"{row.get('reclaimable_gb', 0):.2f} GB"
106
+ )
107
+ else:
108
+ click.echo(f" Komponenty: {svc['details']['components']}")
91
109
  elif svc["service_type"] == "ollama" and svc["details"].get("models"):
92
110
  models = svc["details"]["models"]
93
111
  if models:
@@ -97,6 +115,19 @@ def _display_service_item(svc: dict) -> None:
97
115
  click.echo()
98
116
 
99
117
 
118
+ def _error_message(result: dict) -> str:
119
+ """Human-readable failure reason, even when the command's own stderr was
120
+ empty (e.g. suppressed with 2>/dev/null inside the cleanup command
121
+ itself) — a bare nonzero exit code beats a silently blank "Błąd: "."""
122
+ error = result.get("error")
123
+ if error:
124
+ return error
125
+ returncode = result.get("returncode")
126
+ if returncode is not None:
127
+ return f"polecenie zakończyło się kodem {returncode} bez komunikatu błędu"
128
+ return "nieznany błąd"
129
+
130
+
100
131
  def _execute_safe_cleanup(services: list, scanner) -> float:
101
132
  """Execute cleanup for safe-to-remove services. Returns total space freed in GB."""
102
133
  total_freed = 0.0
@@ -109,9 +140,7 @@ def _execute_safe_cleanup(services: list, scanner) -> float:
109
140
  total_freed += freed
110
141
  click.echo(click.style(f" Zwolniono {freed:.2f} GB", fg="green"))
111
142
  else:
112
- click.echo(
113
- click.style(f" Błąd: {result.get('error', 'nieznany')}", fg="red")
114
- )
143
+ click.echo(click.style(f" Błąd: {_error_message(result)}", fg="red"))
115
144
  return total_freed
116
145
 
117
146
 
@@ -131,18 +160,30 @@ def _format_hint_line(hint: str) -> None:
131
160
  click.echo(click.style(f" {hint}", fg="white"))
132
161
 
133
162
 
134
- def _display_service_group(service_type: str, svcs: list, type_map: dict) -> None:
163
+ def _display_service_group(
164
+ service_type: str,
165
+ svcs: list,
166
+ type_map: dict,
167
+ *,
168
+ show_cleanup_commands: bool = True,
169
+ ) -> None:
135
170
  """Display a single service group with cleanup commands and hints."""
136
171
  from fixos.diagnostics.service_cleanup import ServiceCleaner
137
172
 
138
173
  total_size = sum(s.get("size_gb", 0) for s in svcs)
139
174
  click.echo(f"\n • {service_type.title()}: {total_size:.2f} GB")
140
175
 
141
- unique_commands = list(set(s["cleanup_command"] for s in svcs))
142
- for cmd in unique_commands[:2]:
143
- click.echo(f" {cmd}")
144
- if len(unique_commands) > 2:
145
- click.echo(f" ... (+{len(unique_commands) - 2} more commands)")
176
+ command_key = "cleanup_command" if show_cleanup_commands else "preview_command"
177
+ unique_commands = sorted(
178
+ {s.get(command_key, "") for s in svcs if s.get(command_key)}
179
+ )
180
+ if unique_commands:
181
+ label = "Komenda" if show_cleanup_commands else "Bezpieczny podgląd"
182
+ click.echo(f" {label}:")
183
+ for cmd in unique_commands[:2]:
184
+ click.echo(f" {cmd}")
185
+ if len(unique_commands) > 2:
186
+ click.echo(f" ... (+{len(unique_commands) - 2} more commands)")
146
187
 
147
188
  service_enum = type_map.get(service_type.lower())
148
189
  if service_enum:
@@ -203,17 +244,17 @@ def _display_dangerous_services(services: list) -> None:
203
244
  click.echo()
204
245
  click.echo(
205
246
  click.style(
206
- "⚠️ Niebezpieczne — realne dane, nie cache (wymaga ręcznej, świadomej akcji):",
247
+ "⚠️ Chronione lub mieszane dane (wymaga świadomego wyboru elementów):",
207
248
  fg="red",
208
249
  bold=True,
209
250
  )
210
251
  )
211
252
  click.echo(
212
253
  click.style(
213
- " To nie jest cache do odtworzenia jednym poleceniem — to np. "
214
- "zainstalowane modele AI, kontenery/woluminy, dyski maszyn "
215
- "wirtualnych albo zainstalowane rozszerzenia edytora. Usunięcie "
216
- "może oznaczać realną utratę danych lub długi re-download.",
254
+ " Ta grupa może łączyć dane aktywne z cache (np. Docker) albo "
255
+ "zawierać modele AI, wolumeny, dyski maszyn wirtualnych i "
256
+ "rozszerzenia. fixOS pokazuje bezpieczny podgląd, ale nie proponuje "
257
+ "już zbiorczego kasowania całej grupy.",
217
258
  fg="red",
218
259
  )
219
260
  )
@@ -236,7 +277,12 @@ def _display_dangerous_services(services: list) -> None:
236
277
  }
237
278
 
238
279
  for service_type, svcs in _group_by_service_type(services).items():
239
- _display_service_group(service_type, svcs, type_map)
280
+ _display_service_group(
281
+ service_type,
282
+ svcs,
283
+ type_map,
284
+ show_cleanup_commands=False,
285
+ )
240
286
 
241
287
  click.echo()
242
288
  click.echo(
@@ -293,13 +339,21 @@ def _cleanup_single_service(
293
339
  result = scanner.cleanup_service(service_name, dry_run=dry_run)
294
340
 
295
341
  if result["success"]:
296
- click.echo(click.style(f"Zakończono czyszczenie {service_name}", fg="green"))
297
- if result["space_freed_gb"] > 0:
298
- click.echo(f" Zwolniono: {result['space_freed_gb']:.2f} GB")
342
+ if dry_run:
343
+ click.echo(click.style(f"Symulacja dla {service_name} zakończona", fg="green"))
344
+ if result.get("output"):
345
+ click.echo(f" {result['output']}")
346
+ if result["space_freed_gb"] > 0:
347
+ click.echo(
348
+ f" Szacowane maksimum do odzyskania: "
349
+ f"{result['space_freed_gb']:.2f} GB"
350
+ )
351
+ else:
352
+ click.echo(click.style(f"Zakończono czyszczenie {service_name}", fg="green"))
353
+ if result["space_freed_gb"] > 0:
354
+ click.echo(f" Zwolniono: {result['space_freed_gb']:.2f} GB")
299
355
  else:
300
- click.echo(
301
- click.style(f"Błąd: {result.get('error', 'Nieznany błąd')}", fg="red")
302
- )
356
+ click.echo(click.style(f"Błąd: {_error_message(result)}", fg="red"))
303
357
  if result.get("output"):
304
358
  click.echo(f"Output: {result['output']}")
305
359
 
@@ -96,7 +96,10 @@ def _run_agent_session(cfg, data: dict, max_fixes: int) -> None:
96
96
  "--modules",
97
97
  "-M",
98
98
  default=None,
99
- help="Moduły diagnostyki: audio,thumbnails,hardware,system",
99
+ help=(
100
+ "Moduły diagnostyki: audio,thumbnails,hardware,system,... "
101
+ "(domyślnie szybki zestaw bez głębokiego skanu plików; użyj 'all')"
102
+ ),
100
103
  )
101
104
  @click.option(
102
105
  "--no-show-data",
@@ -159,6 +162,7 @@ def fix(
159
162
  fixos fix --disc --dry-run # analiza dysku bez wykonywania
160
163
  fixos fix --mode autonomous # tryb autonomiczny
161
164
  fixos fix --modules audio,thumbnails # tylko audio i thumbnails
165
+ fixos fix --modules all # także głęboki skan plików
162
166
  fixos fix --yaml --no-interactive # pipeline mode → YAML
163
167
  fixos fix --provider openai --token sk-...
164
168
  """
@@ -70,6 +70,7 @@ def _print_welcome() -> None:
70
70
  ("fixos scan", "", "Diagnostyka systemu bez AI"),
71
71
  ("fixos quickfix", "", "Naprawy offline bez API (baza znanych bugów)"),
72
72
  ("fixos cleanup", "", "Skanuj i czyść dane usług (Docker, Ollama)"),
73
+ ("fixos projects", "", "Skanuj projekty dev (venv, node_modules, ~/github/*/*)"),
73
74
  ("fixos orchestrate", "", "Zaawansowana orkiestracja napraw (graf problemów)"),
74
75
  ("fixos watch", "", "Monitoring w tle z powiadomieniami"),
75
76
  ("fixos report", "", "Eksport diagnostyki do HTML/Markdown/JSON"),
@@ -167,6 +168,7 @@ from fixos.cli.scan_cmd import scan
167
168
  from fixos.cli.fix_cmd import fix
168
169
  from fixos.cli.orchestrate_cmd import orchestrate
169
170
  from fixos.cli.cleanup_cmd import cleanup_services
171
+ from fixos.cli.projects_cmd import projects_cmd
170
172
  from fixos.cli.features_cmd import features
171
173
 
172
174
  cli.add_command(rollback)
@@ -185,4 +187,5 @@ cli.add_command(scan)
185
187
  cli.add_command(fix)
186
188
  cli.add_command(orchestrate)
187
189
  cli.add_command(cleanup_services)
190
+ cli.add_command(projects_cmd)
188
191
  cli.add_command(features)