A Batch Application Launcher for your Dock
- What Is Bunch?
- Syntax Summary
- Launching Apps
- Opening Files
- Quitting Apps
- Opening Web Pages/URL Schemes
- “Focusing” an App
- Running AppleScript
- Running Automator Workflows
- Running Shell Scripts and Shell Commands
- Running different scripts/commands when closing a Bunch
- Bunch Commands
- Hiding Apps
- Closing Windows
- Ignore Apps/Commands When Toggling Or Closing Bunches
- Tips For A Good Bunch
- URL Handler
- Bunches (LaunchBar) Changelog
What Is Bunch?
Bunch is a little macOS utility that sits in your Dock (or your Menu Bar). It doesn’t have any windows. When you right/ctrl-click the Dock icon (or click the menu item), it gives you a list of “Bunches” you can select from, each one launching a group of applications that you configure. Bunches are just easily-edited text files which can be configured to open apps, specific files in an app, and even web pages in your default browser. For the Power Users, It also allows advanced scripting, system commands, and integration via URL handler.
I wrote Bunch because I tend to launch a specific group of apps depending on the context I’m working in. These are apps I wouldn’t launch on login, and don’t need running all the time. I just wanted to make starting a new context into one click. It started with little Script Editor and Automator applets, but I found I wanted something easily configured with text files, quick to set up and easy to modify. It grew from there.
Bunch has expanded a lot. It can serve as a full context switcher, and handle just about everything you’d want to automate when starting a new context (see the Syntax Summary for an overview of all the stuff I’ve added). Still, I originally wrote it in an hour, so you get what you pay for. Bunch is free for now, but you can think of it as donationware if you like…
And yes, the icon is a bunch of grapes. I told you, I wrote this in an hour.
Just download the DMG and double click it to mount. Drag the Bunch icon to the Applications folder. You can then launch Bunch from your Applications folder. (Or with Spotlight. Or Launchbar. Or Alfred. Or the command line. Or AppleScript…)
You’ll probably want Bunch to stay in your Dock for easy access, so go ahead and launch it once, then use Preferences->Launch at Login to add it to your Login Items.
The first time you run it, an example configuration will be written to your home folder. See the configuration section for instructions on personalizing the setup. Use “Reveal Bunches in Finder” to go directly to that folder and start editing/adding Bunches.
To use some of Bunch’s features, you’ll need to give it Accessibility permission in System Preferences. Open System Preferences and go to “Security & Privacy,” then select the “Accessibility” tab from the list on the left. Click the lock icon in the bottom left and unlock the preferences with your system password. Use the (+) button to add Bunch to the list from your Applications folder, and ensure that the checkbox next to it in the list is checked.
By default, Bunch reads plain text files from a folder at
~/bunches (that’s a folder called “bunches” in the base of your Home folder). You can change the location of that folder using “Preferences->Change Bunches Folder” from the Dock icon or menu bar item (possibly to a Dropbox or iCloud folder where you can sync with other machines).
Tip (kinda): when you change the Bunches folder location, it doesn’t move or delete any of the Bunches at the previous location. That means that (in a fairly inelegant way) you can use different folders for different sets of Bunches.
Each Bunch file has the extension
.bunch, so a basic config file would look like
Each Bunch is a separate file, and the name of the Bunch will be taken from the filename (without the
.bunch extension). Once you’ve added your own configuration(s), delete the
Example.bunch file (or rename it with an extension other than
Here’s a quick reference for all of the syntax below:
||close all windows of preceding app|
||open file in preceding app (can be repeated)|
||Launch when opening the Bunch, but ignore when closing|
||Focus app (run at end of bunch to hide all other apps)|
||hide an app|
||open in browser|
||open a system url handler|
||hide dock/show dock/hide desktop/show desktop|
||variable to pass to preceding workflow (can be repeated)|
||Environment variable to export for preceding shell script (can be repeated)|
Within a Bunch file you simply list the apps you want it to launch, one per line. For example, in “Comms.bunch”:
Messages Slack Mail Twitter
You can additionally have an app open specific documents, if the app supports that. After the app name, simply add one or more documents on lines that begin with a dash. For example, to have Numbers open two specific spreadsheets:
Numbers - ~/Documents/job 1.numbers - ~/Documents/job 2.numbers
Paths to documents can use a tilde
~to represent the home directory. Spaces are fine, no quotes or escaping needed.
Put an exclamation point before the app name to quit that app if it’s open. This works on apps that respond to the AppleScript “quit” command, which is most apps. For example, to quit Mail and launch MailMate instead:
Opening Web Pages/URL Schemes
If you want to open web pages as part of a Bunch, you can just put a URL at the beginning of a line (like you would an app) and that URL will be opened in your default browser. If the URL is a URL scheme for an installed app, it will be executed as if called from a link or via the
https://hulu.com https://brettterpstra.com x-marked://open?file=filename.md
“Focusing” an App
If you start an app line with an
@ symbol, it will attempt to focus that app. This should be run as the last line of the file, after all other lines have run. Make sure the app you want to focus has already been launched.
OmniFocus MultiMarkdown Composer @OmniFocus
Everything is launched in the order listed in the Bunch file. Some apps take longer than others to launch or open a file, so execution will continue in the background after the inital launch of the app.
* at the beginning of a line to have the line interpreted as raw AppleScript. There will be some permissions requests and some commands that just refuse to run, but try it out. You can open Console.app to see any errors that your command might run into. This feature is only marginally tested.
* say "Welcome to the communications context" * do shell script "/bin/bash my_cli_tool.sh" * display notification "Bunch Opened"
Running Automator Workflows
If a line starts with an ampersand (&), it will be run as an Automator workflow. These should be created in Automator as a Workflow, and saved with the
Note that all Workflows for Bunch must have a variable named “Bunch” defined. See the end of this section for instructions on adding a variable to a Workflow.
In your Bunch, you can specify a full path to a Workflow like this:
…but if the workflow is in the same folder as your Bunches, you can just list its filename, with or without
.workflow. For example, if my Bunch folder contained
Do Something.workflow, I could use a line in my Bunch with simply:
& Do Something
If you want to keep a subfolder of Workflows in your Bunches folder, just reference them with a relative path, e.g.
& workflows/Do Something
You can pass variables to a workflow the way you pass files to an application in Bunch, using hyphens below the line that calls the workflow, one variable per line:
& Do Something - variable1 = Contents of var 1
The spacing around the
= doesn’t matter, as long as there is a single key and a value. Additional
= in the line will be included in the variable value.
To use these in Automator they must exist in the workflow (if you pass a variable that doesn’t exist, the workflow will not run). Simply open the variables palette in Automator, right click, and select “New Variable”. Make the variable name exactly the same (case sensitive) as the variable you’re passing from Bunch. Now when the workflow is run, that variable will be populated automatically by the lines in your Bunch.
The variable “Bunch” is automatically populated with the name of the opened Bunch, but you have to add an empty varaible with this title or Bunch will get an error when it tries to populate it. In combination with “Run Shell Script” actions, this and your custom variables can be used to run different actions based the arguments provided, allowing re-use of the same workflow in multiple Bunches.
Here’s an example Workflow that integrates Bunch with Timing.app:
Timing.app Workflow for Bunch v1.0.0
See the Bunch and Timing post for details.
Running Shell Scripts and Shell Commands
Lines starting with a dollar sign ($) are run as shell commands. Anything after the
$ will be executed as
/bin/sh -c [your script]. This can be a full path to a shell script file, or a direct command. No output is sent or received by this action, other than the arguments you provide on the “command line.” If the script returns an error, an alert containing the error will be shown when you run the Bunch.
Important: in the case of scripts, ensure that your script has a hashbang (e.g.
chmod a+x myscript.sh).
You can specify direct arguments after the command or shell script path. Like the Automator actions above, you can also use
- ... lines below the script line to set environment variables. Because the
/bin/sh is running outside your user, even the
$HOME variable isn’t set by default (but Bunch figures it out and includes it for you). The following environment variables are available:
$BUNCH=> name of current bunch
$BUNCH_DIR=> the location of your Bunches from preferences
$HOME=> path to user home folder
$PATH=> a basic path is set that includes
If you need to provide an environment to your script, set it up like:
$ /Users/ttscoff/scripts/myscript.rb - HOME=/Users/ttscoff - FOO=bar
These will be the equivalent of an
export FOO=bar command prior to running your script. If you set
HOME, it will override what Bunch sets. If you set
PATH, it will be inserted before (higher priority than) Bunch’s default path in the environment.
As I mentioned, Bunch doesn’t do anything with the output of a command. If you want to react to shell command output, use Automator with a Run Shell Script action. If you want feedback while running, you can always use AppleScript in your shell script:
osascript -e "display notification \"$INFO\""
Running different scripts/commands when closing a Bunch
If you precede any of the above lines (starting with
$) with an exclamation point, that script will be ignored when opening a Bunch and run only when the Bunch is closed (or toggled). Here’s an example that uses the same script with different arguments for open and quit:
# Run this when opening the Bunch $ ~/scripts/myscript.sh open - STATUS=opening # Run this when closing the bunch !$ ~/scripts/myscript.sh close - STATUS=closing
The same works for commands. To run a command when a Bunch closes, use:
You can fork a script using the
$BUNCHvariable. If you have a script with common tasks but you need it to differ between Bunches in some way, do something along the lines of (in Bash):
if [[ $BUNCH == Default ]]; then...
if ENV['BUNCH'] == "Default"
Lines surrounded in parenthesis are Bunch commands. These offer shortcuts to some system tasks.
([hide|show] dock) (dock [left|right|bottom]) ([hide|show] desktop) (do not disturb [on|off]) (dark mode [on|off])
Dock commands (
(show dock)) show and hide the Dock (Turn Hiding On), or reposition the dock (
Desktop commands hide and show desktop icons:
Do not disturb commands toggle notifications. The commands can be abbreviated as
(dnd on) and
(dnd off). Actually,
(dnd on) can just be
(dnd), too. I like to make things intuitive by overcomplicating them sometimes.
Dark mode commands turn macOS Dark Mode on and off:
(dark mode on),
(dark mode off). An “on” command can be shortened to just
(dark mode), and
(dark mode off) can be shortened to
All commands are reversed when closing a Bunch, with the exception of the Dock positioning commands. Use
!(dock bottom) to run a different positioning command when closing. To avoid reversing the command when closing the Bunch, precede the line with a
% symbol, e.g.
To run the command only when closing a bunch, use an exclamation point (
!) before the command, e.g.
If you use “@@” alone on a line, Bunch will hide all visible apps. (Menu bar apps like Dash or TextExpander may not hide properly.) This is ideal for use at the very beginning of a Bunch, giving you a clean slate for a new set of apps.
You can also append an underscore after any single app name and Bunch will attempt to hide it after launching. (This can be flaky depending on how long the app takes to launch.)
If you include a file line containing only “XX”, then all windows for the app will be closed. This can be included before lines that open new files/windows to start with a clean slate.
Finder - XX - ~/Desktop/
This will only work if the app responds to the AppleScript command
close every window.Most apps do, but there are exceptions. A warning dialog will be displayed if the command fails and you should remove the instruction from your Bunch.
Ignore Apps/Commands When Toggling Or Closing Bunches
When you quit a Bunch (or “Toggle Bunches” or “Single Bunch Mode” are enabled), any apps launched by the Bunch will be quit. To avoid quitting an app when the Bunch is quit or toggled off, place a percent symbol before it in the Bunch (e.g.
%Finder). This will launch the app as normal, but ignore it when closing the Bunch.
In this example, CodeRunner will launch and quit with the Bunch, but iTerm will only launch if it’s not already running, and will remain running if the Bunch is quit.
This works for commands as well:
This will enable Dark Mode when opening the Bunch, and leave it in Dark Mode when closing.
Tips For A Good Bunch
Only include apps that you only need for this context, not apps that launch at login or are generally always running. Including apps that you already have running anyway means that if you use any of the “quit” methods to close the bunch, you’ll be closing apps you would normally keep running. Note that you can also bypass this by using the
% trick above for ignoring apps when close.
For example, I only use Xcode when I’m in one of my coding projects. So for any project’s context, I include Xcode (and have it open that project’s file). In Single Context Mode, if I switch to another coding project, Xcode will stay open, but if I switch to a non-coding project from a coding project, Xcode will close.
iTerm, on the other hand, is always running. So I would never include it in a Bunch. No matter what context I switch to or quit, iTerm stays running.
In later versions of Bunch, this could also be handled as:
Once you have one or more
.bunch files in your Bunches folder, launch Bunch (or right click it and choose “Refresh Bunches”). Now when you right-click the Dock icon, you’ll see all available Bunches listed at the top of the popup menu. Select one to launch, quit, or focus the apps as defined in that Bunch file.
If you prefer to run Bunch in the Menu Bar at the top of your display, use Preferences->Run in Menu Bar to move it up there. When it’s in the Menu Bar, the menu is available with a single click (no right click). You can move it back to the Dock using Preferences->Run in Dock.
If you enable “Preferences->Toggle Bunches,” when a Bunch is opened, its menu item in the Dock menu receives a checkmark. Selecting a Bunch with an active checkmark will “toggle” the Bunch, quitting any apps it launched (if they’re running) and reversing any Dock commands.
If “Preferences->Single Bunch Mode” is enabled, clicking a Bunch will quit apps in the previous Bunch before opening it.
Otherwise, clicking a Bunch will always launch the apps in the Bunch, or bring them to front if they’re already running.
In The Dock Menu
Clear Checkmarks: When in Toggle Bunches or Single Bunch modes, this options will clear the checkmarks next to “active” Bunches, forcing them to relaunch next time even if they’re already running.
Quit Apps in…: You can quit the apps listed in any Bunch from this submenu. Files, scripts, and urls (as well as
! lines that already quit an app) are ignored. If the selected Bunch contains a dock command, it’s reversed.
Preferences->Toggle Bunches: When this is enabled, running bunches are shown with a checkmark in the menu, and clicking them again will quit apps contained in that bunch instead of relaunching them.
Preferences->Single Bunch Mode: Turning this on will cause the active Bunch to quit when opening a new Bunch. Any apps in the last Bunch that are not included in the new Bunch will be terminated, and any Bunch commands will be reversed unless the new Bunch contains a Bunch command of the same type (if the command affects the Dock and the new bunch command also affects the Dock, no action is taken).
Preferences->Refresh Bunches: You can use “Refresh Bunches” at any time to update the menu after editing your configutation files. As of version 1.0.10 this shouldn’t be necessary, changes will automatically be detected. You can still use this to force a refresh if something seems out of date.
Preferences->Change Bunches Folder: Select a new folder where Bunch will look for
Preferences->Reveal Bunches in Finder: Opens the folder containing your
.bunch configuration files (Bunches) in Finder for editing.
Preferences->Run In Menu Bar/Run In Dock: Switch between running Bunch with an icon in the Dock and running as a Menu Bar item. In Menu Bar state Bunch won’t show up in the Application Switcher (Cmd-Tab).
Preferences->Launch at Login: Add and remove Bunch from your User Login Items.
Help->Bunch Help: Opens this page in your browser.
Help->Changelog: Opens the full version history in your browser.
Help->Make a donation: Because it’s the right thing to do, in my opinion.
You can also refresh and reveal Bunches in Finder from the File menu, and check for updates and control preferences (Bunch location, Single Bunch Mode) from the Bunch menu.
Bunch has its own URL scheme that you can call from other apps and scripts. The full version of the URL is
x-bunch://open?bunch=[BUNCH NAME]. The url can be shortened, though, to just the Bunch name:
You can also close a Bunch with
x-bunch://close?bunch=[BUNCH NAME], or just
You can also toggle the Bunch, opening if it’s not open, closing if it is, using
x-bunch://toggle?bunch=[BUNCH NAME]. Like the other methods, this also works as
x-bunch://toggle/[BUNCH NAME]. This works even if “Toggle Bunches” isn’t enabled.
If using the “Toggle Bunches” option, Bunches opened/closed via the URL handler will automatically set the launched state of the Bunch in the Dock menu. The
close commands will not toggle Bunches; the commands will execute regardless of current Bunch state.
The Bunch name in the URL handler is case insensitive, so “bunch name” works just as well as “Bunch Name.” Bunch does need to already be running in order to execute a bunch via the URL handler. You can always launch Bunch with
open -a Bunchfrom a script, but you’ll need to give it enough time to initialize.
You can pass Bunch commands and directives directly through the URL handler. With this you can specify a path to a Bunch file outside of your Bunches folder, or even pass a url-encoded string containing Bunch directives.
Open a Bunch file with
Pass Bunch contents directly with
You can set and toggle certain preferences with the
setPref method. Available preferences are:
- configDir=[path to a Bunches folder]
open 'x-bunch://setPref?toggleBunches=1' open 'x-bunch://setPref?configDir=~/Dropbox/Sync/Bunches'
Tip: If you have a task in a task manager that requires a certain set of apps, create a Bunch and then add a link to the task’s notes:
Bunch provides an AppleScript dictionary that you can use to open, close, and toggle Bunches.
tell application "Bunch" to open bunch "Comms" tell application "Bunch" close bunch "Default" toggle bunch "Comms" end tell
Using With Alfred
Jay Miller has created an Alfred action for use with Bunch.
Using With Launchbar
I’ve added a LaunchBar action for Bunch. Download below, unzip it, then double click the unzipped action to install. Selecting the Bunch action in LaunchBar and pressing return will list your available Bunches. If you have “Toggle Bunches” enabled, selecting a Bunch from the list will toggle it (quitting apps if it’s already been opened), otherwise it will simply open the Bunch.
See “Better Bunch for LaunchBar” for the latest changes to the Action.
Using From The Command Line
I created a simple Ruby script that will list bunches, display their content, and launch, close, or toggle them. See the gist for installation and source.
None, really, this is just a stupid early-morning project at this point. I’m happy to know about bugs you run into, and will do my best to find time to fix them, but no promises on prompt updates or anything.
Bunches LaunchBar Action v2.0.1
Some maybe items:
- Menu bar option
- Save as Bunch (save currently open apps as a Bunch)
- Better monitoring of app launches for feedback display
- Probably going to need a preference pane eventually
- Ability to double click bunch files
- Internal Bunch editor
- New commands
dark mode off
- Optimizations and fixes
- Run commands when closing a Bunch:
- Dock positioning commands:
- Launch At Login preference handling
- Fixes Dock show/hide commands being reversed
- Better reporting for Workflow errors
- More dependable implementation for “@@” (hide all apps)
- Fix for AppleScript “Corrupted Dictionary” errors
- AppleScript improvements that will be invisible to the naked eye. Or really any end user.
- Donate button twice in the menu bar version. Nobody needs that much prodding. I mean, you’re going to pitch in or you’re not, right?
- Bunch can be automated with AppleScript
- URL method setPrefs to change certain preferences from script
- Bind bunch menu item states to a property so they’re always up-to-date
- Additional environment variables for shell scripts
- Updated Example.bunch with all the latest goodness
- A script line (*&$) preceded by ! will only run that script when closing the Bunch
- Status item submenu with Check For Updates (and Donate)
- Preferences->”Run in Menu Bar” option
- Preferences->”Launch at Login” option
& workflownameto run automator workflows
$ shell commandto run shell scripts/commands
- Menu command to clear checkmarks in toggle/single bunch mode (force launched Bunches to launch again)
- Url method
rawfor directly loading any Bunch-formatted file or directly passing bunch commands as a string
- (dnd on) and (dnd off) commands for Do Not Disturb
- Watch bunch folder for changes and refresh automatically
- Launching or quitting a Bunch via url command now toggles launched state in Dock menu when Toggle Bunches is active
closemethod to url handler
togglemethod to url handler
- Allow url handler methods to toggle Bunch state in Dock Menu
- Show an alert when commands fail to make it easier to diagnose and fix Bunches
- Add LaunchBar, Alfred, and CLI scripts to documentation
- Add percent (
%) before app name to ignore it when quitting Bunch
XXas a filename to close all windows for the app\
- Desktop icons commands:
- Toggle Bunches mode, checkmark opened Bunches, click checkmarked Bunch to quit
- Single Bunch Mode
- Quit Apps in Bunch… submenu
- Bunch commands
@@alone on a line will hide all apps
- New URL handler
- Ability to change location of Bunches folder
- Allow URL schemes (in addition to http)
- Test if app is running or hidden before launching, hiding, quitting
- Use NSWorkspace instead of AppleScript where possible
_suffix to hide app (experimental)
- Add @focus syntax
- Add *AppleScript syntax
- Improve launch speed
![app name]to quit an app
- Build for older macOS versions
- Sort Bunches alphabetically in Dock menu
- Remove cruft from app menus
- Add “Show Bunches in Finder” to Dock and File menus
Bunches (LaunchBar) Changelog
- Fix for reading Bunch preferences direct from PLIST
- Post a notification after preferences refresh
- Move Settings submenu into initial list
- Caching preferences retrieved from
defaults readto speed things up
- Allow setting a default action (Toggle, Open) that overrides your Bunch preferences
- Every Bunch listed has a child menu that offers whichever actions aren’t default
- Holding modifier keys when opening the action changes the default methods for that run
- Accept strings
- Accept files
- New icons
Speaking of Bunch…
- Bunch and Timing.app
- Bunches LaunchBar Action quick fix
- Bunch for the menu bar
- Better Bunch for LaunchBar
- The latest Bunch stuff
- Another day, another Bunch
- Bunch gets its own URL scheme
- Bunch 1.0.4 with URL schemes support
- Launch AND quit apps with Bunch 1.0.2
- Bunch, a batch app launcher for your Dock