sifty 0.6.0__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 (127) hide show
  1. sifty-0.6.0/LICENSE +21 -0
  2. sifty-0.6.0/PKG-INFO +254 -0
  3. sifty-0.6.0/README.md +211 -0
  4. sifty-0.6.0/pyproject.toml +82 -0
  5. sifty-0.6.0/setup.cfg +4 -0
  6. sifty-0.6.0/src/sifty/__init__.py +3 -0
  7. sifty-0.6.0/src/sifty/__main__.py +6 -0
  8. sifty-0.6.0/src/sifty/ai/__init__.py +1 -0
  9. sifty-0.6.0/src/sifty/ai/advisor.py +71 -0
  10. sifty-0.6.0/src/sifty/ai/agent.py +227 -0
  11. sifty-0.6.0/src/sifty/ai/client.py +176 -0
  12. sifty-0.6.0/src/sifty/ai/context.py +92 -0
  13. sifty-0.6.0/src/sifty/ai/tools.py +546 -0
  14. sifty-0.6.0/src/sifty/cli/__init__.py +1 -0
  15. sifty-0.6.0/src/sifty/cli/app.py +475 -0
  16. sifty-0.6.0/src/sifty/cli/commands/__init__.py +1 -0
  17. sifty-0.6.0/src/sifty/cli/commands/ai_group.py +62 -0
  18. sifty-0.6.0/src/sifty/cli/commands/apps.py +190 -0
  19. sifty-0.6.0/src/sifty/cli/commands/cleanup.py +181 -0
  20. sifty-0.6.0/src/sifty/cli/commands/config_cmd.py +133 -0
  21. sifty-0.6.0/src/sifty/cli/commands/disk.py +124 -0
  22. sifty-0.6.0/src/sifty/cli/commands/junk.py +87 -0
  23. sifty-0.6.0/src/sifty/cli/commands/optimize.py +92 -0
  24. sifty-0.6.0/src/sifty/cli/commands/organize.py +85 -0
  25. sifty-0.6.0/src/sifty/cli/commands/profile.py +58 -0
  26. sifty-0.6.0/src/sifty/cli/commands/purge.py +97 -0
  27. sifty-0.6.0/src/sifty/cli/commands/schedule.py +66 -0
  28. sifty-0.6.0/src/sifty/cli/commands/services.py +64 -0
  29. sifty-0.6.0/src/sifty/cli/commands/startup.py +57 -0
  30. sifty-0.6.0/src/sifty/cli/commands/updates.py +75 -0
  31. sifty-0.6.0/src/sifty/cli/commands/watch.py +58 -0
  32. sifty-0.6.0/src/sifty/cli/output.py +26 -0
  33. sifty-0.6.0/src/sifty/console.py +49 -0
  34. sifty-0.6.0/src/sifty/core/__init__.py +4 -0
  35. sifty-0.6.0/src/sifty/core/apps.py +113 -0
  36. sifty-0.6.0/src/sifty/core/checkup.py +156 -0
  37. sifty-0.6.0/src/sifty/core/cleanup.py +141 -0
  38. sifty-0.6.0/src/sifty/core/disk.py +117 -0
  39. sifty-0.6.0/src/sifty/core/history.py +154 -0
  40. sifty-0.6.0/src/sifty/core/junk.py +395 -0
  41. sifty-0.6.0/src/sifty/core/leftovers.py +222 -0
  42. sifty-0.6.0/src/sifty/core/models.py +114 -0
  43. sifty-0.6.0/src/sifty/core/monitor.py +113 -0
  44. sifty-0.6.0/src/sifty/core/optimize.py +225 -0
  45. sifty-0.6.0/src/sifty/core/organize.py +138 -0
  46. sifty-0.6.0/src/sifty/core/profiles.py +66 -0
  47. sifty-0.6.0/src/sifty/core/purge.py +132 -0
  48. sifty-0.6.0/src/sifty/core/registry_scan.py +129 -0
  49. sifty-0.6.0/src/sifty/core/safety.py +152 -0
  50. sifty-0.6.0/src/sifty/core/schedule.py +78 -0
  51. sifty-0.6.0/src/sifty/core/selfupdate.py +77 -0
  52. sifty-0.6.0/src/sifty/core/services.py +70 -0
  53. sifty-0.6.0/src/sifty/core/startup.py +111 -0
  54. sifty-0.6.0/src/sifty/core/undo.py +28 -0
  55. sifty-0.6.0/src/sifty/core/updates.py +65 -0
  56. sifty-0.6.0/src/sifty/core/vcs.py +163 -0
  57. sifty-0.6.0/src/sifty/core/watch.py +22 -0
  58. sifty-0.6.0/src/sifty/infra/__init__.py +1 -0
  59. sifty-0.6.0/src/sifty/infra/config.py +165 -0
  60. sifty-0.6.0/src/sifty/infra/logging.py +98 -0
  61. sifty-0.6.0/src/sifty/tui/__init__.py +1 -0
  62. sifty-0.6.0/src/sifty/tui/app.py +143 -0
  63. sifty-0.6.0/src/sifty/tui/commands.py +44 -0
  64. sifty-0.6.0/src/sifty/tui/modals.py +32 -0
  65. sifty-0.6.0/src/sifty/tui/screens/__init__.py +1 -0
  66. sifty-0.6.0/src/sifty/tui/screens/path_picker.py +72 -0
  67. sifty-0.6.0/src/sifty/tui/state.py +44 -0
  68. sifty-0.6.0/src/sifty/tui/styles.tcss +264 -0
  69. sifty-0.6.0/src/sifty/tui/views/__init__.py +64 -0
  70. sifty-0.6.0/src/sifty/tui/views/ai.py +354 -0
  71. sifty-0.6.0/src/sifty/tui/views/apps.py +300 -0
  72. sifty-0.6.0/src/sifty/tui/views/base.py +16 -0
  73. sifty-0.6.0/src/sifty/tui/views/cleanup.py +215 -0
  74. sifty-0.6.0/src/sifty/tui/views/disk.py +119 -0
  75. sifty-0.6.0/src/sifty/tui/views/group.py +107 -0
  76. sifty-0.6.0/src/sifty/tui/views/home.py +202 -0
  77. sifty-0.6.0/src/sifty/tui/views/junk.py +141 -0
  78. sifty-0.6.0/src/sifty/tui/views/monitor.py +115 -0
  79. sifty-0.6.0/src/sifty/tui/views/optimize.py +111 -0
  80. sifty-0.6.0/src/sifty/tui/views/purge.py +183 -0
  81. sifty-0.6.0/src/sifty/tui/views/reports.py +100 -0
  82. sifty-0.6.0/src/sifty/tui/views/services.py +116 -0
  83. sifty-0.6.0/src/sifty/tui/views/startup.py +104 -0
  84. sifty-0.6.0/src/sifty/tui/views/updates.py +125 -0
  85. sifty-0.6.0/src/sifty/tui/widgets.py +28 -0
  86. sifty-0.6.0/src/sifty/windows/__init__.py +5 -0
  87. sifty-0.6.0/src/sifty/windows/admin.py +95 -0
  88. sifty-0.6.0/src/sifty/windows/hyperv.py +67 -0
  89. sifty-0.6.0/src/sifty/windows/notify.py +26 -0
  90. sifty-0.6.0/src/sifty/windows/recyclebin.py +66 -0
  91. sifty-0.6.0/src/sifty/windows/registry.py +88 -0
  92. sifty-0.6.0/src/sifty/windows/scheduler.py +59 -0
  93. sifty-0.6.0/src/sifty/windows/services_api.py +68 -0
  94. sifty-0.6.0/src/sifty/windows/winget.py +46 -0
  95. sifty-0.6.0/src/sifty.egg-info/PKG-INFO +254 -0
  96. sifty-0.6.0/src/sifty.egg-info/SOURCES.txt +125 -0
  97. sifty-0.6.0/src/sifty.egg-info/dependency_links.txt +1 -0
  98. sifty-0.6.0/src/sifty.egg-info/entry_points.txt +2 -0
  99. sifty-0.6.0/src/sifty.egg-info/requires.txt +18 -0
  100. sifty-0.6.0/src/sifty.egg-info/top_level.txt +1 -0
  101. sifty-0.6.0/tests/test_admin.py +95 -0
  102. sifty-0.6.0/tests/test_agent.py +233 -0
  103. sifty-0.6.0/tests/test_ai_context.py +125 -0
  104. sifty-0.6.0/tests/test_checkup.py +54 -0
  105. sifty-0.6.0/tests/test_cleanup.py +75 -0
  106. sifty-0.6.0/tests/test_cli_json.py +46 -0
  107. sifty-0.6.0/tests/test_config.py +42 -0
  108. sifty-0.6.0/tests/test_disk.py +60 -0
  109. sifty-0.6.0/tests/test_history.py +66 -0
  110. sifty-0.6.0/tests/test_junk.py +106 -0
  111. sifty-0.6.0/tests/test_leftovers.py +92 -0
  112. sifty-0.6.0/tests/test_logsetup.py +67 -0
  113. sifty-0.6.0/tests/test_optimize.py +62 -0
  114. sifty-0.6.0/tests/test_organize.py +81 -0
  115. sifty-0.6.0/tests/test_path_picker.py +72 -0
  116. sifty-0.6.0/tests/test_profiles.py +43 -0
  117. sifty-0.6.0/tests/test_purge.py +94 -0
  118. sifty-0.6.0/tests/test_registry_scan.py +126 -0
  119. sifty-0.6.0/tests/test_safety.py +99 -0
  120. sifty-0.6.0/tests/test_schedule.py +68 -0
  121. sifty-0.6.0/tests/test_services.py +36 -0
  122. sifty-0.6.0/tests/test_startup.py +68 -0
  123. sifty-0.6.0/tests/test_tools.py +115 -0
  124. sifty-0.6.0/tests/test_tui.py +541 -0
  125. sifty-0.6.0/tests/test_updates.py +31 -0
  126. sifty-0.6.0/tests/test_vcs.py +59 -0
  127. sifty-0.6.0/tests/test_watch.py +56 -0
sifty-0.6.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amine Zouaoui
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.
sifty-0.6.0/PKG-INFO ADDED
@@ -0,0 +1,254 @@
1
+ Metadata-Version: 2.4
2
+ Name: sifty
3
+ Version: 0.6.0
4
+ Summary: Sifty — an AI-assisted Windows maintenance CLI/TUI: sift junk, analyze disks, manage apps, updates and files. Recycle Bin only, dry-run by default.
5
+ Author: Amine Zouaoui
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Vortrix5/sifty
8
+ Project-URL: Repository, https://github.com/Vortrix5/sifty
9
+ Project-URL: Issues, https://github.com/Vortrix5/sifty/issues
10
+ Project-URL: Changelog, https://github.com/Vortrix5/sifty/blob/main/CHANGELOG.md
11
+ Keywords: windows,maintenance,cleaner,junk,disk-usage,duplicates,uninstaller,winget,tui,textual,ollama
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: End Users/Desktop
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: Microsoft :: Windows
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: System :: Systems Administration
23
+ Classifier: Topic :: Utilities
24
+ Requires-Python: >=3.11
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: typer>=0.12
28
+ Requires-Dist: rich>=13.7
29
+ Requires-Dist: psutil>=5.9
30
+ Requires-Dist: send2trash>=1.8
31
+ Requires-Dist: pywin32>=306; sys_platform == "win32"
32
+ Requires-Dist: winshell>=0.6; sys_platform == "win32"
33
+ Requires-Dist: windows-toasts>=1.1; sys_platform == "win32"
34
+ Requires-Dist: httpx>=0.27
35
+ Requires-Dist: textual>=0.60
36
+ Provides-Extra: dev
37
+ Requires-Dist: pytest>=8.0; extra == "dev"
38
+ Requires-Dist: pytest-mock>=3.12; extra == "dev"
39
+ Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
40
+ Requires-Dist: textual-dev>=1.5; extra == "dev"
41
+ Requires-Dist: ruff>=0.4; extra == "dev"
42
+ Dynamic: license-file
43
+
44
+ # Sifty
45
+
46
+ > An AI-assisted Windows maintenance CLI + TUI that **sifts the junk from the keep**.
47
+
48
+ ![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue)
49
+ ![Windows](https://img.shields.io/badge/platform-Windows%2010%2F11-0078d4)
50
+ ![License: MIT](https://img.shields.io/badge/license-MIT-green)
51
+ ![CI](https://github.com/Vortrix5/sifty/actions/workflows/ci.yml/badge.svg)
52
+
53
+ Clean junk, analyze disks, find duplicates, manage apps and startup programs,
54
+ apply updates, prune dev artifacts and git worktrees, and organize files — from
55
+ a scriptable CLI or a full-screen terminal UI. The optional AI assistant runs
56
+ **locally** via [Ollama]: nothing leaves your machine, and it only ever sees
57
+ file *metadata* (names, sizes, paths), never file contents.
58
+
59
+ <!-- TODO: add a demo GIF of `sifty tui` here — it sells the project better
60
+ than anything below. `textual run --dev` + any screen recorder works. -->
61
+
62
+ ## Safety first
63
+
64
+ Sifty deletes files and changes system state, so it is built to be hard to misuse:
65
+
66
+ - **Dry-run by default** — every destructive command previews what it would do.
67
+ Real changes need an explicit `--apply`.
68
+ - **Recycle Bin, never permanent delete** — all removals go through one
69
+ `trash()` function backed by Send2Trash. `sifty undo` restores the last clean.
70
+ - **Protected paths** — `C:\Windows`, `Program Files`, `ProgramData`, the drive
71
+ root and your profile root are refused even with `--apply --yes`.
72
+ - **Audit log** — every applied deletion is recorded in `%APPDATA%\sifty\audit.log`.
73
+ - **The AI never deletes anything** — it is advisory; high-risk tool calls
74
+ always require your approval.
75
+
76
+ ## How it compares
77
+
78
+ | Feature | Sifty | CCleaner | Revo Uninstaller | WinDirStat |
79
+ | --- | --- | --- | --- | --- |
80
+ | Junk / cache cleaning | ✅ 11+ categories | ✅ | ➖ | ❌ |
81
+ | Disk usage analysis | ✅ top-N + volumes | ➖ | ❌ | ✅ treemap |
82
+ | Duplicate finder | ✅ SHA-256, NTFS-aware | ✅ (paid) | ❌ | ❌ |
83
+ | App uninstall + leftover scan | ✅ winget + leftovers | ✅ | ✅ + leftovers | ❌ |
84
+ | App updates | ✅ via winget | ✅ (paid) | ❌ | ❌ |
85
+ | Startup manager | ✅ reversible | ✅ | ✅ | ❌ |
86
+ | Dev artifact purge (node_modules, …) | ✅ | ❌ | ❌ | ❌ |
87
+ | Git worktree / WSL2 VHD cleanup | ✅ | ❌ | ❌ | ❌ |
88
+ | Local AI assistant | ✅ Ollama | ❌ | ❌ | ❌ |
89
+ | Scriptable (JSON output) | ✅ | ❌ | ❌ | ❌ |
90
+ | Recycle Bin + undo for everything | ✅ | ➖ | ➖ | n/a |
91
+ | Price | Free, MIT | Freemium | Freemium | Free |
92
+
93
+ Sifty is built **developer-first**: everything is scriptable, the engine is a
94
+ reusable Python library, and it cleans the things developer machines actually
95
+ accumulate (build artifacts, orphaned worktrees, bloated WSL2 disks).
96
+
97
+ ## Install
98
+
99
+ ```powershell
100
+ # from source (recommended while pre-PyPI)
101
+ git clone https://github.com/Vortrix5/sifty && cd sifty
102
+ pipx install --editable . # or: pip install .
103
+
104
+ sifty doctor # check admin rights, winget, Ollama
105
+ ```
106
+
107
+ For development:
108
+
109
+ ```powershell
110
+ python -m venv .venv
111
+ .\.venv\Scripts\python.exe -m pip install -e ".[dev]"
112
+ .\.venv\Scripts\python.exe -m pytest -q
113
+ ```
114
+
115
+ ## Usage
116
+
117
+ ```powershell
118
+ sifty checkup # one read-only scan of everything: junk, updates,
119
+ # orphans, stale files, disk space, startup
120
+ sifty tui # the full-screen interactive app
121
+
122
+ # Junk
123
+ sifty junk scan # show reclaimable space per category
124
+ sifty junk clean # preview removal (dry-run)
125
+ sifty junk clean --apply # send junk to the Recycle Bin (asks first)
126
+
127
+ # Disk
128
+ sifty disk volumes # used/free/total per volume
129
+ sifty disk analyze C:\Users # biggest folders/files under a path
130
+ sifty disk duplicates D:\ # find duplicate files and wasted space
131
+
132
+ # Apps & updates
133
+ sifty apps list --by-size # installed apps, largest first
134
+ sifty apps orphans # broken uninstall entries in the registry
135
+ sifty apps uninstall "App" # uninstall via winget (preview, then --apply)
136
+ sifty apps leftovers "App" # what the uninstaller left behind (then --apply)
137
+ sifty update check # available updates (winget)
138
+ sifty update apply # upgrade everything (asks first)
139
+
140
+ # Developer cleanup
141
+ sifty purge clean # node_modules, dist, __pycache__, target, …
142
+ sifty cleanup duplicates D:\Photos # de-duplicate (keeps one copy each)
143
+ sifty cleanup large C:\Users\you # biggest files under a path
144
+ sifty cleanup stale --days 180 # old items in Downloads
145
+
146
+ # Startup & services
147
+ sifty startup list # startup programs (enabled/disabled)
148
+ sifty startup disable "Spotify" # reversible (sifty startup enable …)
149
+ sifty services list # curated optional services + state
150
+ sifty --admin services disable DiagTrack # toggle one (needs admin)
151
+
152
+ # History & undo
153
+ sifty history # what was cleaned + total space reclaimed
154
+ sifty undo # restore the most recent clean from the Recycle Bin
155
+
156
+ # Organize files
157
+ sifty organize preview C:\Users\you\Downloads --by type
158
+ sifty organize apply C:\Users\you\Downloads --by date
159
+ sifty organize undo # put the last organize's files back
160
+
161
+ # Configuration
162
+ sifty config # all settings + which ones you've overridden
163
+ sifty config set ai.model "llama3.2:3b"
164
+ sifty config edit # open config.toml in your editor
165
+
166
+ # AI (requires Ollama running)
167
+ sifty ai status
168
+ sifty ai ask "what can I safely delete on my C drive?" --path C:\
169
+
170
+ # Scripting — JSON output on read-only commands (auto-enabled when piped)
171
+ sifty --json checkup
172
+ sifty --json disk volumes
173
+ sifty --json apps list --by-size
174
+ ```
175
+
176
+ Some operations (Windows temp, update cache, certain uninstalls) need an
177
+ **Administrator** terminal — `sifty doctor` tells you if you're elevated, and
178
+ `sifty --admin <cmd>` relaunches elevated via UAC.
179
+
180
+ ## The TUI
181
+
182
+ `sifty tui` opens a full-screen app with a seven-section sidebar — Home,
183
+ Clean, Disk, Apps, Monitor, Reports, AI:
184
+
185
+ - **Home** — volume gauges and a **Run checkup** button that scans everything
186
+ at once; findings come with buttons that fix them right there (clean junk,
187
+ clean stale downloads, apply updates — each behind a confirm).
188
+ - **Clean** — Junk / Purge / Optimize / Smart cleanup under one roof (tabs).
189
+ - **Apps** — Installed / Updates / Startup / Services, with fuzzy filter,
190
+ sorting, bulk uninstall, and an automatic leftover scan after uninstalling.
191
+ - **AI** — an agentic chat: tool runs it proposes show **Run/Skip buttons
192
+ inline in the conversation**, and scan results carry follow-up action
193
+ buttons.
194
+
195
+ Press **Ctrl+P** for the command palette (jump to any screen), **F2** to
196
+ elevate, **Space** to mark rows for bulk actions. The **Reports** screen shows
197
+ space reclaimed over time with an **Undo last clean** button.
198
+
199
+ ## AI setup (optional)
200
+
201
+ 1. Install [Ollama] and start it.
202
+ 2. Pull the configured model: `ollama pull qwen2.5:3b`.
203
+ 3. `sifty ai status` should report "running".
204
+
205
+ Configure in `%APPDATA%\sifty\config.toml`:
206
+
207
+ ```toml
208
+ [ai]
209
+ host = "http://localhost:11434"
210
+ model = "qwen2.5:3b"
211
+
212
+ [safety]
213
+ extra_protected_paths = ["D:\\Important"]
214
+
215
+ [junk]
216
+ include_downloads_installers = false
217
+ ```
218
+
219
+ ## Architecture
220
+
221
+ Layered — thin frontends over a reusable engine, OS specifics quarantined:
222
+
223
+ ```text
224
+ src/sifty/
225
+ ├── cli/ # Typer entry point + one thin command module per group
226
+ ├── tui/ # Textual full-screen app (views call core, not cli)
227
+ ├── core/ # the engine: junk, disk, apps, updates, cleanup,
228
+ │ │ # startup, services, organize, checkup, history, …
229
+ │ └── safety.py # ★ protected paths, dry-run guard, trash(), audit log
230
+ ├── windows/ # OS primitives: winget, registry, UAC, Recycle Bin, DISM
231
+ ├── ai/ # Ollama client, advisor prompts, agentic tool loop
232
+ └── infra/ # TOML config + rotating diagnostics log
233
+ ```
234
+
235
+ Frontends depend on `core`; `core` depends on `windows`/`infra`; nothing
236
+ imports upward. A GUI could call the same engine functions (`junk.scan`,
237
+ `disk.find_duplicates`, `checkup.run_checkup`) without a rewrite. See
238
+ [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the design rationale.
239
+
240
+ ## Tests
241
+
242
+ ```powershell
243
+ .\.venv\Scripts\python.exe -m pytest -q # 160+ tests, ~20 s
244
+ ```
245
+
246
+ The safety guardrails are the most heavily tested code in the repo; the Windows
247
+ environment is mocked so the suite also runs on CI. See
248
+ [CONTRIBUTING.md](CONTRIBUTING.md) to get involved.
249
+
250
+ ## License
251
+
252
+ [MIT](LICENSE) © Amine Zouaoui
253
+
254
+ [Ollama]: https://ollama.com
sifty-0.6.0/README.md ADDED
@@ -0,0 +1,211 @@
1
+ # Sifty
2
+
3
+ > An AI-assisted Windows maintenance CLI + TUI that **sifts the junk from the keep**.
4
+
5
+ ![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue)
6
+ ![Windows](https://img.shields.io/badge/platform-Windows%2010%2F11-0078d4)
7
+ ![License: MIT](https://img.shields.io/badge/license-MIT-green)
8
+ ![CI](https://github.com/Vortrix5/sifty/actions/workflows/ci.yml/badge.svg)
9
+
10
+ Clean junk, analyze disks, find duplicates, manage apps and startup programs,
11
+ apply updates, prune dev artifacts and git worktrees, and organize files — from
12
+ a scriptable CLI or a full-screen terminal UI. The optional AI assistant runs
13
+ **locally** via [Ollama]: nothing leaves your machine, and it only ever sees
14
+ file *metadata* (names, sizes, paths), never file contents.
15
+
16
+ <!-- TODO: add a demo GIF of `sifty tui` here — it sells the project better
17
+ than anything below. `textual run --dev` + any screen recorder works. -->
18
+
19
+ ## Safety first
20
+
21
+ Sifty deletes files and changes system state, so it is built to be hard to misuse:
22
+
23
+ - **Dry-run by default** — every destructive command previews what it would do.
24
+ Real changes need an explicit `--apply`.
25
+ - **Recycle Bin, never permanent delete** — all removals go through one
26
+ `trash()` function backed by Send2Trash. `sifty undo` restores the last clean.
27
+ - **Protected paths** — `C:\Windows`, `Program Files`, `ProgramData`, the drive
28
+ root and your profile root are refused even with `--apply --yes`.
29
+ - **Audit log** — every applied deletion is recorded in `%APPDATA%\sifty\audit.log`.
30
+ - **The AI never deletes anything** — it is advisory; high-risk tool calls
31
+ always require your approval.
32
+
33
+ ## How it compares
34
+
35
+ | Feature | Sifty | CCleaner | Revo Uninstaller | WinDirStat |
36
+ | --- | --- | --- | --- | --- |
37
+ | Junk / cache cleaning | ✅ 11+ categories | ✅ | ➖ | ❌ |
38
+ | Disk usage analysis | ✅ top-N + volumes | ➖ | ❌ | ✅ treemap |
39
+ | Duplicate finder | ✅ SHA-256, NTFS-aware | ✅ (paid) | ❌ | ❌ |
40
+ | App uninstall + leftover scan | ✅ winget + leftovers | ✅ | ✅ + leftovers | ❌ |
41
+ | App updates | ✅ via winget | ✅ (paid) | ❌ | ❌ |
42
+ | Startup manager | ✅ reversible | ✅ | ✅ | ❌ |
43
+ | Dev artifact purge (node_modules, …) | ✅ | ❌ | ❌ | ❌ |
44
+ | Git worktree / WSL2 VHD cleanup | ✅ | ❌ | ❌ | ❌ |
45
+ | Local AI assistant | ✅ Ollama | ❌ | ❌ | ❌ |
46
+ | Scriptable (JSON output) | ✅ | ❌ | ❌ | ❌ |
47
+ | Recycle Bin + undo for everything | ✅ | ➖ | ➖ | n/a |
48
+ | Price | Free, MIT | Freemium | Freemium | Free |
49
+
50
+ Sifty is built **developer-first**: everything is scriptable, the engine is a
51
+ reusable Python library, and it cleans the things developer machines actually
52
+ accumulate (build artifacts, orphaned worktrees, bloated WSL2 disks).
53
+
54
+ ## Install
55
+
56
+ ```powershell
57
+ # from source (recommended while pre-PyPI)
58
+ git clone https://github.com/Vortrix5/sifty && cd sifty
59
+ pipx install --editable . # or: pip install .
60
+
61
+ sifty doctor # check admin rights, winget, Ollama
62
+ ```
63
+
64
+ For development:
65
+
66
+ ```powershell
67
+ python -m venv .venv
68
+ .\.venv\Scripts\python.exe -m pip install -e ".[dev]"
69
+ .\.venv\Scripts\python.exe -m pytest -q
70
+ ```
71
+
72
+ ## Usage
73
+
74
+ ```powershell
75
+ sifty checkup # one read-only scan of everything: junk, updates,
76
+ # orphans, stale files, disk space, startup
77
+ sifty tui # the full-screen interactive app
78
+
79
+ # Junk
80
+ sifty junk scan # show reclaimable space per category
81
+ sifty junk clean # preview removal (dry-run)
82
+ sifty junk clean --apply # send junk to the Recycle Bin (asks first)
83
+
84
+ # Disk
85
+ sifty disk volumes # used/free/total per volume
86
+ sifty disk analyze C:\Users # biggest folders/files under a path
87
+ sifty disk duplicates D:\ # find duplicate files and wasted space
88
+
89
+ # Apps & updates
90
+ sifty apps list --by-size # installed apps, largest first
91
+ sifty apps orphans # broken uninstall entries in the registry
92
+ sifty apps uninstall "App" # uninstall via winget (preview, then --apply)
93
+ sifty apps leftovers "App" # what the uninstaller left behind (then --apply)
94
+ sifty update check # available updates (winget)
95
+ sifty update apply # upgrade everything (asks first)
96
+
97
+ # Developer cleanup
98
+ sifty purge clean # node_modules, dist, __pycache__, target, …
99
+ sifty cleanup duplicates D:\Photos # de-duplicate (keeps one copy each)
100
+ sifty cleanup large C:\Users\you # biggest files under a path
101
+ sifty cleanup stale --days 180 # old items in Downloads
102
+
103
+ # Startup & services
104
+ sifty startup list # startup programs (enabled/disabled)
105
+ sifty startup disable "Spotify" # reversible (sifty startup enable …)
106
+ sifty services list # curated optional services + state
107
+ sifty --admin services disable DiagTrack # toggle one (needs admin)
108
+
109
+ # History & undo
110
+ sifty history # what was cleaned + total space reclaimed
111
+ sifty undo # restore the most recent clean from the Recycle Bin
112
+
113
+ # Organize files
114
+ sifty organize preview C:\Users\you\Downloads --by type
115
+ sifty organize apply C:\Users\you\Downloads --by date
116
+ sifty organize undo # put the last organize's files back
117
+
118
+ # Configuration
119
+ sifty config # all settings + which ones you've overridden
120
+ sifty config set ai.model "llama3.2:3b"
121
+ sifty config edit # open config.toml in your editor
122
+
123
+ # AI (requires Ollama running)
124
+ sifty ai status
125
+ sifty ai ask "what can I safely delete on my C drive?" --path C:\
126
+
127
+ # Scripting — JSON output on read-only commands (auto-enabled when piped)
128
+ sifty --json checkup
129
+ sifty --json disk volumes
130
+ sifty --json apps list --by-size
131
+ ```
132
+
133
+ Some operations (Windows temp, update cache, certain uninstalls) need an
134
+ **Administrator** terminal — `sifty doctor` tells you if you're elevated, and
135
+ `sifty --admin <cmd>` relaunches elevated via UAC.
136
+
137
+ ## The TUI
138
+
139
+ `sifty tui` opens a full-screen app with a seven-section sidebar — Home,
140
+ Clean, Disk, Apps, Monitor, Reports, AI:
141
+
142
+ - **Home** — volume gauges and a **Run checkup** button that scans everything
143
+ at once; findings come with buttons that fix them right there (clean junk,
144
+ clean stale downloads, apply updates — each behind a confirm).
145
+ - **Clean** — Junk / Purge / Optimize / Smart cleanup under one roof (tabs).
146
+ - **Apps** — Installed / Updates / Startup / Services, with fuzzy filter,
147
+ sorting, bulk uninstall, and an automatic leftover scan after uninstalling.
148
+ - **AI** — an agentic chat: tool runs it proposes show **Run/Skip buttons
149
+ inline in the conversation**, and scan results carry follow-up action
150
+ buttons.
151
+
152
+ Press **Ctrl+P** for the command palette (jump to any screen), **F2** to
153
+ elevate, **Space** to mark rows for bulk actions. The **Reports** screen shows
154
+ space reclaimed over time with an **Undo last clean** button.
155
+
156
+ ## AI setup (optional)
157
+
158
+ 1. Install [Ollama] and start it.
159
+ 2. Pull the configured model: `ollama pull qwen2.5:3b`.
160
+ 3. `sifty ai status` should report "running".
161
+
162
+ Configure in `%APPDATA%\sifty\config.toml`:
163
+
164
+ ```toml
165
+ [ai]
166
+ host = "http://localhost:11434"
167
+ model = "qwen2.5:3b"
168
+
169
+ [safety]
170
+ extra_protected_paths = ["D:\\Important"]
171
+
172
+ [junk]
173
+ include_downloads_installers = false
174
+ ```
175
+
176
+ ## Architecture
177
+
178
+ Layered — thin frontends over a reusable engine, OS specifics quarantined:
179
+
180
+ ```text
181
+ src/sifty/
182
+ ├── cli/ # Typer entry point + one thin command module per group
183
+ ├── tui/ # Textual full-screen app (views call core, not cli)
184
+ ├── core/ # the engine: junk, disk, apps, updates, cleanup,
185
+ │ │ # startup, services, organize, checkup, history, …
186
+ │ └── safety.py # ★ protected paths, dry-run guard, trash(), audit log
187
+ ├── windows/ # OS primitives: winget, registry, UAC, Recycle Bin, DISM
188
+ ├── ai/ # Ollama client, advisor prompts, agentic tool loop
189
+ └── infra/ # TOML config + rotating diagnostics log
190
+ ```
191
+
192
+ Frontends depend on `core`; `core` depends on `windows`/`infra`; nothing
193
+ imports upward. A GUI could call the same engine functions (`junk.scan`,
194
+ `disk.find_duplicates`, `checkup.run_checkup`) without a rewrite. See
195
+ [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the design rationale.
196
+
197
+ ## Tests
198
+
199
+ ```powershell
200
+ .\.venv\Scripts\python.exe -m pytest -q # 160+ tests, ~20 s
201
+ ```
202
+
203
+ The safety guardrails are the most heavily tested code in the repo; the Windows
204
+ environment is mocked so the suite also runs on CI. See
205
+ [CONTRIBUTING.md](CONTRIBUTING.md) to get involved.
206
+
207
+ ## License
208
+
209
+ [MIT](LICENSE) © Amine Zouaoui
210
+
211
+ [Ollama]: https://ollama.com
@@ -0,0 +1,82 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "sifty"
7
+ version = "0.6.0"
8
+ description = "Sifty — an AI-assisted Windows maintenance CLI/TUI: sift junk, analyze disks, manage apps, updates and files. Recycle Bin only, dry-run by default."
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ authors = [{ name = "Amine Zouaoui" }]
12
+ license = { text = "MIT" }
13
+ keywords = [
14
+ "windows", "maintenance", "cleaner", "junk", "disk-usage", "duplicates",
15
+ "uninstaller", "winget", "tui", "textual", "ollama",
16
+ ]
17
+ classifiers = [
18
+ "Development Status :: 4 - Beta",
19
+ "Environment :: Console",
20
+ "Intended Audience :: Developers",
21
+ "Intended Audience :: End Users/Desktop",
22
+ "License :: OSI Approved :: MIT License",
23
+ "Operating System :: Microsoft :: Windows",
24
+ "Programming Language :: Python :: 3",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
28
+ "Topic :: System :: Systems Administration",
29
+ "Topic :: Utilities",
30
+ ]
31
+ dependencies = [
32
+ "typer>=0.12",
33
+ "rich>=13.7",
34
+ "psutil>=5.9",
35
+ "send2trash>=1.8",
36
+ "pywin32>=306; sys_platform == 'win32'",
37
+ "winshell>=0.6; sys_platform == 'win32'",
38
+ "windows-toasts>=1.1; sys_platform == 'win32'",
39
+ "httpx>=0.27",
40
+ "textual>=0.60",
41
+ ]
42
+
43
+ [project.urls]
44
+ Homepage = "https://github.com/Vortrix5/sifty"
45
+ Repository = "https://github.com/Vortrix5/sifty"
46
+ Issues = "https://github.com/Vortrix5/sifty/issues"
47
+ Changelog = "https://github.com/Vortrix5/sifty/blob/main/CHANGELOG.md"
48
+
49
+ [project.optional-dependencies]
50
+ dev = [
51
+ "pytest>=8.0",
52
+ "pytest-mock>=3.12",
53
+ "pytest-asyncio>=0.23",
54
+ "textual-dev>=1.5",
55
+ "ruff>=0.4",
56
+ ]
57
+
58
+ [project.scripts]
59
+ sifty = "sifty.cli.app:entrypoint"
60
+
61
+ [tool.setuptools.packages.find]
62
+ where = ["src"]
63
+
64
+ [tool.setuptools.package-data]
65
+ sifty = ["tui/*.tcss"]
66
+
67
+ [tool.pytest.ini_options]
68
+ pythonpath = ["src"]
69
+ testpaths = ["tests"]
70
+ asyncio_mode = "auto"
71
+
72
+ [tool.ruff]
73
+ line-length = 120
74
+ target-version = "py311"
75
+ src = ["src", "tests"]
76
+
77
+ [tool.ruff.lint]
78
+ select = ["E", "F", "W", "I", "UP", "B"]
79
+ ignore = [
80
+ "E501", # line length is advisory; Rich markup strings run long
81
+ "B008", # `typer.Option(...)` in defaults is Typer's standard idiom
82
+ ]
sifty-0.6.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ """Sifty — an AI-assisted Windows maintenance CLI that sifts the junk from the keep."""
2
+
3
+ __version__ = "0.6.0"
@@ -0,0 +1,6 @@
1
+ """Enable ``python -m sifty`` as an alternative to the ``sifty`` console script."""
2
+
3
+ from .cli.app import entrypoint
4
+
5
+ if __name__ == "__main__":
6
+ entrypoint()
@@ -0,0 +1 @@
1
+ """Local AI layer (Ollama) — advises, never acts on its own."""
@@ -0,0 +1,71 @@
1
+ """AI advisory prompts.
2
+
3
+ The advisor only ever receives *metadata* — names, sizes, paths, extensions,
4
+ counts — never file contents. It explains and recommends; it never deletes.
5
+ The calling command does the acting, with the usual dry-run/confirm safeguards.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from .client import OllamaClient, OllamaUnavailable
11
+
12
+ SYSTEM_PROMPT = (
13
+ "You are Sifty, a careful Windows maintenance assistant embedded in a CLI/TUI "
14
+ "tool. You are given only file/app metadata, never file contents. Be concise, "
15
+ "practical, and cautious; when unsure whether something is safe to remove, say so. "
16
+ "Format answers in Markdown.\n\n"
17
+ "To remove an installed program, ALWAYS recommend a proper uninstall — Sifty's own "
18
+ "`apps` command (which uses winget under the hood), `winget uninstall`, or Windows "
19
+ "Settings > Apps. NEVER tell the user to manually delete a program's folder under "
20
+ "C:\\Program Files, C:\\Program Files (x86), or to hand-edit files in C:\\Windows, "
21
+ "ProgramData, or their personal documents — Sifty refuses those paths anyway, and "
22
+ "manual deletion leaves the registry and the system in a broken state. Do not "
23
+ "suggest `DISM` or `sfc /scannow` unless the user explicitly reports system file "
24
+ "corruption; they are not part of uninstalling an app.\n\n"
25
+ "Sifty deletes safely (to the Recycle Bin, dry-run by default), so point users at "
26
+ "Sifty's commands rather than destructive manual steps."
27
+ )
28
+
29
+ # Back-compat alias for internal callers.
30
+ _SYSTEM = SYSTEM_PROMPT
31
+
32
+
33
+ def _safe(client: OllamaClient, user_prompt: str) -> str | None:
34
+ """Run a prompt, returning None if the AI is unavailable."""
35
+ if not client.is_available():
36
+ return None
37
+ try:
38
+ return client.chat(_SYSTEM, user_prompt)
39
+ except OllamaUnavailable:
40
+ return None
41
+
42
+
43
+ def explain_item(client: OllamaClient, name: str, path: str, size_human: str) -> str | None:
44
+ """Explain what an item is and whether it's safe to remove."""
45
+ return _safe(
46
+ client,
47
+ f"What is this Windows item, and is it generally safe to delete?\n"
48
+ f"Name: {name}\nPath: {path}\nSize: {size_human}\n"
49
+ f"Answer in 2-3 sentences.",
50
+ )
51
+
52
+
53
+ def summarize_disk(client: OllamaClient, items: list[tuple[str, str]], question: str) -> str | None:
54
+ """Answer a natural-language question about the biggest disk items."""
55
+ listing = "\n".join(f"- {name}: {size}" for name, size in items)
56
+ return _safe(
57
+ client,
58
+ f"Here are the largest items in a directory:\n{listing}\n\n"
59
+ f"User question: {question}\n"
60
+ f"Give a brief, practical answer and flag anything risky to delete.",
61
+ )
62
+
63
+
64
+ def suggest_organization(client: OllamaClient, sample_names: list[str]) -> str | None:
65
+ """Propose a folder scheme for a messy directory from sample filenames."""
66
+ listing = "\n".join(f"- {n}" for n in sample_names[:40])
67
+ return _safe(
68
+ client,
69
+ f"These are sample filenames from a cluttered folder:\n{listing}\n\n"
70
+ f"Suggest a simple folder structure to organize them. Be concise.",
71
+ )