Hammerspoon

(github.com)

240 points | by tosh 9 hours ago

35 comments

  • cmsj 4 hours ago
    Hammerspoon maintainer here - I'm enjoying reading all the comments, and hoping that everyone isn't going to be annoyed that I'm mostly working on a v2 atm, which switches from Lua to JavaScript :D
    • eviks 17 minutes ago
      Have you though of some more modern language agnostic solution like wasm plugins users could write in anything, with the help of typed languages if they like? Or is that not feasible for a scripting project like this?
    • saagarjha 4 hours ago
      Hammerspoon is basically my only reason to write Lua, a language which I really like. I am sure JavaScript is a more pragmatic choice but I will be slightly saddened by it regardless.
      • cole_ 1 hour ago
        Agreed, I never considered it a selling point but I did enjoy having an excuse to explore the language in Hammerspoon (and Neovim too).
    • zimpenfish 4 hours ago
      > a v2 atm, which switches from Lua to JavaScript :D

      Presumably that'll be released in [checks calendar] 18 days?

    • cole_ 1 hour ago
      Thank you for your work on Hammerspoon! I’ve been using it for years.

      Would you mind elaborating on your vision for v2? Was there a certain limitation in the previous architecture that you’re trying to avoid this time around? Was there something in particular that drew you to choosing JavaScript for this version?

    • al_borland 2 hours ago
      Will this lead to some synergy with AppleScript, which added JavaScript a few years ago?
    • pstuart 4 hours ago
      I'm curious if the switch was for dev ergonomics or the mindshare of the languages?
  • incanus77 8 hours ago
    Hammerspoon is the glue that holds my Mac together. For a starter list of things to do with this app, a partial list of the things that I'm using it for:

      - Dumping all open Safari tabs to an Obsidian doc
      - Adding 'hyper' (Ctrl-Opt-Cmd) keybinds to pop a new window for:
        - Safari
        - Finder
        - Terminal / Ghostty
        - VS Code
        - Notes
        - Editing Hammerspoon/AeroSpace/Sketchybar config
        - Reloading Hammerspoon config
        - Reloading Sketchybar
        - Quitting all Dock apps except Finder
        - Screen lock
        - System sleep
        - Opening front Finder folder in VS Code
        - Opening front Safari URL on Archive.today
        - Showing front Safari window tab count
        - Showing front app bundle ID
        - Posting notification about current Music track
        - Controlling my Logi Litra light (various color temps/brightnesses)
        - Starting/stopping a client work timer
      - Tying it to AeroSpace for:
        - Pushing a window to another monitor
        - Performing a two-up window layout
        - Swapping those two windows
        - Closing all other workspace windows
        - Gathering all windows to first workspace
      - Ensuring some background apps stay running if they crash
      - Prompting to unmount disk images if trashed
      - Binding into Skim to jump to specific sections of spec PDFs using terse Markdown URLs
    • zimpenfish 4 hours ago
      I pretty much only use it for two (related) things these days:

      - check the list of open Teams windows; if there's a non-standard one, assume I'm in a meeting and webhook to HomeAssistant to select the "active"[2] preset on my meeting light[0].

      - download my work ical[1] and, if there's a pending meeting (<~15m), webhook-HASS for the "pending" present on the meeting light.

      [0] Just a short strip of WS2812B connected to an ESP32 running WLED.

      [1] Originally this was a simple HTTP to my shared link on outlook.com but then they started requiring authentication (because that's exactly what you want on a SHARED link, you gufftarts); had a look at the Azure SDK and ... bag of milky spanners that is; ended up having to import my work ical into Apple Calendar and then use the ical link for that in Hammerspoon. Oh how we laughed. Especially when I realised it only has about 40% of the actual meetings because somehow "my calendar" is actually 4 or 5 bastardised conglomerations of pain and the ical for "my calendar" is actually just for one of those. AND NOT THE USEFUL ONE EITHER.

      [2] There's various - "camera" for "the one meeting I'm forced to have my camera on", "active" is "I probably have to talk", "passive" is "I'm not going to be talking", and "silent" for things like company presentations where it's just watching a boring Powerpoint over Teams.

      • incanus77 44 minutes ago
        This is a great integration!
    • joemi 5 hours ago
      > - Dumping all open Safari tabs to an Obsidian doc

      I'd love to do this too. Would you mind sharing how you do it? Or is it trivially easy and not worth explaining? (I haven't looked too deeply into HS yet.)

      • incanus77 38 minutes ago
        It's not trivial, but roughly: use AppleScript/osascript to get the URLs, but mostly pass them to a ~50 line Bash script which:

          - Brings in the date path components for the dumped-to folder
          - Makes a hash of the URL for an Obsidian doc (each tab gets their own doc)
          - Uses Chrome command line (--headless --disable-gpu --dump-dom) to save a snapshot of the page contents
          - Uses it again with --screenshot to make a thumbnail
          - Create an Obsidian doc from a template
          - If it's a single tab dump, pass -o to the script, which opens it in Obsidian for review
        
        Lastly, I use the relatively-new Bases feature in Obsidian to make a nice "cards" view of the docs with their thumbnails.

        I'm hoping to clean it up at some point and maybe release it, but it's one of those classic one-shot systems that just works for me for now.

      • michaelteter 3 hours ago
        I have no idea how that person is doing it, but I suspect it could be using osascript. Here's how I do it from my homegrown Go bookmark tool:

          const fetchTabsScript = `
          tell application "Brave Browser"
              set output to ""
              repeat with w in windows
                  repeat with t in tabs of w
                      set output to output & (URL of t) & "|||" & (title of t) & "\n"
                  end repeat
              end repeat
              return output
          end tell
          `  
          
          func GetOpenTabs() ([]Tab, error) {
           cmd := exec.Command("osascript", "-e", fetchTabsScript)
           output, err := cmd.Output()
            // ...
          }
    • piskov 7 hours ago
      Keyboard stuff is better handled with Karabiner elements
      • dbalatero 5 hours ago
        Karabiner can _create_ new keys like hyper, but you _bind_ them with Hammerspoon.
  • iLemming 6 hours ago
    Shameless plug/proud self-promotion - https://github.com/agzam/spacehammer "Spacemacs|Doom inspired Hammerspoon modal toolkit"

    I can't even work on Mac without it. It let's you do stuff like "alt+spc a b" (apps -> browser) or "alt+spc m j/k" (media -> vol up/down), or edit just about any text of any app in your editor (Emacs atm) - with all the tools you have there - spellchecking, thesaurus, translation, LLMs, etc.

    You can plug it to your favorite WM (I'm currently using Yabai) and do tons of other interesting things. Because it's all written in Fennel, one can develop things in a tight feedback loop with a connected REPL - e.g., I can ask Claude to inspect things in the running Slack app or Firefox and make interesting automations - all without ever leaving my editor.

    • jedbrooke 6 hours ago
      > "alt+cmd m j/k" (media -> vol up/down)

      if only keyboards came with built in buttons for adjusting the volume… oh wait. Unless of course you are suffering on a touch bar mac, then I completely understand.

      • zimpenfish 4 hours ago
        > if only keyboards came with built in buttons for adjusting the volume…

        99% of my working day, my fingers are on or near alt/cmd/m/j/k (a nice easy position in the centre of the keyboard.)

        They are not on or indeed anywhere even vaguely near fn+f10/f11/f12 (which are, in fact, diametrically opposite corners of the keyboard.)

      • iLemming 5 hours ago
        It's not about "having" or "not having" keys for specific actions, it's all about freedom and feeling of control. When you take and apply the idea of modality, you quickly realize that you are no longer constrained with the number of combinations you can have or the type of keyboard you're using. Everything can be controlled by (mostly) using home-row keys - h/j/k/l - without having to memorize weird combinations of modifiers and keys - "was it Ctrl+Alt+Cmd F, or just Ctrl+Cmd F?"

        alt+cmd (was a typo, I meant to say alt+space), which is configurable - I myself prefer using cmd+space. That opens the "main" modal, from where you can configure "conditional branching" - e.g. "m" - for "media", or "a" - for "apps", so with "alt+space m j/k" you can do volume up/down, while pressing h/l could be "previous/next song". Then, "alt+spc a b" activates the browser, and "alt+spc a t" - could be bind to activate "terminal", etc.

        It only looks like you have to press more keys to achieve anything, in practice - you quickly develop muscle memory. Then switching between the apps, moving windows around and resizing them, controlling playback, etc. - it all gains incredible productivity without affecting the focus point. You don't need to keep moving your hand for the mouse, you don't need to memorize and deal with myriad of modifier-driven key combinations - you control precisely what you need, without ever having to contort your fingers to hold modifiers, without ever thinking "what should I bind this action to, all memoizable keys are already taken, I suppose I'll just bind it to this impossible combo with a key that has no semantic meaning for the thing..." With Spacehammer you can create mnemonically-handy actions e.g., "o f" for "Open in Finder", while in another context that may work as "Open in Firefox".

  • zdw 8 hours ago
    I fake a tiling window manager on Mac with Hammerspoon, resizing to fit in specific corners/sizes:

         -- resize based on ratios
        function ratioResize(xr, yr, wr, hr)
          return function ()
            local win = hs.window.focusedWindow()
            win:moveToUnit({x=xr,y=yr,w=wr,h=hr})
          end
        end
    
        -- 4 corners, different sizes
        hs.hotkey.bind({"cmd", "ctrl"}, "w", ratioResize(0,     0, 2/5, 2/3))
        hs.hotkey.bind({"cmd", "ctrl"}, "e", ratioResize(2/5,   0, 3/5, 2/3))
        hs.hotkey.bind({"cmd", "ctrl"}, "s", ratioResize(0,   2/3, 2/5, 1/3))
        hs.hotkey.bind({"cmd", "ctrl"}, "d", ratioResize(2/5, 2/3, 3/5, 1/3))
    
    And to throw windows to other monitors:

        -- send to next screen
        hs.hotkey.bind({"cmd", "ctrl"}, ";", function()
          local win = hs.window.focusedWindow()
          local screen = win:screen()
          local next_screen = screen:next()
    
          win:moveToScreen(next_screen)
        end)
    • comboy 7 hours ago
      I highly recommend Aerospace[1], went through a few approaches, I cared about not completely compromising security either, it works really well if you come from something like i3

      1. https://github.com/nikitabobko/AeroSpace

      • idle_zealot 6 hours ago
        Seconding this. I find MacOS unusable without it. I'll ask here because websearch is failing me: is there a way to fix the focus stealing that happens when you have multiple windows of an application on different displays? Specifically, say workspace 1 and 2 are on monitor Left, while 3 and 4 are on Right. Application A has a window on workspace 1, B has one window on 2 and another on 3, and C has a window on 4. Workspace 1 is active on display Left, workspace 4 is active on Right. If I switch to workspace 3 the following happens:

        - the switch goes through, Left displays workspace 1, right displays 3 (desired state)

        - Application B is focused, presumably because its window on 3 becomes active (also desired)

        - Display Left switches to display workspace 2, presumably because it contains a window belonging to the newly focused application B? (I don't want this)

        - the window of application B on workspace 2 steals focus from the one on workspace 3 (???)

        • airstrike 5 hours ago
          Thirding the recommendation, and I also have this same issue. It's quite frustrating—but still better than no Aerospace!
        • JSR_FDED 5 hours ago
          So what you’re saying is:

          Charlie's paternal grandfather Reginald married twice—first to Mildred, mother of Charlie's father Arthur and his siblings Beatrice (a nun with spiritual godchildren) and Cecil (whose widow Dorothy married Charlie's maternal uncle Edward). What is the name of Charlie's goddaughter?

    • mortar 1 hour ago
      I do this too, really happy with my setup - I use hyper+arrow keys to move windows around a monitor (split in thirds on 40”+ or halves on the built-in screen), or jump to another monitor, and hyper+enter to fullscreen. When you push against an edge in full screen it reduces the window size in stages, it all feels natural.
    • jeberle 7 hours ago
      I use it similarly, but I add spots for side x side as well as left, center, right. I only use Hammerspoon for this and a couple tiny things, but it's completely worth it for this alone. Use math to specify window sizes & location. Insanity.

        local mode = hs.screen.primaryScreen():currentMode()
        local mods = {"ctrl", "alt", "cmd"}  -- mash those keys
        
        -- regular app windows
        do
          local w   = 1094  -- no clip on GitHub, HN
          local h   = 1122  -- tallish
          local x_1 =    0                               -- left edge
          local x_2 = math.max(0, (mode.w - w - w) / 2)  -- left middle
          local x_3 =             (mode.w - w) / 2       -- middle
          local x_4 = math.min(mode.w - w, x_2 + w + 1)  -- right middle
          local x_5 =          mode.w - w                -- right edge
          local y   =   23  -- top of screen below menu bar
        
          hs.hotkey.bind(mods, "2", function() move_win(  0, y, mode.w, mode.h) end)  -- max
        
          hs.hotkey.bind(mods, "3", function() move_win(x_1, y, w, h) end)
          hs.hotkey.bind(mods, "4", function() move_win(x_2, y, w, h) end)
          hs.hotkey.bind(mods, "5", function() move_win(x_3, y, w, h) end)
          hs.hotkey.bind(mods, "6", function() move_win(x_4, y, w, h) end)
          hs.hotkey.bind(mods, "7", function() move_win(x_5, y, w, h) end)
        end
        
        function move_win(x, y, w, h)
          hs.window.focusedWindow():setFrame(hs.geometry.rect(x, y, w, h))
        end
    • ackfoobar 5 hours ago
      https://github.com/peterklijn/hammerspoon-shiftit

      I use ShiftIt (a lovely project, but dead) reimplemented in Hammerspoon. It is very comprehensive.

    • apazzolini 6 hours ago
      I like the miro windows manager plugin: https://github.com/miromannino/miro-windows-manager

      It's nice to be able to iterate through the halves/thirds configurations for different cases.

    • piskov 7 hours ago
      Moom is really the best
  • pjm331 9 hours ago
    here is my entire config

        hs.hotkey.bind({"ctrl"}, "D", function()
          hs.grid.show()
        end)
    
    i've tried all of the other fancy window managers and for me nothing has ever beat the ease of use of just

    (1) ctrl-d to see the grid, (2) type the letter where you want the top left corner of your window to be, (3) type the letter where you want the bottom right corner to be

    window resized

    • matthewmc3 4 hours ago
      Wow... that's... incredible. I've used Hammerspoon forever and never knew that existed.

      Just messing around I found you can extend the grid size with `hs.grid.setGrid('4x4')`, which you also may then want to shrink the text size with `hs.grid.ui.textSize = 30`, and finally if you use an alternative keyboard layout (eg: Colemak), you can set the grid to use it with `hs.grid.HINTS`. They really thought of everything with this feature.

    • elAhmo 8 hours ago
      This is amazing! I have a slightly more elaborate setup that allows me to resize from one or another side, similar to what Apple added recently but with more flexibility, but this is super interesting, thanks for sharing!
    • hrmtst93837 7 hours ago
      Neat until you need to sync configs or keep multiple machines in harmony, at which point dotfile headaches stack up with Hammerspoon and Lua. Adding complex logic like window rules, app-specific behavior, or handling monitor changes strips away some of that hotkey simplicity and leads to endless tweaking. Still, for avoiding the mouse, it's one of the few flexible options left on macOS that doesn't feel ancient. Tradeoffs everywhere but nowhere else really compares in control.
    • stackghost 8 hours ago
      Not that I insert EOFs very often, but does that conflict with CTRL+D in the terminal?
      • xyzzy_plugh 8 hours ago
        I use EOF all the time to end terminal sessions.
      • theshrike79 7 hours ago
        Make caps lock a hyperkey (shift+ctrl+option+cmd) and use that for non-overlapping shortcuts
        • 1-more 7 hours ago
          make caps lock control on hold, double quote on tap. Make control hyperkey on hold, angle bracket on tap. My keyboard firmware is very odd. This is not easily done with soft remaps to the point that I don't bother trying.
          • dbalatero 39 minutes ago
            If you're on macOS have you tried Karabiner Elements? It seems to do just fine with software mapping my macbook keyboard.
      • pjm331 8 hours ago
        yeah the CTRL+D definitely gives me problems from time to time but thus far i have been too lazy to fix it
  • dbalatero 5 hours ago
    Some stuff I've made in Hammerspoon you can use:

    - Vim mode everywhere in macOS: https://github.com/dbalatero/VimMode.spoon

    - Modifier keys + click/drag to resize or move windows: https://github.com/dbalatero/SkyRocket.spoon

    - Show an overlay helper of all your keybinds when you hold modifier keys down: https://github.com/dbalatero/HyperKey.spoon

    And my huge pile of random scripts/configs: https://github.com/dbalatero/nixpkgs/tree/main/home/modules/...

  • juancn 8 hours ago
    I use it to hide Zoom's screen sharing controls so they don't come back when pressing Esc:

        -- Hide Zoom's "share" windows so it doesn't come back on ESC keypress
        local zoomWindow = nil
        local originalFrame = nil
        
        hs.hotkey.bind({"cmd", "ctrl", "alt"}, "H", function()
          print("> trying to hide zoom")
          if not zoomWindow then
            print(">  looking for window")
            zoomWindow = hs.window.find("zoom share statusbar window")
          end
        
          if zoomWindow then
            print(">  found window")
            if originalFrame then
              print(">    restoring")
              zoomWindow:setFrame(originalFrame)
              originalFrame = nil
              zoomWindow = nil
            else
              print(">    hiding")
              originalFrame = zoomWindow:frame()
              local screen = zoomWindow:screen()
              local frame = zoomWindow:frame()
              frame.x = screen:frame().w + 99000
              frame.y = screen:frame().h + 99000
              zoomWindow:setFrame(frame)
            end
          else
            print(">  window not found")
          end
        end)
    • henrebotha 6 hours ago
      Oh my god, immediately worth installing just for this
  • msephton 1 hour ago
    I use it to: - implement a keyboard based window manager - arrange/quit/launch some things based on whether my MBP is docked or not - resize and reposition certain windows that don't remember their own size and position - certain other hotkeys - probably stuff I forgot and rely on!

    I'll be sad when it moves from Lua to JavaScript, but I guess that's better than moving to Tcl.

  • fudged71 1 hour ago
    I recently set up Hammerspoon to surveil my own computer usage actions (active tab/window, typing state, scrolling) to have a next-action predictor. It shows the predicted next action at the top of the screen but I was thinking of using it to improve voice command accuracy.
  • alexfortin 8 hours ago
    I use it to enable/disable the wifi when I disconnec/connect the macbook to a specific usb hub with ethernet connection:

      local usbWatcher = hs.usb.watcher.new(function(device)
        if device.productName == "EMEET SmartCam C960" then
          if device.eventType == "added" then
            hs.execute("networksetup -setairportpower en0 off")
            hs.notify.new({title="Wi-Fi", informativeText="Disabled (USB device connected)"}):send()
          elseif device.eventType == "removed" then
            hs.execute("networksetup -setairportpower en0 on")
            hs.notify.new({title="Wi-Fi", informativeText="Re-enabled (USB device removed)"}):send()
          end
        end
      end)
      usbWatcher:start()
  • theshrike79 7 hours ago
    I tried to find a proper window control tool for macOS for a while, tested Rectangle and Magnet and dunno how many.

    Then I just figured out that I have Hammerspoon, it can control windows -> recreate one exactly how I like it. Been using it for a year now and it's 99% perfect. Some specific applications (coughFirefoxcough) sometimes get into a weird state that doesn't work, but I can live with that.

    It can also pop all windows to a specific layout with a single shortcut by combining the active wifi + monitor setup to detect if I'm at home, at work, or working at home.

    • piskov 7 hours ago
      Moom works like a charm
  • overflowy 8 hours ago
    I use this to remap app keys:

        local appHotkeys = {}
    
        local function remapAppHotkey(appName, fromMods, fromKey, toMods, toKey, delay)
            if not appHotkeys[appName] then
                appHotkeys[appName] = {}
            end
            local hotkey = hs.hotkey.new(fromMods, fromKey, function()
                hs.eventtap.keyStroke(toMods, toKey, delay or 0)
            end)
            table.insert(appHotkeys[appName], hotkey)
        end
        
        local appWatcher = hs.application.watcher.new(function(appName, eventType)
            local hotkeys = appHotkeys[appName]
            if not hotkeys then return end
            for _, hotkey in ipairs(hotkeys) do
                if eventType == hs.application.watcher.activated then
                    hotkey:enable()
                elseif eventType == hs.application.watcher.deactivated then
                    hotkey:disable()
                end
            end
        end)
        
        appWatcher:start()
    
        -- Remap app hotkeys
        remapAppHotkey("Finder", { "cmd" }, "q", { "cmd" }, "w", 0.5)
        ... etc ...
  • golem14 9 hours ago
    Has anyone worked on making a config replicating aerospace?

    Hammerspoon seems like a superset and it’s probably better to just have one, instead of two tools warring about who gets the keypresses?

    • hirvi74 8 hours ago
      What features are you trying to replicate from Aerospace?
      • golem14 8 hours ago
        Well, a tiling window and workspace manager. But as I am typing this, I’m realizing they hammerspoon can probably do some of the window placement, but maybe not handling workspaces and global state.

        I was hoping I could be lazy and ask, and a not-lazy person could give a ready made answer :)

        • r5Khe 5 hours ago
          It can definitely handle virtual workspaces and global state (if I'm understanding what you mean). I have an Aerospace-like implementation here: https://github.com/mybuddymichael/Helm.spoon

          It has several features from Aerospace, but Hammerspoon's window management performance is not nearly as good as Aerospace's (not surprising!).

          Overall, I've found it easier to just fork Aerospace and add various extra features to it, so that's what I'm doing now.

        • hirvi74 5 hours ago
          If workspace management is an another term for managing desktop/spaces, then you are going to be hard pressed to find anything that is not a brittle hack.

          I am writing a window manager bundled with other knick-knacks for myself. I have a "solution" for moving windows between spaces, but in the most vile way possible.

          The only way I have managed to move windows between spaces is by, and this is no joke, recording the mouse position, moving the mouse to an app's titlebar, automating the 'click and hold' on the window's titlebar, then having the keybindings for "Switch to Next/Previous Space" fire off, and then moving the mouse back to the original position.

          Because of the animations, all of junk requires carefully timed, short sleeps, which are also not likely consistent across various hardware/OS versions (can't test it myself).

          Also, I have no idea what happens if my solution is tried on apps with pop-up windows, 'headless' apps (no title bar), electron apps, etc..

          Apple's support for spaces is notoriously atrocious. There is no clean way to move windows from one space to another or to create/delete spaces. Though there was a built in way in OSX Snow Leopard, IIRC. Why it was removed? I have no idea.

          Aerospace creates its own virtual desktops/spaces instead of trying to fight against the OS. I have never used Aerospace, so I cannot comment on its efficacy. But that is probably the cleanest solution we currently have available.

          • golem14 5 hours ago
            Sadly, I think you’re right.

            Aerospace is pretty cool, i recommend it, but I have not really worked out how full screen interacts with spaces. It’s a mess with and without aerospace.

  • kcrwfrd_ 5 hours ago
    I despair at not being able to easily send a window to another space with a keyboard shortcut on macOS.

    Yabai supports this perfectly (especially combined with instant, animation-free space switching) but it requires disabling system integrity protection--which is a non-starter on a work computer.

    Aerospace solves it with their own spaces implementation.

    I was able to put together a hammerspoon script that does the job decently enough for my purposes: https://gist.github.com/kcrwfrd/6f3dcaec0e08e0e77b2884588a34...

  • saagarjha 4 hours ago
    Hammerspoon is one of the first apps I install on my Mac. Not having it makes it more or less broken to me.
  • nxobject 2 hours ago
    Thank you so much for doing what Apple's neglected to do for many years! The way they let AppleScript/JXA rot was criminal.
  • jjmiv 8 hours ago
    is there a particular reason this was shared?

    otherwise I'm slowly working on a Spoon that figures out if there is an active meeting in Zoom, Teams, Huddle, Google Meet and will allow for muting, video enable/disable and screen sharing etc

    • al_borland 7 hours ago
      My guess is someone just found it. When I was moving to macOS for my work laptop, I was looking for something to replace AutoHotKey. It took me a long time and a lot of digging to actually find HammerSpoon.
  • trjordan 8 hours ago
    I utterly love Hammerspoon.

    It's fun to combine with qmk [0], which gives you a bunch more options for hotkeys on your keyboard via layers. I've ended up with a layer where half the keyboard is Hammerspoon shortcuts directly to apps (e.g. go to Slack, to Chrome, etc.) and half of it is in-app shortcuts (like putting cmd-number on the home row, for directly addressing chrome tabs).

    Between this and one of the tiling window manager-adjacent tools (I use Sizeup), I can do all my OS-level navigation directly. "Oh I want to go to Slack and go to this DM" is a few keystrokes away, and not dependent on what else I was doing.

    [0] https://qmk.fm/

    • henrebotha 6 hours ago
      My QMK Tmux "layer" is still one of my favourite customisations. Prepends Ctrl-B to everything I type.
  • weitzj 8 hours ago
    I love hammerspoon. That's it :D

    It's lua, so you can get creative with https://fennel-lang.org/

  • dbalatero 5 hours ago
    I have an unreleased pile of tutorial projects with Hammerspoon. I think not all chapters are finished, so I need to clean up and finish it at some point soon: https://learnhammerspoon.com
  • mwagstaff 8 hours ago
    Can't live without Hammerspoon on Mac.

    Can't live without AutoHotkey on Windows.

    Thanks to everyone who contributed to both!

  • ifh-hn 6 hours ago
    It's this like Mac equivalent to autohotkey on windows?
    • msephton 1 hour ago
      Kinda, I'd say Hammerspoon can do more.
  • john-tells-all 9 hours ago
    I'd love to have a global "toggle Teams mute" button.
    • roxolotl 7 hours ago
      ```

      hs.loadSpoon("MicMute")

      binding = { toggle = { {"ctrl", "alt"}, "m" } }

      spoon.MicMute:bindHotkeys(binding)

      ```

      You'll have to add the MicMute spoon which just mean downloading the zip here, unzipping, and opening the .spoon. https://www.hammerspoon.org/Spoons/MicMute.html

    • hirvi74 8 hours ago
      What do you mean? Like muting the entire application so no sound comes from Teams or muting yourself while on a call? For the latter, I thought 'Option + Space' worked (or used to)?
      • reddit_clone 4 hours ago
        Cmd+Shift+m mutes/un-mutes your Mic when focus is on teams window.

        I think GP is asking about a global (from any application) mute/unmute teams Mic. I have wished for one for ever.

  • regus 7 hours ago
    How does this compare to AppleScript?
  • jmcguckin 8 hours ago
    I use it to give me focus-follows-mouse and to have a large circle surrounding the mouse when i move it, to aid finding it.
  • selectnull 7 hours ago
    Love hammerspoon. I use it to map double CMD to swap between the terminal and the browser.
  • swiftcoder 8 hours ago
    I always confuse "hammerspoon" and "rowhammer"
    • iLemming 6 hours ago
      So, the trivia behind the name is interesting. It all starts with a project called "Mjolnir" (Thor's Hammer). The original idea was for a lightweight automation engine with pluggable architecture. Someone wished to have "batteries included" version, the author said they're not interested in that direction, so the fork was born. What's meant to be a hard-fork, so really not a fork, but rather a "spoon", hence the name.
  • rco8786 3 hours ago
    Love Hammerspoon
  • gedy 6 hours ago
    If you are on macOS but miss Paperwm or niri, etc this is a good compromise thanks to Hammerspoon: https://github.com/mogenson/PaperWM.spoon
  • ChrisArchitect 7 hours ago
  • hmokiguess 8 hours ago
    what's your favourite spoon?
  • hirvi74 8 hours ago
    I have fond memories of this app. However, after many years, I have moved on. I am in the process of writing my own replacement for some of the various use cases that Hammerspoon once provided me. Though, Hammerspoon will always be a source of great inspiration.
  • rolymath 8 hours ago
    Is paperwm jittery for everyone?
  • cjbarber 7 hours ago
    See also:

    KeyboardMaestro

    Automator and AppleScript

    Raycast

  • scm7k 6 hours ago
    [dead]