mac_cleaner 1.0.0 → 1.0.1

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.
@@ -0,0 +1,156 @@
1
+ require 'open3'
2
+ require 'fileutils'
3
+ require 'digest'
4
+
5
+ module MacCleaner
6
+ class Analyzer
7
+ MIN_LARGE_FILE_SIZE = 1_000_000_000 # 1GB
8
+ MIN_MEDIUM_FILE_SIZE = 100_000_000 # 100MB
9
+ CACHE_DIR = File.expand_path("~/.cache/mac_cleaner")
10
+
11
+ def initialize(path: "~")
12
+ @path = File.expand_path(path)
13
+ @path_hash = Digest::MD5.hexdigest(@path)
14
+ @large_files = []
15
+ @medium_files = []
16
+ @directories = []
17
+ @aggregated_directories = []
18
+ FileUtils.mkdir_p(CACHE_DIR)
19
+ end
20
+ def analyze
21
+ if cache_valid?
22
+ puts "Loading from cache..."
23
+ load_from_cache
24
+ display_results
25
+ return
26
+ end
27
+
28
+ puts "Analyzing #{@path}..."
29
+ scan_large_files
30
+ scan_medium_files
31
+ scan_directories
32
+ @aggregated_directories = aggregate_by_directory(@large_files + @medium_files)
33
+ save_to_cache
34
+ display_results
35
+ end
36
+
37
+ private
38
+
39
+ def scan_large_files
40
+ puts "Scanning for large files..."
41
+ cmd = "mdfind -onlyin '#{@path}' \"kMDItemFSSize > #{MIN_LARGE_FILE_SIZE}\""
42
+ stdout, stderr, status = Open3.capture3(cmd)
43
+
44
+ return unless status.success?
45
+
46
+ stdout.each_line do |line|
47
+ path = line.strip
48
+ size = File.size(path)
49
+ @large_files << { path: path, size: size }
50
+ end
51
+
52
+ @large_files.sort_by! { |f| -f[:size] }
53
+ end
54
+
55
+ def scan_medium_files
56
+ puts "Scanning for medium files..."
57
+ cmd = "mdfind -onlyin '#{@path}' \"kMDItemFSSize > #{MIN_MEDIUM_FILE_SIZE} && kMDItemFSSize < #{MIN_LARGE_FILE_SIZE}\""
58
+ stdout, stderr, status = Open3.capture3(cmd)
59
+
60
+ return unless status.success?
61
+
62
+ stdout.each_line do |line|
63
+ path = line.strip
64
+ size = File.size(path)
65
+ @medium_files << { path: path, size: size }
66
+ end
67
+
68
+ @medium_files.sort_by! { |f| -f[:size] }
69
+ end
70
+
71
+ def scan_directories
72
+ puts "Scanning directories..."
73
+ cmd = "du -d 1 -k '#{@path}'"
74
+ stdout, stderr, status = Open3.capture3(cmd)
75
+
76
+ return unless status.success?
77
+
78
+ stdout.each_line do |line|
79
+ size, path = line.split("\t")
80
+ next if path.strip == @path
81
+ @directories << { path: path.strip, size: size.to_i * 1024 }
82
+ end
83
+
84
+ @directories.sort_by! { |d| -d[:size] }
85
+ end
86
+
87
+ def display_results
88
+ puts "\n--- Top 10 Large Files ---"
89
+ @large_files.first(10).each do |file|
90
+ puts "#{format_bytes(file[:size])}\t#{file[:path]}"
91
+ end
92
+
93
+ puts "\n--- Top 10 Medium Files ---"
94
+ @medium_files.first(10).each do |file|
95
+ puts "#{format_bytes(file[:size])}\t#{file[:path]}"
96
+ end
97
+
98
+ puts "\n--- Top 10 Directories ---"
99
+ @directories.first(10).each do |dir|
100
+ puts "#{format_bytes(dir[:size])}\t#{dir[:path]}"
101
+ end
102
+
103
+ puts "\n--- Top 10 Aggregated Directories ---"
104
+ @aggregated_directories.first(10).each do |dir|
105
+ puts "#{format_bytes(dir[:size])} in #{dir[:count]} files\t#{dir[:path]}"
106
+ end
107
+ end
108
+
109
+ def cache_valid?
110
+ cache_file = "#{CACHE_DIR}/#{@path_hash}.cache"
111
+ return false unless File.exist?(cache_file)
112
+ (Time.now - File.mtime(cache_file)) < 3600 # 1 hour
113
+ end
114
+
115
+ def save_to_cache
116
+ cache_file = "#{CACHE_DIR}/#{@path_hash}.cache"
117
+ data = {
118
+ large_files: @large_files,
119
+ medium_files: @medium_files,
120
+ directories: @directories,
121
+ aggregated_directories: @aggregated_directories
122
+ }
123
+ File.write(cache_file, Marshal.dump(data))
124
+ end
125
+
126
+ def load_from_cache
127
+ cache_file = "#{CACHE_DIR}/#{@path_hash}.cache"
128
+ data = Marshal.load(File.read(cache_file))
129
+ @large_files = data[:large_files]
130
+ @medium_files = data[:medium_files]
131
+ @directories = data[:directories]
132
+ @aggregated_directories = data[:aggregated_directories]
133
+ end
134
+
135
+ def format_bytes(bytes)
136
+ return "0B" if bytes.zero?
137
+ units = ["B", "KB", "MB", "GB", "TB"]
138
+ i = (Math.log(bytes) / Math.log(1024)).floor
139
+ "%.2f%s" % [bytes.to_f / 1024**i, units[i]]
140
+ end
141
+
142
+ def aggregate_by_directory(files)
143
+ directories = Hash.new { |h, k| h[k] = { size: 0, count: 0 } }
144
+
145
+ files.each do |file|
146
+ dir = File.dirname(file[:path])
147
+ directories[dir][:size] += file[:size]
148
+ directories[dir][:count] += 1
149
+ end
150
+
151
+ directories.map do |path, data|
152
+ { path: path, size: data[:size], count: data[:count] }
153
+ end.sort_by! { |d| -d[:size] }
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,497 @@
1
+ require 'fileutils'
2
+
3
+ module MacCleaner
4
+ class Cleaner
5
+ def initialize(dry_run: false, sudo: false)
6
+ @dry_run = dry_run
7
+ @sudo = sudo
8
+ @total_size_cleaned = 0
9
+ end
10
+
11
+ def clean
12
+ CLEANUP_SECTIONS.each do |section|
13
+ if section[:sudo] && !@sudo
14
+ puts "\nSkipping '#{section[:name]}' (requires sudo)"
15
+ next
16
+ end
17
+ puts "\n#{section[:name]}"
18
+ section[:targets].each do |target|
19
+ clean_target(target, section[:sudo])
20
+ end
21
+ end
22
+ puts "\nCleanup complete. Total space freed: #{format_bytes(@total_size_cleaned)}"
23
+ end
24
+
25
+ private
26
+
27
+ def clean_target(target, sudo = false)
28
+ if target[:command]
29
+ puts " - #{target[:name]}"
30
+ system(target[:command]) unless @dry_run
31
+ return
32
+ end
33
+
34
+ paths = safe_glob(target[:path])
35
+ return if paths.empty?
36
+
37
+ deletion_candidates = []
38
+ total_size = 0
39
+
40
+ paths.each do |path|
41
+ next unless File.exist?(path)
42
+
43
+ size = get_size(path, sudo)
44
+ next if size.zero?
45
+
46
+ total_size += size
47
+ deletion_candidates << path
48
+ end
49
+
50
+ return if total_size.zero?
51
+
52
+ puts " - #{target[:name]}: #{format_bytes(total_size)}"
53
+ @total_size_cleaned += total_size
54
+
55
+ return if @dry_run
56
+
57
+ deletion_candidates.each do |path|
58
+ if sudo
59
+ system("sudo", "rm", "-rf", path)
60
+ else
61
+ FileUtils.rm_rf(path, verbose: false)
62
+ end
63
+ end
64
+ rescue MacCleaner::TooManyOpenFilesError
65
+ puts " - #{target[:name]}: skipped (too many files to scan)"
66
+ rescue Errno::EPERM, Errno::EACCES
67
+ # Skip paths we cannot access
68
+ end
69
+
70
+ def get_size(path, sudo = false)
71
+ return 0 unless File.exist?(path)
72
+ return 0 unless File.readable?(path)
73
+ command = sudo ? "sudo du -sk \"#{path}\"" : "du -sk \"#{path}\""
74
+ begin
75
+ `#{command}`.split.first.to_i * 1024
76
+ rescue
77
+ 0
78
+ end
79
+ end
80
+
81
+ def format_bytes(bytes)
82
+ return "0B" if bytes.zero?
83
+ units = ["B", "KB", "MB", "GB", "TB"]
84
+ i = (Math.log(bytes) / Math.log(1024)).floor
85
+ "%.2f%s" % [bytes.to_f / 1024**i, units[i]]
86
+ end
87
+
88
+ def safe_glob(pattern)
89
+ expanded = File.expand_path(pattern)
90
+ return [] unless File.exist?(expanded) || wildcard_pattern?(expanded)
91
+
92
+ segments = expanded.split(File::SEPARATOR)
93
+
94
+ current_paths =
95
+ if expanded.start_with?(File::SEPARATOR)
96
+ segments.shift
97
+ [File::SEPARATOR]
98
+ else
99
+ [segments.shift || expanded]
100
+ end
101
+
102
+ segments.reject!(&:empty?)
103
+ return current_paths if segments.empty? && File.exist?(expanded)
104
+
105
+ segments.each do |segment|
106
+ current_paths = current_paths.each_with_object([]) do |base, acc|
107
+ next unless base
108
+ next unless File.exist?(base)
109
+
110
+ if wildcard_pattern?(segment)
111
+ next unless File.directory?(base)
112
+
113
+ begin
114
+ Dir.each_child(base) do |entry|
115
+ next if entry == "." || entry == ".."
116
+ next unless File.fnmatch?(segment, entry, GLOB_FLAGS)
117
+ acc << File.join(base, entry)
118
+ end
119
+ rescue Errno::EMFILE
120
+ raise MacCleaner::TooManyOpenFilesError
121
+ rescue Errno::ENOENT, Errno::EACCES, Errno::EPERM
122
+ next
123
+ end
124
+ else
125
+ candidate = File.join(base, segment)
126
+ acc << candidate if File.exist?(candidate)
127
+ end
128
+ end
129
+
130
+ return [] if current_paths.empty?
131
+ end
132
+
133
+ current_paths.map { |path| File.expand_path(path) }.uniq.sort
134
+ end
135
+
136
+ def wildcard_pattern?(segment)
137
+ segment.match?(WILDCARD_PATTERN)
138
+ end
139
+
140
+ GLOB_FLAGS = File::FNM_EXTGLOB | File::FNM_DOTMATCH
141
+ WILDCARD_PATTERN = /[*?\[\]{}]/.freeze
142
+ private_constant :GLOB_FLAGS, :WILDCARD_PATTERN
143
+
144
+ CLEANUP_SECTIONS = [
145
+ {
146
+ name: "Deep System Cleanup",
147
+ sudo: true,
148
+ targets: [
149
+ { name: "System library caches", path: "/Library/Caches/*" },
150
+ { name: "System library updates", path: "/Library/Updates/*" },
151
+ ]
152
+ },
153
+ {
154
+ name: "System Essentials",
155
+ targets: [
156
+ { name: "User app cache", path: "~/Library/Caches/*" },
157
+ { name: "User app logs", path: "~/Library/Logs/*" },
158
+ { name: "Trash", path: "~/.Trash/*" },
159
+ { name: "Crash reports", path: "~/Library/Application Support/CrashReporter/*" },
160
+ { name: "Diagnostic reports", path: "~/Library/DiagnosticReports/*" },
161
+ { name: "QuickLook thumbnails", path: "~/Library/Caches/com.apple.QuickLook.thumbnailcache" },
162
+ ]
163
+ },
164
+ {
165
+ name: "macOS System Caches",
166
+ targets: [
167
+ { name: "Saved application states", path: "~/Library/Saved Application State/*" },
168
+ { name: "Spotlight cache", path: "~/Library/Caches/com.apple.spotlight" },
169
+ { name: "Font registry cache", path: "~/Library/Caches/com.apple.FontRegistry" },
170
+ { name: "Font cache", path: "~/Library/Caches/com.apple.ATS" },
171
+ { name: "Photo analysis cache", path: "~/Library/Caches/com.apple.photoanalysisd" },
172
+ { name: "Apple ID cache", path: "~/Library/Caches/com.apple.akd" },
173
+ { name: "Safari webpage previews", path: "~/Library/Caches/com.apple.Safari/Webpage Previews/*" },
174
+ { name: "iCloud session cache", path: "~/Library/Application Support/CloudDocs/session/db/*" },
175
+ ]
176
+ },
177
+ {
178
+ name: "Developer Tools",
179
+ targets: [
180
+ { name: "npm cache directory", path: "~/.npm/_cacache/*" },
181
+ { name: "npm logs", path: "~/.npm/_logs/*" },
182
+ { name: "Yarn cache", path: "~/.yarn/cache/*" },
183
+ { name: "Bun cache", path: "~/.bun/install/cache/*" },
184
+ { name: "pip cache directory", path: "~/.cache/pip/*" },
185
+ { name: "pip cache (macOS)", path: "~/Library/Caches/pip/*" },
186
+ { name: "pyenv cache", path: "~/.pyenv/cache/*" },
187
+ { name: "Go build cache", path: "~/Library/Caches/go-build/*" },
188
+ { name: "Go module cache", path: "~/go/pkg/mod/cache/*" },
189
+ { name: "Rust cargo cache", path: "~/.cargo/registry/cache/*" },
190
+ { name: "Kubernetes cache", path: "~/.kube/cache/*" },
191
+ { name: "Container storage temp", path: "~/.local/share/containers/storage/tmp/*" },
192
+ { name: "AWS CLI cache", path: "~/.aws/cli/cache/*" },
193
+ { name: "Google Cloud logs", path: "~/.config/gcloud/logs/*" },
194
+ { name: "Azure CLI logs", path: "~/.azure/logs/*" },
195
+ { name: "Homebrew cache", path: "~/Library/Caches/Homebrew/*" },
196
+ { name: "Homebrew lock files (M series)", path: "/opt/homebrew/var/homebrew/locks/*" },
197
+ { name: "Homebrew lock files (Intel)", path: "/usr/local/var/homebrew/locks/*" },
198
+ { name: "Git config lock", path: "~/.gitconfig.lock" },
199
+ ]
200
+ },
201
+ {
202
+ name: "Tool Caches",
203
+ targets: [
204
+ { name: "npm cache", command: "npm cache clean --force" },
205
+ { name: "pip cache", command: "pip cache purge" },
206
+ { name: "Go cache", command: "go clean -modcache" },
207
+ { name: "Homebrew cleanup", command: "brew cleanup -s" },
208
+ ]
209
+ },
210
+ {
211
+ name: "Sandboxed App Caches",
212
+ targets: [
213
+ { name: "Wallpaper agent cache", path: "~/Library/Containers/com.apple.wallpaper.agent/Data/Library/Caches/*" },
214
+ { name: "Media analysis cache", path: "~/Library/Containers/com.apple.mediaanalysisd/Data/Library/Caches/*" },
215
+ { name: "App Store cache", path: "~/Library/Containers/com.apple.AppStore/Data/Library/Caches/*" },
216
+ { name: "Sandboxed app caches", path: "~/Library/Containers/*/Data/Library/Caches/*" },
217
+ ]
218
+ },
219
+ {
220
+ name: "Browser Cleanup",
221
+ targets: [
222
+ { name: "Safari cache", path: "~/Library/Caches/com.apple.Safari/*" },
223
+ { name: "Chrome cache", path: "~/Library/Caches/Google/Chrome/*" },
224
+ { name: "Chrome app cache", path: "~/Library/Application Support/Google/Chrome/*/Application Cache/*" },
225
+ { name: "Chrome GPU cache", path: "~/Library/Application Support/Google/Chrome/*/GPUCache/*" },
226
+ { name: "Chromium cache", path: "~/Library/Caches/Chromium/*" },
227
+ { name: "Edge cache", path: "~/Library/Caches/com.microsoft.edgemac/*" },
228
+ { name: "Arc cache", path: "~/Library/Caches/company.thebrowser.Browser/*" },
229
+ { name: "Brave cache", path: "~/Library/Caches/BraveSoftware/Brave-Browser/*" },
230
+ { name: "Firefox cache", path: "~/Library/Caches/Firefox/*" },
231
+ { name: "Opera cache", path: "~/Library/Caches/com.operasoftware.Opera/*" },
232
+ { name: "Vivaldi cache", path: "~/Library/Caches/com.vivaldi.Vivaldi/*" },
233
+ { name: "Firefox profile cache", path: "~/Library/Application Support/Firefox/Profiles/*/cache2/*" },
234
+ ]
235
+ },
236
+ {
237
+ name: "Cloud Storage Caches",
238
+ targets: [
239
+ { name: "Dropbox cache", path: "~/Library/Caches/com.dropbox.*" },
240
+ { name: "Dropbox cache", path: "~/Library/Caches/com.getdropbox.dropbox" },
241
+ { name: "Google Drive cache", path: "~/Library/Caches/com.google.GoogleDrive" },
242
+ { name: "Baidu Netdisk cache", path: "~/Library/Caches/com.baidu.netdisk" },
243
+ { name: "Alibaba Cloud cache", path: "~/Library/Caches/com.alibaba.teambitiondisk" },
244
+ { name: "Box cache", path: "~/Library/Caches/com.box.desktop" },
245
+ { name: "OneDrive cache", path: "~/Library/Caches/com.microsoft.OneDrive" },
246
+ ]
247
+ },
248
+ {
249
+ name: "Office Applications",
250
+ targets: [
251
+ { name: "Microsoft Word cache", path: "~/Library/Caches/com.microsoft.Word" },
252
+ { name: "Microsoft Excel cache", path: "~/Library/Caches/com.microsoft.Excel" },
253
+ { name: "Microsoft PowerPoint cache", path: "~/Library/Caches/com.microsoft.Powerpoint" },
254
+ { name: "Microsoft Outlook cache", path: "~/Library/Caches/com.microsoft.Outlook/*" },
255
+ { name: "Apple iWork cache", path: "~/Library/Caches/com.apple.iWork.*" },
256
+ { name: "WPS Office cache", path: "~/Library/Caches/com.kingsoft.wpsoffice.mac" },
257
+ { name: "Thunderbird cache", path: "~/Library/Caches/org.mozilla.thunderbird/*" },
258
+ { name: "Apple Mail cache", path: "~/Library/Caches/com.apple.mail/*" },
259
+ ]
260
+ },
261
+ {
262
+ name: "Extended Developer Caches",
263
+ targets: [
264
+ { name: "pnpm store cache", path: "~/.pnpm-store/*" },
265
+ { name: "pnpm global store", path: "~/.local/share/pnpm/store/*" },
266
+ { name: "TypeScript cache", path: "~/.cache/typescript/*" },
267
+ { name: "Electron cache", path: "~/.cache/electron/*" },
268
+ { name: "node-gyp cache", path: "~/.cache/node-gyp/*" },
269
+ { name: "node-gyp build cache", path: "~/.node-gyp/*" },
270
+ { name: "Turbo cache", path: "~/.turbo/*" },
271
+ { name: "Next.js cache", path: "~/.next/*" },
272
+ { name: "Vite cache", path: "~/.vite/*" },
273
+ { name: "Vite global cache", path: "~/.cache/vite/*" },
274
+ { name: "Webpack cache", path: "~/.cache/webpack/*" },
275
+ { name: "Parcel cache", path: "~/.parcel-cache/*" },
276
+ { name: "Android Studio cache", path: "~/Library/Caches/Google/AndroidStudio*/*" },
277
+ { name: "Unity cache", path: "~/Library/Caches/com.unity3d.*/*" },
278
+ { name: "JetBrains Toolbox cache", path: "~/Library/Caches/com.jetbrains.toolbox/*" },
279
+ { name: "Postman cache", path: "~/Library/Caches/com.postmanlabs.mac/*" },
280
+ { name: "Insomnia cache", path: "~/Library/Caches/com.konghq.insomnia/*" },
281
+ { name: "TablePlus cache", path: "~/Library/Caches/com.tinyapp.TablePlus/*" },
282
+ { name: "MongoDB Compass cache", path: "~/Library/Caches/com.mongodb.compass/*" },
283
+ { name: "Figma cache", path: "~/Library/Caches/com.figma.Desktop/*" },
284
+ { name: "GitHub Desktop cache", path: "~/Library/Caches/com.github.GitHubDesktop/*" },
285
+ { name: "VS Code cache", path: "~/Library/Caches/com.microsoft.VSCode/*" },
286
+ { name: "Sublime Text cache", path: "~/Library/Caches/com.sublimetext.*/*" },
287
+ { name: "Poetry cache", path: "~/.cache/poetry/*" },
288
+ { name: "uv cache", path: "~/.cache/uv/*" },
289
+ { name: "Ruff cache", path: "~/.cache/ruff/*" },
290
+ { name: "MyPy cache", path: "~/.cache/mypy/*" },
291
+ { name: "Pytest cache", path: "~/.pytest_cache/*" },
292
+ { name: "Jupyter runtime cache", path: "~/.jupyter/runtime/*" },
293
+ { name: "Hugging Face cache", path: "~/.cache/huggingface/*" },
294
+ { name: "PyTorch cache", path: "~/.cache/torch/*" },
295
+ { name: "TensorFlow cache", path: "~/.cache/tensorflow/*" },
296
+ { name: "Conda packages cache", path: "~/.conda/pkgs/*" },
297
+ { name: "Anaconda packages cache", path: "~/anaconda3/pkgs/*" },
298
+ { name: "Weights & Biases cache", path: "~/.cache/wandb/*" },
299
+ { name: "Cargo git cache", path: "~/.cargo/git/*" },
300
+ { name: "Rust documentation cache", path: "~/.rustup/toolchains/*/share/doc/*" },
301
+ { name: "Rust downloads cache", path: "~/.rustup/downloads/*" },
302
+ { name: "Gradle caches", path: "~/.gradle/caches/*" },
303
+ { name: "Maven repository cache", path: "~/.m2/repository/*" },
304
+ { name: "SBT cache", path: "~/.sbt/*" },
305
+ { name: "Docker BuildX cache", path: "~/.docker/buildx/cache/*" },
306
+ { name: "Terraform cache", path: "~/.cache/terraform/*" },
307
+ { name: "Paw API cache", path: "~/Library/Caches/com.getpaw.Paw/*" },
308
+ { name: "Charles Proxy cache", path: "~/Library/Caches/com.charlesproxy.charles/*" },
309
+ { name: "Proxyman cache", path: "~/Library/Caches/com.proxyman.NSProxy/*" },
310
+ { name: "Grafana cache", path: "~/.grafana/cache/*" },
311
+ { name: "Prometheus WAL cache", path: "~/.prometheus/data/wal/*" },
312
+ { name: "Jenkins workspace cache", path: "~/.jenkins/workspace/*/target/*" },
313
+ { name: "GitLab Runner cache", path: "~/.cache/gitlab-runner/*" },
314
+ { name: "GitHub Actions cache", path: "~/.github/cache/*" },
315
+ { name: "CircleCI cache", path: "~/.circleci/cache/*" },
316
+ { name: "Oh My Zsh cache", path: "~/.oh-my-zsh/cache/*" },
317
+ { name: "Fish shell backup", path: "~/.config/fish/fish_history.bak*" },
318
+ { name: "Bash history backup", path: "~/.bash_history.bak*" },
319
+ { name: "Zsh history backup", path: "~/.zsh_history.bak*" },
320
+ { name: "SonarQube cache", path: "~/.sonar/*" },
321
+ { name: "ESLint cache", path: "~/.cache/eslint/*" },
322
+ { name: "Prettier cache", path: "~/.cache/prettier/*" },
323
+ { name: "CocoaPods cache", path: "~/Library/Caches/CocoaPods/*" },
324
+ { name: "Ruby Bundler cache", path: "~/.bundle/cache/*" },
325
+ { name: "PHP Composer cache", path: "~/.composer/cache/*" },
326
+ { name: "NuGet packages cache", path: "~/.nuget/packages/*" },
327
+ { name: "Ivy cache", path: "~/.ivy2/cache/*" },
328
+ { name: "Dart Pub cache", path: "~/.pub-cache/*" },
329
+ { name: "curl cache", path: "~/.cache/curl/*" },
330
+ { name: "wget cache", path: "~/.cache/wget/*" },
331
+ { name: "curl cache (macOS)", path: "~/Library/Caches/curl/*" },
332
+ { name: "wget cache (macOS)", path: "~/Library/Caches/wget/*" },
333
+ { name: "pre-commit cache", path: "~/.cache/pre-commit/*" },
334
+ { name: "Git config backup", path: "~/.gitconfig.bak*" },
335
+ { name: "Flutter cache", path: "~/.cache/flutter/*" },
336
+ { name: "Gradle daemon logs", path: "~/.gradle/daemon/*" },
337
+ { name: "Android build cache", path: "~/.android/build-cache/*" },
338
+ { name: "Android SDK cache", path: "~/.android/cache/*" },
339
+ { name: "iOS device cache", path: "~/Library/Developer/Xcode/iOS DeviceSupport/*/Symbols/System/Library/Caches/*" },
340
+ { name: "Xcode Interface Builder cache", path: "~/Library/Developer/Xcode/UserData/IB Support/*" },
341
+ { name: "Swift package manager cache", path: "~/.cache/swift-package-manager/*" },
342
+ { name: "Bazel cache", path: "~/.cache/bazel/*" },
343
+ { name: "Zig cache", path: "~/.cache/zig/*" },
344
+ { name: "Deno cache", path: "~/Library/Caches/deno/*" },
345
+ { name: "Sequel Ace cache", path: "~/Library/Caches/com.sequel-ace.sequel-ace/*" },
346
+ { name: "Sequel Pro cache", path: "~/Library/Caches/com.eggerapps.Sequel-Pro/*" },
347
+ { name: "Redis Desktop Manager cache", path: "~/Library/Caches/redis-desktop-manager/*" },
348
+ { name: "Navicat cache", path: "~/Library/Caches/com.navicat.*" },
349
+ { name: "DBeaver cache", path: "~/Library/Caches/com.dbeaver.*" },
350
+ { name: "Redis Insight cache", path: "~/Library/Caches/com.redis.RedisInsight" },
351
+ { name: "Sentry crash reports", path: "~/Library/Caches/SentryCrash/*" },
352
+ { name: "KSCrash reports", path: "~/Library/Caches/KSCrash/*" },
353
+ { name: "Crashlytics data", path: "~/Library/Caches/com.crashlytics.data/*" },
354
+ ]
355
+ },
356
+ {
357
+ name: "Applications",
358
+ targets: [
359
+ { name: "Xcode derived data", path: "~/Library/Developer/Xcode/DerivedData/*" },
360
+ { name: "Simulator cache", path: "~/Library/Developer/CoreSimulator/Caches/*" },
361
+ { name: "Simulator temp files", path: "~/Library/Developer/CoreSimulator/Devices/*/data/tmp/*" },
362
+ { name: "Xcode cache", path: "~/Library/Caches/com.apple.dt.Xcode/*" },
363
+ { name: "iOS device logs", path: "~/Library/Developer/Xcode/iOS Device Logs/*" },
364
+ { name: "watchOS device logs", path: "~/Library/Developer/Xcode/watchOS Device Logs/*" },
365
+ { name: "Xcode build products", path: "~/Library/Developer/Xcode/Products/*" },
366
+ { name: "VS Code logs", path: "~/Library/Application Support/Code/logs/*" },
367
+ { name: "VS Code cache", path: "~/Library/Application Support/Code/Cache/*" },
368
+ { name: "VS Code extension cache", path: "~/Library/Application Support/Code/CachedExtensions/*" },
369
+ { name: "VS Code data cache", path: "~/Library/Application Support/Code/CachedData/*" },
370
+ { name: "IntelliJ IDEA logs", path: "~/Library/Logs/IntelliJIdea*/*" },
371
+ { name: "PhpStorm logs", path: "~/Library/Logs/PhpStorm*/*" },
372
+ { name: "PyCharm logs", path: "~/Library/Logs/PyCharm*/*" },
373
+ { name: "WebStorm logs", path: "~/Library/Logs/WebStorm*/*" },
374
+ { name: "GoLand logs", path: "~/Library/Logs/GoLand*/*" },
375
+ { name: "CLion logs", path: "~/Library/Logs/CLion*/*" },
376
+ { name: "DataGrip logs", path: "~/Library/Logs/DataGrip*/*" },
377
+ { name: "JetBrains cache", path: "~/Library/Caches/JetBrains/*" },
378
+ { name: "Discord cache", path: "~/Library/Application Support/discord/Cache/*" },
379
+ { name: "Slack cache", path: "~/Library/Application Support/Slack/Cache/*" },
380
+ { name: "Zoom cache", path: "~/Library/Caches/us.zoom.xos/*" },
381
+ { name: "WeChat cache", path: "~/Library/Caches/com.tencent.xinWeChat/*" },
382
+ { name: "Telegram cache", path: "~/Library/Caches/ru.keepcoder.Telegram/*" },
383
+ { name: "ChatGPT cache", path: "~/Library/Caches/com.openai.chat/*" },
384
+ { name: "Claude desktop cache", path: "~/Library/Caches/com.anthropic.claudefordesktop/*" },
385
+ { name: "Claude logs", path: "~/Library/Logs/Claude/*" },
386
+ { name: "Microsoft Teams cache", path: "~/Library/Caches/com.microsoft.teams2/*" },
387
+ { name: "WhatsApp cache", path: "~/Library/Caches/net.whatsapp.WhatsApp/*" },
388
+ { name: "Skype cache", path: "~/Library/Caches/com.skype.skype/*" },
389
+ { name: "DingTalk (iDingTalk) cache", path: "~/Library/Caches/dd.work.exclusive4aliding/*" },
390
+ { name: "AliLang security component", path: "~/Library/Caches/com.alibaba.AliLang.osx/*" },
391
+ { name: "DingTalk logs", path: "~/Library/Application Support/iDingTalk/log/*" },
392
+ { name: "DingTalk holmes logs", path: "~/Library/Application Support/iDingTalk/holmeslogs/*" },
393
+ { name: "Tencent Meeting cache", path: "~/Library/Caches/com.tencent.meeting/*" },
394
+ { name: "WeCom cache", path: "~/Library/Caches/com.tencent.WeWorkMac/*" },
395
+ { name: "Feishu cache", path: "~/Library/Caches/com.feishu.*/*" },
396
+ { name: "Sketch cache", path: "~/Library/Caches/com.bohemiancoding.sketch3/*" },
397
+ { name: "Sketch app cache", path: "~/Library/Application Support/com.bohemiancoding.sketch3/cache/*" },
398
+ { name: "ScreenFlow cache", path: "~/Library/Caches/net.telestream.screenflow10/*" },
399
+ { name: "Adobe cache", path: "~/Library/Caches/Adobe/*" },
400
+ { name: "Adobe app caches", path: "~/Library/Caches/com.adobe.*/*" },
401
+ { name: "Adobe media cache", path: "~/Library/Application Support/Adobe/Common/Media Cache Files/*" },
402
+ { name: "Adobe peak files", path: "~/Library/Application Support/Adobe/Common/Peak Files/*" },
403
+ { name: "Final Cut Pro cache", path: "~/Library/Caches/com.apple.FinalCut/*" },
404
+ { name: "Final Cut render cache", path: "~/Library/Application Support/Final Cut Pro/*/Render Files/*" },
405
+ { name: "Motion render cache", path: "~/Library/Application Support/Motion/*/Render Files/*" },
406
+ { name: "DaVinci Resolve cache", path: "~/Library/Caches/com.blackmagic-design.DaVinciResolve/*" },
407
+ { name: "Premiere Pro cache", path: "~/Library/Caches/com.adobe.PremierePro.*/*" },
408
+ { name: "Blender cache", path: "~/Library/Caches/org.blenderfoundation.blender/*" },
409
+ { name: "Cinema 4D cache", path: "~/Library/Caches/com.maxon.cinema4d/*" },
410
+ { name: "Autodesk cache", path: "~/Library/Caches/com.autodesk.*/*" },
411
+ { name: "SketchUp cache", path: "~/Library/Caches/com.sketchup.*/*" },
412
+ { name: "Raycast cache", path: "~/Library/Caches/com.raycast.macos/*" },
413
+ { name: "MiaoYan cache", path: "~/Library/Caches/com.tw93.MiaoYan/*" },
414
+ { name: "Filo cache", path: "~/Library/Caches/com.filo.client/*" },
415
+ { name: "Flomo cache", path: "~/Library/Caches/com.flomoapp.mac/*" },
416
+ { name: "Spotify cache", path: "~/Library/Caches/com.spotify.client/*" },
417
+ { name: "Apple Music cache", path: "~/Library/Caches/com.apple.Music" },
418
+ { name: "Apple Podcasts cache", path: "~/Library/Caches/com.apple.podcasts" },
419
+ { name: "Apple TV cache", path: "~/Library/Caches/com.apple.TV/*" },
420
+ { name: "Plex cache", path: "~/Library/Caches/tv.plex.player.desktop" },
421
+ { name: "NetEase Music cache", path: "~/Library/Caches/com.netease.163music" },
422
+ { name: "QQ Music cache", path: "~/Library/Caches/com.tencent.QQMusic/*" },
423
+ { name: "Kugou Music cache", path: "~/Library/Caches/com.kugou.mac/*" },
424
+ { name: "Kuwo Music cache", path: "~/Library/Caches/com.kuwo.mac/*" },
425
+ { name: "IINA cache", path: "~/Library/Caches/com.colliderli.iina" },
426
+ { name: "VLC cache", path: "~/Library/Caches/org.videolan.vlc" },
427
+ { name: "MPV cache", path: "~/Library/Caches/io.mpv" },
428
+ { name: "iQIYI cache", path: "~/Library/Caches/com.iqiyi.player" },
429
+ { name: "Tencent Video cache", path: "~/Library/Caches/com.tencent.tenvideo" },
430
+ { name: "Bilibili cache", path: "~/Library/Caches/tv.danmaku.bili/*" },
431
+ { name: "Douyu cache", path: "~/Library/Caches/com.douyu.*/*" },
432
+ { name: "Huya cache", path: "~/Library/Caches/com.huya.*/*" },
433
+ { name: "Aria2 cache", path: "~/Library/Caches/net.xmac.aria2gui" },
434
+ { name: "Transmission cache", path: "~/Library/Caches/org.m0k.transmission" },
435
+ { name: "qBittorrent cache", path: "~/Library/Caches/com.qbittorrent.qBittorrent" },
436
+ { name: "Downie cache", path: "~/Library/Caches/com.downie.Downie-*" },
437
+ { name: "Folx cache", path: "~/Library/Caches/com.folx.*/*" },
438
+ { name: "Pacifist cache", path: "~/Library/Caches/com.charlessoft.pacifist/*" },
439
+ { name: "Steam cache", path: "~/Library/Caches/com.valvesoftware.steam/*" },
440
+ { name: "Steam app cache", path: "~/Library/Application Support/Steam/appcache/*" },
441
+ { name: "Steam web cache", path: "~/Library/Application Support/Steam/htmlcache/*" },
442
+ { name: "Epic Games cache", path: "~/Library/Caches/com.epicgames.EpicGamesLauncher/*" },
443
+ { name: "Battle.net cache", path: "~/Library/Caches/com.blizzard.Battle.net/*" },
444
+ { name: "Battle.net app cache", path: "~/Library/Application Support/Battle.net/Cache/*" },
445
+ { name: "EA Origin cache", path: "~/Library/Caches/com.ea.*/*" },
446
+ { name: "GOG Galaxy cache", path: "~/Library/Caches/com.gog.galaxy/*" },
447
+ { name: "Riot Games cache", path: "~/Library/Caches/com.riotgames.*/*" },
448
+ { name: "Youdao Dictionary cache", path: "~/Library/Caches/com.youdao.YoudaoDict" },
449
+ { name: "Eudict cache", path: "~/Library/Caches/com.eudic.*" },
450
+ { name: "Bob Translation cache", path: "~/Library/Caches/com.bob-build.Bob" },
451
+ { name: "CleanShot cache", path: "~/Library/Caches/com.cleanshot.*" },
452
+ { name: "Camo cache", path: "~/Library/Caches/com.reincubate.camo" },
453
+ { name: "Xnip cache", path: "~/Library/Caches/com.xnipapp.xnip" },
454
+ { name: "Spark cache", path: "~/Library/Caches/com.readdle.smartemail-Mac" },
455
+ { name: "Airmail cache", path: "~/Library/Caches/com.airmail.*" },
456
+ { name: "Todoist cache", path: "~/Library/Caches/com.todoist.mac.Todoist" },
457
+ { name: "Any.do cache", path: "~/Library/Caches/com.any.do.*" },
458
+ { name: "Zsh completion cache", path: "~/.zcompdump*" },
459
+ { name: "less history", path: "~/.lesshst" },
460
+ { name: "Vim temporary files", path: "~/.viminfo.tmp" },
461
+ { name: "wget HSTS cache", path: "~/.wget-hsts" },
462
+ { name: "Input Source Pro cache", path: "~/Library/Caches/com.runjuu.Input-Source-Pro/*" },
463
+ { name: "WakaTime cache", path: "~/Library/Caches/macos-wakatime.WakaTime/*" },
464
+ { name: "Notion cache", path: "~/Library/Caches/notion.id/*" },
465
+ { name: "Obsidian cache", path: "~/Library/Caches/md.obsidian/*" },
466
+ { name: "Logseq cache", path: "~/Library/Caches/com.logseq.*/*" },
467
+ { name: "Bear cache", path: "~/Library/Caches/com.bear-writer.*/*" },
468
+ { name: "Evernote cache", path: "~/Library/Caches/com.evernote.*/*" },
469
+ { name: "Yinxiang Note cache", path: "~/Library/Caches/com.yinxiang.*/*" },
470
+ { name: "Alfred cache", path: "~/Library/Caches/com.runningwithcrayons.Alfred/*" },
471
+ { name: "The Unarchiver cache", path: "~/Library/Caches/cx.c3.theunarchiver/*" },
472
+ { name: "TeamViewer cache", path: "~/Library/Caches/com.teamviewer.*/*" },
473
+ { name: "AnyDesk cache", path: "~/Library/Caches/com.anydesk.*/*" },
474
+ { name: "ToDesk cache", path: "~/Library/Caches/com.todesk.*/*" },
475
+ { name: "Sunlogin cache", path: "~/Library/Caches/com.sunlogin.*/*" },
476
+ ]
477
+ },
478
+ {
479
+ name: "Virtualization Tools",
480
+ targets: [
481
+ { name: "VMware Fusion cache", path: "~/Library/Caches/com.vmware.fusion" },
482
+ { name: "Parallels cache", path: "~/Library/Caches/com.parallels.*" },
483
+ { name: "VirtualBox cache", path: "~/VirtualBox VMs/.cache" },
484
+ { name: "Vagrant temporary files", path: "~/.vagrant.d/tmp/*" },
485
+ ]
486
+ },
487
+ {
488
+ name: "Application Support Logs",
489
+ targets: [
490
+ { name: "App logs", path: "~/Library/Application Support/*/log/*" },
491
+ { name: "App logs", path: "~/Library/Application Support/*/logs/*" },
492
+ { name: "Activity logs", path: "~/Library/Application Support/*/activitylog/*" },
493
+ ]
494
+ }
495
+ ]
496
+ end
497
+ end