Multi-Tools aren't the only GeekTool

Desktop customizing is about more than style; often times it's about workflow, and just being on top of what's happening on your network. Sometimes you just need to know, at a glance, what's running, how much traffic there is, or just that everything is as it should be. The best solution is usually the one that is out of the way, but ready at a moments notice... and if it can look good doing it, all the better.

I know I may have my Apple Cult Card revoked for admitting this in public, but Steve Jobs and his crew are not the best UI designers in the world. Is the Mac OS interface pretty, certainly, but is it awesome? Does it do what you want, when, and how? That's for each user to decide, and that's where customizing comes in.

Sure you can change the desktop image, move the Dock around, and in Leopard even make the menu bar translucent; when it comes to really tricking things out the best the fine folks in Cupertino did was make it very easy to change the file/folder/drive icons.

When it comes to displaying continuously updating text and images on the desktop Windows users have so many options it's hard to pick one. BSD/Linux users also have a fair amount of options for getting status information on their desktops. OS X just isn't feeling the love. Sure there are a lot of Dashboard Widgets, and there are ways to make those stay in the foreground. There are some menu bar status monitors, and even some apps to show basic info in the Dock by way of dynamic icons. That's not going to get server logs or the graphs output by tools like MRTG or RRD on your desktop.

That's where the deceptively versatile PrefPane GeekTool comes in. It's been around for a while, but it surprises me still how many long-time Mac users have never heard of it. The most current version is 2.1.2 and is meant to run on Panther and Tiger as a Universal Binary. I had no problem getting it to run on my PPC Leopard machine and only took one simple modification to make it run perfectly on my Intel Leopard laptop (I'll cover that next post), though it will run without the change.

So just what does it do? At its core GeekTool just embeds images, text files, or the output of scripts into the desktop at a defined refresh rate... but that's where its power comes from. With even the most basic of shell commands you can output a simple calendar, show how long your system has been running, or display the name of the currently logged in user. Toss in sed, awk, or grep, and now you can display CPU load, memory usage, and process information formatted in any way you like.

Ready to go beyond one or two line shell commands, point GeekTool at a shebang (or hashbang if you prefer) coded file, and run PHP, Python, or Perl (what's with all the P's anyway?) scripts too.

It works just as well with existing files as it does running commands, so showing the content of a log file, or keeping an RRD graph refreshed is just as simple.

The displayed text and background can be any color, or font. Images can be local files or via HTTP. Both can be done borderless or with a choice of border types and drop shadows, as well as any level of transparency. Always on top can also be chosen if you want something important visible at all times.

While there is no obvious multi-display support, making use of more than one display is trivial. Items are positioned on screen by clicking and dragging them into position or by entering X, Y, Height, and Width values; X and Y can be negative numbers. So entering numbers that extend beyond the boundaries of your main display will push the item onto the display that is positioned there in your Display PrefPane.

GeekTool also allows items to be enabled and disabled in groups. So when your MacBook isn't connected to the second monitor just switch groups to one that doesn't include that monitor so those processes don't run.

So just what am I doing with it? I'm pretty boring in that way; I've got the usual CPU, memory, uptime stuff. A calendar that marks the current day. A tail of my system log and firewall log. As well as my current internal IPv4, and external IPv4 and IPv6 addresses. I think about prettying it up from time to time, but in the end, I just like seeing what's going on. I usually have far too many windows open to see my desktop anyway, so the glitz doesn't matter. I just do a quick four finger up swipe, see my desktop and all the status info, then another down swipe, and back to work. Now I do have my memory, CPU, and uptime/load averages right along the bottom edge of the screen so I can usually see them no matter what. I toy with putting disk space down there too but haven't committed to the idea just yet.

Some good references for settings and scripts to get you started down your own GeekTool powered information nirvana (and where I got most of my ideas):

Ultimate GeekTool Setup by Nick Young

GeekTool and Bash One-Liners by Rupa Deadwyler

Monitor Your Mac and More with GeekTool by Gina Trapani

Before I wrap this up, I want to impress upon you just how important the DIY nature of GeekTool is to its power. Though you can't really tell from a still image, that LED is showing me my CPU load by color. The LED was actually a reddish yellow (because I haven't worked out the exact values for yellow just yet) because I was testing and had the threshold set to trigger all colors easily.

Since I don't plan on leaving this rig setup (because I don't have a stash of Teensy's laying around) it's running with its own entry in GeekTool, and it's own shell script, but it wouldn't be hard to make it part of the primary CPU status script with a condition check to make sure the /dev entry for the Teensy was there.

For reference, though, and so you can't say I never gave you anything. Here is the shell script and Arduino sketch to get that last bit of fun working.


#!/bin/sh
# geektool_cpu_teensy.sh
# Trigger LED colour change based on
# CPU ldle status as read from top
# This code requires catty be installed
# http://sourceforge.net/projects/catty

idleCPU=$(top -l 2 | awk '/CPU usage/ && NR > 5 {print $12}'
 | awk -F '.' '{print $1}')

if [ $idleCPU -gt 80 ]
  then
    catty -d /dev/cu.usbmodem12341 -b 9600 -w 'Gr'
elif [ $idleCPU -gt 65 ]
  then
    catty -d /dev/cu.usbmodem12341 -b 9600 -w 'Y'
else
    catty -d /dev/cu.usbmodem12341 -b 9600 -w 'Rg'
fi


// rgb_led.pde
// Switch LED colours based on serial input

int incomingByte = 0;

byte r_pin = PIN_B7;
byte g_pin = PIN_C5;
byte b_pin = PIN_C6;

void setup() {
  Serial.begin(9600);
  pinMode(PIN_D6, OUTPUT);
  digitalWrite(PIN_D6, LOW);
  delay(1000);
  digitalWrite(PIN_D6, HIGH);
  delay(1000);
  digitalWrite(PIN_D6, LOW);
  pinMode(r_pin, OUTPUT);
  pinMode(g_pin, OUTPUT);
  pinMode(b_pin, OUTPUT);
  Serial.flush();
  digitalWrite(PIN_D6, HIGH);
}

void loop() {
  incomingByte = Serial.read();
  if (incomingByte >= 0) {
    if (char(incomingByte) == 'Y') {
      analogWrite(r_pin, 255);
      analogWrite(g_pin, 125);
    }
    else if (char(incomingByte) == 'y') {
      analogWrite(r_pin, 0);
      analogWrite(g_pin, 0);
    }
    else if (char(incomingByte) == 'u') {
      analogWrite(r_pin, 125);
      analogWrite(g_pin, 125);
    }
    else if (char(incomingByte) == 'r') {
      analogWrite(r_pin, 0);
    }
    else if (char(incomingByte) == 'R') {
      analogWrite(r_pin, 255);
    }
    else if (char(incomingByte) == 't') {
      analogWrite(r_pin, 125);
    }
    else if (char(incomingByte) == 'g') {
      analogWrite(g_pin, 0);
    }
    else if (char(incomingByte) == 'G') {
      analogWrite(g_pin, 255);
    }
    else if (char(incomingByte) == 'h') {
      analogWrite(g_pin, 125);
    }
    else if (char(incomingByte) == 'b') {
      analogWrite(b_pin, 0);
    }
    else if (char(incomingByte) == 'B') {
      analogWrite(b_pin, 255);
    }
    else if (char(incomingByte) == 'n') {
      analogWrite(b_pin, 125);
    }
  }
}


Both are Copyright Jody K Delauney 2009. Released under BSD two clause license. Full text of the license and commented sources are available for geektool_cpu_teensy.sh and rgb_led.pde.