FreshDesk 1.0.0 Fleet disk-reclamation planning Techlosoft App Janitor family - Team variant =============================================================================== WHAT IT IS ------------------------------------------------------------------------------- FreshDesk answers the question an IT team actually has about disk space: "Across all of our machines, where is the reclaimable space, which machines are the worst, and if we ran this policy everywhere, how much would we get back?" Every machine runs one command and drops a JSON report on a share. FreshDesk merges all of those reports into one fleet-wide picture, and turns any single category into a cleanup proposal that can be approved before anyone touches a disk. A one-machine cleaner cannot answer any of that. It can tell you that THIS laptop has 12 GB of cache. It cannot tell you that 60% of your fleet's reclaimable space is old installers sitting on nine machines, or that one kiosk accounts for a third of the total. FRESHDESK NEVER DELETES ANYTHING ------------------------------------------------------------------------------- This is the most important sentence in this file. FreshDesk MEASURES and PLANS. It does not delete, move, rename, truncate or modify a single file. There is no --apply flag, no --force, no "clean" command, and no code path anywhere in the program that removes anything. The source contains no call to os.Remove, os.RemoveAll, os.Rename, os.Truncate, os.Chmod or os.Chtimes, and shells out to nothing. The ONLY thing FreshDesk ever writes is the file you name with --out (and the directory that file lives in, if it does not exist yet). Everything else it touches, it opens read-only. Deletion is somebody else's job, deliberately: AppJanitor pattern-based cleanup on one machine CleanInstall policy-driven cleanup with a ledger of what it removed Take an approved FreshDesk plan to one of those tools and let it do the removal, with its own confirmation and its own audit trail. Splitting "measure" from "remove" is the point: the tool that produces the number that justifies a cleanup is not the tool that carries it out. HOW REPORTS TRAVEL ------------------------------------------------------------------------------- Reports are FILES. They are not pushed over a network, and FreshDesk contains no networking code of any kind - no agent, no server, no listening port, no outbound call, no telemetry. Each machine writes a report with --out. You collect those files however you already move files around: a file share, a sync folder, an RMM script that copies artifacts back, scp, a USB stick, an email attachment. FreshDesk then reads a directory full of them with --dir. That is a deliberate v1 choice. It means FreshDesk works in an air-gapped network on day one, needs no credentials, opens no ports, and can be audited by reading two commands in a batch file. Networked agents are on the roadmap below, not in this build. THE CATEGORY LIST IS BUILT-IN AND DOCUMENTED - NOT EXHAUSTIVE ------------------------------------------------------------------------------- FreshDesk measures six categories of well-known reclaimable space: temp_files scratch files and interrupted downloads caches regenerable application and browser caches logs application logs and rotated log archives crash_dumps crash reports, minidumps and core files old_installers downloaded installer packages kept after install empty_dirs directories left behind with no entries at all The patterns behind them are a fixed list compiled into the program. They are written out in full in the "PATTERNS" section below so you can check exactly what a number means before you act on it. They are NOT an exhaustive inventory of everything reclaimable on a machine. Applications invent new cache locations constantly, and a pattern list is always behind. Read a FreshDesk total as "at least this much is reclaimable under the documented rules", never as "this is all of it". If your fleet has an application that hoards space somewhere this list does not name, FreshDesk will not see it, and it will say nothing about it rather than guessing. Equally, a match is not a recommendation. FreshDesk reports that a file sits in a cache directory. Whether your organisation wants that file gone is a policy decision for a human, which is exactly why plan output is a proposal and not an action. COMMANDS ------------------------------------------------------------------------------- freshdesk survey --machine --roots [,...] --out [--categories ] [--json] The agent each machine runs. Walks the given roots, measures every category, and writes a JSON report. Per category it records the file count, the total bytes, and the oldest and newest item. The report also carries a per-item inventory (path, bytes, modification time) so that later merging and age filtering are exact rather than estimated. Example: freshdesk survey --machine reception-01 \ --roots C:\Users\reception\AppData,C:\Windows\Temp \ --out \\fileshare\freshdesk\reception-01.json freshdesk fleet [more.json ...] [--dir ] [--threshold ] [--top ] [--json] Merges every report into the fleet picture: total reclaimable space, a per-machine table sorted worst-first with each machine's share of the total, a per-category breakdown across the whole fleet, and the largest single items found anywhere. Machines at or above --threshold are flagged, and the command exits 2 so a scheduled job can notice. Example: freshdesk fleet --dir \\fileshare\freshdesk --threshold 5GB --top 20 freshdesk plan --dir [report.json ...] --category [--min-age 30d] [--json] Turns one category into an approvable proposal: what a fleet-wide cleanup of that category would recover, per machine and in total, plus how much was held back for being too recent. Nothing is deleted; the output is a number to take to whoever signs off, and then to AppJanitor or CleanInstall. Example: freshdesk plan --dir \\fileshare\freshdesk --category caches --min-age 30d PATTERNS ------------------------------------------------------------------------------- Matching is case-insensitive throughout. A "dir" pattern is matched against every directory component of a path below the survey root; one matching component claims the file. A "file" pattern is matched against the file's own name. temp_files dirs tmp, temp, .tmp, temporary internet files files *.tmp, *.temp, *.part, *.partial, *.crdownload, ~$* caches dirs cache, caches, .cache, cache2, cacheddata, cachestorage files *.cache logs dirs logs, log, diagnosticlogs files *.log, *.log.[0-9], *.log.gz, *.log.old, *.log.[0-9].gz crash_dumps dirs crashdumps, crashes, crashreports, crash reports, diagnosticreports, minidumps files *.dmp, *.mdmp, *.dump, *.crash, core.[0-9]* old_installers dirs installers, installer cache, packagecache files *.msi, *.msp, *.dmg, *.pkg, *.deb, *.rpm, *.appx, *.msix, *setup*.exe, *install*.exe empty_dirs Any directory below a root with no entries at all. The root itself is never counted. The directory's own size (st_size) is what is reported. Counting rules, in full: - Categories are evaluated in the order printed above and the FIRST match claims a file, so no byte is ever counted twice. A file called app.log inside a cache directory is counted as caches, because caches is evaluated before logs. - Symbolic links are never followed and never counted. - A file reachable through two different --roots is counted once. - Sizes are apparent size (st_size), the same number find -printf '%s' and stat report, not on-disk allocated blocks. - An unreadable directory is recorded in the report's "errors" list and the rest of the survey continues. AGES ------------------------------------------------------------------------------- --min-age accepts 12h, 30d, 6w, or a bare number meaning days. An item counts toward a plan when its age is at least the given value, measured at plan time from the modification time recorded in the survey. That rule is exactly equivalent to find's -mtime +(N-1). If you want to check a 30-day plan by hand: find -type f -mtime +29 Ages shown in tables are whole days rounded to the nearest day, so a few hours of clock skew or a DST shift never turns a 400-day-old file into a 399-day-old one. EXIT CODES ------------------------------------------------------------------------------- 0 success 1 usage error, unreadable input, or no usable reports 2 fleet completed and at least one machine is at or above --threshold FAULT ISOLATION ------------------------------------------------------------------------------- One bad report never stops a merge. A file that is empty, malformed, not a FreshDesk report, missing its machine name, or written by a newer format version is skipped with a printed reason, and every other report still merges correctly. Only when NOTHING is usable does the command fail. BUILDING ------------------------------------------------------------------------------- Go standard library only. No third-party dependencies, no module downloads. GOPROXY=off go build -o freshdesk . Cross-compiled binaries in dist/: freshdesk-windows-amd64.exe freshdesk-darwin-arm64 freshdesk-darwin-amd64 freshdesk-linux-amd64 ROADMAP ------------------------------------------------------------------------------- Networked agents A collector service so machines can hand their reports in directly instead of writing them to a share and hoping something copies them back. Reports stay signed, small and inspectable; the file-drop path stays supported and stays the default for air-gapped sites. Scheduled surveys Run the survey on a schedule and keep the history, so the fleet view gains a time axis: which machines are filling up fastest, whether last month's cleanup actually held, and what a site looks like the week before term starts rather than only today. Approval workflow Route a plan to whoever has to sign it off, record the approval, and hand the APPROVED plan - not a fresh guess - to AppJanitor or CleanInstall to execute, with the resulting ledger linked back to the plan that authorised it. FreshDesk still will not do the deleting. It will just make sure the tool that does is working from a number a human agreed to. NAMING ------------------------------------------------------------------------------- "FreshDesk" is an internal working name only. It collides with Freshdesk by Freshworks and must be cleared (trademark, domain and marketplace search) before any public build, landing page or store listing.