Hacker News new | past | comments | ask | show | jobs | submit login
Hammerspoon – Powerful automation of OS X with Lua (hammerspoon.org)
266 points by weitzj on July 14, 2016 | hide | past | favorite | 122 comments



I've got a simple USB watching script (with hammerspoon) to lock my computer when I remove my yubikey. I just yank the yubikey and go.

I also have it iMessage me when it's removed. In case someone else grabs it when I'm not near it.

I also have it wake up the screen when I plug it in, combined with Knock I can get in and out of my computer quickly and easily.


This reminds me of the pull request I did for Hammerspoon to allow your scripts to watch more screen lock and user switching events. My goal was to delete keys from the ssh-agent when the screen locks or the computer suspends.

http://fanf.livejournal.com/139925.html


Please share this? Would love to have something like this for as often as I'm pulled away from my desk


Here's the gist: https://gist.github.com/ojkelly/45dda0a5a7066c6a79a038ece8bd...

In the original post, I left out that I also have a usb LED sign [1] that I also have programmed, so people know when they can and cannot interrupt me. Again controlled with hammerspoon and my yubikey.

[1] http://dreamcheeky.com/led-message-board


Fantastic idea! One day I hope this will be replaced by me walking away (with my phone) for more than X meters. Meanwhile, this seems like a great solution. What else do you use the ubikey for?


would love to see that.


Yeah - code or it doesn't exist!


very nice ideas!


I've written a script for this to snap windows just like windows (consider it a free cinch & sizeup replacement).

- Drag to the left or right to cover that half of the screen. - Drag to the top for maximise - Drag to a corner for corner snap - Control + Option + Arrow to snap to left or right of screen, maximise or center - Control + Option + Command + Arrow to snap to corner of screen

https://gist.github.com/spartanatreyu/850788a0441e1c5565668a...


In that vein, you may like https://github.com/eczarny/spectacle


I went from cinch+sizeup to spectacle to hammerspoon.

Spectacle just didn't have the window options and wasn't being actively developed to add the options that everyone was asking for.

It's the oldest issue (3 years) on the project:

https://github.com/eczarny/spectacle/issues/37



Don't think shiftit supports mouse snapping


I was a big spectacle user on 10.8, for some reason I ended up migrating to Magnet (in the app store) on 10.11.

Use it nonstop all day to snap stuff half-screen right/left/up/down, no to mention (finally!) full screen.

Intrigued by Hammerspoon.


I use this window snapper for Mac. Very polished and costs a dollar in the app store: http://magnet.crowdcafe.com/


Another option is Slate, scriptable with JS


I think Slate isn't maintained anymore.


It doesn't seem like it, but it's still pretty nice! Window hints is my favorite feature.


Hammerspoon is awesome, I've been using it for quite some time for just few basic tasks (like move a window from one monitor to another), but those have become irreplaceable part of my desktop experience.

Recently I've made this hammerspoon "plugin": https://github.com/selectnull/hammerspoon-alttab

I would love to have feedback, if anyone is interested (it's not perfect, i'm aware of few bugs, but it solves my problem most of the time).


He man. Looks cool.. Maybe I'll extend it to just filter out any applications that have no window in the current space. Cleans up the cmd-tab list a lot


Sure, try it. It might work better than my version. I do have some other ideas for this problem (usually, i just want to fast switch between terminal and browser) but I'd like to see what other people come up with.

Let me know if you make something.


iTerm lets you designate a key to toggle it. I use (with a resignment by Karabiner) CapsLock which is otherwise wasted space.


God... I friggin' LOVE the name and logo of this project.

"HammerSpoon"

It perfectly conveys what an elegant kludge it is.


Hammerspoon is a fork from https://github.com/sdegutis/mjolnir. Mjolnir is a hammer of Thor. So it's kinda hammer but not the same hammer and it's kinda fork, yet it's not meant to be merged back - so not really a fork. Hence the name.


Why was it forked?


So there's a little history behind this:

As we added feature after feature to Mjolnir, and it grew to a monolithic collection of barely-related modules (APIs), I realized that it didn't make a lot of sense for users to keep upgrading to "newer" versions of Mjolnir, when in reality it was just the modules bundled with Mjolnir that were new or changed, and Mjolnir itself wasn't changed at all.

So I made the decision to decentralize the APIs. Instead of being bundled into Mjolnir itself, users would be able to download Mjolnir and then download or upgrade modules independently of Mjolnir.

This was pretty unpopular, because it meant Mjolnir was no longer "batteries included", so Hammerspoon was forked by the portion of the community that preferred that batteries included approach. Honestly, I don't even know how much of the community (if any) continued to use Mjolnir.


Huh, interesting. It sounds like you and the Hammerspoon devs are on good terms, so it's not clear why this couldn't have been resolved in the Mjolnir project. Does this have anything to do with <http://sdegutis.github.io/2016-05-30/why-i-dont-side-program...? Did you actually prefer to have other people take over the project?


Nope, that has nothing to do with what I said in that blog post. In fact, the point in that blog post was that I enjoy making things like Mjolnir, and specifically prefer it over building apps like, well, anything you'd see on the front page of the Mac App Store any day of the week.

They forked it because of a difference of opinion: I believe that separation of the core app and the modules into separate projects is ultimately better, and they don't.

When they're separate projects, there's a lot of potential for really interesting tools to be built around them, between them, or bridging them together.

Imagine having a GUI app that manages third party modules for you, installing and loading them at a single click. Or a plugin that centralizes plugin settings into a unified single GUI window. These are the kinds of things that this separation was meant to allow and encourage.

But when it's a batteries-included app, every single aspect of it needs to be built into the app. It becomes monolithic. Every feature anyone could ever want needs to be bundled into it, and even though this is more convenient at first, it ends up bloated. It also doesn't allow for any competition between features in the same domain.

The authors behind Hammerspoon prefer the batteries-included approach. They're not wrong, it's not a matter of right or wrong. It's just a difference of opinion. People who want that approach will prefer Hammerspoon. People who want to build tools around their existing tools will probably prefer Mjolnir.


Sounds like the distro problem. Yes, a lean, mean, linux machine is great, but when you have to hunt around for all the tools you want, it becomes a pain to manage. Far nicer to have a curated set of tools that most people can agree upon.

In this case, mjolnir, the lean mean core, then the various subprojects, and finally the "distro", containing a curated set of popular modules that people can download as a turnkey system. Then, if you want your own custom setup, minus the bloat, you can set up your own distro. If you just want to use the damn thing and don't care about how the sausage is made, use the "recommended" distro.


To elaborate:

Have a centralized repository containing pointers to all available modules. Module creators can publish to this repository. Cocoapods does this rather nicely, and uses github for the centralized repo.

Then have a tool inside mjolnir that allows administration of the repo (request adding your module, publish a new version of your module, etc).

Then have a "distro" format that lists what modules are included in your distro. This is doubly cool because if you have to install another machine, you just call upon your distro, it installs everything and you're good to go. It also makes upgrading to the latest and greatest modules a breeze.

I guarantee that 90% of your users will just go with the "recommended" distro, but the developers will love you for making it a lot easier to contribute. It's all about lowering friction, for users, power users, and devs.


Hello, from under my (lua? )rock! I still use Mjolnir. I kinda liked the separate modules approach...


Hi! Glad you still find Mjolnir useful :) Neither app is right or wrong, they're just differences of approach. See my reply to Camillo.


"When all you have is a Hammerspoon, everything looks like a ___"

Suggestions for filling in the blank, are welcome :)



Coconut


Oh, that's very good.


hehe -- it immediately made me think of the php hammer (but no offense meant )

I've played around with Lua in Codea -- really liked it: https://github.com/TwoLivesLeft/Codea-Runtime

see also: https://itunes.apple.com/us/app/codea/id439571171?mt=8


Hammerspoon is amazing, and even more impressively, it's amazingly well maintained and its API is incredibly well thought out by its really talented development team. It really is a must-have for anyone who wants ultimate programmatic control over OS X.

Check out the really gentle follow-along tutorial:

http://www.hammerspoon.org/go/


You're too kind :)

I think we made some terrible API decisions, but we'll fix them up eventually!

(Also for those following along at home, sdegutis is the author of a long line of OS X automation tooling, up to and including Mjolnir, which we forked to make Hammerspoon. He is awesome)


That's right. Sdegutis built Zephyros (Ruby OSX automation, also other Lang support), then Phoenix (JavaScript OSX Automation), then Hydra (Lua based) which became Mjolnir, which is forked to Hammerspoon.

Phoneix lives on as Phoenix 2.2 https://github.com/kasper/phoenix


I'm sticking to Phoenix. Are there any advantages in using Lua script instead of JavaScript?


If you prefer Lua there is. I don't see any advantages myself. Phoneix is a permanent fixture on all my macs.


It’s nice we have great options to choose from. Everyone has their own preferences. :)


I'm curious - what do you think were terrible API decisions?


One thing I love about Hammerspoon is the flexibility and power some of the modules like drawing and event spoofing give you. It allows really neat things like the tabs and hints modules (which I wrote) and lately I hacked together a module that lets me scroll pages hands-free using mouth noises (see https://github.com/trishume/thume.popclick if you want to test it before I try and PR it to Hammerspoon).

It's useful both for general window management as well as system hackery. It's the closest OS X users can get to the power of Linux.


This is really, really cool, but:

> It has a very low false negative rate, but often has false positives.

Seems like it would get triggered constantly around noises like A/C, or wind, or the inevitable coworker who quietly hisses behind you while you've got your headphones on.

(It would be me. I would 100% be that coworker.)


It's only succeptible to some very specific false postives. But yes it is annoying (my roommate was having fun scrolling my computer from a distance today).

The answer is that all the false positives I encounter are human-triggered so if you are alone and not doing anything else except reading, they aren't much of an issue.

You can also buy super directional headsets that don't pick up anything else, even other people making the noises standing next to you. I have one and it works great, just not as convenient as the tiny mike on my earbuds.


On Linux, if you use GNOME Shell, the closest thing i can think of for desktop automation are GNOME Shell Extensions [1], one can access everything that is available via GObject Introspection [2]. Demos [3], Platform API overview [4]. The GNOME Shell Extensions site [5] provides nice list and easy install.

[1] https://live.gnome.org/GnomeShell/Extensions [2] https://live.gnome.org/GObjectIntrospection [3] https://developer.gnome.org/gnome-devel-demos/unstable/ [4] https://developer.gnome.org/platform-overview/stable/ [5] https://extensions.gnome.org/


I use Cinnamon. Any idea if these would work on it? I love automating my desktop workflows


No, sorry, I don't know. I was quite happy moving from gnome 2 to gnome 3, I tried cinnamon once or twice but I am happy with gnome shell.


Looks great. I'll have to download it and have a go.

Another seemingly great product for Apple not by Apple. I just downloaded the app Continous to my iPad Pro, and I am programming happily in F# on it. It has cut into my Pythonista time, another non-Apple made app.

Maybe Apple's focus more on hardware, and leaving software a bit behind is working out for them. It seems users are stepping up and creating some really productive software.


When I first started using a Mac a year ago I found the UI very awkward to use but then I found this little app. Hammerspoon makes osx great again! Even just moving windows around or maximizing (without going fullscreen) is so useful.

I almost never use Dock, Spotlight or Finder now. It's great!

Wrap it all in a personal Cask, and you're good to go! https://github.com/Jeppesen-io/homebrew-hammerspoon


You can maximize without going fullscreen by holding down option when you click the green button.


Ridiculously poor usability. The obvious solution is to have a fourth 'traffic light' with a meaningful icon.


Steve Jobs - fashion over function


This change happened after he died IIRC, but yeah. I miss the old zoom button.


That doesn't work on OS X 10.11. Just tried it - Nothing happens. You need a tool like Spectacle/Magnet (or potentially Hamerspoon, haven't tried it yet) - I don't know of any way to maximize a screen using basic OS X 10.11 interface, which is bizarre if you think about it.


It works just fine on OS X 10.11 [1]. Holding down 'option' while you hover over the green traffic light icon changes the glyph to a '+'. Clicking it maximises the window.

[1] https://support.apple.com/kb/PH21894?locale=en_US


It really doesn't. I just did so in Safari. Held the Option key, hovered over the green traffic light, and it first reduced the size of the screen. I clicked on it again, and it filled the screen vertically, but not horizontally. Still need to use Magnet/Spectacle to maximize my window.


I think the problem really is Apple's use of the term "maximise" doesn't mean what it does on other platforms, and really it's a misnomer entirely. "Optimise" would be a better adjective, and its behaviour differs slightly depending on the app. For example, in Safari it'll resize the browser window to what it thinks is best for the content you're viewing.

Thankfully, tools like you've discovered address this behaviour and add a lot of other useful window management features anyway.


The weird thing is the behavior doesn't seem to be predictable. I just maximized my screen with Magnet (cause window to stretch out both horizontally and vertically), then I option-clicked on the Green Streetlight - Nothing happened. Then I made the window a bit narrower. Clicked again. Nothing happened. Then I made it a bit shorter. Clicked Again - Window stretched up to top, but didn't change width. Made it narrower. Clicked again. Window returned to previous width. Clicked again, this time returned to the same narrower size as one step previous.

It seems like the Option+Click on the streetlight is kind of like a toggle of the last two previous sizes, but not always - sometimes it stretches to the top, sometimes it doesn't do anything.

I've been a dedicated OS X user since 10.3 - and, despite spending 15-20 minutes at a stretch every year or so (such as tonight) - I've never really understood what the green button is supposed to do. I kind of find it amazing that such a horribly inconsistent user interface control has persisted for 15+ years.

But yet - Magnet (much like Spectacle before it) does exactly what I want. Ctrl+Option+Enter = Maximize window (which is exactly what I bet 99% of people want the Green Button to do)


Shift-option click did it for me, which is really cool. I've wanted this and didn't know it.


Shift option click didn't do it for me in Safari.


Did you try shift or alt, or combinations of those? I'm pretty sure it's been hidden in OSX for a while, but I think the shortcuts were changed at some point.


Tried them all. Doesn't work on my Laptop (running 10.11.5)


Since you're a relatively new Mac user, you might be interested in how to hack the Cocoa text input system: http://www.hcs.harvard.edu/~jrus/Site/cocoa-text.html

For example, you could make text editing (in apps that use the Cocoa text editor libraries and input fields etc..., which are most of them) act like Vim or Emacs, or Windows, or whatever you want.


Saw "OS X", "Lua", and "automation" and immediately assumed Steven Degutis was behind this...lo-and-behold: https://github.com/Hammerspoon/hammerspoon/blob/master/CREDI...

Awesome work! (And if you haven't already, check out some of Steven's other projects. Very fun/interesting code.)


I have always lamented the lack of such automation techniques on Linux. Even though Linux systems are open and free software platforms, their desktop interfaces are ironically less programmable as compared to OSX and Windows.


There's http://javauto-lang.org/ and http://www.sikuli.org/ that work on Linux


I've started writing a Hammerspoon config inspired by Spacemacs if anyone interested. https://github.com/agzam/spacehammer


Nice. I recently gotten into playing Dolphin emulator, but it doesn't disable the screensaver and mine is set to turn on after one minute. I was looking for a way to listen for a certain app to open and set the the screensaver to never turn on and reset it to one minute when the app is closed. It seemed like there was no real way to do it aside from polling if the app is still open. I'll see what this can do


That was simple: https://gist.github.com/emehrkay/351a875c96336c530668b31c386... seems to work

Im going to change the events to activated/deactived so that I can leave the app on, but only change the screensaver when in use.


One thing I don't see mentioned in this thread yet:

You can trigger any action based on app events as well. So anytime an app is launched, quit, hidden, unhidden, etc. - you can then take any other action.

Also, I created a 'modal' set of shortcuts for my machine. By pressing a leader, I switch to 'normal' mode and every letter has a binding. Very powerful.


I've been using it for a while. I couldn't tolerate osx without it.


Could you give some examples of what you use it for?


I have written a custom i3 like window manager that I use for tiling. I use it to catch keyboard shortcuts and open new windows/lock screen/movement commands/etc.


I'm using Hammerspoon for fast space switching, placing/resizing/focussing windows on a screen, reconnecting to current wifi network (for the flakey company network), caffeinate (prevent from sleep) and battery notifications (i.e detect when plug gets disconnected).

Here's my configuration: https://github.com/pstadler/dotfiles/blob/master/hammerspoon...


Very cool! Is there an equivalent for those of us in the Windows world?


Autohotkey[1] has some of the functionality at least:

[1] https://www.google.com/?q=autohotkey


Thanks for the prompt reply! I was looking for more of a you can do things in Lua and get to Windows functions. AutoHotKey looks cool, but it appears to be it's own little language.

I'm pretty fluent in Lua, so being able to leverage ability like Hammerspoon does would be great.


AHK is a terribly designed language, but holy hell, you can do some nifty stuff with it. For instance, I like to download music from YouTube and SoundCloud using youtube-dl but I disliked having to open up and manually copy and pasting the URL, etc. I found an AHK script that gets the URL name of the current active Firefox window, edited it a little so that it pipes that URL into a batch file, and now if I find a song I like, all I have to do is hit a hotkey chord and after about 30 seconds, it's in my Music folder. It is a total hack - the kind of thing AHK was made for - but somehow it works!


pywinauto exposes a lot of the same functions to Python.

https://pywinauto.github.io/


There is RobotJS which is cross platform https://github.com/octalmage/robotjs


How are people using this? I haven't automated anything on my OS X machine, but I've also never spent any time thinking about what I might automate.


Your computer should be waiting for you, not you waiting for your computer. Any single job you're doing more than once, look at how you can do it easier.

Look at emmet if you do anything involving html.

Maybe setup a process that watches a folder and builds/compiles anything placed in there.

If you need to do a job 10 times that takes 5 hours to do each time and you can automate that job in 30 hours so each job now only takes 1 hour each then you've saved 10 hours of time.

At my work I've made an enewsletter editor app (turned 2 week job down to 3 days job) and a language file editor for the content we output (turned 1 week job into 1 day job)

All that extra time gives you more breathing room between projects, more polish time for those projects or more time to learn new things.


I use it primarily as a windows manager and an easy way to start and stop Spotify/iTunes.

This (https://github.com/Linell/hammerspoon-config) is my configuration, which is about as basic as it gets. The documentation has a billion other, cooler things that can be done.


Has anyone tried to implement a fully blown list of tests (TDS) for a production Mac app using this ? ( or mjolnir ). In one of my previous assignments, we had to build automation for our Desktop Mac App, We tried AppleScripts and a couple of other open source libraries , None of them worked out we had to settle for manual testing !


Something I don't see on the front page, the first few screens of the Getting Started page, or the landing page of the API docs is the version of Lua being used.

Edit: After binding a hotkey to hs.alert.show(_VERSION), it seems to be Lua 5.3.

Edit 2: Oh Hammerspoon has an interactive console. Typing _VERSION in there would have been slightly simpler.


My question is, how does this compare with AppleScript? I've had macs for ages, and I used to automate things with AppleScript (I still do, but I used to, too). I imagine there are some things hammerspoon can do that AppleScript can't do and vice versa. Can the two compliment each other? Call each other?


This is great. One of my biggest pain points when switching to OS X was finding a good replacement for autohotkey.


Touche. Autohotkey can do an awful lot with its custom scripting language, but access to Lua in there would be interesting.


Besides the nice Getting Started Guide and the API documentation there is also a Wiki with sample configs https://github.com/Hammerspoon/hammerspoon/wiki


Slightly tangential question:

At http://www.hammerspoon.org/go/#colonsyntax it mentions the following calls are identical:

win:frame()

hs.window.frame(win)

My Lua knowledge is a bit rusty but should the second line not be:

win.frame(win) ?


The section in question, "A quick aside on colon syntax", is referring to the code from the section above it, "Introduction to window movement":

    local win = hs.window.focusedWindow()
    local f = win:frame()
win is presumable a copy ("instance") of the table hs.window created by focusedWindow().

Meaning hs.window.focusedWindow() returns a copy of the hs.window table.

With that being said, win.frame(win) would just be hs.window.frame(win), so you're also correct. It's just a poorly worded example explaining Lua's colon syntax feature.


More specifically, hs.window.focusedWindow() returns a userdata, with a metatable where the __index entry is the hs.window table. This means that looking up entries on the returned win object (e.g. looking up win.frame) will end up looking up the same key on the hs.window table. Or in other words, it's not literally a copy of the table, but it behaves like it. It's prototype-based inheritance, similar to JavaScript.


I didn't actually look at the implementation of these functions and tables, but yea, I am fairly familiar with Lua and metatables from my days of working on WoW addons.

As for JavaScript, my opinion is that Lua is everything JavaScript should have been: A clean, minimal, sanely designed, language. JavaScript on the other hand is nothing but mistakes piled upon mistakes. It's really disheartening to see JavaScript get shoved into places Lua fits better, like as Gnome Shell's scripting language. Oh well.


Ah, thank you for clarifying this.


I was just trying to write my custom Swift Accessibility Application, but hopefully Hammerspoon will suffice. Then I might get rid of Spectacle and SmartScroll, which are nice, but I do not need all these features.

Then I can just put a Lua file in my dotfiles.


Could this, say, automate the conversion of a folder of Word docs to Pages format? Because I've just tried to do this with AppleScript, and cannot, for the life of me, find the right incantation to get Pages to save the open doc.


Oh how this tool reminds me of the good old PowerPro for Windows... (http://powerpro.cresadu.com)


Currently I use spectacle and magnet for window management and will setup hammerspoon later today. It looks great and the documentation is impressive! Nice work!


I wonder how easy it would be to tap into the Accessibility API? I would like to create an NLP interface for visually impaired, using intents.


It's actually built on the OSX accessibility APIs afaik


Aha! Very cool; should look deeper. Don't know if there is any ultimate connection, but the fact that LuaJit and Torch7 go together invites exploration.


How does it compare to mjolnir?


Mjolnir is decentralized and modularized, where everything is a plugin. Hammerspoon is batteries-included, where everything is built in. Neither is better or worse, they're just different approaches.


strictly better than mjolnir, since it's a fork that never removed anything and only ever improved.


There's so many positive comments here. What's going on?


Exactly my thoughts.


My thoughts - It gives people powerful scriptability over things they couldn't control before. It has been refined down a few products/generations so its molded for more people to find it useful. It is free. Nobody is trying to sell anything or take anything away. So, maybe there is no need for any negativity.


Very cool.

Can people give some real world examples of what they are using this for?


After jumping through some hoops, I now have caps lock usable as a shortcut button. Here's some things I do with it:

CAPS + 1 = Bring up Bash

CAPS + 2 = Bring up IntelliJ

CAPS + 3 = Bring up Chrome

CAPS + 4 = Bring up Geany

CAPS + 5 = Bring up SourceTree

CAPS + F1 = Chat software

CAPS + F2 = Email

CAPS + F = Full screen the current app (But not really fullscreen - it's like option + green button, except width too)

CAPS + W = Cycle the wifi

CAPS + V = Paste text from the clipboard by typing it in, accounting for tab indentations. This is useful for copying things from Outlook into Confluence. Stupid Confluence.


I've always found that mapping Caps Lock to Ctrl is the most useful thing you can do with it.


I like mapping it to cmd-shift-alt-ctrl. Lets you add a whole new set of hotkeys that are a pain to press otherwise.


That's what I did.


I use it to have a history of my clipboard (my own jumpcut!)

https://github.com/victorso/.hammerspoon/blob/master/tools/c...


For me, I use cmd+alt+control to let me access shortcuts like:

cmd+alt+control+k emaKs cmd+alt+control+T Trello cmd+alt+control+M chroMe

And I have cmd+alt+control+/ print this bubble message onto the screen to help remember them all: https://fetchh--captured.s3.amazonaws.com/2016-07-15_135709....


I made my app shortcuts with cmd+function keys - less keys to press.

I was a bit surprised, but cmd+fx doesn't seem to override any useful app builtin shortcuts either for the apps I use.


1. Automating network connection switching and related tiggered actions

2. Site specific apps (e.g. trello)

3. Custom browser chooser per URL

4. Clipboard manager

5. Downloader manager

6. Various system information displays

7. Pomodoro timer

8. Various utilities.


I'm using it as a basic window manager and an easy way to start and stop music without having to take my hands out of their usual position.

Here (https://github.com/Linell/hammerspoon-config) is my configuration, although it's nothing fancy.


I have two large monitors side by side.

Hammerspoon is the only utility that could give me what I wanted: Window columns sized ⅓ ⅔ on the left monitor, and ⅔ ⅓ on the right monitor.


Pretty excited to try this out! Thanks for sharing!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: