This is a tip for those of you dealing with long build times, which for me, is anything greater than about 4 seconds 😉

The problem that those of us with NADD face is the second we are waiting for something to finish, we [alt|cmd]+Tab to a browser and start reading slashdot, rotten tomatoes, daringfireball, or any of a million other sites. Likely, you classify this “quick field trip” as multitasking and because you are so very good at multitasking (despite what all the experts say), you disregard the fact that your build was probably finished 10 minutes ago.

Well, I finally came to grips with these facts:

  • I cannot multitask. I can only context switch. And user-to-kernel-to-user is getting slower in my old age.
  • Half the time I’m looking at my browser, I’m flipping back to see if the build has finished. Further exacerbating the context switch problem.
  • I cannot bring myself to firewall off my favorite, “industry news” sites.

So with that, I decided to fix what I could. That is, decreasing my “response latency” for “asynchronous tasks.” You’ll need to be running on a Mac. But you’re a super leet programmer so I’m sure you already are. OS X has a frickin’ awesome text-to-speech capability. Bundled along with that is a command line app: say.

Try it out, type at the terminal:

say "Why didn't I think of that?"

Now, for those of you who remember Dr. Spaitso, you probably just shit yourself at how great the default voice sounds. (Though, if you are my wife, you are duly unimpressed.)

So I’m sure you see where I’m going with this. Let’s get down to it.

Open up your GRAILS_PROJECT/scripts/Events.groovy file, add the following:

eventStatusFinal = { msg ->

    String.metaClass.say = {
        ["osascript", "-e", "tell application "iTunes" to set sound volume to 30"].execute()
        "say "${delegate}"".execute().waitFor()
        ["osascript", "-e", "tell application "iTunes" to set sound volume to 100"].execute()

    if(msg.startsWith("Server running.")) {
        "Application is running".say()
    } else {

I made this a metaClass option originally because it came from a groovy bootstrap groovy script. You could just as easily make it a local closure or method.

The gist is that every time an event completes, it will read aloud the status line. But first, it turns down the music playing in itunes. (It just so happens that I have iTunes turned all the way up and use the system volume to regulate. If you don’t do that, you will probably have to adjust the volume values)

Pretty neat! I actually use this in some fashion in all my projects now… maven, ant, even xcode. It really helps.

Update: I created a Grails plugin that handles this all for you:

About the Author:

Learned something? Great! Need help on your development project? I can help @ Brilliant Chemistry or get in touch direct:

  • Ruby on Rails
  • iOS Development
  • System Architecture & Performance

Get in touch:


  1. haah says:

    This is pretty inovative, thanks for sharing

  2. Federico says:

    Very nice 😉

    I’m going to adapt it to my Fedora Desktop 🙂

  3. Joey Novak says:


    I have made scripts before that just used the “beep” command, but using a tts engine is an awesome idea!


  4. Jon Chase says:

    Nice idea to integrate this with Grails directly!

    I’ve had a similar problem – long running shell scripts (not always Grails related though). I started using the “say” command from shell scripts, and then decided to get a little fancy with it and use some recorded audio as well using the “afplay” command.

    I recorded my exploits here, and the comments also have tips for playing audio from Linux and .NET as well. And as one commenter suggested, don’t for get Growl either!


  5. Jeroen says:

    osascript -e “tell application “iTunes” to set sound volume to 30″ -e ‘say “Application is running faster on a mac than on windows”‘ -e “tell application “iTunes” to set sound volume to 100″


Leave a Comment