展示HN:Yashiki – 一个受River启发的,用Rust编写的macOS平铺窗口管理器。
Show HN: Yashiki – A tiling window manager for macOS in Rust, inspired by River

原始链接: https://github.com/typester/yashiki

## Yashiki:基于 Rust 的 macOS 平铺式窗口管理器 Yashiki 是一个为 macOS 12.0+ 构建的、基于 Rust 的平铺式窗口管理器,提供高度可定制和高效的工作流程。它利用基于标签的工作区(使用位掩码实现灵活的窗口组织),并支持具有独立标签配置的多显示器设置。 主要功能包括通过 JSON 协议实现外部布局引擎,允许用户使用任何语言创建自定义布局,以及强大的规则系统,可根据应用程序、标题或其他属性自动配置窗口。配置通过简单的 shell 脚本 (~/.config/yashiki/init) 进行 – 无需禁用 SIP。 Yashiki 提供光标扭曲(鼠标跟随焦点)、状态栏状态流等功能,可通过 Homebrew 安装 (`brew tap typester/yashiki; brew install --cask yashiki`)。它目前处于早期开发阶段,这意味着 API 和配置可能会发生变化。Yashiki 必须授予辅助功能权限才能正常工作。 有几个布局引擎可用(tatami, byobu),可以通过 `cargo install` 安装。提供了丰富的 CLI 工具来管理窗口、标签、布局和配置。

## Yashiki:一款新的macOS窗口管理器 开发者“typester”发布了Yashiki,一款用Rust构建的macOS平铺窗口管理器。Yashiki的灵感来自AwesomeWM和River(Linux窗口管理器,以动态布局著称),旨在为寻求比Rectangle等现有选项更灵活窗口管理的macOS用户填补空白。 该项目在一个周末内完成,源于作者从Linux过渡到macOS后对现有macOS窗口管理器不满。Yashiki专注于动态布局,允许自动窗口排列。 目前,该项目缺乏现成的视觉演示(截图或视频),正如一位评论员指出的那样,这将有助于展示其独特的功能并使其与更简单的工具区分开来。开发者可以回答问题并进一步解释设计背后的“River/Awesome理念”。更多信息请参见作者的博客:[https://typester.dev/blog/2026/01/18/yashiki-window-manager](https://typester.dev/blog/2026/01/18/yashiki-window-manager)。
相关文章

原文

macOS tiling window manager written in Rust.

  • Tag-based workspaces - Bitmask tags (like awesome/river) allow windows to belong to multiple tags and view any combination
  • External layout engines - Stdin/stdout JSON protocol lets you write custom layouts in any language
  • Multi-monitor support - Each display has independent tags
  • Window rules - Automatically configure windows by app name, bundle identifier, or title
  • Cursor warp - Mouse follows focus (configurable: disabled, on-output-change, on-focus-change)
  • State streaming - Real-time events for status bars and external tools
  • No SIP disable required - Uses only public Accessibility API
  • Shell script configuration - Config is just a shell script (~/.config/yashiki/init)

Early development stage. API and configuration format may change.

  • macOS 12.0+
  • Accessibility permission (System Settings → Privacy & Security → Accessibility)
brew tap typester/yashiki
brew install --cask yashiki

The cask installs:

  • Yashiki.app to /Applications
  • CLI tools: yashiki, yashiki-layout-tatami, yashiki-layout-byobu

Note: Yashiki.app is not signed. On first launch, allow it in System Settings → Privacy & Security. Or install with --no-quarantine:

brew install --cask --no-quarantine yashiki
# Core daemon and CLI
cargo install yashiki

# Install layout engines you want to use
cargo install yashiki-layout-tatami   # Master-stack layout
cargo install yashiki-layout-byobu    # Accordion layout

Grant Accessibility Permission

  1. Open System Settings → Privacy & Security → Accessibility
  2. Add Yashiki.app (if installed via Homebrew or as app bundle)
  3. Or add your terminal app if running yashiki start directly (Not recommended)

For a detailed walkthrough, see the Quick Start Guide.

  1. Launch Yashiki.app:

    • If installed via Homebrew: Open /Applications/Yashiki.app
    • The app will request Accessibility permission on first launch

    Note: Running yashiki start from terminal is not recommended as it requires granting Accessibility permission to your terminal app.

  2. Create config file ~/.config/yashiki/init:

    #!/bin/sh
    
    # Add Homebrew to exec path (if needed for custom layout engines)
    # yashiki add-exec-path /opt/homebrew/bin
    
    # Layout configuration
    yashiki layout-set-default tatami
    yashiki set-outer-gap 10  # Gap between windows and screen edges (global)
    yashiki layout-cmd --layout tatami set-inner-gap 10  # Gap between windows (layout-specific)
    
    # Cursor warp (mouse follows focus)
    yashiki set-cursor-warp on-focus-change
    
    # Tag bindings (tag N = bitmask $((1<<(N-1))))
    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
    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
    
    # Multi-monitor
    yashiki bind alt-o output-focus next
    yashiki bind alt-shift-o output-send next
  3. Make it executable:

    chmod +x ~/.config/yashiki/init
  4. Restart yashiki to apply config:

    • Quit with yashiki quit
    • Relaunch Yashiki.app

Yashiki uses a shell script for configuration. The init script is executed when the daemon starts.

Format: <modifiers>-<key>

Modifiers:

  • alt (Option key)
  • ctrl (Control key)
  • shift
  • cmd (Command key)

Examples: alt-1, alt-shift-j, ctrl-alt-return

Tags use bitmask format:

  • Tag 1 = 1 (binary: 001)
  • Tag 2 = 2 (binary: 010)
  • Tag 3 = 4 (binary: 100)
  • Tags 1+2 = 3 (binary: 011)

In shell scripts: $((1<<0)) = 1, $((1<<1)) = 2, $((1<<2)) = 4

yashiki start              # Start daemon
yashiki quit               # Stop daemon
yashiki version            # Show version
yashiki bind alt-1 tag-view 1    # Bind hotkey
yashiki unbind alt-1             # Unbind hotkey
yashiki list-bindings            # List all bindings
yashiki tag-view 1               # Switch to tag 1
yashiki tag-view 3               # View tags 1+2 (bitmask 3)
yashiki tag-toggle 2             # Toggle tag 2 visibility
yashiki tag-view-last            # Switch to previous tags
yashiki window-move-to-tag 1     # Move focused window to tag 1
yashiki window-toggle-tag 2      # Toggle tag 2 on focused window
yashiki window-focus next        # Focus next window
yashiki window-focus prev        # Focus previous window
yashiki window-focus left        # Focus window to the left
yashiki window-focus right       # Focus window to the right
yashiki window-focus up          # Focus window above
yashiki window-focus down        # Focus window below
yashiki window-swap next         # Swap with next window
yashiki window-swap prev         # Swap with previous window
yashiki window-swap left         # Swap with window to the left
yashiki window-swap right        # Swap with window to the right
yashiki window-swap up           # Swap with window above
yashiki window-swap down         # Swap with window below
yashiki window-toggle-fullscreen # Toggle fullscreen (AeroSpace-style)
yashiki window-toggle-float      # Toggle floating state
yashiki window-close             # Close focused window
yashiki output-focus next        # Focus next display
yashiki output-focus prev        # Focus previous display
yashiki output-send next         # Move window to next display
yashiki output-send prev         # Move window to previous display
yashiki tag-view --output 2 1    # Switch tag on display 2
yashiki tag-view --output "DELL" 1  # Target display by name
yashiki retile                   # Apply layout
yashiki layout-set-default tatami     # Set default layout
yashiki layout-set byobu              # Set layout for current tag
yashiki layout-set --tags 4 byobu     # Set layout for tag 3
yashiki layout-get                    # Get current layout
yashiki layout-cmd set-main-ratio 0.6 # Send command to layout
yashiki layout-cmd --layout tatami set-inner-gap 10  # Configure specific layout
yashiki list-windows             # List managed windows
yashiki list-windows --all       # Include ignored windows (popups, tooltips)
yashiki list-windows --debug     # Show debug info (ax_id, subrole, window_level, buttons)
yashiki list-outputs             # List all displays
yashiki get-state                # Get current state
yashiki exec "open -a Safari"    # Execute command
yashiki exec --track "borders"   # Execute and terminate on yashiki quit
yashiki exec-or-focus --app-name Safari "open -a Safari"  # Focus or launch

The --track option is useful for launching companion tools like JankyBorders that should run alongside yashiki:

# In ~/.config/yashiki/init
yashiki exec --track "borders active_color=0xffe1e3e4"

Control whether mouse cursor follows window focus.

yashiki set-cursor-warp disabled          # Don't move cursor (default)
yashiki set-cursor-warp on-output-change  # Move cursor when switching displays
yashiki set-cursor-warp on-focus-change   # Always move cursor to focused window
yashiki get-cursor-warp                   # Get current mode

Control the gap between windows and screen edges. Applied globally to all layouts and fullscreen windows.

yashiki set-outer-gap 10              # Set all sides to 10px
yashiki set-outer-gap 10 20           # Set vertical=10px, horizontal=20px
yashiki set-outer-gap 10 20 15 25     # Set top=10, right=20, bottom=15, left=25 (CSS-style)
yashiki get-outer-gap                 # Get current outer gap

Subscribe to real-time state change events (useful for status bars like engawa):

yashiki subscribe                     # Subscribe to all events
yashiki subscribe --snapshot          # Get initial snapshot on connect
yashiki subscribe --filter focus,tags # Filter specific events

Event types: window, focus, display, tags, layout

Events are streamed as JSON lines to stdout.

The exec path is used for exec commands and custom layout engine discovery.

yashiki exec-path                # Get current exec path
yashiki set-exec-path "/path1:/path2"  # Set exec path
yashiki add-exec-path /opt/homebrew/bin       # Add to start (high priority)
yashiki add-exec-path --append /usr/local/bin # Add to end (low priority)

Default exec path: <yashiki_executable_dir>:<system_PATH>

Automatically configure window properties based on app name, bundle identifier, title, AXIdentifier, AXSubrole, window level, or button states.

By default, new windows inherit the display's current visible tags. Use the tags action to override this.

# Match by app name
yashiki rule-add --app-name Finder float
yashiki rule-add --app-name Safari tags 2

# Match by bundle identifier (app-id)
yashiki rule-add --app-id com.apple.finder float
yashiki rule-add --app-id "com.google.*" output 2    # Glob pattern

# Match by window title
yashiki rule-add --title "*Preferences*" float

# Match by AXIdentifier (useful for special windows like Ghostty Quick Terminal)
yashiki rule-add --ax-id "com.mitchellh.ghostty.quickTerminal" float

# Match by AXSubrole (AX prefix optional: "Dialog" matches "AXDialog")
yashiki rule-add --subrole Dialog float
yashiki rule-add --subrole FloatingWindow float

# Match by window level (normal, floating, modal, utility, popup, other, or numeric)
yashiki rule-add --window-level other ignore      # Ignore non-normal windows (palettes, etc.)
yashiki rule-add --window-level floating float    # Float utility panels

# Match by button states (exists, none, enabled, disabled)
yashiki rule-add --fullscreen-button none float   # Float windows without fullscreen button
yashiki rule-add --close-button none ignore       # Ignore windows without close button (popups)
yashiki rule-add --app-id com.mitchellh.ghostty --fullscreen-button disabled ignore  # Ghostty Quick Terminal

# Ignore windows completely (never manage - useful for popups/dropdowns)
yashiki rule-add --subrole AXUnknown ignore  # Ignore all popup windows
yashiki rule-add --app-id org.mozilla.firefox --subrole AXUnknown ignore  # Firefox popups only
yashiki rule-add --app-id com.microsoft.Outlook --ax-id none --subrole none ignore  # Outlook invisible windows

# Combined matching (more specific)
yashiki rule-add --app-name Safari --title "*Preferences*" float
yashiki rule-add --app-id com.mitchellh.ghostty --subrole FloatingWindow float

# Other actions
yashiki rule-add --app-name Preview dimensions 800 600
yashiki rule-add --app-name Preview position 100 100

# Remove rule
yashiki rule-del --app-name Finder float

# List all rules
yashiki list-rules

Available actions:

Action Example Description
ignore ignore Never manage (skip completely)
float float Window floats (excluded from tiling)
no-float no-float Override float rule
tags tags 2 Set window tags
output output 2 Move to display
position position 100 200 Set position
dimensions dimensions 800 600 Set size

Rules are sorted by specificity - more specific rules take priority.

For detailed window rules configuration including how to find AX attributes (--ax-id, --subrole), see docs/window-rules.md.

For app-specific workarounds (Firefox flickering, etc.), see docs/workarounds.md.

Classic tiling layout with main area and stack.

Commands:

Command Description
set-main-ratio <0.1-0.9> Set main area ratio
inc-main-ratio Increase main ratio
dec-main-ratio Decrease main ratio
inc-main-count Add window to main area
dec-main-count Remove window from main area
zoom [window_id] Move window to main area
set-inner-gap <px> Gap between windows

AeroSpace-style stacked windows with focused window at front.

Commands:

Command Description
set-padding <px> Stagger offset between windows
set-orientation <h|v> Horizontal or vertical stacking
toggle-orientation Toggle orientation

Yashiki supports external layout engines via stdin/stdout JSON protocol.

See docs/layout-engine.md for the specification.

# Run daemon with debug logging
RUST_LOG=info cargo run -p yashiki -- start

# Run CLI commands
cargo run -p yashiki -- list-windows

# Run tests
cargo test --all

# Format code
cargo fmt --all
yashiki/                  # WM core daemon + CLI
yashiki-ipc/              # Shared protocol definitions
yashiki-layout-tatami/    # Master-stack layout engine
yashiki-layout-byobu/     # Accordion layout engine

Inspired by:

  • river - External layout protocol, multi-monitor model
  • AeroSpace - Virtual workspaces approach, accordion layout
  • dwm / awesomewm - Tag-based workspaces

MIT License - see LICENSE for details.

联系我们 contact @ memedata.com