Welcome to Yashiki! This guide will help you get up and running with your new tiling window manager.
- Prerequisites
- Installation
- Granting Accessibility Permission
- Understanding Core Concepts
- Creating Your First Config
- Starting Yashiki
- Your First Workflow
- Config Examples
- Common Issues
- Next Steps
- macOS 12.0 (Monterey) or later
- Homebrew (recommended for installation)
brew tap typester/yashiki
brew install --cask yashikiImportant: Yashiki.app is not notarized (ad-hoc signed). macOS will show a warning on first launch. You have two options:
-
After installation: Go to System Settings → Privacy & Security, scroll down, and click "Open Anyway" when prompted.
-
During installation: Install with the
--no-quarantineflag to skip the warning:brew install --cask --no-quarantine yashiki
The cask installs:
Yashiki.appto/Applications- CLI tools:
yashiki,yashiki-layout-tatami,yashiki-layout-byobu
If you have Rust installed, you can install from crates.io:
# Core daemon and CLI
cargo install yashiki
# Install the layout engines you want to use
cargo install yashiki-layout-tatami # Master-stack layout
cargo install yashiki-layout-byobu # Accordion layoutYashiki needs Accessibility permission to manage windows. This is a one-time setup.
Go to System Settings → Privacy & Security → Accessibility
If you installed via Homebrew:
- Click the + button
- Navigate to
/Applications/and select Yashiki.app - Toggle the switch to enable it
If you're running yashiki start from terminal (development only):
- Add your terminal app (e.g., Terminal, iTerm2, Ghostty) instead
- This is not recommended for regular use
After adding, you should see Yashiki.app (or your terminal) listed with the toggle enabled.
Before diving into configuration, let's understand the key concepts that make Yashiki different from other window managers.
Most window managers use numbered workspaces where each window belongs to exactly one workspace. Yashiki uses tags (inspired by dwm/awesomewm/river):
| Traditional Workspaces | Yashiki Tags |
|---|---|
| Window belongs to one workspace | Window can have multiple tags |
| View one workspace at a time | View any combination of tags |
| Switch workspaces | Toggle tags on/off |
The Bitmask System
Tags are represented as bits in a number (bitmask):
| Tag | Bitmask | Binary | Shell Expression |
|---|---|---|---|
| Tag 1 | 1 |
001 |
$((1<<0)) |
| Tag 2 | 2 |
010 |
$((1<<1)) |
| Tag 3 | 4 |
100 |
$((1<<2)) |
| Tag 4 | 8 |
1000 |
$((1<<3)) |
| Tags 1+2 | 3 |
011 |
View both tags simultaneously |
| Tags 1+3 | 5 |
101 |
View tags 1 and 3 together |
This allows powerful operations like viewing multiple tags at once or assigning a window to multiple tags.
Unlike native macOS Spaces, Yashiki uses virtual workspaces:
- All windows exist on a single macOS Space
- "Hiding" a window moves it off-screen (to the bottom-right corner)
- No SIP disable required
- Switching tags is instant (no sliding animation)
This approach has tradeoffs:
- Pros: Fast, no SIP disable, works with all apps
- Cons: Mission Control shows all windows, Cmd+Tab shows all apps
Yashiki uses external layout engines (like river) instead of built-in layouts:
- tatami: Master-stack layout (one main window + stack)
- byobu: Accordion layout (stacked windows with stagger)
Layout engines are separate processes that communicate via JSON, so you can even write your own in any language.
Tatami Layout (Master-Stack)
+------------------+--------+
| | 2 |
| +--------+
| 1 | 3 |
| (main) +--------+
| | 4 |
+------------------+--------+
Byobu Layout (Accordion)
+--+--+--+------------------+
| | | | |
|1 |2 |3 | 4 |
| | | | (focused) |
| | | | |
+--+--+--+------------------+
Unlike traditional config files, Yashiki's configuration is an executable file that runs when the daemon starts:
- Config file:
~/.config/yashiki/init - Any executable works: shell script, Python, Ruby, compiled binary, etc.
- The executable runs CLI commands like
yashiki bind ...to configure the daemon - Changes take effect after restarting the daemon
Most users write shell scripts, but you can use any language you prefer:
#!/usr/bin/env python3
import subprocess
for i in range(1, 10):
subprocess.run(["yashiki", "bind", f"alt-{i}", "tag-view", str(1 << (i-1))])Let's create a minimal but functional configuration.
mkdir -p ~/.config/yashikiCreate ~/.config/yashiki/init:
#!/bin/sh
# Layout configuration
yashiki layout-set-default tatami
yashiki set-outer-gap 10
yashiki layout-cmd --layout tatami set-inner-gap 8
# Tag bindings: alt-1 through alt-9 switch to tags 1-9
# alt-shift-1 through alt-shift-9 move windows to tags 1-9
for i in 1 2 3 4 5 6 7 8 9; do
yashiki bind "alt-$i" tag-view "$((1<<(i-1)))"
yashiki bind "alt-shift-$i" window-move-to-tag "$((1<<(i-1)))"
done
# Window focus (vim-style)
yashiki bind alt-j window-focus next
yashiki bind alt-k window-focus prev
# Layout adjustment
yashiki bind alt-h layout-cmd dec-main-ratio
yashiki bind alt-l layout-cmd inc-main-ratio
# Window management
yashiki bind alt-f window-toggle-fullscreen
yashiki bind alt-shift-f window-toggle-float
yashiki bind alt-shift-c window-close
# Multi-monitor
yashiki bind alt-o output-focus next
yashiki bind alt-shift-o output-send nextchmod +x ~/.config/yashiki/initLet's break down what each section does:
Layout Setup
yashiki layout-set-default tatami # Use tatami as the default layout
yashiki set-outer-gap 10 # 10px gap between windows and screen edges
yashiki layout-cmd --layout tatami set-inner-gap 8 # 8px gap between windowsTag Bindings (the loop)
for i in 1 2 3 4 5 6 7 8 9; do
yashiki bind "alt-$i" tag-view "$((1<<(i-1)))"
yashiki bind "alt-shift-$i" window-move-to-tag "$((1<<(i-1)))"
doneThis loop creates 18 bindings:
alt-1switches to tag 1,alt-2to tag 2, etc.alt-shift-1moves the focused window to tag 1, etc.
The expression $((1<<(i-1))) calculates the bitmask: when i=1, it's 1<<0=1; when i=2, it's 1<<1=2; when i=3, it's 1<<2=4, and so on.
If you installed via Homebrew, simply open Yashiki.app from /Applications or Spotlight.
The app will:
- Start the daemon
- Execute your init script
- Begin managing windows
Open a terminal and run:
yashiki list-windowsYou should see a list of your open windows with their IDs, titles, and tags.
yashiki list-bindingsThis shows all hotkeys you've configured.
Now let's try out the basic operations. Open a few windows (e.g., Terminal, Safari, Finder) to practice.
With multiple windows on the same tag:
- Press
alt-jto focus the next window - Press
alt-kto focus the previous window
The windows should tile automatically in the tatami (master-stack) layout.
- Press
alt-hto decrease the main area ratio (make it smaller) - Press
alt-lto increase the main area ratio (make it larger)
- Focus a window you want to move
- Press
alt-shift-2to move it to tag 2 - Press
alt-2to switch to tag 2 and see the window
- Press
alt-fto make the focused window fullscreen - Press
alt-fagain to return to tiled mode
This is tiling-style fullscreen within the current Space, not macOS native fullscreen (which creates a separate Space).
- Press
alt-shift-fto toggle floating mode on the focused window - Floating windows can be moved and resized freely
- They're excluded from the tiling layout
- Press
alt-oto focus the next monitor - Press
alt-shift-oto send the focused window to the next monitor
Each monitor has its own set of visible tags.
Here are progressively more advanced configurations.
The bare minimum to get started:
#!/bin/sh
yashiki layout-set-default tatami
for i in 1 2 3 4 5 6; do
yashiki bind "alt-$i" tag-view "$((1<<(i-1)))"
done
yashiki bind alt-j window-focus next
yashiki bind alt-k window-focus prevA balanced configuration for daily use:
#!/bin/sh
# Layout
yashiki layout-set-default tatami
yashiki set-outer-gap 10
yashiki layout-cmd --layout tatami set-inner-gap 10
# Cursor warp (mouse follows focus)
yashiki set-cursor-warp on-focus-change
# Auto-raise (focus follows mouse) - with 100ms delay to avoid accidental focus changes
yashiki set-auto-raise enabled --delay 100
# Tags
for i in 1 2 3 4 5 6 7 8 9; do
yashiki bind "alt-$i" tag-view "$((1<<(i-1)))"
yashiki bind "alt-shift-$i" window-move-to-tag "$((1<<(i-1)))"
done
yashiki bind alt-0 tag-view-last
# Window focus
yashiki bind alt-j window-focus next
yashiki bind alt-k window-focus prev
yashiki bind alt-h layout-cmd dec-main-ratio
yashiki bind alt-l layout-cmd inc-main-ratio
yashiki bind alt-comma layout-cmd inc-main-count
yashiki bind alt-period layout-cmd dec-main-count
# Window management
yashiki bind alt-f window-toggle-fullscreen
yashiki bind alt-shift-f window-toggle-float
yashiki bind alt-shift-c window-close
yashiki bind alt-z layout-cmd zoom
# Multi-monitor
yashiki bind alt-o output-focus next
yashiki bind alt-shift-o output-send next
# Common float rules
yashiki rule-add --app-name Finder float
yashiki rule-add --app-name "System Settings" float
yashiki rule-add --subrole Dialog floatFull-featured configuration with multiple layouts and advanced rules:
#!/bin/sh
# Extend PATH for custom layout engines
yashiki add-exec-path /opt/homebrew/bin
# Layout configuration
yashiki layout-set-default tatami
yashiki layout-set --tags 4 byobu # Tag 3 uses byobu
yashiki set-outer-gap 8
yashiki layout-cmd --layout tatami set-inner-gap 8
yashiki layout-cmd --layout byobu set-padding 40
# Cursor warp
yashiki set-cursor-warp on-focus-change
# Auto-raise (focus follows mouse)
yashiki set-auto-raise enabled --delay 100
# Tags (all 9 tags)
for i in 1 2 3 4 5 6 7 8 9; do
yashiki bind "alt-$i" tag-view "$((1<<(i-1)))"
yashiki bind "alt-shift-$i" window-move-to-tag "$((1<<(i-1)))"
yashiki bind "alt-ctrl-$i" window-toggle-tag "$((1<<(i-1)))"
done
yashiki bind alt-0 tag-view-last
yashiki bind alt-tab tag-view-last
# Window focus (vim + directional)
yashiki bind alt-j window-focus next
yashiki bind alt-k window-focus prev
yashiki bind alt-left window-focus left
yashiki bind alt-right window-focus right
yashiki bind alt-up window-focus up
yashiki bind alt-down window-focus down
# Layout controls
yashiki bind alt-h layout-cmd dec-main-ratio
yashiki bind alt-l layout-cmd inc-main-ratio
yashiki bind alt-comma layout-cmd inc-main-count
yashiki bind alt-period layout-cmd dec-main-count
yashiki bind alt-z layout-cmd zoom
yashiki bind alt-i layout-cmd inc-inner-gap
yashiki bind alt-shift-i layout-cmd dec-inner-gap
# Window management
yashiki bind alt-f window-toggle-fullscreen
yashiki bind alt-shift-f window-toggle-float
yashiki bind alt-shift-c window-close
yashiki bind alt-return retile
# Multi-monitor
yashiki bind alt-o output-focus next
yashiki bind alt-shift-o output-send next
# App launchers
yashiki bind alt-shift-return exec "open -n /Applications/Ghostty.app"
yashiki bind alt-s exec-or-focus --app-name Safari "open -a Safari"
yashiki bind alt-c exec-or-focus --app-name "Google Chrome" "open -a 'Google Chrome'"
# Keybinding modes (river-style)
yashiki declare-mode resize
yashiki declare-mode passthrough
# Enter resize/passthrough mode
yashiki bind alt-r enter-mode resize
yashiki bind alt-p enter-mode passthrough
# Resize mode: h/j/k/l to adjust layout, escape/return to exit
yashiki bind --mode resize h layout-cmd dec-main-ratio
yashiki bind --mode resize l layout-cmd inc-main-ratio
yashiki bind --mode resize j layout-cmd dec-main-count
yashiki bind --mode resize k layout-cmd inc-main-count
yashiki bind --mode resize escape enter-mode normal
yashiki bind --mode resize return enter-mode normal
# Passthrough mode: all keys pass through, alt-p to exit
yashiki bind --mode passthrough alt-p enter-mode normal
# Companion tools (terminated on yashiki quit)
yashiki exec --track "borders active_color=0xffe1e3e4"
# Window rules - Float dialogs and utilities
yashiki rule-add --app-name Finder float
yashiki rule-add --app-name "System Settings" float
yashiki rule-add --app-name "System Preferences" float
yashiki rule-add --subrole Dialog float
yashiki rule-add --subrole FloatingWindow float
yashiki rule-add --fullscreen-button none float
# Window rules - Ignore popups (prevents flickering)
yashiki rule-add --subrole AXUnknown ignore
yashiki rule-add --close-button none ignore
# Window rules - App-specific
yashiki rule-add --app-name Safari tags 2 # Safari on tag 2
yashiki rule-add --app-name Slack tags 8 # Slack on tag 4
yashiki rule-add --app-name "Google Chrome" output 2 # Chrome on external monitor
yashiki rule-add --app-id org.mozilla.firefox --subrole AXUnknown ignore # Firefox popups
# Ghostty Quick Terminal
yashiki rule-add --app-id com.mitchellh.ghostty --fullscreen-button disabled ignoreSymptoms: Windows are not arranged automatically.
Solutions:
- Verify Yashiki is running:
yashiki list-windows - Check Accessibility permission is granted
- Try manual retile:
yashiki retile - Some windows may be floating - check with
yashiki list-windows
Symptoms: Pressing configured hotkeys does nothing.
Solutions:
- Verify bindings are registered:
yashiki list-bindings - Make sure your init script is executable:
chmod +x ~/.config/yashiki/init - Restart Yashiki:
yashiki quitthen relaunch the app - Check for conflicting system hotkeys in System Settings → Keyboard → Keyboard Shortcuts
Symptoms: Yashiki can't control windows even after granting permission.
Solutions:
- Remove Yashiki from Accessibility list
- Restart Yashiki
- Re-add and re-enable the permission
- Try rebooting your Mac if issues persist
Symptoms: Changes to ~/.config/yashiki/init have no effect.
Solutions:
- Verify the file exists:
ls -la ~/.config/yashiki/init - Make sure it's executable:
chmod +x ~/.config/yashiki/init - Check for syntax errors:
sh -n ~/.config/yashiki/init - Restart Yashiki to reload the config
Symptoms: Windows flicker or layout constantly recalculates.
Cause: Some apps create temporary popup windows that trigger relayout.
Solution: Add ignore rules for these windows:
# Firefox popups
yashiki rule-add --app-id org.mozilla.firefox --subrole AXUnknown ignore
yashiki rule-add --app-id org.mozilla.firefox --subrole none ignore
# Generic fix for all popups
yashiki rule-add --subrole AXUnknown ignore
yashiki rule-add --close-button none ignoreSee workarounds.md for more app-specific solutions.
Symptoms: New windows appear on an unexpected monitor.
Solutions:
- Use
outputrules to control window placement:yashiki rule-add --app-name "Google Chrome" output 2 - Check which display is which:
yashiki list-outputs
Now that you have Yashiki up and running, here are some resources to explore further:
- Window Rules Guide - Comprehensive guide to window rules including finding AX attributes
- Layout Engine Protocol - Create your own custom layout engine
- App Workarounds - Solutions for app-specific issues
Run yashiki without arguments to see all available commands, or check the README.md for the full CLI reference.
- Use
yashiki get-stateto see the current state of all windows and displays - Use
RUST_LOG=yashiki=debug yashiki startto debug issues - Check
yashiki list-windowsto see which windows are managed and their tags - Use
yashiki exec --trackto launch companion tools like JankyBorders - they'll be terminated automatically when yashiki quits
- Issues: github.com/typester/yashiki/issues
- Source Code: github.com/typester/yashiki