Bunch

A Batch Application Launcher for your Dock

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.

Installation

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.

Accessibility Permissions

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.

Setup/Configuration

See an example .bunch file.

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 ~/bunches/Example.bunch.

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 .bunch).

Syntax Summary

Here’s a quick reference for all of the syntax below:

Bunch Line Action
AppName Launch app
- XX close all windows of preceding app
- File open file in preceding app (can be repeated)
%AppName Launch when opening the Bunch, but ignore when closing
!AppName Quit app
@AppName Focus app (run at end of bunch to hide all other apps)
AppName_ hide an app
http://url open in browser
urlhandler:// open a system url handler
(command) hide dock/show dock/hide desktop/show desktop
* AppleScript command to execute
& Automator Workflow to run
- key=value variable to pass to preceding workflow (can be repeated)
$ script_or_cmd [args] to execute
- KEY=value Environment variable to export for preceding shell script (can be repeated)

Launching Apps

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

Opening Files

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.

Quitting Apps

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:

!Mail
MailMate

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 open command.

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.

Running AppleScript

Put a * 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 .workflow extension.

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:

& ~/Dropbox/MyWorkflow.workflow

…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

An Automator Workflow for integrating Timing.app with your Bunches

Published 07/02/19.

Updated 07/02/19. Changelog

DonateMore info…

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. #!/usr/bin/env ruby, #!/bin/bash, or #!/usr/bin/osascript -l JavaScript) and that it has executable permissions (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 /usr/local/bin

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 *, &, or $) 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:

!(hide dock)

You can fork a script using the $BUNCH variable. 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...

Or Ruby:

if ENV['BUNCH'] == "Default"

Et cetera.

Bunch Commands

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 ((hide dock), (show dock)) show and hide the Dock (Turn Hiding On), or reposition the dock ((dock left), (dock bottom), (dock right)).

Desktop commands hide and show desktop icons: (hide desktop), (show desktop).

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 (light mode).

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. %(hide dock).

To run the command only when closing a bunch, use an exclamation point (!) before the command, e.g. !(show desktop).

Hiding Apps

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.)

Closing Windows

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.

%iTerm
CodeRunner

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:

%(dark mode)

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:

%iTerm
Xcode

Usage

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 .bunch files.

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.

URL Handler

Open

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: x-bunch://[BUNCH NAME].

Close

You can also close a Bunch with x-bunch://close?bunch=[BUNCH NAME], or just x-bunch://close/[BUNCH NAME].

Toggle

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 open and 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 Bunch from a script, but you’ll need to give it enough time to initialize.

Raw

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 file param:

x-bunch://raw?file=~/MiscBunch.bunch

Pass Bunch contents directly with txt param:

x-bunch://raw?txt=%21MeisterTask

setPref

You can set and toggle certain preferences with the setPref method. Available preferences are:

  • configDir=[path to a Bunches folder]
  • toggleBunches=[1|0]
  • singleBunchMode=[1|0]

Examples:

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: x-bunch://open/bunch=WorkBunch

Tip: You can use simple shell scripts with apps like BetterTouchTool and Keyboard Maestro to assign bunches to hotkeys. If you have a cool programmable keypad, just imagine the possibilities…

AppleScript

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

Integration

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.

Support

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.

Download

Bunch v1.1.7

A Batch app launcher for the macOS Dock

Published 05/14/19.

Updated 07/12/19. Changelog

DonateMore info…

Bunches LaunchBar Action v2.0.1

A LaunchBar action for Bunch

Published 05/22/19.

Updated 06/08/19. Changelog

DonateMore info…

Roadmap

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

Changelog

1.1.7
New commands dark mode and dark mode off
Optimizations and fixes
1.1.6
Run commands when closing a Bunch: !(hide dock)
Dock positioning commands: !(dock [left|right|bottom])
Launch At Login preference handling
Fixes Dock show/hide commands being reversed
1.1.5
Better reporting for Workflow errors
More dependable implementation for “@@” (hide all apps)
1.1.4
Fix for AppleScript “Corrupted Dictionary” errors
1.1.3
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?
1.1.2
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
1.1.1
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)
1.1.0
Preferences->”Run in Menu Bar” option
Preferences->”Launch at Login” option
1.0.10
Use & workflowname to run automator workflows
Use $ shell command to run shell scripts/commands
Menu command to clear checkmarks in toggle/single bunch mode (force launched Bunches to launch again)
Url method raw for 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
1.0.9
Add close method to url handler
Add toggle method 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
1.0.8
Add percent (%) before app name to ignore it when quitting Bunch
Add XX as a filename to close all windows for the app\
Desktop icons commands: (hide desktop) and (show desktop)
1.0.7
Toggle Bunches mode, checkmark opened Bunches, click checkmarked Bunch to quit
Single Bunch Mode
Quit Apps in Bunch… submenu
Bunch commands (hide dock) (show dock)
1.0.6
@@ alone on a line will hide all apps
1.0.5
New URL handler x-bunch:
Ability to change location of Bunches folder
1.0.4
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
Allow _ suffix to hide app (experimental)
1.0.3
Add @focus syntax
Add *AppleScript syntax
1.0.2
Improve launch speed
Allow ![app name] to quit an app
Build for older macOS versions
Sort Bunches alphabetically in Dock menu
1.0.1
Remove cruft from app menus
Add “Show Bunches in Finder” to Dock and File menus

Bunches (LaunchBar) Changelog

2.1
Fix for reading Bunch preferences direct from PLIST
Post a notification after preferences refresh
Move Settings submenu into initial list
2.0
Caching preferences retrieved from defaults read to 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…

Related Projects