Automating iTerm with JXA (JavaScript Application Scripting)

Mac Automator Robot

I’m a big fan automation. Whenever I can find a shortcut or write a script that will speed up my daily tasks I will happily sit down and write a tool.

Every day when I come in to work I type in Alfred: ssh . This kicks off a script that will create a new iTerm window; SSH into 7 different servers and log in to their tmux sessions. It will even create new tabs for me as well!

To accomplish this I wrote out a really ugly piece of code in AppleScript. (I have changed the ssh hosts, tmux session names, and shortened the number ssh sessions for brevity).

As you can see its pretty ugly and straightforward. Every time I build a new server I need to tack it on to this ugly code. This is when I decided to take some time and learn about JXA (Javascript Application Scripting).

First off I didn’t even know it was abbreviated as JXA, or called Javascript Application Scripting. I spent my early hours googling for “Javascript AppleScript [problem | method | command]”. Learning the language was called JXA was a big help and provided a lot more resources in Google.

The second big hurdle was finding documentation on how to work with iTerm. After powering up Apple’s Script Editor, I selected Window -> Library. This list gives you documentation to all of the Apple’s native apps that you can use with JXA. Unfortunately no iTerm! This is an easy fix, select the + in the top left hand corner, do a search for “iTerm” on your Mac, and click Open. You should now have all the method and variable documentation available in iTerm. Be sure to change the language at the top to “JavaScript”.

iTerm JXA Documentation.

Finally time to start writing some JXA! Some basic iTerm JXA methods first.

// include the iTerm application to your JXA script
iTerm = Application('iTerm2');
// OSX has a set of standard scripting additions available to use, // these should be included
iTerm.includeStandardAdditions = true;

More info on includeStandardAdditions can be found here.

// Create a new iTerm window
var window = iTerm.createWindowWithDefaultProfile();

iTerm conventions and hierarchy
 — The Main application window of iTerm. You can have multiple windows.
Tabs — Within each window you can have multiple tabs.
Sessions- Within each tab you can have multiple sessions, which can be split horizontally or vertically.

// Lets write something in to first window
window.tabs[0].sessions[0].write({ text: 'whoami', newline: true });

With this command we are calling the window we created, the first tab and first session and writing out the `whoami` command, we are also going to send a newline after the command to run it. Note that many JXA methods use named parameters.

// Let's split the tab into two sessions
// Let's write something into the new session
window.tabs[0].sessions[1].write({ text: 'pwd', newline: true });
// finally let's create a new tab in the window

With all these commands and a grasp of JavaScript I was ready to re-write my SSH automation script.

The end result of the script:
- Run through a list of servers
- Create a tab every 2 servers
- Vertically split each tab in to two sessions
- SSH into each server and attach to a tmux session.

Much cleaner and easier to maintain! Also much easier to add new servers to the serversList array.

I hope this article is helpful, and provides other starting JXA developers some direction in writing our own automation tools. If you see a bug or an easier way to do something let me know, I would love to clean up the script a bit.

What are your favorite automation scripts with JXA, AppleScript, or Alfred? I love seeing what everyone else is using.

Some helpful links I found while working on this project: 
- JXA Cookbook
- Apple About Mac Scripting
- Javascript for Automation in macOS