macarchy

The tiling desktop from Linux, on the MacBook you already own. One command restyles the terminal, editor, status bar, window borders and wallpaper. Windows tile over native Spaces. Say what you want out loud and it happens. System Integrity Protection stays on.

retro-82
one theme, every app
$ theme-set retro-82

This mock, this page and your desktop read the same colors.sh. Press /, type theme-set, and watch them repaint together.

What macarchy is, and what it is not

macarchy is one Mac desktop config, published as is. It themes the apps in that setup and no others: Ghostty, Zellij, Neovim, SketchyBar, JankyBorders and the wallpaper. theme-set <name> repoints one symlink and pokes each of them to re-read its config, so they repaint together. yabai tiles windows inside each Space, skhd binds the keys, and alt+/ pops up a searchable list of every binding.

If your terminal is Kitty or your editor is VS Code, nothing here restyles it today. A theme directory has no file for those apps, so a switch leaves them alone. The mechanism is Omarchy’s and could drive more apps; that is the plan below. Your Ghostty, Zellij and Neovim configs stay yours, since macarchy hooks in with one line each.

Theming
23 themes, 5 of them light. theme-set, theme-pick, theme-next, theme-bg, theme-port, theme-new. docs/theme-system.md
Windows
yabai + skhd + SketchyBar + JankyBorders over native Spaces. No scripting addition, no csrutil. docs/window-management.md
Hotkey discovery
macarchy-keys: a which-key style popup on alt+/. Descriptions come from the # comments in skhdrc.
Raycast
A generated “Set Theme” script command. theme-raycast-sync regenerates it.
Workspace agent
ws: plain English or voice control of windows, Spaces, theme and Zellij tabs, on device. Talk to your desktop.
Planned
Theme files for other terminals (Alacritty, Kitty, WezTerm, iTerm2), editors (VS Code, Zed) and browsers, a pick-your-apps install, and light themes without hand fix-ups. None of it exists yet; the README keeps the list.
Requirements
macOS with Homebrew. Scripts run on the bash 3.2 that ships with the system.
Licence
MIT.

Install macarchy

Two routes, depending on how you already manage dotfiles. Either way, one step stays manual: macOS makes you grant Accessibility permission by hand.

Full README

Clone and run the installer

install.sh bootstraps Homebrew, installs the packages, sets a handful of macOS defaults, links home/ into $HOME (with stow if it is on PATH, otherwise plain symlinks), seeds the default theme, generates wallpapers and writes ~/.config/macarchy/config from the example. It is idempotent, so re-running is safe.

sh
$ git clone https://github.com/jlargs64/macarchy ~/Projects/macarchy
$ cd ~/Projects/macarchy
$ ./install.sh --dry-run   # prints every action, changes nothing
$ ./install.sh

Only want the files linked, no packages or defaults? stow -t "$HOME" home.

Or let an agent walk you through it

sh
$ curl -fsSL https://raw.githubusercontent.com/jlargs64/macarchy/main/install-agent.sh \
    | sh -s -- claude   # or codex, pi, opencode, gemini, copilot, cursor, amp

Launches that agent CLI interactively, seeded with AGENT-INSTALL.md, which walks through the same steps. It still asks before it runs anything. No agent installed? install-agent.sh --print dumps the prompt to paste into any chat agent instead.

Or pull it into chezmoi

If your dotfiles live in chezmoi, add macarchy as a tagged archive external rather than a submodule. One entry per directory, eight in total; stripComponents = 2 strips macarchy-0.1.0/home/ off every path.

.chezmoiexternal.toml · one of eight
[".config/theme"]
    type = "archive"
    url = "https://github.com/jlargs64/macarchy/archive/refs/tags/v0.1.0.tar.gz"
    exact = true
    stripComponents = 2
    include = [".config/theme/**"]

chezmoi only writes files. After the first chezmoi apply, run ~/.config/theme/bin/theme-maintain once by hand. Homebrew packages and defaults are yours to run too, or copy those blocks out of install.sh.

Pick a theme, change everything

Every app reads its colours from ~/.config/theme/current, a symlink. Switching repoints it and nudges each app; no app knows a theme’s name. 23 ship, 5 of them light. Pick one here and this page repaints the same way.

Port another

shift+alt+/ opens theme-pick, an fzf picker with a swatch strip per theme and a picture of its background above the palette. alt+b opens theme-bg-pick, the current theme’s backgrounds with a picture of each, Omarchy-style; Enter applies it. The pictures are drawn by theme-img with chafa over the Kitty graphics protocol in Ghostty (kitty and WezTerm too), iTerm2’s own protocol in iTerm2, and unicode blocks anywhere else. shift+alt+t cycles themes and shift+alt+b cycles the wallpaper within one; the choice is remembered per theme.

The wallpaper follows the theme on every Space. macOS stores it per Space, so every Space points at one fixed file and a switch rewrites the file. A new Space enrolls itself the first time you land on it: yabai runs theme-wallpaper-enroll --here on each Space switch, which points only the desktops on screen at the file and does nothing when they already are. Without yabai, run theme-wallpaper-enroll once by hand instead. theme-port <name> brings in anything else from Omarchy’s catalogue. Light themes need --allow-light and a look afterwards: the SketchyBar and border colour maths were written for dark backgrounds.

Drive the windows

alt focuses and queries. shift+alt moves and mutates. alt+/ lists every binding when you forget one. alt+letter is left free for your app launchers.

Focus, move, resize

alt - h / j / k / l
focus window west / south / north / east
shift + alt - h / j / k / l
warp window in that direction
ctrl + alt - h / l
shrink / grow horizontally
ctrl + alt - j / k
grow / shrink vertically
alt + drag
left-drag moves, right-drag resizes

Everything else

shift + alt - t
cycle the desktop theme
shift + alt - b
cycle the wallpaper within the current theme
shift + alt - /
pop up theme-pick, an fzf theme picker with swatches and a picture of each background
alt - b
pop up theme-bg-pick, the current theme's backgrounds with pictures
shift + alt - r
macarchy-restart: yabai, then borders, then the bar, then skhd, in that order
alt - /
pop up macarchy-keys
ctrl - number
switch Space (native macOS, enable it under Keyboard Shortcuts › Mission Control)

Layout

alt - =
balance the tree
alt - s
toggle the Space between bsp (tiled) and stack
alt - [ / alt - ]
focus previous / next window in the stack
shift + alt - s
next new window stacks onto this one
shift + alt - e / d
next new window splits right / below
alt - r
rotate layout 90°
alt - g
toggle float, centred on a 4×4 grid
alt - f
zoom to fullscreen within the tile tree
alt - c
center the window in a column with gutters; again to put it back
shift + alt - f
native macOS fullscreen
alt - v
flip split orientation

Talk to your desktop

Say what you want done to the desktop in plain words, and a 14 MB on-device model turns it into yabai, Zellij and theme commands. Nothing leaves the machine.

Dry run is the default. ws prints what it would do until MACARCHY_AGENT_EXECUTE=true is set in ~/.config/macarchy/config. The pipeline, the tool list and how to add a tool are in docs/agent.md.

sh
# prints what it would run
$ ws "put slack on space 2 and switch to the kanagawa theme"
# runs it
$ ws -x "focus helium"
# alt - w: press to listen, press again to run
$ ws --voice

By voice

alt - w
press once to start listening, again to stop. Handy transcribes offline and ws prints or runs the result
alt - space
Handy’s own dictation hotkey for typing anywhere: hold to talk, tap to toggle. Set inside Handy, not skhd

Make it yours

A config file, a six-file theme contract, and a porter for anything in Omarchy’s catalogue that is not here yet.

Config

~/.config/macarchy/config is copied from the example on first install. Edit it and re-run theme-set or theme-raycast-sync, or restart SketchyBar, as relevant. Nothing needs a reinstall.

~/.config/macarchy/config
MACARCHY_DEFAULT_THEME=retro-82   # theme-set with no argument, and the seed on first install
MACARCHY_FONT="Hack Nerd Font"    # SketchyBar icon/label font
MACARCHY_SPACES=9                 # highest Space number the bar draws (1-9, global across displays)
MACARCHY_RAYCAST_AUTHOR=""        # @raycast.author line; blank omits it
MACARCHY_WIFI_IFACE=en0           # interface the wifi bar plugin reads
Layout

Gaps, padding, the bar strip and the border are settings in the same file, not edits to yabairc. All pixels; the defaults are in lib.sh, so a line you delete falls back to them. yabairc, bordersrc and sketchybarrc all read them.

SettingDefaultMeaning
MACARCHY_GAP8gap between tiled windows
MACARCHY_PADDING_TOP8gap under the bar
MACARCHY_PADDING_BOTTOM20gap above the screen edge; bigger than the rest because the border draws outside the window
MACARCHY_PADDING_LEFT / _RIGHT8side gaps (a centered column adds its own, see Wide displays)
MACARCHY_BAR_HEIGHT32SketchyBar strip; yabai reserves the same height at the top of every display (external_bar)
MACARCHY_BORDER_WIDTH6JankyBorders focus border
MACARCHY_BORDER_STYLEroundround or square
MACARCHY_CENTER_WIDTH16:10centered column width, as an aspect ratio relative to the display height or a pixel count (2200)
MACARCHY_CENTER_SINGLEtruecenter a lone window automatically; false leaves only alt+c

After a change, restart what reads them:

sh
$ yabai --restart-service; brew services restart borders; sketchybar --reload

Or shift+alt+r, which runs macarchy-restart for all of them.

Add a theme

A theme is a directory under ~/.config/theme/themes/<name>/ with the six files shown above. Copy an existing theme, edit, then theme-set <name> and theme-raycast-sync. colors.sh exports bare hex, no # and no 0x.

colors.sh
export THEME_NAME=<name>
export NVIM_COLORSCHEME=<name neovim's :colorscheme accepts>
export BG=......      export FG=......      export ACCENT=......
export ACCENT2=......  export MUTED=......
export RED=......     export GREEN=......   export YELLOW=......
export BLUE=......    export MAGENTA=......  export CYAN=......
Make your own

theme-new <name> copies the active theme’s colors.sh under a new name and generates everything else from it, Neovim included. Edit the 11 colours, rebuild, switch.

sh
$ theme-new mine
$ $EDITOR ~/.config/theme/themes/mine/colors.sh
$ theme-new --regen mine
$ theme-set mine
Port one from Omarchy

theme-port <name> fetches an Omarchy theme’s colors.toml and neovim.lua and writes the macarchy files from them. --src DIR reads a local Omarchy checkout instead. Light themes need --allow-light. Two outputs deserve a human look afterwards: ACCENT2 is a heuristic, and a theme with no upstream Neovim plugin gets a placeholder to fill in.

sh
$ theme-port everforest
$ theme-set everforest

When something looks wrong

  • Start with macarchy-doctor. It checks every component you installed, packages, permissions, services and the theme state, and prints a fix line under each failure. It is read-only and never starts or installs anything; --quiet prints only warnings and failures, and the exit status is 1 when something failed.
  • Hotkeys stopped landing. skhd stops receiving hotkeys while an app has secure keyboard entry on, which a password field turns on and some terminals keep on. macarchy-doctor reports which app has it.
  • Something is stuck. shift+alt+r runs macarchy-restart: yabai, then borders, then the bar, then skhd, in that order.
  • A window ended up off every display. macarchy-rescue pulls it back onto the focused one.
  • An app opens but shows no window after a monitor comes back or the Mac wakes. yabai kept a window it can no longer move, and the app keeps showing it. A notification names the app; macarchy-rescue --relaunch quits and reopens it.
  • Ghostty shows a “Configuration Errors” dialog after a switch. The theme’s ghostty fragment names a theme Ghostty does not have. Names are exact: Catppuccin Mocha, not catppuccin-mocha. Check with ghostty +list-themes.
  • Space indicators look wrong after a reboot. mru-spaces must stay off; the installer sets it. yabai and the bar both assume Space N stays Space N.
  • Switching Spaces feels floaty. The installer already halves the slide to 0.1s. The stronger option is System Settings › Accessibility › Display › Reduce Motion, left off by default because it flattens animations system-wide.
  • Neovim did not repaint. Its server socket is under $TMPDIR on macOS, not /tmp. theme-set searches both. If the theme reports a different g:colors_name (kanagawa reports kanagawa), the colours are still correct.
sh
$ macarchy-doctor                             # every component, a fix line per failure
$ macarchy-restart                            # yabai, borders, the bar, skhd
$ macarchy-rescue                             # off-display windows, back onto this one
$ macarchy-rescue --relaunch                  # and reopen an app whose window will not move
$ readlink ~/.config/theme/current            # which theme is active
$ ghostty +show-config 2>&1 >/dev/null        # theme-name errors show here
$ nvim --headless -c 'lua print(vim.g.colors_name) vim.cmd("qa!")'
$ sketchybar --query bar | jq .color          # expect 0xff<BG>
$ tail /tmp/yabai_$USER.err.log
esc
↑ ↓ move↵ runesc close