AeroSpace Tiling Window Manager for macOS

repository·main·Indexed 10 days ago

https://github.com/nikitabobko/aerospace

An i3-inspired tiling window manager for macOS featuring a tree-based layout and emulated virtual workspaces. It provides a keyboard-centric experience via a client-server architecture, utilizing a CLI for configuration and window management without requiring SIP to be disabled. Compatible with macOS 13+ (pre-built), macOS 14+ (debug), and macOS 15+ (release).

Tokens
44K
Snippets
171
Records
212
Agent score
97%

What's inside AeroSpace

  1. How the AeroSpace client and server interact

    main

    AeroSpace operates using a client-server model. The aerospace CLI binary acts as the client, while AeroSpace.app acts as the server. They communicate via a predefined UNIX file.

    When you execute a command via the CLI, the following lifecycle occurs:

    1. Client-side Parsing: The client parses the arguments. If parsing fails, it reports errors; if -h or --help is provided, it displays help text.
    2. Transmission: If arguments are valid, the client sends them to the server.
    3. Server Execution: The server parses the arguments a second time and executes the command.
    4. Response: The server sends the stdout, stderr, and the exit code back to the client.
    5. Client Output: The client displays the stdout and stderr, then terminates with the exit code returned by the server.
  2. How binding modes work

    main

    Binding modes allow you to create different sets of keyboard shortcuts. When you switch to a new mode, all bindings from the previous mode are deactivated, and only the bindings defined for the new mode become active. The initial mode is main.

    To use binding modes, you must:

    1. Define a binding in the current mode that switches to the target mode.
    2. Declare the target mode and its bindings.

    Example of a resize mode:

    [mode.main.binding]
        alt-r = 'mode resize'      # Switch to 'resize' mode
    
    [mode.resize.binding]
        minus = 'resize smart -50'
        equal = 'resize smart +50'
    [mode.main.binding]
        alt-r = 'mode resize'
    
    [mode.resize.binding]
        minus = 'resize smart -50'
        equal = 'resize smart +50'
  3. How Subscribe mode works in the AeroSpace Socket API

    main

    When a client sends a request where args starts with "subscribe", the server switches from one-shot command mode to event-streaming mode.

    1. The client sends one ClientRequest frame.
    2. The server sends an unbounded stream of ServerEvent frames.
    3. The client must not send anything else on the connection while in this mode.
    4. The server keeps writing until the connection is closed.

    The remaining args after "subscribe" follow the same syntax as the aerospace subscribe CLI command (e.g., --all, --no-send-initial, or an explicit list of event types).

  4. Core Concepts of AeroSpace

    main

    AeroSpace is an i3-inspired tiling window manager for macOS designed for advanced users and developers. Key architectural concepts include:

    • Tree Paradigm: The tiling window manager is based on a tree-structured layout.
    • Virtual Workspaces: Instead of relying on native macOS Spaces (which have significant limitations), AeroSpace employs its own emulation of virtual workspaces.
    • Keyboard Centric: The workflow is designed to be driven by the keyboard.
    • CLI First: The project provides a command-line interface, including manpages and shell completion.
    • Plain Text Configuration: Configuration is handled via text files (dotfiles friendly), and there is no GUI for configuration.
    • Multi-monitor Support: Follows an i3-like paradigm for managing multiple monitors.
  5. Use AeroSpace Shell syntax for command sequences

    main

    AeroSpace implements a subset of Shell syntax to allow combining commands using operators like ;, ||, &&, and | (pipe). This is useful for complex keybindings.

    Precedence Rules

    • AeroSpace's precedence differs from traditional shells: && has higher binding power than ||. For example, foo || bar && baz is parsed as foo || (bar && baz).
    • The pipe operator | behaves like set -o pipefail in traditional shells.

    Example of a complex binding:

    [mode.main.binding]
        # Move node to workspace 1, then switch to workspace 1
        alt-shift-1 = 'move-node-to-workspace 1; workspace 1'
    
        # List empty workspaces on focused monitor and switch to the next one
        alt-right = 'list-workspaces --monitor focused --empty no | workspace --stdin next'
    [mode.main.binding]
        alt-shift-1 = 'move-node-to-workspace 1; workspace 1'
        alt-right = 'list-workspaces --monitor focused --empty no | workspace --stdin next'
  6. Migrate from legacy 'on-window-detected' syntax

    main

    The if.* syntax inside on-window-detected is soft deprecated. While still supported, you are encouraged to use the if = 'test ...' syntax which utilizes the test helper command.

    Legacy (Soft Deprecated):

    on-window-detected = [
        {
            if.app-id = 'com.apple.systempreferences',
            run = ['layout floating', 'move-node-to-workspace S'],
        },
    ]

    Recommended:

    on-window-detected = [
        {
            if = 'test %{app-bundle-id} = com.apple.systempreferences',
            run = ['layout floating', 'move-node-to-workspace S'],
        },
    ]
  7. Install AeroSpace manually

    main

    If you prefer not to use Homebrew, follow these steps:

    1. Download the latest zip from the releases page.
    2. Unpack the zip.
    3. Move AeroSpace.app to /Applications.
    4. (Optional) Move the bin/aerospace binary to a directory in your $PATH to enable CLI interaction.

    Resolving macOS Security Warnings If you see the error "AeroSpace.app" can't be opened because Apple cannot check it for malicious software, use one of these methods:

    Option 1: CLI

    xattr -d com.apple.quarantine /Applications/AeroSpace.app

    Option 2: Finder

    1. Navigate to /Applications/AeroSpace.app in Finder.
    2. Right-click the app and select Open.
  8. Query AeroSpace configuration options with the CLI

    main

    The aerospace config command allows you to inspect your loaded configuration. Currently, only mode.* configuration options are supported for querying.

    Note that the configuration is a recursive structure of maps, arrays, strings, and integers. If you attempt to print a complex object (like a map or array) without using the --json or --keys flags, the output will only be supported for scalar types (strings/integers) or arrays of scalar types.

    aerospace config --get <name> [--json] [--keys]
    # or
    aerospace config --major-keys
    # or
    aerospace config --all-keys
    # or
    aerospace config --config-path
  9. Use aerospace focus-back-and-forth to toggle focus

    main

    The aerospace focus-back-and-forth command switches focus between the currently focused element (a window or an empty workspace) and the single previously focused element stored in history.

    Important Limitations:

    • AeroSpace only stores one previously focused window in its history.
    • If the previously focused window has been closed, the command will fail and exit with a non-zero exit code because there is no window to switch back to.

    Best Practice: To ensure a smooth experience even when a window is closed, combine this command with workspace-back-and-forth using a logical OR (||). This allows the system to attempt to switch focus back to a window, and if that fails (e.g., the window is gone), it will attempt to switch back to the previous workspace instead.

    aerospace focus-back-and-forth || aerospace workspace-back-and-forth