Skip to content

v1.0.9: Platform-Aware Architecture (Windows & Linux)

Choose a tag to compare

@github-actions github-actions released this 17 Aug 23:59
· 7 commits to master since this release

Platform-aware architecture release: Startup, Services, and System Updates managers that adapt to Windows or Linux, plus cross-platform App Updates.

Added

  • Platform Capability Registry: introduces crapcleaner.system.capabilities, the single source of truth for which system-management features the running operating system provides and what each one is called there. The navigation rail, the page set, the view headings, and the CLI all read from it, so no user-facing code branches on the operating system. Supporting another platform means adding backend modules and one registry entry per capability.
  • Platform-Neutral Dispatchers & Per-OS Backends: splits the startup, service, and update managers into a shared dispatcher holding the data model, cache, and safety rules, over a backend per operating system in crapcleaner.system.backends. Platform dependencies stay inside their own backend: winreg, PowerShell, and sc.exe appear only in the Windows modules, and systemctl, pkexec, and package-manager commands only in the Linux ones.
  • Linux Service Management via systemd: adds full parity with the Windows Services page for systemd, listing both system and user units with their active state and unit-file state, and offering start, stop, restart, and enable/disable/mask. System units elevate per command through pkexec so the application need not run as root, and units that keep a session alive - dbus, systemd-logind, polkit, user@, getty@ - are guarded the same way critical Windows services are.
  • Linux System Updates: adds distribution update management through apt, dnf/yum, pacman, and zypper, reporting pending updates with security errata marked, recent package history, and whether a reboot is pending.
  • Linux Startup Entry Management: completes XDG autostart support with enable, disable, and remove alongside the existing listing. A user entry shadows the packaged entry of the same name, and disabling or removing a system entry in root-owned /etc/xdg/autostart writes a user-level override that hides it rather than touching a file the package manager owns.
  • Graceful Handling of Unsupported Features: pages whose platform tooling is absent are hidden rather than shown broken, a navigation section whose entries are all unavailable is omitted, and every dispatcher entry point returns the registry's explanation instead of letting a platform command fail. A Linux system without systemd shows no Services page at all.
  • Platform-Filtered Memory Actions: offers only the reclamation actions the running kernel provides, so Windows lists the standby list purge and Linux lists the filesystem cache drop. Each action's description names the exact call that system will make - EmptyWorkingSet on Windows, malloc_trim and drop_caches on Linux - rather than listing every platform's mechanism at once. Requesting a hidden action by id still reports why it is unavailable instead of an unknown-action error.
  • --capabilities CLI Flag: reports which platform features the current operating system supports, with --json for automation.
  • Linux Privilege Escalation: teaches elevate() and relaunch_as_admin() to use pkexec, and reports administrative rights on Linux from the effective user id rather than assuming every non-Windows user is privileged.
  • Windows Startup Manager: introduces a dedicated Startup Applications manager that allows users to view, enable, disable, add, and remove programs and scripts configured to launch automatically with Windows. Inspects Current User and All Users Registry Run/RunOnce keys, modern StartupApproved flags, and user/system Startup folders with intelligent publisher discovery and boot impact estimations.
  • Windows Update Manager: adds comprehensive Windows Update inspection and management via PowerShell COM APIs (Microsoft.Update.Session). Displays pending update titles, KB IDs, severity levels, download states, package sizes, and support URLs, initiates update downloads and installations with administrative elevation enforcement, and provides complete installed hotfix history auditing.
  • Windows Services Manager: introduces interactive background service management enabling users to view, start, stop, restart, and configure startup types (Automatic, Automatic (Delayed Start), Manual, Disabled) for all installed Windows services. Features safety guardrails protecting critical OS services from accidental stoppage or disablement, multi-criteria filtering, and one-click access to the system management console (services.msc).
  • App Updates via Package Managers: adds a cross-platform application update manager (crapcleaner.system.package_managers) that detects the package managers installed on the current system and reports every available application upgrade in one place. Supports winget and chocolatey on Windows and apt/apt-get, flatpak, snap, pacman, and dnf/yum on Linux, with a two-minute result cache, live search, and per-manager filtering. Upgrades run one package at a time, across a multi-row selection, or across an entire manager, and a queued selection continues past any package that fails. Installers are allowed 30 minutes for a single package and 2 hours for a whole-manager upgrade, since large IDE, SDK, and creative-suite installers routinely run for many minutes.
  • Column-Accurate Package Manager Parsing: reads winget upgrade output using the column offsets declared in its own header, so a value that exactly fills its column, and is therefore separated from the next by a single space, still yields a usable package ID and version.
  • Friendly Windows Error Explanations: introduces crapcleaner.utils.windows_errors, translating raw 0x8024xxxx Windows Update and servicing failure codes into a plain-language title and remediation hint instead of surfacing the bare hexadecimal code.
  • New Sidebar Navigation & Material Icons: adds Startup Apps, Services, App Updates, and System Updates to the left navigation rail under the System tier, carrying the rocket_launch, tune, and system_update Material Icons, dynamically recoloured for each of the 43 theme palettes. The icon map also gains miscellaneous_services, play_arrow, and stop for use in the service control surfaces.
  • Platform-Aware Navigation Rail: teaches the sidebar to accept the set of pages the running platform actually provides, and to take each label from the capability registry so a page reads Windows Services on Windows and systemd Services on Linux.
  • CLI Management Options: adds --startup, --services, and --system-updates command-line flags with full --json export support for headless automation and terminal diagnostics. --windows-updates remains accepted as an alias.
  • Sortable Table Header Hover Feedback: adds a QHeaderView::section:hover style across all 43 themes so sortable column headers visibly respond before they are clicked.
  • Shared Visual Effects Toolkit: introduces crapcleaner.gui.effects with an animated count-up label, a history sparkline, a proportional segmented bar, and hover-depth and accent-glow helpers. Every colour resolves from a palette token, so all 43 themes are covered without per-theme code, and every animation honours the Reduce motion preference by landing on its final value instead of easing to it. Depth is split deliberately: widgets that repeat inside a scroll area use a painted hover, because a QGraphicsEffect renders through an offscreen pixmap that disables subpixel text antialiasing, while a real drop shadow is reserved for single hero surfaces.
  • Live Vitals Sparklines: draws a rolling 60-sample history under the Memory, Processor, Graphics, and Network cards on the Dashboard. The strips are fed from the vitals tick the Dashboard already runs, so no card owns a timer. Percentages plot against a fixed 0–100 ceiling for comparability over time, and network throughput auto-scales to its own peak.
  • Reclaimable Breakdown Panel: fills the empty lower third of the Dashboard with a proportional bar and the top categories by size, coloured by safety level. Before a first scan it lists the category groups a scan would check, so the panel is informative rather than blank on a fresh install.
  • Counting Headline Figures: eases the reclaimable total on the hero card and in the breakdown panel up to its new value when a scan completes.

Changed

  • Faster CLI Quick Scan: limits the --quick scan to the first five non-administrative, default-selected categories and caps it at 200 files, so a terminal health check returns promptly.
  • Platform-Neutral Storage Presets: resolves the Storage Breakdown preset buttons through the stdlib and the platform helpers, so Temp points at the real temporary directory and AppData becomes App Config pointing at $XDG_CONFIG_HOME on Linux.
  • Deprecated Windows-Flavoured Names: crapcleaner.system.windows_updates, WindowsUpdateItem, WindowsUpdateReport, WindowsUpdateView, WindowsUpdateWorker, WindowsUpdateInstallWorker, and open_services_msc remain importable as aliases of their platform-neutral replacements in system_updates, SystemUpdatesView, SystemUpdateWorker, SystemUpdateInstallWorker, and open_services_console.

Fixed

  • Windows Junctions Followed During Scanning And Cleanup: skips reparse points during every filesystem traversal. A Windows directory junction reports itself as an ordinary directory through S_ISLNK, os.path.islink, and DirEntry.is_dir(follow_symlinks=False), so the only reliable signal is its reparse tag, which nothing checked. A junction loop therefore recursed until the file budget ran out, counting the same files repeatedly and truncating the result, and a junction pointing outside the scanned tree presented unrelated files as reclaimable junk. crapcleaner.utils.files.walk_safe now backs the scan, preview, cleanup, duplicate, large-file, old-file, file-type, installer, and package-cache walks; links are reported as entries in their own right, so deleting a tree removes the link and leaves its target alone.
  • Deletion Following Junctions On Python 3.10 And 3.11: detaches links inside a tree before calling shutil.rmtree, which only learned to recognise junctions in Python 3.12 via os.DirEntry.is_junction. On the older interpreters this project supports, removing a cleanup target that contained a junction deleted the files it pointed at. The read-only attribute pass is likewise confined to the tree being removed.
  • Storage Breakdown Performance: analysing a large folder drops from roughly two minutes to about half a minute. analyze_file_types issued a fresh os.stat for every file even though the directory listing already carried its size, which alone accounted for about ninety of those seconds; sizes now come from the listing through walk_safe_entries. Directory measurement additionally walks top-level subtrees in parallel, which is safe because enumeration is dominated by syscalls that release the interpreter lock, and results are summed and re-sorted afterwards so the output never depends on completion order.
  • Storage Breakdown Progress And Cancellation: reports the current stage, files seen, and directory while an analysis runs, and adds a Cancel button. The three analysis passes all accepted a stop event and a progress callback, but the worker passed neither, so a multi-minute analysis showed no feedback and could not be stopped.
  • Application Startup: the window appears in roughly a third of the time. All sixteen pages were constructed before the window could be shown; pages are now built the first time they are opened, and a page built after a theme change picks up the current theme.
  • Windows-Only File Manager Commands In The GUI: replaces six unguarded explorer invocations with a platform-aware helper that uses the freedesktop file manager interface or xdg-open on Linux, and names the file manager correctly in menu labels. One of those call sites interpolated a path into a command string, so a file name containing a quote could alter the command; arguments are now always passed as a list.
  • Scan Performance: a full scan of every non-administrative category drops from over ten minutes to roughly one second on the development machine, and directory walking rises from about 108 files per second to over 100,000. validate_cleanup_path rebuilt the protected-root list and re-read config.json for every candidate file, costing around forty _getfinalpathname syscalls and a JSON parse each. The protected roots and exclusion rules are now cached and invalidated explicitly, a scan resolves each directory once instead of each file, and subdirectory checks derive from their parent without touching the filesystem.
  • Truncated Scan Totals: reclaimable totals were being cut short wherever a junction loop consumed the per-category file budget with duplicate entries, so the reported figure was both wrong and unstable between runs.
  • Exclusion Edits Not Applying: publishes a cache invalidation when settings are saved, so an exclusion added in Preferences takes effect on the next scan rather than after a restart.
  • Unreadable Stat Cards After Switching To A Light Theme: re-applies stat card and elevation-notice colours on every theme change. Those labels carry an inline stylesheet baked at construction time, which outranks the global sheet, so moving from a dark theme to a light one previously left the Safe Caches, Dev & AI Caches, Drives Detected, and Lifetime Cleaned values near-white on a near-white card. Affects the Dashboard and History views.
  • Ambiguous View Shortcuts: binds Ctrl+1Ctrl+9 and Ctrl+0 to the first ten sidebar views only. With sixteen pages the numbering previously wrapped round, binding Ctrl+1 through Ctrl+6 twice each, which Qt treats as ambiguous and refuses to fire at all.
  • Table Sorting RecursionError: resolves Error calling Python override of QTableWidgetItem::__lt__(): RecursionError: maximum recursion depth exceeded when sorting any table or tree column that falls back to a text comparison. PySide re-dispatches super().__lt__() straight back into the Python override that calls it, so NumericItem and _SizeSortedItem compare text directly.
  • Directory Size Scan File Budget: counts every visited entry against max_files in compute_dir_size and stops unwinding as soon as the budget is reached, keeping a deeply nested directory tree within its scan limit.
  • Repeated Protected-Path Import In Scan Loop: hoists the validate_cleanup_path import out of the per-file inner loop in compute_dir_size.

Full Changelog: v1.0.8.1...v1.0.9