|
1 | 1 | # GhostTile |
2 | 2 |
|
3 | | -GhostTile hides selected apps from the Dock and Cmd+Tab on macOS. |
| 3 | +<p align="center"> |
| 4 | + <img src="docs/imgs/appIcon-new.png" alt="GhostTile" width="128"> |
| 5 | +</p> |
4 | 6 |
|
5 | | -It ships as both: |
6 | | -- A native macOS menu bar app |
7 | | -- A CLI for scripting and recovery flows |
| 7 | +Hide running macOS apps from the Dock and Cmd+Tab. Native menu-bar app, native CLI, signed and notarized — no daemons, no runtime swizzling. |
| 8 | + |
| 9 | +> Why this exists and how it's built: see [Background](#background). |
8 | 10 |
|
9 | 11 | Requires macOS 15+. |
10 | 12 |
|
11 | | -## What GhostTile Changes |
| 13 | +## Features |
12 | 14 |
|
13 | | -GhostTile prepares managed apps by: |
| 15 | +- Hide any running app from the Dock and Cmd+Tab while it keeps working in the background |
| 16 | +- Status bar menu plus Dock submenu for one-click reveal / hide / activate |
| 17 | +- Quick Switch overlay (`⌃⇧Tab`) for keyboard-only navigation between hidden apps |
| 18 | +- **Spotlight & Shortcuts.app integration** via native App Intents — hide, show, focus from `⌘Space` |
| 19 | +- CLI with stable JSON output for scripts, cron, Hammerspoon, Alfred |
| 20 | +- `ghosttile://` URL scheme for Shortcuts.app and external launchers |
| 21 | +- Sparkle auto-updates in signed builds |
14 | 22 |
|
15 | | -- staging `ghosthide.dylib` inside the target app bundle |
16 | | -- patching the main executable to load that helper |
17 | | -- re-signing the modified app ad hoc |
| 23 | +## Install |
18 | 24 |
|
19 | | -That gives GhostTile a persistent way to keep selected apps out of the Dock after normal launches. If an app misbehaves, use `ghosttile restore "<App Name>"` to remove GhostTile's changes from that app. |
| 25 | +### Homebrew |
20 | 26 |
|
21 | | -## Install |
| 27 | +```bash |
| 28 | +brew install --cask hewigovens/tap/ghosttile |
| 29 | +``` |
22 | 30 |
|
23 | | -### App |
| 31 | +### Direct download |
24 | 32 |
|
25 | | -- Download the latest `GhostTile.app` archive from GitHub Releases, then move it to `/Applications` |
26 | | -- Or build locally with `just build` |
| 33 | +Grab the latest signed + notarized build from [GitHub Releases](https://github.com/hewigovens/ghosttile-cli/releases/latest) and move `GhostTile.app` to `/Applications`. |
27 | 34 |
|
28 | | -### CLI |
| 35 | +### From source |
29 | 36 |
|
30 | | -- GhostTile.app bundles a matching CLI and can install it from Settings |
31 | | -- Or build locally with `just build-cli` |
| 37 | +```bash |
| 38 | +git clone https://github.com/hewigovens/ghosttile-cli |
| 39 | +cd ghosttile-cli |
| 40 | +just build |
| 41 | +``` |
| 42 | + |
| 43 | +The app bundle ships with a matching `ghosttile` CLI; install it from **Settings → CLI**, or build it standalone with `just build-cli`. |
32 | 44 |
|
33 | 45 | ## Quick Start |
34 | 46 |
|
35 | | -1. Launch `GhostTile.app` |
36 | | -2. Add an app from the `Running` list, click `+`, or drag an `.app` bundle into the `Managed` column |
37 | | -3. GhostTile prepares the app if needed, relaunches it hidden, and stores it in the managed list |
38 | | -4. Use the managed row actions to show it in the Dock, hide it again, or restore it |
| 47 | +1. Launch `GhostTile.app`. |
| 48 | +2. Add an app from the **Running** sidebar, click **+**, or drag an `.app` bundle into the **Managed** column. |
| 49 | +3. GhostTile prepares the bundle (binary patch + re-sign), relaunches the app hidden, and records it in the managed list. |
| 50 | +4. Use the row actions to show in the Dock, hide again, focus, or restore the original binary. |
| 51 | + |
| 52 | +The status bar menu also toggles GhostTile's own Dock presence, activates managed apps, shows/hides them, and opens Settings. |
| 53 | + |
| 54 | +## How It Works |
| 55 | + |
| 56 | +GhostTile prepares each managed app by: |
39 | 57 |
|
40 | | -The status bar menu also lets you toggle whether GhostTile itself appears in the Dock, activate managed apps, show or hide them, and open Settings. |
| 58 | +1. Staging `ghosthide.dylib` inside the target app bundle. |
| 59 | +2. Patching the main executable to load that helper at launch. |
| 60 | +3. Re-signing the modified bundle ad hoc. |
41 | 61 |
|
42 | | -## CLI Usage |
| 62 | +The app then launches normally but presents itself as an accessory process — no Dock tile, no Cmd+Tab entry. The dylib also listens for distributed notifications so GhostTile can flip Dock visibility live without restarting the app. |
| 63 | + |
| 64 | +If anything goes wrong, `ghosttile restore "<App Name>"` restores the original binary and removes GhostTile's modifications. |
| 65 | + |
| 66 | +## Spotlight Actions |
| 67 | + |
| 68 | +GhostTile registers four App Shortcuts that surface in Spotlight and in Shortcuts.app: |
| 69 | + |
| 70 | +| Action | Phrase | |
| 71 | +|---|---| |
| 72 | +| Hide app from Dock | *"Hide \<app\> with GhostTile"* | |
| 73 | +| Show app in Dock | *"Show \<app\> with GhostTile"* | |
| 74 | +| Focus managed app | *"Focus \<app\> with GhostTile"* | |
| 75 | +| Open the GhostTile window | *"Open GhostTile"* | |
| 76 | + |
| 77 | +Trigger any of them from `⌘Space`. The same actions are available in Shortcuts.app for use in automations. |
| 78 | + |
| 79 | +## CLI |
43 | 80 |
|
44 | 81 | ```bash |
45 | | -ghosttile list |
| 82 | +ghosttile list # managed apps |
| 83 | +ghosttile status # running + dock state |
46 | 84 | ghosttile manage "App Name" |
47 | 85 | ghosttile manage "/Applications/App Name.app" |
48 | | -ghosttile status |
49 | 86 | ghosttile hide "App Name" |
50 | 87 | ghosttile show "App Name" |
51 | 88 | ghosttile focus "App Name" |
52 | 89 | ghosttile restore "App Name" |
53 | 90 | ``` |
54 | 91 |
|
55 | | -Use `--json` with `list` and `status` for machine-readable output. |
| 92 | +Pass `--json` to `list` and `status` for machine-readable output. |
56 | 93 |
|
57 | 94 | ## Permissions |
58 | 95 |
|
59 | | -- App Management: needed to prepare and restore apps from the GUI |
60 | | -- Terminal administrator prompt: used for fallback flows when protected file operations fail |
61 | | -- Screen Recording: only needed for Overview thumbnails |
| 96 | +- **App Management** — required to prepare and restore apps from the GUI. |
| 97 | +- **Terminal administrator** — used as a fallback for protected file operations. |
| 98 | +- **Screen Recording** — only needed for the Overview thumbnail grid. |
62 | 99 |
|
63 | 100 | ## Caveats |
64 | 101 |
|
65 | | -- System apps and SIP-protected apps are not supported |
66 | | -- Some hardened apps need extra preparation before they can be launched with the helper dylib |
67 | | -- Some apps can still promote themselves back into the Dock after launch |
68 | | -- App preparation modifies the target bundle in place, so use `restore` before troubleshooting unrelated app issues |
| 102 | +- System apps and SIP-protected apps are not supported. |
| 103 | +- Some hardened apps need extra preparation before they can launch with the helper dylib. |
| 104 | +- A few apps re-promote themselves into the Dock after launch; that's app-specific behavior, not a GhostTile bug. |
| 105 | +- App preparation modifies the target bundle in place — `restore` it before troubleshooting unrelated app issues. |
69 | 106 |
|
70 | | -## Spotlight Actions |
| 107 | +## Auto-update |
71 | 108 |
|
72 | | -GhostTile registers App Shortcuts so you can hide, show, and focus managed apps straight from Spotlight (and Shortcuts.app). Open Spotlight and type "GhostTile" to see the available actions. |
| 109 | +Signed releases ship with Sparkle. Check manually from **Check for Updates…** in the GhostTile menu, or leave automatic checks enabled in Settings. |
73 | 110 |
|
74 | | -## Auto-update |
| 111 | +## Background |
75 | 112 |
|
76 | | -GhostTile uses Sparkle for in-app updates in signed release builds. You can check manually from the app, or leave automatic checks enabled in Settings. |
| 113 | +GhostTile 2.0 is a ground-up rewrite. The original stalled against modern macOS hardening; the new version is built around explicit staging, code signing, and notarization rather than runtime tricks. [Rewriting GhostTile for Modern macOS](https://hewig.dev/posts/rewriting-ghosttile) covers the motivation and design decisions in more detail. |
77 | 114 |
|
78 | | -## Development Docs |
| 115 | +## Development |
79 | 116 |
|
80 | 117 | - Contributor setup: [CONTRIBUTING.md](CONTRIBUTING.md) |
81 | 118 | - Security reporting: [SECURITY.md](SECURITY.md) |
82 | | -- Internal engineering notes: [`docs/dev`](docs/dev) |
| 119 | +- Engineering notes: [`docs/dev`](docs/dev) |
83 | 120 |
|
84 | 121 | ## License |
85 | 122 |
|
86 | | -BSL 1.1 — source available and free to use, modify, and redistribute. The paid marketplace restriction remains in the license as a legacy reminder of the project's commercial roots. Converts to Apache-2.0 on 2030-03-23. See [LICENSE](LICENSE). |
| 123 | +BSL 1.1 — source available and free to use, modify, and redistribute. The paid-marketplace restriction is a legacy reminder of the project's commercial roots; the license converts to Apache-2.0 on 2030-03-23. See [LICENSE](LICENSE). |
0 commit comments