Skip to content

Fix ripgrep resolution for Nix installs - #3946

Merged
austinywang merged 18 commits into
mainfrom
issue-3657-ripgrep-nix-paths
May 19, 2026
Merged

austinywang merged 18 commits into
mainfrom
issue-3657-ripgrep-nix-paths

Conversation

@austinywang

@austinywang austinywang commented May 12, 2026 •

Copy link
Copy Markdown
Contributor

Closes #3657

Summary

  • add a managed automation.ripgrepBinaryPath setting for cmux.json and Settings > Automation
  • resolve project-search ripgrep from the configured path before defaults
  • include common nix-darwin ripgrep locations in the default resolver

Verification

  • Reproduced the old resolver behavior locally with a Dock-style empty PATH and only /etc/profiles/per-user/nixuser/bin/rg available: observed nil, expected the Nix rg path.
  • Added regression coverage in the first commit; did not run local tests per repo policy.
  • Ran git diff --check and JSON parsing for Resources/Localizable.xcstrings and web/data/cmux.schema.json.

Note

Medium Risk
Medium risk because it changes how rg is located for both project Find and session indexing, which can alter search behavior or introduce new failure paths when the configured binary is invalid.

Overview
Fixes ripgrep discovery by introducing a shared RipgrepExecutableResolver that prefers a user-configured automation.ripgrepBinaryPath (with ~ expansion), adds common Nix install locations, and falls back to PATH.

Adds a new managed setting surfaced in Settings → Automation and cmux.json (schema/template/JSON-path allowlist/search aliases/localizations), shows a localized error in Find when the configured path is not executable, and logs a warning + falls back for session search. Includes regression tests covering resolver precedence, nix paths, tilde expansion, invalid overrides, and settings-file import.

Reviewed by Cursor Bugbot for commit 84eb661. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Adds a managed automation.ripgrepBinaryPath and a shared resolver to find rg for Find and session search. It prefers the configured path (with ~), then macOS defaults, Nix profiles, then PATH; Find shows a localized error for non-executable overrides, and session search logs a warning and falls back. Fixes #3657.

  • New Features

    • Added automation.ripgrepBinaryPath in cmux.json and Settings → Automation (schema, template default, JSON-path allowlist, managed import, localizations, settings search alias, UI field).
  • Bug Fixes

    • Replaced ad‑hoc lookup with RipgrepExecutableResolver shared by Find and session indexing. Precedence: configured path (~ supported) → macOS (/opt/homebrew/bin/rg, /usr/local/bin/rg, /opt/local/bin/rg, /usr/bin/rg) → Nix (/etc/profiles/per-user/<user>/bin/rg, /run/current-system/sw/bin/rg, /nix/var/nix/profiles/default/bin/rg, ~/.nix-profile/bin/rg, /nix/var/nix/profiles/per-user/<user>/profile/bin/rg) → PATH. Find surfaces a localized “not executable” error; session search logs a warning and falls back to substring search. Tests cover precedence, Nix paths (including Home Manager/per-user), tilde expansion, invalid overrides, message text, and settings import.

Written for commit 84eb661. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • New Features
    • Added configurable custom ripgrep binary path in automation settings
    • Implemented validation to verify the specified path is executable
    • New error message displays when configured path is not executable
    • Full localization support across multiple languages

Review Change Stack

@vercel

vercel Bot commented May 12, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment May 19, 2026 8:07am
cmux-staging Building Building Preview, Comment May 19, 2026 8:07am

@coderabbitai

coderabbitai Bot commented May 12, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds a user-configurable automation.ripgrepBinaryPath setting that lets users point cmux to custom ripgrep installations, refactors executable discovery into a resolver that checks the configured path and Nix profile directories, and wires the setting into the schema, settings UI, and search system with full test coverage.

Changes

Custom ripgrep binary path support

Layer / File(s) Summary
Ripgrep executable resolver and integration
Sources/FileExplorerSearchController.swift, cmuxTests/FileExplorerStoreTests.swift, Resources/Localizable.xcstrings
New RipgrepExecutableResolver type checks a user-configured custom path in UserDefaults, then probes Nix profile paths (/etc/profiles/per-user/$USER/bin, /run/current-system/sw/bin), then falls back to default install locations and PATH. Returns .found(executable), .configuredPathNotExecutable(path), or .notFound. FileSearchController's search() uses the resolver result to either execute ripgrep, emit a localized error for non-executable configured paths, or fail with the existing "rg not installed" message. Four new unit tests validate resolver precedence, Nix path discovery, executability checks, and error message formatting. New localized error string for configured paths that exist but are not executable.
Settings schema and persistence
web/data/cmux.schema.json, Sources/CmuxSettingsJSONPathSupport.swift, Sources/KeyboardShortcutSettingsFileStore+Template.swift, Sources/KeyboardShortcutSettingsFileStore.swift, cmuxTests/KeyboardShortcutSettingsFileStoreStartupTests.swift
automation.ripgrepBinaryPath added to the web schema as a string property with default "" and description. supportedSettingsJSONPaths allowlist updated to recognize the path. Default JSONC template includes the field initialized to empty string. Settings file parser now extracts ripgrepBinaryPath from the automation section and writes it to UserDefaults under RipgrepIntegrationSettings.customRipgrepPathKey. New startup test verifies the settings file store reads and persists the value.
Settings UI, search integration, and localization
Sources/cmuxApp.swift, Sources/SettingsNavigation.swift, Sources/SettingsSearchAliases.swift, Resources/Localizable.xcstrings
SettingsView adds @AppStorage binding for customRipgrepPath, renders a text field in Automation settings with placeholder guidance, and includes the setting in reset-all flow. Navigation index adds a ripgrep-path setting entry with localized title. Settings search alias system maps automation:ripgrep-path to localized keywords. Localization file includes UI label, placeholder text, subtitle, search alias tags, and error message across en, ja, and ko.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • manaflow-ai/cmux#2655: Extends the CmuxSettingsFileStore.supportedSettingsJSONPaths allowlist that was introduced in PR #2655.
  • manaflow-ai/cmux#3294: Adds related settings search alias and localization entries that follow patterns established in PR #3294's settings-search refactoring.
  • manaflow-ai/cmux#3409: Extends settings infrastructure (schema, KeyboardShortcutSettingsFileStore, search/labels, localization) that PR #3409 refactored.

Poem

🐰 A rabbit hops through Nix paths with glee,
Custom ripgrep binaries run wild and free!
No more hardcoded searches, just one config line—
Resolver finds rg in profiles so fine.
✨ Search now works where Nix dwells, divine! 🔍


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Cmux Architecture Rethink ❓ Inconclusive No result was produced after verification. Marking as INCONCLUSIVE. Re-run the check or adjust instructions to produce a final result.
✅ Passed checks (13 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix ripgrep resolution for Nix installs' clearly and concisely summarizes the main objective of the changeset: resolving ripgrep discovery on Nix-managed systems.
Linked Issues check ✅ Passed All requirements from #3657 are met: (1) new automation.ripgrepBinaryPath setting added to cmux.json and Settings UI [multiple files], (2) ripgrep resolution priority implemented with configured path first [FileExplorerSearchController.swift], (3) Nix profile paths integrated into default resolver, and (4) localized error handling for non-executable paths [FileExplorerSearchController.swift, Localizable.xcstrings].
Out of Scope Changes check ✅ Passed All changes directly support the two requested fixes: persisted setting infrastructure (CmuxSettingsJSONPathSupport.swift, KeyboardShortcutSettingsFileStore.swift, SettingsNavigation.swift, SettingsSearchAliases.swift, cmuxApp.swift, schema.json, template), ripgrep resolver implementation (FileExplorerSearchController.swift), and regression tests; no unrelated modifications found.
Cmux Swift Actor Isolation ✅ Passed PR introduces no new Swift 6 actor isolation violations. Value models are properly Sendable, UI controllers are correctly @MainActor, and background tasks use proper weak-self captures.
Cmux Swift Blocking Runtime ✅ Passed No blocking synchronization primitives introduced. RipgrepExecutableResolver uses synchronous FileManager checks, appropriate for init-time path resolution.
Cmux No Hacky Sleeps ✅ Passed Check applies to TypeScript, JavaScript, and shell scripts. PR modifies only Swift files, JSON schema, and localization. No targeted file types were modified. Swift sleeps covered by separate rule.
Cmux Swift Concurrency ✅ Passed All new code is purely synchronous. No DispatchQueue.global, new Combine, completion handlers, or fire-and-forget Tasks. Only @AppStorage (SwiftUI) and XCTest additions, which are allowed.
Cmux Swift @Concurrent ✅ Passed No Swift concurrent annotation violations. Nonisolated async functions doing file I/O are properly called from Task.detached blocks with explicit actor hops. No incorrect @concurrent usage found.
Cmux Swift File And Package Boundaries ✅ Passed No oversized files created. FileExplorerSearchController under limit. All additions have clear responsibilities. RipgrepExecutableResolver appropriately scoped, testable with injection.
Cmux Swift Logging ✅ Passed No logging violations detected. PR adds ripgrep resolution without introducing print, NSLog, debugPrint, dump, file logging, or MainActor-coupled Logger issues in production code.
Cmux Swiftui State Layout ✅ Passed SwiftUI state layout compliant. Uses @AppStorage (modern pattern), no @Published/@observableobject, no render-time mutations, no GeometryReader layout issues.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR only adds UI to existing Settings window (cmux.settings), which is already registered. No new windows created.
Description check ✅ Passed The PR description is comprehensive and complete, covering the summary, verification steps, and all key information about the changes.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-3657-ripgrep-nix-paths

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented May 12, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes ripgrep discovery for Nix installs by replacing two independent ad-hoc resolver functions (in FileSearchController and SessionIndexStore) with a single shared RipgrepExecutableResolver that respects a new user-configurable automation.ripgrepBinaryPath setting and adds common Nix profile locations to the default search list.

  • RipgrepExecutableResolver follows a four-level precedence: configured path (with ~ expansion) → macOS defaults → Nix profile paths → PATH. A non-empty configured path that fails the executable check returns .configuredPathNotExecutable instead of silently falling through, so Find surfaces a localized String(format:)-substituted error and session search emits a unified-log warning before falling back to the Foundation scan.
  • Settings plumbing is fully wired: cmux.schema.json, the JSON-path allowlist, the settings template, the managed import, Settings → Automation UI (with localized label/subtitle/placeholder), the search index, and search aliases all include the new automation.ripgrepBinaryPath key.
  • Localization is complete across all three supported locales (en, ja, ko) for every new user-facing string, including the %@ format-specifier error key consumed by String(format:).

Confidence Score: 5/5

Safe to merge — the resolver is well-isolated, all three locales are covered, the configuredPathNotExecutable path is surfaced correctly in both Find and session search, and the previous review issues are fully addressed.

The change consolidates two previously divergent resolver implementations into a single, dependency-injectable RipgrepExecutableResolver. The session search path changed from a one-time static-let to per-call resolution, which is intentional (settings changes take effect immediately) and the overhead is trivial (stat calls). Localization, JSON schema, managed import, allowlist, search index, and settings UI are all updated in lockstep. Seven new resolver unit tests and one settings-import integration test cover all meaningful code paths. No blocking primitives, no actor-isolation regressions, no sensitive data in logs.

No files require special attention.

Important Files Changed

Filename Overview
Sources/FileExplorerSearchController.swift Introduces RipgrepExecutableResolver, RipgrepIntegrationSettings, and FileExplorerSearchMessages; replaces ad-hoc rg lookup with the shared resolver and correctly surfaces a localized String(format:)-substituted error for the configuredPathNotExecutable case.
Sources/SessionIndexStore.swift Replaces static-let cached path with resolvedRipgrepPath() that delegates to the shared resolver; correctly adds an os.Logger warning before falling back to Foundation scan on configuredPathNotExecutable.
Resources/Localizable.xcstrings Adds four new string keys with complete en/ja/ko translations and a %@ format specifier in the error key consumed by String(format:).
Sources/cmuxApp.swift Adds @AppStorage for customRipgrepPath, a Settings > Automation card with a localized TextField, and resets the value in resetSettings().
cmuxTests/FileExplorerStoreTests.swift Adds seven resolver tests covering precedence, tilde expansion, Nix/Home Manager paths, non-executable override rejection, and %@ substitution verification.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Search triggered\nFind or Session] --> B[RipgrepExecutableResolver.resolution]
    B --> C{configuredPath\nnon-empty?}
    C -- Yes --> D{isExecutable\nconfiguredPath?}
    D -- Yes --> E[.found — use configured binary]
    D -- No --> F[.configuredPathNotExecutable]
    F --> G{Caller?}
    G -- FileSearchController --> H[Emit localized error\nin Find UI]
    G -- SessionIndexStore --> I[os_log warning\nfall back to Foundation scan]
    C -- No --> J[Check default paths\n/opt/homebrew, /usr/local,\n/opt/local, /usr/bin,\nNix profile paths ×5]
    J --> K{Any path\nexecutable?}
    K -- Yes --> E
    K -- No --> L[Walk PATH entries]
    L --> M{rg found\nin PATH?}
    M -- Yes --> E
    M -- No --> N[.notFound]
    N --> O{Caller?}
    O -- FileSearchController --> P[Emit rg-not-installed\nerror in Find UI]
    O -- SessionIndexStore --> Q[Fall back to\nFoundation substring scan]
Loading

Reviews (13): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile

Comment thread Sources/FileExplorerSearchController.swift Outdated
Comment thread Sources/FileExplorerSearchController.swift Outdated
Comment thread Sources/SessionIndexStore.swift Outdated
@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@austinywang
austinywang merged commit 3187c15 into main May 19, 2026
24 checks passed
@austinywang austinywang mentioned this pull request May 19, 2026

This branch was successfully deployed

1 active deployment
Preview – cmux — 84eb661c Deployed May 19, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add ripgrepBinaryPath setting + extend rg search to nix profile paths

1 participant