Skip to content

mjolnirapp/mjolnir

Repository files navigation

Mjolnir

Mjolnir logo

Lightweight automation and productivity power-tool for OS X

  • Current version: Mjolnir 1.0.1
  • Requires: OS X 10.12 or higher

What is Mjolnir?

Mjolnir is an OS X app that lets you automate common tasks using the language Lua. At its core, it doesn't actually do anything besides load up a Lua environment; the real power lies in all the useful modules that you can install.

You write a "config", which just means ~/.mjolnir/init.lua. This file, along with whatever modules it requires, have full access to the built-in mjolnir module, and all Lua modules that you have installed (e.g. from LuaRocks or any way you want to install them).

Try it out

  1. Download the latest release, unzip, right-click Mjolnir.app, choose "Open". Or, install it with Homebrew:

    $ brew install --cask mjolnir
  2. Install Lua into /usr/local e.g. from Homebrew, and then install LuaRocks:

    $ brew update
    $ brew install lua
    $ brew install luarocks
  3. Install some modules from this list: https://luarocks.org/search?q=mjolnir

    $ luarocks install mjolnir.hotkey
    $ luarocks install mjolnir.application

    Note: you don't need to install every module, since some of them have lower-level ones as dependencies, e.g. installing mjolnir-hotkey automatically installs mjolnir-keycodes, etc.

  4. Create ~/.mjolnir/init.lua, and at the top, require the modules you installed, e.g. like this:

    local application = require "mjolnir.application"
    local hotkey = require "mjolnir.hotkey"
    local window = require "mjolnir.window"
    local fnutils = require "mjolnir.fnutils"

    NOTE: The mjolnir.window module comes with mjolnir.application, so you don't need to (and can't) install it separately. Also, mjolnir.fnutils is already installed as a dependency of the other modules, so you don't need to explicitly install it.

  5. Start writing some fun stuff!

    hotkey.bind({"cmd", "alt", "ctrl"}, "D", function()
       local win = window.focusedwindow()
       local f = win:frame()
       f.x = f.x + 10
       win:setframe(f)
    end)
  6. Reload config using mjolnir.reload() in the console.

Uninstalling

If for any reason you want to undo everything in the above steps, do:

$ luarocks purge --tree=/usr/local
$ brew uninstall lua luarocks
$ rm ~/.luarocks/config.lua

Installing to $HOME

If you run luarocks --local install ... instead of luarocks install ..., it will install to ~/.luarocks/ instead of /usr/local. Update your package.path and package.cpath accordingly, as noted in the FAQ.

Finding modules

Check out https://luarocks.org/search?q=mjolnir for a list of published Mjolnir modules.

Notable modules:

  • mjolnir.hotkey for creating global hotkeys
  • mjolnir.application for inspecting and manipulating running OS X applications and windows
  • mjolnir.alert for showing on-screen messages

Documentation

Mjolnir and mjolnir-modules use Dash for documentation. You can install Mjolnir's docset from the User Contributed section of the Downloads tab in Dash's Preferences window. It should generally update on its own.

Publishing modules

Wrote an awesome module, and want to share with the world? Check out the sample-plugin subdirectory.

When it's published, please announce it on our mailing list :)

Avoid the temptation to reformat the Repos page in the wiki. It uses a strict format that's needed by the documentation generator.

Principles

Development of Mjolnir.app and the core Mjolnir modules follow these principles:

  1. They must be stable. The app should never crash. You should only ever have to launch it once, and it should stay running until you quit. Period.

  2. They must be lightweight. They should never do anything that drains your computer's battery. They should never poll for anything. They should use as little RAM as possible. Everything they do should feel instant and snappy, never sluggish or delayed.

  3. They should be completely transparent. There should be no surprises in how it's behaving, or what's being executed and when. Everything should be fully predictable.

  4. They must not be bloated. The app and core modules must always adhere to the minimalist philosophy, no excuses. Everything else can be a separate Lua module.

FAQ

  1. Add Spaces support!

    Not a question. But anyway, there are no public or private APIs to manage Spaces in OS X 10.9 or 10.10, there are only private APIs that work in 10.8. No open source project has been able to crack this problem yet, not just us.

  2. Does LuaRocks have a way to upgrade modules automatically?

    Sadly no. But it can be done manually by removing a module and re-installing it. I'm hoping maybe one day some enthusiastic Mjolnir users can jump in and improve the tooling around this. ;)

  3. I'm getting an error like this: "attempt to index field 'win' (a nil value)"

    Disable and re-enable accessibility. It may look enabled, but do it anyway. (This is an OS X bug, not a Mjolnir bug.)

  4. I don't have things in /usr/local, so I can't load modules!

    Add the path to package.path and package.cpath in your init-file. For example, if you're using Boxen, add this:

    package.path = package.path .. ';/opt/boxen/homebrew/share/lua/5.3/?.lua'
    package.cpath = package.cpath .. ';/opt/boxen/homebrew/lib/lua/5.3/?.so'

Mjolnir vs. other apps

  1. Hydra, Phoenix, or Zephyros?

    Those are my old apps. Mjolnir is their spiritual successor.

  2. Slate

    They're both programmer-centric with somewhat similar goals but different approaches. Mjolnir is more modularized, Slate is more all-in-one. Try them both and see which one suits you better.

  3. Spectacle, Moom, SizeUp, Divvy

    Mjolnir is intended for programmers who want to write programs that customize their environment. It's not intended to be a drag-n-drop solution; it's meant to allow you to write your own personalized productivity enhancement suite to keep and to use long-term.

  4. Hammerspoon

    Hammerspoon is a fork of Mjolnir (get it? a "fork and/or spoon" of Mjolnir aka. Thor's "hammer"? :) ). It was created to turn Mjolnir back into an all-in-one application, for those who prefer that over a completely decentralized module system with a bare-bones core (kind of like the debate of monolithic kernel vs microkernel). It's actively maintained, like literally there's commit activity every week.

Community

Our mailing list is a fine place to share ideas, and follow releases and announcements.

We also have a shrinking IRC channel on freenode, #mjolnir.

Credits and Thanks

Mjolnir is developed by Steven Degutis with the help of various contributors.

Special thanks, in no special order:

  • @Habbie for his constant help and support ever since the moment I first jumped into #lua and said "anyone wanna try out an OS X window manager scriptable in Lua?" and being the first person to join our IRC channel and for helping with nearly every Lua question I had

  • @cmsj, @Keithbsmiley, @BrianGilbert, @muescha, @chdiza, @asmagill, @splintax, @arxanas, and @DomT4 for all their help and support

  • @jasonm23 for writing, not one, not two, but three app icons for this project

  • @jhgg for contributing so many awesome modules to the project

  • @kapeli for his patience with my constant Dash questions and PRs

  • Everyone else who has helped who I've probably forgotten: thanks for all your help!

  • Everyone who has donated: thank you so much for your support!

See the in-app About panel for the open source licenses for the software Mjolnir uses internally (basically just Lua's license).

Changes

NOTE: When upgrading, System Preferences will pretend like Mjolnir's accessibility is enabled, showing a checked checkbox. But in fact, you'll still need to be disable and re-enable it. This is a bug in OS X.

0.4.3

  • Removed donation requests

0.4.{0,1,2}

  • Default implementation of mjolnir.showerror(err) now opens the console and focuses Mjolnir
  • There's a new variable, mjolnir.configdir = "~/.mjolnir/" for users and modules to coordinate
  • New mjolnir.focus() function to make Mjolnir the focused app
  • The original print function is now stored in mjolnir.rawprint (rather than mjolnir.print, to disambiguate it)
  • New mjolnir.openconsole() function to open console (and bring Mjolnir to front)

0.3.1

  • Renamed global mj to mjolnir

0.3

  • The UI has changed drastically. Expect nothing to be in the same place or look the same. Pretend it's a brand new app.
  • Modules are now handled by LuaRocks instead of by the app itself.
  • The "core" namespace has been renamed to "mj".
  • The 'mj.window' module now ships with the 'mj.application' LuaRocks package since they depend on each other.
  • mj.screen:frame_without_dock_or_menu() is now called mj.screen:frame()
  • mj.screen:frame_including_dock_and_menu() is now called mj.screen:fullframe()

License

Released under MIT license.

Copyright (c) 2014 Steven Degutis

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.