Skip to content

My Personal Mac Productivity Setup

Productivity, Mac7 min read

I will update both posts on future adjustments to my setup, so stay tuned! I would say this is not a perfect setup, but for me, it saves a lot of time and context switchings on my day to day activities on my Macbook. This setup can be used by anyone who has Mac no matter what job he/she has & activity she/he does, but some sections are for software engineer/developer or whatever engineer you name it. Please be reminded that this is only my preference of setup, so this may not suit your workflow and needs.

Why would you invest time on this?

I love the idea of automation, shortcuts, and simplicity. That brought me to this setup with a lot of keyboard movements, simple, unified plus beautiful integrations across apps.

  • Efficient & fast
  • Less context-switching - Our focus span is limited even for small switching like from keyboard to mouse
  • Well integrated
  • Simple, seamless and unified

I think those are enough to justify one hour of your time for setting this up. Let's get started!

Karabiner-Elements + Hammerspoon ⚡

Aren't you ever tired of pressing ⌘ + tab every time you want to switch between apps? And how many times have you missed the apps that you want to switch on so you have to go through the cycle again? I felt your pain. Fortunately, I found something that can mitigate this problem, Karabiner-Elements + Hammerspoon

So let's begin. First download and install Karabiner-Elements & Hammerspoon. Alternatively, you can use Brew

1brew cask install hammerspoon
2brew cask install karabiner-elements

After you have downloaded and installed both of them, the next step is to set up a hyperkey on Karabiner-Elements. This hyperkey will be your primary access button to hammerspoon shortcuts.

On my setup, because I barely used capslock, I made it as my hyperkey and translate it as ⌘ + control + option + shift.


Karabiner-Elements Preferences

The next step is to setup hammerspoon. Let's make the configuration file in ~/.hammerspoon/init.lua

First thing first, let's add our hyperkey

1-- Specify your combination (your hyperkey)
2local hyper = { "cmd", "alt", "ctrl", "shift" }

then reload the configuration through hammerspoon. But wait, isn't that inefficient we have to open the hammerspoon app and click reload every time we change the configuration file? Yes, it is, so a better option to have a shortcut for reloading the configuration.

Let's add the code to our configuration.

1-- Specify your combination (your hyperkey)
2local hyper = { "cmd", "alt", "ctrl", "shift" }
4-- We use 0 to reload the configuration
5hs.hotkey.bind(hyper, "0", function()
6 hs.reload()
7 end)
9-- Notify about the config reload{title="Hammerspoon", informativeText="Config loaded"}):send()

So that's it, let's reload manually again (I promise, just one more time). After that, try to reload it using shortcut, press hyperkey + 0 to reload.

Cool! Now we're able to quickly reload our configuration every time we change it. Let's add some useful stuff there.

Window Control


Window Control Example

I like the idea of being able to move around apps' windows as quickly as possible without moving my mouse any inch. So let's try to add these features using our hyperkey. First, the very basic thing is that we want to move a focused app's window to left side, top, right side, bottom, top-left, top-right, bottom-left and bottom-right.

Add this code to the existing configuration

1function move_window(direction)
2 return function()
3 local win = hs.window.focusedWindow()
4 local app = win:application()
5 local app_name = app:name()
6 local f = win:frame()
7 local screen = win:screen()
8 local max = screen:frame()
9 if direction == "left" then
10 -- +-----------------+
11 -- | | |
12 -- | HERE | |
13 -- | | |
14 -- +-----------------+
15 f.x = max.x
16 f.y = max.y
17 f.w = max.w / 2
18 f.h = max.h
19 elseif direction == "right" then
20 -- +-----------------+
21 -- | | |
22 -- | | HERE |
23 -- | | |
24 -- +-----------------+
25 f.x = max.x + (max.w / 2)
26 f.y = max.y
27 f.w = max.w / 2
28 f.h = max.h
29 elseif direction == "up" then
30 -- +-----------------+
31 -- | HERE |
32 -- +-----------------+
33 -- | |
34 -- +-----------------+
35 f.x = max.x
36 f.w = max.w
37 f.y = max.y
38 f.h = max.h / 2
39 elseif direction == "down" then
40 -- +-----------------+
41 -- | |
42 -- +-----------------+
43 -- | HERE |
44 -- +-----------------+
45 f.x = max.x
46 f.w = max.w
47 f.y = max.y + (max.h / 2)
48 f.h = max.h / 2
49 elseif direction == "upLeft" then
50 -- +-----------------+
51 -- | HERE | |
52 -- +--------+ |
53 -- | |
54 -- +-----------------+
55 f.x = max.x
56 f.y = max.y
57 f.w = max.w/2
58 f.h = max.h/2
59 elseif direction == "upRight" then
60 -- +-----------------+
61 -- | | HERE |
62 -- | +--------|
63 -- | |
64 -- +-----------------+
65 f.x = max.x + (max.w / 2)
66 f.y = max.y
67 f.w = max.w/2
68 f.h = max.h/2
69 elseif direction == "downLeft" then
70 -- +-----------------+
71 -- | |
72 -- +--------+ |
73 -- | HERE | |
74 -- +-----------------+
75 f.x = max.x
76 f.y = max.y + (max.h / 2)
77 f.w = max.w/2
78 f.h = max.h/2
79 elseif direction == "downRight" then
80 -- +-----------------+
81 -- | |
82 -- | +--------|
83 -- | | HERE |
84 -- +-----------------+
85 f.x = max.x + (max.w / 2)
86 f.y = max.y + (max.h / 2)
87 f.w = max.w/2
88 f.h = max.h/2
89 end
91hs.hotkey.bind(hyper, "Left", move_window("left"))
92hs.hotkey.bind(hyper, "Right", move_window("right"))
93hs.hotkey.bind(hyper, "Up", move_window("up"))
94hs.hotkey.bind(hyper, "Down", move_window("down"))
95hs.hotkey.bind(hyper, "[", move_window("upLeft"))
96hs.hotkey.bind(hyper, "\\", move_window("upRight"))
97hs.hotkey.bind(hyper, "'", move_window("downLeft"))
98hs.hotkey.bind(hyper, "home", move_window("downRight"))

With this, now we're able to move our app's window easily using hyperkey + (any direction). The other thing that we need to add is the ability to quickly make an app into fullscreen and resize it to screen-size. So let's add below code

1hs.hotkey.bind(hyper, "return", function()
2 -- +--------------+
3 -- | |
4 -- | HERE |
5 -- | |
6 -- +---------------+
7 local win = hs.window.focusedWindow();
8 if not win then return end
9 win:moveToUnit(hs.layout.maximized)
10 end)
12-- this one for fullscreen mode
13 hs.hotkey.bind(hyper, "f", function()
14 local win = hs.window.frontmostWindow()
15 win:setFullscreen(not win:isFullscreen())
16 end)

Now, give it a try, move your window around while reading this.

For me, this is productive and efficient enough for window management.

Launch Our Favorite Apps Quickly

We ain't got time to move our mouse to click or spotlight to search for apps that we love between our nice-to-have-but-barely-used apps. We also got no time for scrolling through tons of active applications to switch into the one that we want to focus on. A better way to deal with this is that with hammerspoon we can quickly launch or focus our favorite apps. It's just a couple of LOCs to enable this ability in our configuration. Let's add it

1-- these are only my favourite apps, you can replace it with yours
2local applicationHotkeys = {
3 c = 'Google Chrome',
4 t = 'iTerm',
5 s = 'Slack',
6 e = 'IntelliJ IDEA',
7 q = 'WebStorm',
8 j = 'Music',
9 i = 'Spark',
10 r = 'Reminders',
11 w = 'Bear',
12 d = 'Stocks'
15for key, app in pairs(applicationHotkeys) do
16 hs.hotkey.bind(hyper, key, function()
17 hs.application.launchOrFocus(app)
18 end)

How to use it: e.g. Google Chrome → Hyperkey + c and that's it, now no more tabs-cycling / apps-clicking / spotlight-search-typing. Awesome!


These are only nice-to-have configurations which I think worth mentioning

  • Check Network Connection Quickly (using Google DNS)
1function pingResult(object, message, seqnum, error)
2 if message == "didFinish" then
3 avg = tonumber(string.match(object:summary(), '/(%d+.%d+)/'))
4 if avg == 0.0 then
5"No network")
6 elseif avg < 200.0 then
7"Network good (" .. avg .. "ms)")
8 elseif avg < 500.0 then
9"Network poor(" .. avg .. "ms)")
10 else
11"Network bad(" .. avg .. "ms)")
12 end
13 end
16hs.hotkey.bind(hyper, "p", function()
17"", 1, 0.01, 1.0, "any", pingResult)

Use hyperkey + p to run it.

  • Lock Screen & Put your system to sleep
1-- this one for lock the screen
2hs.hotkey.bind(hyper, "l", function()
3 hs.caffeinate.lockScreen()
6-- this one is for putting the system to sleep
7hs.hotkey.bind(hyper, "z", function()
8 hs.caffeinate.systemSleep()

Hyperkey + l to lock the screen and Hyperkey + z to put the system to sleep
To summarize, we now have:

  • Window Control
  • Quick App Switcher
  • Browser Keyboard Only Mode

Beyond above, there are tons of uncovered karabiner-elements + hammerspoon potentials. So keep exploring its possibilities!

Spotlight Better Replacement

I guess most of you have known this great software, Alfred Not only this has most of the spotlight's features, but it does offer additional features and extensive workflows. Alfred has a huge potential if we tweak it to its limit, especially on the workflow part.

Alfred's Most Useful Features

By default, Alfred comes with very useful additional features beyond spotlight's features, including:

  • Websearch
  • Clipboard History
  • Terminal action
  • Of course, Music Control 🎵 (there's also a Spotify version) Alfred-Music-Control
    Apple Music Control on Alfred
  • etc

Alfred's Workflow

To empower its hidden abilities, we should go further into its workflow parts.

The essentials workflows to me that the community has offered are:

There are other nice-to-have workflows like Airpod & Reminder workflows etc. Spare your time to explore other workflows here


A very useful app is not complete without a beautiful UI, and I don't like Alfred's default theme to be honest.
Fortunately, there are tons of Alfred's themes offered by Alfred's community, but my solid choice would be Simple Dark by Sindre Sorhus

Super Power Browser

Let's admit it, browser is one of the crucial parts in our day to day activities on the laptop, and for this my choice of browser would be the most popular browser: Google Chrome. It's super fast and super extensive with the cons of RAM consumption sadly. But with what it offers is a really good trade-off in my opinion. So let's charge Chrome with these awesome extensions and configurations.


This extension lets us extend our keyboard-only mode by selecting different parts of the page and annotates it with a set of key combinations that we can use to determine which part we want to click/focus. Pretty awesome right?


Vimium in action

By default, to start vimium-state and open selected part (if link) we can either press f to do it on the current tab or shift + f to do it on a new tab. After that followed by annotation combination keys, you want to select. For the example above, selecting C would make it to focuses on the search bar and selecting A + M will follow the Wikipedia link for vimium.

Dark Reader

This extension is not related to our ultimate keyboard-only mode setup, but this is worth mentioning. Dark Reader, in the simplest definition (at least this is what I do with this extension) is an extension that lets you make any page to be in dark mode. It's a huge deal for me because sometimes my eyes can't stand again those lights coming up from bright sites and not every site has dark mode toggle right?

This is an example for above same Google search result for vimium keyword with Dark Reader


Dark Mode everywhere

It works perfectly on almost all pages. I recommend this one into your browser extension list.

Remote Desktop Chrome

Remote Desktop is essential to me when I'm AFK or too lazy to sit in front of my computer. I like to control it through my phone, and it gives me the ability to turn my phone into a remote control for my computer. So if you have some similar situations like me, then this extension is a good one to pick up.

Site Blocker

Chrome can help us to be more productive, but sometimes it's also a great source of distractions, it's like a two-edged sword. I found an extension to reduce the distractions, at least on chrome, it's Block Site.

This extensive works by blocking certain websites that you want to be blocked during your work mode or manually block it.

Session Box

It's a tedious work when you want to switch between your accounts in the same websites.
Wouldn't it be cool if we can have those sessions alive and switch between them easily?

Session Box is here to solve this kind of problem. It offers session grouping as well.


This section is mostly for developers who may need this, but it may apply for others to set up as well. So this is basically my terminal overview:


My terminal appearance

I'm using iTerm2 for my default MacOS' terminal replacement. I'm also using ZSH with OhMyZSH config, which is way better compared to default sh from MacOS.

For countless ZSH theme switching, I ended up with this gorgeous theme; PowerLevel10K


Intellij IDEA

Probably I'm not in the part of the widest open-source code editor, VSCode. Previously I was using it, but I felt like it lacked some features that I needed, for example, intelligent refactoring. That made me decided to move to IntelliJ by Jetbrain.

At first, I was having multiple jetbrain editors for each purpose and language. But then over time, it became more like bloated unused Editors rather than efficient. So I took research for a while, and I found that what I needed can be achieved with one Jetbrain's editor through plugins. My choice is IntelliJ IDEA. By default, it's more like a JVM-centric code editor.

Here are my top plugins for Intellij IDEA:

Other plugins are mostly programming language plugins & miscellaneous. Be careful to not bloat the IDE with unnecessary plugins, or its performance will suffer a lot.



This is my go-to password manager, it's free, rich features and well integrated across environments. For those who are into a password manager, I suggest going with LastPass both App and Extension

There is also an alfred's workflow for lastpass by Stuart Ryan


Most popular note-taking app out there is Evernote, but I don't like its complicated features and bloated stuff.
I prefer to have a simple, cheap, useful, efficient yet beautiful Note App; Bear.

Bear offers markdown-like syntax in its editor, so it's a developer-friendly note app. It offers tons of features that they mention in their sites, but the most useful features so far to me are:

  • Hashtag Organization (Can be multi-level nested hashtags) & Cross-Note Links


An example of Hashtag organization
  • Programming Language Syntax supports (over 150 Programming Languages)
  • Portability (export notes to various formats)
  • Well-integrated with Alfred (Bear workflow by drgrib)

That's it, my overall not so detailed Personal Mac Productivity Setup that to me has shifted my velocity of productivity. I admit that it's a quite long, complicated, and confusing article. This is my first article, so any feedback is appreciated.

if you found this article is useful, share it with others. Try to revisit it once in a while for my updated setup. Thanks for reading.

© 2021 by Alfian Dhimas.
Personal Site