Skip to content

Add app-hider extension - #33526

Open
LeonidAlekseev wants to merge 1 commit into
raycast:mainfrom
LeonidAlekseev:ext/app-hider
Open

LeonidAlekseev wants to merge 1 commit into
raycast:mainfrom
LeonidAlekseev:ext/app-hider

Conversation

@LeonidAlekseev

@LeonidAlekseev LeonidAlekseev commented Nov 14, 2026 •

Copy link
Copy Markdown

Description

App Hider hides Mac apps from Launchpad, Spotlight and Finder, and restores them later.

Selected apps are moved from /Applications or ~/Applications into a Spotlight-excluded folder (~/Library/Application Support/App Hider/Hidden.noindex). Hidden apps can still be launched from Raycast and restored to their original location at any time.

Safety notes for reviewers

  • Every hide and restore asks for confirmation first.
  • Only top-level app bundles in /Applications and ~/Applications are offered. Symlinks and system locations (/System/...) are never touched.
  • Apps are moved with an atomic rename on the same volume, with no copying. A move is rolled back if the restore record can't be saved.
  • If an app is running, it's only moved after the user agrees to quit it.
  • Administrator rights are requested through the standard macOS password prompt, only for system-owned bundles (e.g. App Store apps) and only after a confirmation dialog.
  • Launchpad is refreshed after hiding or restoring (ResetLaunchPad + killall Dock on macOS 15 and older, killall Spotlight on macOS 26+). This can be turned off in the extension preferences.

Screencast

List of hidden and visible apps
Hide confirmation
Actions

Checklist

- Use failureToastOptions for the scan error toast
- Update package-lock
- Address Store review feedback
- Add package-lock and Store screenshots
- Fix lint: use Raycast common shortcuts and run Prettier
- Prepare extension for the Raycast Store
- Add screenshot to README
- Replace extension icon with a slashed eye
- Initial commit: App Hider Raycast extension
@raycastbot raycastbot added new extension Label for PRs with new extensions platform: macOS labels Nov 14, 2026
@raycastbot

Copy link
Copy Markdown
Collaborator

Congratulations on your new Raycast extension! 🚀

We're currently experiencing a high volume of incoming requests. As a result, the initial review may take up to 15 business days.

Once the PR is approved and merged, the extension will be available on our Store.

@LeonidAlekseev LeonidAlekseev left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Useful extension.

@LeonidAlekseev
LeonidAlekseev marked this pull request as ready for review November 14, 2026 21:33
@greptile-apps

greptile-apps Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The change affects app locations and launcher listings on a user’s Mac.

The Launchpad layout-loss warning must be added before merging.

Findings

  1. P1 App moves erase Launchpad layouts ▶
  2. P2 Interrupted hides lose their records ▶
  3. P2 Array registries drop restore records ▶
  4. P2 Move errors show wrong advice ▶
Fix with agent prompt
### Issue 1
extensions/app-hider/src/manage-apps.tsx:291-293
On macOS 15 and older, hiding or restoring an app resets Launchpad folders and icon order because `resetLaunchpad` defaults to true. Neither move confirmation mentions this loss. The repository requires confirmation before an irreversible change. Add the layout warning to those confirmations, or ask separately before resetting, as the manual refresh already does.

### Issue 2
extensions/app-hider/src/manage-apps.tsx:467-476
`hideApp` moves the bundle before saving its restore record. If Raycast crashes or is force-quit between those steps, the catch block cannot roll back the move. Later scans read hidden apps only from the registry, so the app disappears from the extension and needs manual recovery. Save a pending move before renaming, then repair unfinished moves on startup.

### Issue 3
extensions/app-hider/src/manage-apps.tsx:173-174
`readRegistry` accepts any valid JSON as a `Registry`. If a damaged or manually repaired file contains `[]`, scanning succeeds, but hiding an app adds a string-keyed property to that array. `JSON.stringify` drops that property, so saving succeeds without the restore record and no rollback runs. Reject arrays and check entry fields before allowing moves.

### Issue 4
extensions/app-hider/src/manage-apps.tsx:386
`moveBundle` assigns `EPERM` to every non-cancellation error from the administrator command. `errorMessage` then replaces the actual error with App Management instructions. If a move fails because the disk is full or another filesystem error occurs, users are told to change an unrelated permission. Preserve the original error and show permission advice only for an actual permission denial.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

Adds App Hider, a macOS extension that moves apps into a Spotlight-excluded folder and restores or launches them later.

  • Raycast lets you hide selected Mac apps and bring them back later.

Acknowledged limitations:

  • LeonidAlekseev documents that launching hidden apps can make them appear again and that moved apps may stop updating. These were not reported.
  • LeonidAlekseev documents the classic Launchpad reset itself. The finding concerns its absence from the move confirmations, not the chosen refresh method.

Reviews (1) · Last reviewed commit: "Add app-hider extension" · Reviewed by Greptile

Comment on lines +291 to +293
async function refreshLaunchpadIfEnabled(): Promise<void> {
if (!getPreferenceValues<Preferences>().resetLaunchpad) return;
await refreshAppLauncher().catch(() => undefined);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 App moves erase Launchpad layouts

On macOS 15 and older, hiding or restoring an app resets Launchpad folders and icon order because resetLaunchpad defaults to true. Neither move confirmation mentions this loss. The repository requires confirmation before an irreversible change. Add the layout warning to those confirmations, or ask separately before resetting, as the manual refresh already does.

Rule Used: Destructive actions What: An action that deletes or overwrites something, or otherwise needs the user's care, uses style={Action.Style.Destructive}. If it can't be undone, ask first with confirmAlert and Alert.ActionStyle.Destructive, using th... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/app-hider/src/manage-apps.tsx
Line: 291-293

Comment:
**App moves erase Launchpad layouts**

On macOS 15 and older, hiding or restoring an app resets Launchpad folders and icon order because `resetLaunchpad` defaults to true. Neither move confirmation mentions this loss. The repository requires confirmation before an irreversible change. Add the layout warning to those confirmations, or ask separately before resetting, as the manual refresh already does.

**Rule Used:** Destructive actions  What: An action that deletes or overwrites something, or otherwise needs the user's care, uses `style={Action.Style.Destructive}`. If it can't be undone, ask first with `confirmAlert` and `Alert.ActionStyle.Destructive`, using th... ([source](https://github.com/raycast/extensions/blob/56309172f3ecebc3248e0cb208eae69c79e85bb6/.greptile/config.json))

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +467 to +476
await moveBundle(app.path, hiddenPath);

try {
registry[app.path] = {
name: app.name,
originalPath: app.path,
hiddenPath,
hiddenAt: new Date().toISOString(),
};
await writeRegistry(registry);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Interrupted hides lose their records

hideApp moves the bundle before saving its restore record. If Raycast crashes or is force-quit between those steps, the catch block cannot roll back the move. Later scans read hidden apps only from the registry, so the app disappears from the extension and needs manual recovery. Save a pending move before renaming, then repair unfinished moves on startup.

Knowledge Base Used: Extension command implementation patterns

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/app-hider/src/manage-apps.tsx
Line: 467-476

Comment:
**Interrupted hides lose their records**

`hideApp` moves the bundle before saving its restore record. If Raycast crashes or is force-quit between those steps, the catch block cannot roll back the move. Later scans read hidden apps only from the registry, so the app disappears from the extension and needs manual recovery. Save a pending move before renaming, then repair unfinished moves on startup.

**Knowledge Base Used:** [Extension command implementation patterns](https://app.greptile.com/-/switch-tenant?tenant=raycast&next=%2Fcustom-context%2Fknowledge-base%2Fraycast%2Fextensions%2F-%2Fdocs%2Fextension-command-implementation.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +173 to +174
try {
return JSON.parse(raw) as Registry;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Array registries drop restore records

readRegistry accepts any valid JSON as a Registry. If a damaged or manually repaired file contains [], scanning succeeds, but hiding an app adds a string-keyed property to that array. JSON.stringify drops that property, so saving succeeds without the restore record and no rollback runs. Reject arrays and check entry fields before allowing moves.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/app-hider/src/manage-apps.tsx
Line: 173-174

Comment:
**Array registries drop restore records**

`readRegistry` accepts any valid JSON as a `Registry`. If a damaged or manually repaired file contains `[]`, scanning succeeds, but hiding an app adds a string-keyed property to that array. `JSON.stringify` drops that property, so saving succeeds without the restore record and no rollback runs. Reject arrays and check entry fields before allowing moves.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

);
} catch (error) {
if (isUserCancel(error)) throw new CancelledError();
throw Object.assign(new Error(errorMessage(error)), { code: "EPERM" });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Move errors show wrong advice

moveBundle assigns EPERM to every non-cancellation error from the administrator command. errorMessage then replaces the actual error with App Management instructions. If a move fails because the disk is full or another filesystem error occurs, users are told to change an unrelated permission. Preserve the original error and show permission advice only for an actual permission denial.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/app-hider/src/manage-apps.tsx
Line: 386

Comment:
**Move errors show wrong advice**

`moveBundle` assigns `EPERM` to every non-cancellation error from the administrator command. `errorMessage` then replaces the actual error with App Management instructions. If a move fails because the disk is full or another filesystem error occurs, users are told to change an unrelated permission. Preserve the original error and show permission advice only for an actual permission denial.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new extension Label for PRs with new extensions platform: macOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants