macOS menu-bar utility for pasted shell Command Recipes — start them, see what’s running, stop them, and quick-start recent ones.
Commands run through your login shell ($SHELL -l -c), so PATH matches Terminal. No Dock icon.
Requires macOS 14+ · License: MIT
RunThis is a local power-user tool. It will run whatever Start / Status / Stop commands you save, with your full user privileges and login-shell environment. There is no sandbox, no command allowlist, and no confirmation on start.
- Treat
~/Library/Application Support/RunThis/recipes.jsonlike an executable script folder: anyone or anything that can write it can make RunThis run code as you when you start a recipe (or when Status commands refresh). - Recipes (including inline
VAR=…), Quit Reports, and Session Snapshots are plain text — not a secrets vault. Do not store passwords or API keys in recipe fields. - Owned Process stop/quit sends SIGTERM to the login-shell process RunThis started; child processes may outlive that. Background Services are left alone on quit by design.
The software is provided “as is”, without warranty of any kind. You are responsible for the commands you paste and for reviewing recipes before starting them. See SECURITY.md.
Build from source (Xcode / Swift 6 toolchain):
git clone https://github.com/noahpatterson/RunThis.git
cd RunThis
./scripts/bundle-app.sh
open dist/RunThis.appOr for day-to-day development:
swift build
swift run RunThisLook for the terminal icon in the menu bar (tooltip: RunThis). Drag dist/RunThis.app to /Applications if you want it in Launchpad.
The bundle is ad-hoc signed for local use. macOS may warn on first open; use System Settings → Privacy & Security if needed. There is no notarized release binary in this repo yet.
Menu order:
- Running — recipes that are up; choose a row to Stop
- Recent — last few quick-starts (capped; overflow via All Recipes)
- All Recipes… — searchable full catalog; choose a row to start
- Add Command Recipe… — define a new recipe
- Reveal Recipes in Finder — opens the on-disk store
- Quit RunThis
| Field | Role |
|---|---|
| This: | Start Command (required). Help text: “(a command)”. Multi-line paste = one recipe. |
| Status: | Optional. Exit 0 = running (used for Background Services). |
| Stop: | Optional stop command. |
| Run Mode | Explicit: Owned Process or Background Service (never inferred from Status). |
| Working Directory | Optional path or folder picker. Empty → home. ~ / ~/… expanded at run. |
Owned Process — RunThis starts the command and keeps the process. Stop terminates it (or runs Stop when you provided one). On quit, Owned Processes are terminated.
Background Service — Start is one-shot; running state comes from Status (exit 0). Stop runs your Stop command when present. On quit, Background Services are left alone.
Starting a recipe that’s already running shows Already running (no second start). Identity is the saved recipe, not matching Start Command text across recipes.
Bare brew services info / list always exit 0. Prefer a translating Status Command, for example:
brew services info --json FORMULA | jq -e '.[0].running'- Empty → home
- Same directory for Start, Status, and Stop
- Explicit path missing or not a directory → alert (no silent home fallback)
~/Library/Application Support/RunThis/
recipes.json
QuitReport-YYYYMMDD-HHmmss.txt # only if something was running at quit
SessionSnapshot-YYYYMMDD-HHmmss.json
Reveal Recipes in Finder opens that folder. Quit artifacts are timestamped (local wall-clock); they are not overwritten and have no retention cap in v1 — delete them in Finder when you want.
swift test
swift scripts/generate-app-icon.swift . # regenerate AppIcon.icns
./scripts/bundle-app.sh # dist/RunThis.app| Target | Role |
|---|---|
RunThisCore |
Recipe session, runners, store, quit artifacts (testable without AppKit) |
RunThisApp |
Menu-bar accessory + sheets |
RunThisCoreTests |
Session-seam and adapter tests |
Domain glossary: CONTEXT.md. Product shape: docs/spec.md.
Live logs, background status polling, cloud sync, secrets vault, PID force-kill, display names/nicknames, restore-last-session UX (Session Snapshot is written for later), notarized releases.
See CONTRIBUTING.md.
MIT © 2026 Noah Patterson