Skip to content

waxim/butt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Butt

A tiny macOS menu bar app for running the bash commands you keep forgetting.

Butt lives in your menu bar. Click the icon, pick a command, and it runs in the background. The icon turns green if it worked and red if it didn't. Commands can be grouped, given a working folder, and prompt for arguments at run time. Every run's stdout and stderr is saved to a log file you can browse later.

Born from the everyday tax of context-switching to a terminal, hunting for the right directory, and re-typing the same incantation for the hundredth time. Butt is the smallest possible thing that fixes that.

Features

  • Menu bar only — no dock icon, no window cluttering your desktop.
  • Groups — organise commands into collapsible submenus.
  • Working directory per command — no more cd ~/projects/foo && ….
  • Runtime arguments — define {{name}} placeholders and Butt prompts you for them when you click. Supports plain and secret (password-style) inputs, default values, and format hints.
  • Live status — the menu bar icon shows the last run's outcome at a glance:
    • green check — last run succeeded
    • red exclamation — last run failed
    • yellow play — something is currently running
  • Log viewer — every run is recorded with timing, exit code, arguments, and full stdout+stderr captured live. Cancel long-running commands from the log viewer.
  • Configurable shell — defaults to /bin/zsh -l -c … so your aliases and PATH match Terminal.

Requirements

  • macOS 14.0 (Sonoma) or later
  • Apple Silicon (M-series) Mac
  • Swift 5.10+ toolchain (ships with Xcode 15.3 / Command Line Tools)

Install

From source

git clone https://github.com/<your-username>/butt.git
cd butt
./build.sh

The script produces build/Butt.app. Drag it to /Applications (or run it straight from build/):

open build/Butt.app

To build and launch in one step:

./build.sh run

For a debug build:

./build.sh debug

Quitting the app

Click the menu bar icon and choose Quit Butt (⌘Q while the menu is open).

First run

Butt seeds two example commands under an "Examples" group so you can try it immediately:

  • Hello — prompts for a name and prints Hello <name>!
  • Disk usage (home) — runs du -sh ~

Click the menu bar icon, hover over Examples, and pick one.

Configuring commands

Open Configure… from the menu (⌘,).

Each command has:

Field Notes
Name Shown in the menu.
Group Used as the submenu name. New groups are created on the fly.
Working Folder Resolved with ~ expansion. The shell is launched with this as cwd.
Shell Defaults to /bin/zsh. Anything that takes -c works (/bin/bash, /usr/bin/env fish, …).
Login shell (-l) When on, your login profile (PATH, aliases) is loaded. Recommended for parity with Terminal.
Command The bash snippet. Multi-line is fine. Use {{argName}} to reference arguments.
Arguments Each argument has a name (used in {{…}}), a placeholder/format hint, an optional default, and a "secret" flag for password-style inputs.
Notes Free-form, not used at run time.

Argument substitution

Arguments are substituted into the command verbatim. If an argument may contain whitespace or shell-meaningful characters, quote the placeholder:

git checkout "{{branch}}"
curl -H "Authorization: Bearer {{token}}" https://api.example.com/{{path}}

Mark tokens, passwords, etc. as Secret so the input field hides the value and the run record stores it as ••• instead of the plaintext.

Saving / running

⌘S saves changes. ⌘R saves and runs. The Run button does the same.

Status indicators

The menu bar icon reflects an aggregate state:

  • terminal (template) — idle, no recent runs
  • green check — last run succeeded
  • red exclamation — last run failed
  • yellow play — at least one run is in progress

Each command in the menu also shows its own last-run indicator, so you can tell at a glance which deploys went out and which need attention.

Logs

Open Show Logs… (⌘L) to see the most recent runs (newest first).

For each run you get:

  • Status, exit code, duration, started-at
  • The argument values that were used (secrets masked)
  • The full captured stdout + stderr, live-tailing while the run is in flight
  • A "Reveal in Finder" shortcut to the raw log file
  • A Cancel button while the run is still going

Butt keeps the most recent 200 runs on disk and prunes older ones automatically. Clear All in the sidebar wipes the lot.

File locations

Everything lives under ~/Library/Application Support/Butt/:

~/Library/Application Support/Butt/
├── config.json          # your commands and groups
├── runs.json            # run history index
└── logs/
    └── <run-uuid>.log   # one file per run, full stdout+stderr

config.json is plain JSON — feel free to back it up, sync it across machines, or hand-edit it.

Uninstall

rm -rf /Applications/Butt.app
rm -rf ~/Library/Application\ Support/Butt

How it works

Butt is ~700 lines of Swift built as a single Swift Package executable wrapped in a .app bundle. The UI is SwiftUI (MenuBarExtra + Window scenes), state is held in @Observable services, and commands are spawned with Foundation.Process against the configured shell. Stdout/stderr pipes are read asynchronously via readabilityHandler and streamed straight to the on-disk log file, so the log viewer can live-tail the output without buffering in memory.

The bundle sets LSUIElement = true and the app sets activation policy to .accessory, so it's menu-bar-only with no dock icon.

Project layout

butt/
├── Package.swift
├── build.sh              # builds + assembles + ad-hoc signs the .app
├── Resources/
│   └── Info.plist
└── Sources/Butt/
    ├── ButtApp.swift     # @main, scenes, app delegate
    ├── AppState.swift
    ├── Models/           # ButtCommand, CommandRun
    ├── Services/         # CommandStore, LogStore, CommandRunner, Paths
    └── Views/            # SwiftUI views

Contributing

Issues and pull requests are welcome. Some easy wins if you're looking for a starting point:

  • A real app icon (currently a placeholder SF Symbol)
  • Drag-to-reorder for groups and commands in the configure window
  • Import / export of config.json from the UI
  • Optional desktop notifications when long-running commands finish
  • A "duplicate command" action

Before opening a PR, please run swift build -c release --arch arm64 and make sure the app launches cleanly with ./build.sh run.

License

MIT — see LICENSE.

About

A simple command line runner that sits in your mac bar

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors