Token导航 LogoToken导航

Agent Skill · 开发

puremac-macos-cleaner(puremac macOS cleaner 命令行)

puremac-macos-cleaner 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

puremac-macos-cleaner 是开发类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为执行命令;许可证信息还不明确,第三方扫描有提醒项,按安装量在开发类的 21,746 个 Skill 里排第 5,932。

总安装 5,378周安装 231GitHub Stars 39下载 1,885核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:puremac-macos-cleaner(puremac macOS cleaner 命令行)
来源仓库:https://github.com/aradotso/trending-skills
仓库路径:skills/puremac-macos-cleaner
安装命令:
npx skills add https://github.com/aradotso/trending-skills --skill puremac-macos-cleaner
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/aradotso/trending-skills --skill puremac-macos-cleaner

这个 Skill 是做什么的

开发类 Skill 面向写代码、改代码和排查问题,一般会读写仓库文件,部分还会执行构建或测试命令。

用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息。适合在需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库和原始 README 核验具体用法。安装方式:通过 npx 从指定 GitHub 仓库添加技能。建议确认权限范围、维护状态及是否会触发联网或文件读写。

来源仓库内路径:skills/puremac-macos-cleaner

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/aradotso/trending-skills --skill puremac-macos…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要执行命令,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

puremac-macos-cleaner 怎么安装?

在终端执行 npx skills add https://github.com/aradotso/trending-skills --skill puremac-macos-cleaner。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

puremac-macos-cleaner 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

puremac-macos-cleaner 需要什么权限?

权限级别是执行命令。安装流程涉及命令执行,可能通过 npx skills add https://github.com/aradotso/trending-skills --skill puremac-macos-cleaner 联网下载 Skill 或依赖。用户安装前应确认命令来源、仓库内容和执行环境。

puremac-macos-cleaner 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

puremac-macos-cleaner 用的人多吗?

公开数据是累计安装 5,378 次,近一周安装 231 次,下载 1,885 次,GitHub 39 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

puremac-macos-cleaner 安全吗?

第三方扫描有提醒项,说明存在需要人工确认的行为。安装前请打开源码看清它读了什么、联网到哪里。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。

先想清楚的地方

  • 需要执行命令,装到常用环境前要先评估影响面。
  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方扫描存在提醒项或未通过项,需要人工逐条确认。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理开发类任务、又不想每次都手写提示词的人。

不太适合

  • 不能接受 Skill 在你机器上执行命令的人。
  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

开发类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
skill-vetter

技能审查员 · OpenClaw

8,779,018986操作浏览器MIT-0通过
ontology

本体论 · OpenClaw

6,636,960576只读MIT-0通过
entra-app-registration

内部应用程序注册 · Codex、Claude

6,631,872764接触敏感数据未明确通过
entra-app-registration

内部应用程序注册 · Codex、Claude

3,757,680201接触敏感数据未明确通过
nano-banana-pro

纳米香蕉专业版 · OpenClaw

3,526,898364接触敏感数据MIT-0有提醒
puremac-macos-cleaner

puremac macOS cleaner 命令行 · 本页

5,37839执行命令未明确有提醒

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

PureMac macOS Cleaner

Skill by ara.so — Daily 2026 Skills collection.

PureMac is a free, native SwiftUI macOS application that cleans system junk, user caches, Xcode derived data, Homebrew caches, mail attachments, and purgeable APFS space. It is a privacy-respecting, open-source alternative to CleanMyMac X with no telemetry, no subscriptions, and no network calls.


Install

Homebrew (recommended)

brew tap momenbasel/tap
brew install --cask puremac

Direct Download

Download the latest .app from Releases, unzip, and drag to /Applications.

Build from Source

brew install xcodegen
git clone https://github.com/momenbasel/PureMac.git
cd PureMac
xcodegen generate
xcodebuild \
  -project PureMac.xcodeproj \
  -scheme PureMac \
  -configuration Release \
  -derivedDataPath build \
  build
open build/Build/Products/Release/PureMac.app

Requirements: macOS 13.0+, Swift 5.9, Xcode 15+.


Project Structure

PureMac/
├── PureMac/
│   ├── App/
│   │   └── PureMacApp.swift          # App entry point
│   ├── Views/
│   │   ├── ContentView.swift         # Main window
│   │   ├── ScanView.swift            # Smart scan UI
│   │   ├── CategoryDetailView.swift  # Per-category drill-down
│   │   └── SettingsView.swift        # Schedule & preferences
│   ├── Models/
│   │   ├── CleanCategory.swift       # Category definitions
│   │   └── ScanResult.swift          # Scan result model
│   ├── Services/
│   │   ├── ScannerService.swift      # File scanning logic
│   │   ├── CleanerService.swift      # Deletion logic
│   │   ├── SchedulerService.swift    # Auto-clean scheduling
│   │   └── PurgeableService.swift    # APFS purgeable space
│   └── Utilities/
│       └── FileSizeFormatter.swift
├── project.yml                       # XcodeGen spec
└── CONTRIBUTING.md

Core Concepts

Clean Categories

PureMac operates on named categories, each mapping to specific filesystem paths:

CategoryKey Paths
System Junk/Library/Caches, /Library/Logs, /tmp, ~/Library/Logs
User Cache~/Library/Caches, npm/pip/yarn/pnpm caches
Mail Attachments~/Library/Mail Downloads
Trash~/.Trash
Large & Old Files~/Downloads, ~/Documents, ~/Desktop (>100 MB or >1 year old)
Purgeable SpaceAPFS Time Machine snapshots via tmutil
Xcode JunkDerivedData, Archives, CoreSimulator/Caches
Homebrew Cache~/Library/Caches/Homebrew

Large & Old Files are never auto-selected — the user must explicitly choose items before cleaning.


Working with the Codebase

Adding a New Clean Category

  1. Define the category in CleanCategory.swift:
// CleanCategory.swift
enum CleanCategory: String, CaseIterable, Identifiable {
    case systemJunk       = "System Junk"
    case userCache        = "User Cache"
    case mailAttachments  = "Mail Attachments"
    case trash            = "Trash"
    case largeOldFiles    = "Large & Old Files"
    case purgeableSpace   = "Purgeable Space"
    case xcodeJunk        = "Xcode Junk"
    case homebrewCache    = "Homebrew Cache"
    // Add your new category here:
    case gradleCache      = "Gradle Cache"

    var id: String { rawValue }

    var iconName: String {
        switch self {
        case .systemJunk:      return "trash.circle"
        case .userCache:       return "internaldrive"
        case .xcodeJunk:       return "hammer"
        case .homebrewCache:   return "shippingbox"
        case .gradleCache:     return "archivebox"   // new
        default:               return "folder"
        }
    }
}
  1. Add scanning logic in ScannerService.swift:
// ScannerService.swift
func scanCategory(_ category: CleanCategory) async throws -> ScanResult {
    switch category {
    case .gradleCache:
        return try await scanPaths([
            FileManager.default.homeDirectoryForCurrentUser
                .appendingPathComponent(".gradle/caches")
        ])
    // ...existing cases
    default:
        throw ScannerError.unsupportedCategory
    }
}

private func scanPaths(_ urls: [URL]) async throws -> ScanResult {
    var files: [ScannedFile] = []
    let fm = FileManager.default

    for url in urls {
        guard fm.fileExists(atPath: url.path) else { continue }
        let enumerator = fm.enumerator(
            at: url,
            includingPropertiesForKeys: [.fileSizeKey, .contentModificationDateKey],
            options: [.skipsHiddenFiles]
        )
        while let fileURL = enumerator?.nextObject() as? URL {
            let values = try fileURL.resourceValues(forKeys: [.fileSizeKey, .contentModificationDateKey])
            let size = Int64(values.fileSize ?? 0)
            let modified = values.contentModificationDate ?? Date.distantPast
            files.append(ScannedFile(url: fileURL, size: size, modifiedDate: modified))
        }
    }

    let totalBytes = files.reduce(0) { $0 + $1.size }
    return ScanResult(category: .gradleCache, files: files, totalBytes: totalBytes)
}
  1. Add cleaning logic in CleanerService.swift:
// CleanerService.swift
func clean(_ result: ScanResult, selectedFiles: Set<URL>? = nil) async throws -> Int64 {
    let filesToDelete = selectedFiles.map { Array($0) } ?? result.files.map(\.url)
    var bytesFreed: Int64 = 0
    let fm = FileManager.default

    for url in filesToDelete {
        do {
            let attrs = try fm.attributesOfItem(atPath: url.path)
            let size = attrs[.size] as? Int64 ?? 0
            try fm.removeItem(at: url)
            bytesFreed += size
        } catch {
            // Log but continue — don't abort on single-file failure
            print("Failed to delete \(url.lastPathComponent): \(error.localizedDescription)")
        }
    }
    return bytesFreed
}

Scheduled Auto-Cleaning

Configure via Settings → Schedule tab. Intervals: hourly, 3h, 6h, 12h, daily, weekly, biweekly, monthly.

// SchedulerService.swift — how scheduling is implemented
import UserNotifications

class SchedulerService: ObservableObject {
    @AppStorage("schedulingEnabled")    var schedulingEnabled: Bool = false
    @AppStorage("cleaningInterval")     var cleaningInterval: String = "daily"
    @AppStorage("autoCleanAfterScan")   var autoCleanAfterScan: Bool = false
    @AppStorage("autoPurgePurgeable")   var autoPurgePurgeable: Bool = false

    private var timer: Timer?

    func scheduleIfNeeded() {
        timer?.invalidate()
        guard schedulingEnabled else { return }
        let interval = intervalSeconds(for: cleaningInterval)
        timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { [weak self] _ in
            Task { await self?.runScheduledClean() }
        }
    }

    private func intervalSeconds(for key: String) -> TimeInterval {
        switch key {
        case "hourly":    return 3_600
        case "3h":        return 10_800
        case "6h":        return 21_600
        case "12h":       return 43_200
        case "daily":     return 86_400
        case "weekly":    return 604_800
        case "biweekly":  return 1_209_600
        case "monthly":   return 2_592_000
        default:          return 86_400
        }
    }

    @MainActor
    private func runScheduledClean() async {
        let scanner = ScannerService()
        let cleaner = CleanerService()
        for category in CleanCategory.allCases where category != .largeOldFiles {
            if let result = try? await scanner.scanCategory(category), autoCleanAfterScan {
                _ = try? await cleaner.clean(result)
            }
        }
        if autoPurgePurgeable {
            try? await PurgeableService.shared.purge()
        }
    }
}

Enable scheduling programmatically:

let scheduler = SchedulerService()
scheduler.cleaningInterval = "weekly"
scheduler.autoCleanAfterScan = true
scheduler.autoPurgePurgeable = false
scheduler.schedulingEnabled = true
scheduler.scheduleIfNeeded()

Purgeable Space (APFS Snapshots)

PureMac uses tmutil to delete local Time Machine snapshots — this is the only operation requiring elevated privileges:

// PurgeableService.swift
import Foundation

class PurgeableService {
    static let shared = PurgeableService()

    func listSnapshots() async throws -> [String] {
        let output = try await shell("tmutil listlocalsnapshots /")
        return output
            .split(separator: "\n")
            .map(String.init)
            .filter { $0.hasPrefix("com.apple.TimeMachine") }
    }

    func purge() async throws {
        let snapshots = try await listSnapshots()
        for snapshot in snapshots {
            try await shell("tmutil deletelocalsnapshots \(snapshot)")
        }
    }

    @discardableResult
    private func shell(_ command: String) async throws -> String {
        try await withCheckedThrowingContinuation { continuation in
            let task = Process()
            task.launchPath = "/bin/bash"
            task.arguments = ["-c", command]
            let pipe = Pipe()
            task.standardOutput = pipe
            task.terminationHandler = { _ in
                let data = pipe.fileHandleForReading.readDataToEndOfFile()
                continuation.resume(returning: String(data: data, encoding: .utf8) ?? "")
            }
            do { try task.run() } catch { continuation.resume(throwing: error) }
        }
    }
}

Xcode Cache Paths

// Paths cleaned by the Xcode Junk category
let home = FileManager.default.homeDirectoryForCurrentUser

let xcodePaths: [URL] = [
    home.appendingPathComponent("Library/Developer/Xcode/DerivedData"),
    home.appendingPathComponent("Library/Developer/Xcode/Archives"),
    home.appendingPathComponent("Library/Developer/CoreSimulator/Caches"),
]

Scan these and safely delete their contents without removing the directories themselves.


SwiftUI View Patterns

Scan Progress View

// Example: triggering a scan from a SwiftUI view
struct ScanView: View {
    @StateObject private var scanner = ScannerService()
    @State private var results: [ScanResult] = []
    @State private var isScanning = false

    var body: some View {
        VStack {
            if isScanning {
                ProgressView("Scanning…")
            } else {
                Button("Smart Scan") {
                    Task { await runScan() }
                }
            }
            List(results, id: \.category) { result in
                CategoryRow(result: result)
            }
        }
    }

    private func runScan() async {
        isScanning = true
        results = []
        for category in CleanCategory.allCases {
            if let result = try? await scanner.scanCategory(category) {
                results.append(result)
            }
        }
        isScanning = false
    }
}

File Inspector (Click-to-Inspect)

// Show files before deletion — users can deselect
struct CategoryDetailView: View {
    let result: ScanResult
    @State private var selected: Set<URL> = []
    @State private var cleaned = false

    var body: some View {
        List(result.files, id: \.url, selection: $selected) { file in
            HStack {
                Image(systemName: "doc")
                Text(file.url.lastPathComponent)
                Spacer()
                Text(ByteCountFormatter.string(fromByteCount: file.size, countStyle: .file))
                    .foregroundStyle(.secondary)
            }
        }
        .toolbar {
            Button("Clean Selected") {
                Task {
                    let cleaner = CleanerService()
                    _ = try? await cleaner.clean(result, selectedFiles: selected)
                    cleaned = true
                }
            }
            .disabled(selected.isEmpty)
        }
    }
}

Configuration (AppStorage Keys)

All preferences are stored in UserDefaults via @AppStorage:

KeyTypeDefaultDescription
schedulingEnabledBoolfalseEnable scheduled cleaning
cleaningIntervalString"daily"Interval key (see above)
autoCleanAfterScanBoolfalseAuto-clean after scheduled scan
autoPurgePurgeableBoolfalseAuto-purge APFS snapshots

Read/write from anywhere:

UserDefaults.standard.set(true,    forKey: "schedulingEnabled")
UserDefaults.standard.set("weekly", forKey: "cleaningInterval")

Building & Testing

# Generate Xcode project from project.yml
xcodegen generate

# Build Release
xcodebuild \
  -project PureMac.xcodeproj \
  -scheme PureMac \
  -configuration Release \
  -derivedDataPath build \
  build

# Run tests
xcodebuild test \
  -project PureMac.xcodeproj \
  -scheme PureMac \
  -destination 'platform=macOS'

# Open built app
open build/Build/Products/Release/PureMac.app

Contributing

  1. Fork and clone the repo.
  2. Run xcodegen generate to create the .xcodeproj.
  3. Create a feature branch: git checkout -b feature/gradle-cache-cleaning
  4. Follow existing patterns in ScannerService / CleanerService.
  5. Never add network calls, analytics SDKs, or telemetry of any kind.
  6. Large & Old Files must never be auto-selected for deletion.
  7. Open a PR against main.

See CONTRIBUTING.md for full guidelines.


Troubleshooting

ProblemSolution
xcodegen: command not foundbrew install xcodegen
App blocked by GatekeeperThe release build is notarized; if building from source, run xattr -cr PureMac.app
Purgeable scan returns 0 bytesNo local Time Machine snapshots exist — this is normal if TM is off
Xcode paths not foundXcode has not been used yet or DerivedData was already cleared
tmutil requires passwordPurgeable purge may prompt for admin credentials — this is expected macOS behavior
Scheduled cleaning not triggeringEnsure the app is running (it is not a background daemon); check Settings → Schedule

Safety Guarantees

  • Never deletes system-critical files or application bundles.
  • Only removes caches, logs, temp files, and user-selected items.
  • Large & Old Files require explicit user selection before deletion.
  • Purgeable operations target only APFS Time Machine snapshots — not free space.
  • All filesystem operations use FileManager.removeItem(at:) — no rm -rf shell calls for regular cleaning.

平台分布

Codex

35.26%
按下载量换算665

Claude

30.19%
按下载量换算569

Cursor

21.62%
按下载量换算408

Gemini CLI

10.44%
按下载量换算197

安全审计

Gen Agent Trust Hub

通过

Socket

可疑

Snyk

可疑

权限和风险

执行命令

安装流程涉及命令执行,可能通过 npx skills add https://github.com/aradotso/trending-skills --skill puremac-macos-cleaner 联网下载 Skill 或依赖。用户安装前应确认命令来源、仓库内容和执行环境。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在提醒或未通过项,安装前请自行复核。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills