Audit SaneScript and compare against Mac competitors?
I can audit this repo’s app (SaneClick / SaneScript) thoroughly from the source, but I can’t honestly “compare against competitors” or “rate each app” without you telling me which competitor apps you care about (and what “MAC” means here—Mac App Store? macOS generally? Mac Admin tools?). Below is a full audit of this app grounded in the code, plus a shortlist of likely competitor categories; once you name the competitors (or I can propose a set), I’ll score them 1–10 and give a final recommendation.
##1) What the app actually does (functionality audit)
###Architecture (from code)
- Host app (SwiftUI) manages a library + user scripts, saves them to JSON, shows UI.
ScriptStorepersists toscripts.json/categories.jsonin an App Group container when available. (SaneScript/Services/ScriptStore.swift)
- Finder Sync extension (
SaneScriptExtension/FinderSync.swift) injects a context menu into Finder and triggers execution. - IPC mechanism: Extension writes
pending_execution.jsoninto the App Group container and sends aDistributedNotificationCenterping (com.sanescript.executeScript). Host app then reads the file and runs the script. (FinderSync.swift,ScriptExecutor.swift)
###Script execution model
- Supports Shell Command (bash), AppleScript, Automator workflow.
- Host-side execution is via
Process():/bin/bash -c <content> ...paths(ScriptExecutor.executeBash)/usr/bin/osascript -e <wrapped script> ...paths(executeAppleScript)/usr/bin/automator <workflowPath>with paths via stdin (executeAutomator)
- (
SaneScript/Services/ScriptExecutor.swift)
- Host-side execution is via
###Functional strengths
- Curated “library” UX: toggles install/enable quickly from categories (host UI in
ContentViewandScriptLibraryView). - Smart filtering: menu shows scripts only when
appliesTo+ extension filters match selection. (FinderSync.menu(for:)andExtensionScript.matchesFiles) - Test before save for bash/AppleScript in editor. (
ScriptEditorView.testScript())
###Functional gaps / bugs / inconsistencies (important)
- Bash argument passing inconsistency (likely a bug)
- In-app testing uses:
bash -c content+ paths (ScriptEditorView.runBashTestsetsprocess.arguments = ["-c", content] + paths)- With
bash -c, the first arg after script becomes$0, so$1becomes the second provided item. This contradicts the UI help text (“files passed as $1, $2…”).
- With
- Actual execution uses:
["-c", content, "bash"] + paths(correct pattern so$1is first selected path). (ScriptExecutor.executeBash) - Result: scripts that rely on
$1may behave differently in Test vs real Finder run.
- In-app testing uses:
- Extension status UI appears hardcoded
SettingsViewshows “Status: Active” in green unconditionally; it does not useExtensionStatusService.checkStatus()even though that service exists. (SettingsView.swift,ExtensionStatusService.swift)
- Menu scope is very broad
- Extension sets
finderSync.directoryURLs = Set(mountedVolumes)so it monitors all mounted volumes. (FinderSync.init) - That’s good for “works everywhere,” but it can impact performance or be more intrusive than needed on large/remote mounts.
- Extension sets
##2) UI/UX audit (based on SwiftUI views)
###What’s good
- Clear primary action (“Browse Library”), with “More Options” tucked away. (
ContentView) - Category-based mental model is strong; “Enable All” toggle per category is convenient.
- Script editor is structured well (Basic Info, filters, code, preview) and uses monospaced editor + test output modal. (
ScriptEditorView)
###UX issues / opportunities
- Script execution feedback: The app posts
executionCompletedNotificationand storeslastResult, but I didn’t see a strong user-visible “toast” or history view in the parts inspected. If execution fails from Finder, users may not notice or know where to look. - Discoverability of extension enablement: status is currently not reliable (hardcoded). This is a big UX papercut because Finder extensions frequently get “enabled but not running.”
- Library vs installed scripts confusion potential: In
ContentView, the detail shows all library scripts and toggling installs/enables them. This is nice, but users may expect “Your Actions” list to reflect installed only. - Accessibility: Some accessibility identifiers exist (editor controls), good for UI tests; but overall accessibility labeling/VoiceOver coverage isn’t fully clear without a broader pass.
##3) Security audit (threat model + code-backed findings)
###Baseline security posture (good)
- No network telemetry by design (privacy policy). (
PRIVACY.md) - Sparkle updater present; and there’s an explicit check to ensure
SUEnableSystemProfilingisn’t enabled. (UpdateService.swift) - Scripts run as the user, not elevated. (
SECURITY.md+Process()usage)
###Key risks (inherent + implementation)
- Arbitrary code execution by design
- This app is literally a script runner reachable from Finder. If a malicious script is added/imported, it can do anything the user can do.
- Mitigation is mostly “user awareness.” (
SECURITY.mdacknowledges no validation)
- IPC trust boundary: any process in the same user context can signal execution
- Host listens for
DistributedNotificationCentereventcom.sanescript.executeScript. (ScriptExecutor.init) - But the real payload is read from the App Group file
pending_execution.json. - If another process can write to the App Group container (usually only same TeamID apps with that App Group entitlement), it could request execution of a chosen script id with chosen paths.
- Practically: this is mostly a concern if the system is already compromised or another app with same App Group exists (unlikely), but it’s still the critical boundary.
- Host listens for
- Single pending file = race/overwrite
- The extension writes to a fixed filename:
pending_execution.jsonwith.atomic. (FinderSync.executeScript) - If the user triggers two scripts quickly (or multi-Finder events), later writes could overwrite earlier request. The host tries to dedupe by requestId and lock file, but the single file design still risks lost requests.
- The extension writes to a fixed filename:
- No output sanitization issues (low)
- Output is just shown in app UI; no obvious injection vector unless it’s later used in an unsafe way (not seen).
###Security improvements worth considering
- Make IPC queue-based (e.g., one file per request ID in a folder) instead of a single
pending_execution.json. - Consider validating that the sender is the extension (hard with DistributedNotificationCenter) or rely exclusively on file watcher events.
- Add a “danger mode” warning for imported scripts and show script diff/preview before enabling.
##4) Overall rating for this app (1–10)
These are my scores for SaneClick/SaneScript itself, based on the code and UX patterns:
- Functionality: 7.5/10
Strong core workflow and library; a few rough edges (bash test mismatch, extension status UX, single-file IPC). - UI/UX: 7/10
Clean and focused, but needs better “extension status truth” + clearer execution feedback and troubleshooting. - Security (for its category): 6.5/10
It’s a script runner (inherently high risk). Implementation is mostly reasonable (sandbox, Sparkle sanity check), but IPC + lack of script validation keep it from scoring higher. - Reliability/robustness: 7/10
ScriptStore backups/corruption handling are good; IPC could drop events; FinderSync across all volumes can be fragile on some systems.
Overall: 7/10
##5) Competitors on Mac (what to compare against)
You asked “compare against competitors for MAC.” Common competitors/alternatives in this space fall into:
- Finder enhancements / context menu tools (often Finder extensions or Finder hacks)
- Launcher/automation tools that can act on selected files (not always context menu)
- Finder replacements (Path Finder, ForkLift, etc.—not direct competitors, but overlap)
To do the “rate each app 1–10” part, tell me which ones you mean. If you want, I can compare against a representative set like:
- Dropzone
- Hazel
- BetterTouchTool (and/or BetterSnapTool family)
- Keyboard Maestro
- Raycast / Alfred workflows
- Automator/Services / Shortcuts (built-in)
…but I don’t want to invent a competitor list and mis-rank something you don’t care about.
##Final recommendation (based on this audit so far)
If your goal is: “I want a simple, privacy-respecting Finder right-click action menu with a curated set of scripts and the ability to add my own”, this app is a good choice, with two caveats:
- fix/understand the bash test vs actual execution arg mismatch, and
- expect the normal macOS Finder extension quirks (enablement/running status).
###What I need from you to finish the competitor comparison + 1–10 ratings
- What does “MAC” mean here (Mac App Store specifically, or macOS in general)?
- List the competitor apps you want rated (3–8 is ideal), or say “pick the top 5 competitors” and I’ll propose a list and rate them.
##Closest competitors (macOS) to SaneClick/SaneScript
SaneClick’s direct competitors are apps that add custom Finder context-menu items that run scripts/commands. The closest match I can substantiate quickly is:
- Context Menu (Mac App Store) – purpose-built for running shell scripts from Finder context menu (per independent write-up referencing pricing and features).
- Automator Quick Actions / Services (built-in) – native way to add Finder context menu actions.
- Shortcuts (macOS) – can act on Finder items and be exposed via Finder/Services in many cases.
- Keyboard Maestro – heavy-duty automation; can act on Finder selections (usually via hotkeys/palette rather than true Finder menu integration).
- Dropzone – file action launcher (drag/drop shelf), not a Finder right‑click menu, but overlaps strongly in “file actions”.
There are also Finder “enhancers” (e.g., XtraFinder/TotalFinder-style) but many are historically brittle/abandonware; I’m not including them as primary competitors unless you want that segment.
##Audit of SaneClick (this repo) — UI/UX, security, functionality
###Functionality (what it does well / gaps)
Strengths
- Curated library + one-toggle install/enable workflow is strong (
ContentView,ScriptLibraryView). - Smart filtering by “applies to” + extension matching exists in both host model and extension (
Script.matchesFiles,ExtensionScript.matchesFiles,FinderSync.menu(for:)). - Supports Shell, AppleScript, Automator execution (
ScriptExecutor). - Local JSON persistence with backups and corrupted-file preservation is good (
ScriptStore).
Notable functional issues
- Bash “Test” ≠ real execution argument behavior (likely bug):
- Real run uses
bash -c <script> bash <paths…>so$1is first file (ScriptExecutor.executeBash). - Test uses
bash -c <script> <paths…>so$1becomes the second file (because first arg after-cbecomes$0) (ScriptEditorView.runBashTest).
This can cause scripts to “work in Finder” but fail in Test (or vice versa).
- Real run uses
- Extension status UX is misleading:
SettingsViewshows Status “Active” hardcoded and doesn’t useExtensionStatusServiceeven though it exists.
###UI/UX
Good
- Clear “Browse Library” as primary onboarding path; “More Options” hides advanced scripting.
- Script editor is clean, grouped, includes a preview row and test output modal.
Needs improvement
- Execution feedback/history isn’t clearly surfaced (there is
ScriptExecutor.lastResult+ notification, but UX around it isn’t obvious from the views inspected). - Extension enablement troubleshooting should be first-class and accurate (use
ExtensionStatusService.checkStatus()).
###Security
Good
- No analytics/telemetry by design (
PRIVACY.md). - Uses Sparkle updater and explicitly checks that system profiling isn’t enabled (
UpdateService). - Scripts run as the user (no elevation), which is the correct baseline for this category (
SECURITY.md,Process()usage).
Risks (inherent + implementation)
- This is fundamentally an arbitrary code execution tool—security depends on trusting scripts you enable/import.
- IPC uses a fixed
pending_execution.jsonin App Group + distributed notification trigger. It’s reasonable, but a single pending file can be overwritten under rapid triggers; and it’s not a queue.
##Ratings (1–10)
###SaneClick / SaneScript (this app)
- UI/UX: 7/10
- Functionality: 7.5/10
- Security (for its category): 6.5/10
Overall: 7/10
###Competitors (closest on macOS)
- Context Menu (Mac App Store app)
- UI/UX: 8/10 (mature single-purpose UX; commonly includes confirmation/output options per review)
- Functionality: 8/10 (purpose-built Finder menu scripting; granular targeting)
- Security: 6/10 (same inherent “run scripts on files” risk; depends on safety features like confirmations)
Overall: 8/10
- Automator Quick Actions / Services (built-in)
- UI/UX: 5/10 (powerful but clunky; creation/management isn’t friendly)
- Functionality: 7/10 (can integrate into Finder, but building/maintaining actions is tedious)
- Security: 7/10 (Apple-native plumbing, but still runs your code with your permissions)
Overall: 6.5/10
- Shortcuts (macOS)
- UI/UX: 7/10 (more approachable than Automator; still gets complex)
- Functionality: 7/10 (excellent automation, Finder integration varies by action; not always “right-click first”)
- Security: 7/10 (permission prompts, sandboxing patterns; still can run shell scripts)
Overall: 7/10
- Keyboard Maestro
- UI/UX: 6/10 (dense, power-user oriented)
- Functionality: 9/10 (automation depth is best-in-class; Finder selection workflows possible)
- Security: 6/10 (very powerful automation surface area; macros can do a lot)
Overall: 8/10 (if you’ll actually use the power)
- Dropzone
- UI/UX: 8/10 (very polished “action shelf” workflow)
- Functionality: 7/10 (great for file actions, but not truly “Finder right-click menu”)
- Security: 6.5/10 (actions/plugins can be powerful; depends what you install)
Overall: 7/10
##Final recommendation
- If your priority is “Finder right‑click menu with lots of ready-to-use actions + privacy-first + lightweight”: SaneClick is a solid pick, but I’d only call it “best” after fixing the bash test vs run mismatch and making extension status/troubleshooting accurate.
- If you want the most polished direct Finder context-menu scripting experience today and don’t care about open-source: Context Menu is likely the strongest closest competitor.
- If you want maximum automation power beyond Finder menus: Keyboard Maestro wins, but it’s not as simple.
If you want, I can:
- propose a “top 7” competitor set (including Finder enhancers) and re-score, and/or
- produce a prioritized fix list for SaneClick to reach “9/10” (UX + robustness + IPC).
##Prioritized fix list to push SaneClick toward “9/10” (UX + robustness + security)
###P0 (must-fix: correctness / trust)
-
Fix Bash “Test” argument passing to match real execution
- Current mismatch:
- Real run:
bash -c <content> bash <paths…>(ScriptExecutor.executeBash) - Test:
bash -c <content> <paths…>(ScriptEditorView.runBashTest)
- Real run:
- Impact: scripts behave differently in Test vs Finder; breaks confidence.
- Fix: in
runBashTest, use the same convention as production:process.arguments = ["-c", content, "bash"] + paths
- Also update the help text if needed, but after the fix the help text becomes true.
- Current mismatch:
-
Make Settings “Extension Status” real (not hardcoded)
SettingsViewcurrently always displays “Active” in green.- You already have
ExtensionStatusService.checkStatus()that usespluginkit+pgrep. - Fix: poll status on appear + on timer (or a refresh button), and show
.active / .enabledNotRunning / .disabledwith instructions (“Restart Finder”, deep-link to Extensions settings).
###P1 (robustness: reduce “Finder extension weirdness” + dropped actions)
-
Replace single
pending_execution.jsonwith a queue- Current design can overwrite requests if triggered quickly.
- Suggested approach:
- Extension writes
Requests/<requestId>.jsoninto the App Group. - Host watches that folder and processes files in timestamp order, deleting after lock+read.
- Extension writes
- This also simplifies dedupe: file name is requestId.
-
Improve execution feedback in the moment
- Today results are stored in
ScriptExecutor.lastResultand a notification is posted. - Add UX:
- A small in-app “Last run” banner/toast.
- A “Run History” view (even just last N results in memory, optionally persisted).
- When launched from Finder, optionally auto-focus a compact result window.
- Today results are stored in
-
Guardrails for dangerous scripts
- Add optional per-script toggles:
- “Confirm before running”
- “Show output after run”
- Especially valuable for destructive file operations.
- Add optional per-script toggles:
###P2 (security hardening aligned with product intent)
-
Script import safety
- On import, show a diff/preview and require explicit enablement (import as disabled).
- Display a warning if script contains common dangerous patterns (best-effort lint, not “security theater”).
-
Minimize extension surface area
- Today extension registers all mounted volumes (
finderSync.directoryURLs = Set(mountedVolumes)). - Consider allowing a mode to scope it (e.g., user home only) or at least skip network volumes by default if performance complaints arise.
- Today extension registers all mounted volumes (
###P3 (polish & quality)
- Unify models between host and extension
- There are separate
ExecutionRequeststructs in both targets; keep them in a shared file/target to prevent drift.
- There are separate
- Automator workflow UX
- Add validation (“file exists”, “is .workflow”) and clearer messaging why testing isn’t supported.
- Accessibility & keyboarding
- Ensure the primary flows are fully navigable: library search → toggles → editor save/test.
##Highest ROI “9/10” path (if you only do 3 things)
- Fix Bash test args (P0.1)
- Real extension status + troubleshooting UI (P0.2)
- Queue-based IPC requests (P1.3)
If you want, I can point to the exact functions/lines to change for (1) and outline a concrete folder-based IPC design that still works with your current file watcher + lock strategy.
END OF POST