I’ve recently started a new job and am setting up a MacBook Pro M4. I’ve been using either a native Linux Desktop, or a Linux Desktop as a VM on a Windows box for most of my career. There are a number things about the Mac that are different than Intel based machines running Linux following are the list of changes that I have made to make it usable as a development environment.
Show all files in an “Open” dialog box
Press Cmd + Shift + .
Set system time to UTC
sudo ln -sf /usr/share/zoneinfo/UTC /etc/localtime
To display time in seconds go to System Settings > Menu Bar > Clock and select “Display the time with seconds”
If you also want to display a clock that shows your local time install Clocker.
Disable the Mission Control space-switching hotkeys
These four shortcuts are what stop Ctrl+Left and Ctrl+Right ever reaching an application.
┌─────┬──────────────────┬────────────────────┐
│ ID │ Shortcut │ macOS action │
├─────┼──────────────────┼────────────────────┤
│ 79 │ Ctrl+Left │ Move left a space │
├─────┼──────────────────┼────────────────────┤
│ 80 │ Ctrl+Shift+Left │ Move left a space │
├─────┼──────────────────┼────────────────────┤
│ 81 │ Ctrl+Right │ Move right a space │
├─────┼──────────────────┼────────────────────┤
│ 82 │ Ctrl+Shift+Right │ Move right a space │
└─────┴──────────────────┴────────────────────┘
# Run the following in a terminal:
for id in 36 37 79 80 81 82; do
defaults write com.apple.symbolichotkeys AppleSymbolicHotKeys -dict-add "$id" '<dict><key>enabled</key><false/></dict>'
done
/System/Library/PrivateFrameworks/SystemAdministration.framework/Resources/activateSettings -u
# Run the following to verify it
defaults read com.apple.symbolichotkeys AppleSymbolicHotKeys | grep -A2 -E '^\s+(36|37|79|80|81|82) ='
# The previous command should output the following:
36 = {
enabled = 0;
};
37 = {
enabled = 0;
};
79 = {
enabled = 0;
};
80 = {
enabled = 0;
};
81 = {
enabled = 0;
};
82 = {
enabled = 0;
};
Disable the “Press and Hold” Feature
By default, holding down a given key will display a pop-up/tooltip that displays accented version of the given character. I use a Vim plugin with the IDEs that I use and when trying to navigate by holding down either the w or b chars the cursor only moves by one work and then shows an accented character. To disable it
- Run the following command in a terminal and then restarting applications. This turns off the feature that will show accented characters:
defaults write -g ApplePressAndHoldEnabled -bool false
- Turn up the Key Repeat rate by going to
System Setting > Keyboard and adjust the slider for the “Key repeat rate”. If this still feels too slow you can crank it up with the following terminal settings which enable values much lower than the UI allows to be set
# Sets a very short delay before repeating
defaults write -g InitialKeyRepeat -int 15
# Sets a very fast repeat rate
defaults write -g KeyRepeat -int 2
Configuring Home and End Keys
This is configuration for Safari, Mail, Notes and most other native, Cocoa based applications.
- Create the following directory:
mkdir -p ~/Library/KeyBindings
- Create and edit the binding file
vi ~/Library/KeyBindings/DefaultKeyBinding.dict
- Paste the following content into it
{
"\UF729" = "moveToBeginningOfLine:";
"\UF72B" = "moveToEndOfLine:";
"$\UF729" = "moveToBeginningOfLineAndModifySelection:";
"$\UF72B" = "moveToEndOfLineAndModifySelection:";
"^\UF702" = "moveWordLeft:";
"^\UF703" = "moveWordRight:";
"^$\UF702" = "moveWordLeftAndModifySelection:";
"^$\UF703" = "moveWordRightAndModifySelection:";
"^\U007F" = "deleteWordBackward:";
"^\UF728" = "deleteWordForward:";
}
Then save and close that file and restart applications and/or restart the Mac.
iTerm2 Specific Configurations
Configure Home and End keys to work properly
- Go to Settings > Profiles > Keys > Key Bindings and click the + at the bottom left.
- For the Home Key:
- Keyboard Shortcut: Press your physical Home key.
- Action: Select Send Hex Code.
- Code:
0x01 (This is the hex for Ctrl+A).
- For the End Key:
- Keyboard Shortcut: Press your physical End key.
- Action: Select Send Hex Code.
- Code:
0x05 (This is the hex for Ctrl+E).
Using ghostty
I am giving ghostty a try as it plays nice with herdr. Following are my configurations for it.
This is dependent on disabling the Mission Control hotkeys as described above.
~/.zshrc Entries
# Word motion and word delete on the Ctrl keys, the Linux terminal
# convention. zsh ships no binding for any of these sequences, so the keys
# do nothing until bound here. ^[[1;5D is Ctrl+Left, ^[[1;5C is Ctrl+Right
# and ^[[3;5~ is Ctrl+Delete.
bindkey "^[[1;5D" backward-word
bindkey "^[[1;5C" forward-word
bindkey "^[[3;5~" kill-word
ghostty config file
Write the following config into ~/.config/ghostty/config and restart ghostty
# Home and End emit ESC[H and ESC[F by default. Send the control characters
# that readline and the zsh line editor act on directly instead: 0x01 is
# Ctrl-A, beginning of line, and 0x05 is Ctrl-E, end of line.
keybind = home=text:\x01
keybind = end=text:\x05
# Alt plus a delete key removes a whole word. ESC d is the readline
# kill-word function, which deletes forward from the cursor. 0x1b 0x7f is ESC
# followed by DEL, which readline binds to backward-kill-word.
keybind = alt+delete=esc:d
keybind = alt+backspace=text:\x1b\x7f
# Let these Cmd keys reach Herdr and Neovim.
keybind = super+t=unbind
keybind = super+w=unbind
keybind = super+k=unbind
keybind = super+e=unbind
keybind = super+shift+g=unbind
# Look and feel
background = #14151c
foreground = #FDFDFD
font-size = 14
cursor-style = bar
cursor-style-blink = false
scrollback-limit = 100000
# Option sends Alt rather than composing a Unicode character, so Alt+B and
# Alt+F reach the shell as ESC b and ESC f. Readline binds those to
# backward-word and forward-word.
macos-option-as-alt = true
palette = 0=#282A2B
palette = 1=#F3977F
palette = 2=#5ADECD
palette = 3=#F272A2
palette = 4=#886F97
palette = 5=#C574DD
palette = 6=#79E6F3
palette = 7=#FDFDFD
palette = 8=#415844
palette = 9=#FF4971
palette = 10=#18E3C8
palette = 11=#FF8037
palette = 12=#556FFF
palette = 13=#B0D143
palette = 14=#3FDCEE
palette = 15=#BEBEC1
# Draw the line between splits in a color that stands off the background,
# rather than the near-background default that is hard to pick out.
split-divider-color = #3f435e
# Fade inactive splits harder than the 0.7 default, so the focused split is
# obvious at a glance.
unfocused-split-opacity = 0.5
# Widen the gap between the text and the split edge, so each pane reads as
# its own block instead of text running up against the divider.
window-padding-x = 6
window-padding-y = 4
# ---------------------------------------------------------------------------
# Linux terminal key conventions.
#
# Linux terminals keep bare Ctrl for control codes and put application
# shortcuts on Ctrl+Shift. The Cmd bindings Ghostty ships stay in place, so
# both conventions work.
# ---------------------------------------------------------------------------
# Clipboard. Bare Ctrl+C has to stay SIGINT, which is why Linux puts copy on
# Ctrl+Shift+C.
keybind = ctrl+shift+c=copy_to_clipboard
keybind = ctrl+shift+v=paste_from_clipboard
keybind = ctrl+shift+a=select_all
# Tabs and windows.
keybind = ctrl+shift+t=new_tab
keybind = ctrl+shift+n=new_window
keybind = ctrl+shift+w=close_surface
keybind = ctrl+shift+q=quit
# Tab cycling. Ctrl plus a page key moves between tabs. Adding Shift moves the
# current tab itself along the tab bar.
keybind = ctrl+page_up=previous_tab
keybind = ctrl+page_down=next_tab
keybind = ctrl+shift+page_up=move_tab:-1
keybind = ctrl+shift+page_down=move_tab:1
# Find. Ctrl+Shift+G is find-next and Ctrl+Shift+H is find-previous. These also
# restore search, which the super+e and super+shift+g unbinds above gave up.
keybind = ctrl+shift+f=start_search
keybind = ctrl+shift+g=navigate_search:next
keybind = ctrl+shift+h=navigate_search:previous
# Font size. Ctrl+= and Ctrl++ both grow the font, because the plus sign needs
# Shift on a US layout and either form can arrive here.
keybind = ctrl+==increase_font_size:1
keybind = ctrl++=increase_font_size:1
keybind = ctrl+-=decrease_font_size:1
keybind = ctrl+0=reset_font_size
# Scrollback. Ghostty binds Shift plus a page key to extend the selection.
# Linux terminals scroll with them instead.
keybind = shift+page_up=scroll_page_up
keybind = shift+page_down=scroll_page_down
keybind = f11=toggle_fullscreen
# Splits, following Terminator. Ctrl+Shift+E splits side by side and
# Ctrl+Shift+O stacks one split above the other.
keybind = ctrl+shift+e=new_split:right
keybind = ctrl+shift+o=new_split:down
# Ctrl+Backspace has no standard terminal sequence, unlike Ctrl+Left,
# Ctrl+Right and Ctrl+Delete, which .zshrc binds by their sequences. Emit
# ESC DEL, which zsh already binds to backward-kill-word.
keybind = ctrl+backspace=text:\x1b\x7f
# Move between splits with Alt and an arrow. This replaces Ghostty's default
# alt+arrow_left and alt+arrow_right, which sent ESC b and ESC f for word
# motion. Word motion stays on Alt+B and Alt+F, which zsh binds natively, and
# on the Ctrl arrows bound in .zshrc.
keybind = alt+arrow_left=goto_split:left
keybind = alt+arrow_right=goto_split:right
keybind = alt+arrow_up=goto_split:up
keybind = alt+arrow_down=goto_split:down
# Highlight to copy, middle-click to paste, the X11 primary selection
# workflow. macOS has no separate selection clipboard, so both ends route
# through the system clipboard, and highlighting text overwrites whatever was
# last copied. The primary-paste and primary values these replace are
# documented as having no effect on macOS.
copy-on-select = clipboard
middle-click-action = clipboard-paste
# Advertise a terminal type every remote host already knows. Ghostty's own
# xterm-ghostty record exists only inside the app bundle, at
# Contents/Resources/terminfo, and ssh forwards TERM but not TERMINFO. A
# remote shell given xterm-ghostty therefore finds no record and loses arrow
# keys, color and the alternate screen. The xterm prefix is still required,
# because vim keys off it to enable modifyOtherKeys.
term = xterm-256color
Configure F-keys to work without pressing fn
- Open System Setting > Keyboard and click on Keyboard shortcuts
- Click on Function Keys in the left-hand nav
- Toggle the Use F1, F2, etc. keys as standard function keys
Getting Alt-Tab to Switch Applications
Download and install the AltTab application.
Configuring Primary Selection and Middle Click Paste
One of the things that I use all of the time under Linux is to select text and then middle-click to paste it. This is one of those Linux features that once you get used to, you just have to have.
Configure iTerm2
- Open iTerm2 settings
- Go to General > Selections
- Check the box “Applications in terminal may access clipboard”
- Check the box “Copy to clipboard on selection”
- Go to Pointer > Bindings
- If “Middle Button” is not there, click the “+” button at the bottom of the window
- Set the following
- Button/Gesture: Middle Button
- Click Type: Single Click
- Action: Paste from Selection…: There are a whole host of additional options from there that you can choose from. I left the default settings.
Screenshots
Configure the OS to write screenshots to a specific directory
# Set the new location
mkdir -p $HOME/Pictures/Screenshots
defaults write com.apple.screencapture location $HOME/Pictures/Screenshots
# Apply the changes (restarts the UI server)
killall SystemUIServer
Additional brew Packages
Helpful Keyboard Shortcuts
- Enter a path to a file in a dialog box: By default, Mac makes you click everything. Many times you know exactly where the file is on the filesystem and you just want to type it in and hit
Enter. To do so, you need to open the dialog box and then press Command + Shift + G and then you can enter the path to the file.
- View hidden files and directories in a dialog box: By default, Mac always hides “dotfiles” and directories in a dialog box. To see them open the dialog box and then press
Command + Shift + Period.
Development SDKs
Installing Go
Initially, I just went with brew install go, but this turned into a big mess. While working on a project where I was writing a K8s Custom Resource Definition I ran into a buzz saw of mismatched versions and edge cases with the Apple Silicon/ARM architectural problems with the go development toolchain.
Instead of using brew for the go SDK
- Download the
.tar.gz file from https://go.dev/dl/ for your architecture
- Unpack it, rename the
go directory go1.x.x and move the directory to /usr/local/
- Create a symlink,
/usr/local/go to point to the version specific go directory
- Ensure that
/usr/local/go/bin is in your PATH
- Install any other required go libraries with
go install or by downloading the binaries and putting them in your $GOPATH
go install golang.org/x/tools/gopls@latest
go install github.com/go-delve/delve/cmd/dlv@latest