Skip to content
CAI
Software that uses CAICheck a score

nikitabobko/AeroSpace

61.7

Adequate · 3 August 2026

571k

lines of production code

Swift

primary language

2

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

AeroSpace is a macOS window manager that provides programmatic control over window tiling, focus, and workspace management through a robust CLI and GUI. It features a comprehensive set of commands for layout, navigation, and configuration, supporting both keyboard-driven workflows and mouse interactions. The system manages window states, monitors, and applications with a focus on reliability and thread safety, while also offering a customizable menu bar interface and automatic configuration reloading.

How it got here

2023–2024 — Architecture modernization and CLI overhaul

31 changes.

This period focused on a comprehensive architectural overhaul, replacing the previous CLI implementation with a robust, type-safe command-line interface and a modernized internal model for window and focus management. The team introduced concurrency support, automated build tooling, and extensive test coverage to stabilize the codebase while adding significant new features like mouse-driven window management and configuration hot-reloading.

2025–2026 — UI overhaul and test coverage

5 changes.

This period focused on expanding the application's capabilities through new accessibility dumps and a comprehensive experimental UI framework for menu bar customization. Concurrently, the team significantly increased test coverage for client-server communication and shell execution logic, while also restructuring the Xcode project to support git worktrees.

Features

Added accessibility dumps for 1Password, Alacritty, Apple apps, and more

Added new accessibility dump files for 1Password, Alacritty, Apple Calendar, Apple Mail, and other applications. These dumps capture the accessibility tree structure and properties of various windows, enabling better window detection and management for these applications.

axDumps · high confidence

Enable mouse-driven window management and focus-follows-mouse

Users can now move, resize, and switch focus using the mouse. The new focus-follows-mouse feature automatically focuses the window under the cursor as it moves. Mouse drag interactions are now handled directly, allowing users to move tiling and floating windows, swap their positions, and resize them by dragging edges or corners. This replaces previous limitations where such interactions were blocked or required keyboard commands.

Sources/AppBundle/mouse · high confidence

Introduce app metadata constants for AeroSpace

A new file, appMetadata.swift, has been added to the Common source directory. This file defines the application identifier (stableAeroSpaceAppId) and name (aeroSpaceAppName) for the AeroSpace application, with specific debug-time values for the app ID and name when compiled in DEBUG mode.

Sources/Common · high confidence

Introduce auto-reload of configuration file on change

AeroSpace can now automatically reload the configuration file when it is modified on disk. This is controlled by the new \auto-reload-config\ boolean config option. When enabled, the application watches the config file and triggers a reload after a short debounce delay, allowing users to edit their configuration in a text editor and see changes take effect immediately without manual intervention.

Sources/AppBundle/config · high confidence

Introduce environment variable forwarding and DFS navigation support

The model layer now supports forwarding AEROSPACE\_WINDOW\_ID and AEROSPACE\_WORKSPACE environment variables from the client to the server, enabling context-aware operations. Additionally, a new DFS (depth-first search) navigation model is introduced, adding dfs-next and dfs-prev direction types to the system's directional logic, allowing users to navigate through windows in a depth-first order rather than just cardinal directions.

Sources/Common/model · high confidence

Introduce main app entry point with menu bar and message window integration

The application now initializes with a main entry point that manages the shared state for the system tray menu and a new customizable message view. This change introduces the primary SwiftUI App struct that wires together the TrayMenuModel and MessageModel, automatically opening a dedicated window to display messages such as configuration errors.

Sources/AeroSpaceApp · high confidence

Introduces new concurrency and utility primitives

The utility layer now includes several new types to support the app's concurrency model and internal state management. A new AwaitableOneTimeBroadcastLatch provides an async-safe, cancellable one-time broadcast mechanism. AxSubscription wraps the macOS Accessibility Observer API to manage event subscriptions safely. ThreadGuardedValue enforces thread-safety for specific values. Additionally, helper classes like UniqueToken, MruStack, and CompletableFuture are added to support internal logic, while extensions on Set, CGPoint, and NSRunningApplication provide utility methods for the rest of the codebase.

Sources/AppBundle/util · high confidence

New and refactored build and release scripts

The project introduces several new shell scripts in the script/ directory to improve the build, release, and development workflows. A new script/build-brew-cask.sh generates the Homebrew cask definition for the application. A script/install-dep.sh manages third-party dependencies (SwiftLint, SwiftFormat, XcodeGen, Periphery, Complgen) using a marker-based caching system to avoid redundant downloads. A script/generate-cmd-help.sh automatically generates Swift source code from AsciiDoc documentation files. Additionally, existing scripts have been reorganized and improved: script/clean-project.sh and script/clean-xcode.sh handle project cleanup, script/check-uncommitted-files.sh enforces clean working directories, and script/setup.sh centralizes environment setup, including a check for Bash version 5 and a wrapper for the Swift compiler. The script/publish-release.sh orchestrates the release process, including tagging, opening the GitHub release page, and updating the cask repository.

script · high confidence

New commands for window management, configuration inspection, and debugging

Added several new commands to the CLI: \balance-sizes\ to equalize window sizes in a workspace; \close-all-but-current\ to close all windows except the currently focused one; \config\ to inspect the current configuration (get key, list keys, or dump all); \debug-windows\ to record and dump debug information about focused windows; \echo\ to print formatted strings; \enable\ to toggle AeroSpace on/off; \eval\ to evaluate shell expressions; \exec-and-forget\ to run shell commands in the background; \false\ to return a failure exit code; \flatten-workspace-tree\ to remove all nesting in a workspace; \focus-back-and-forth\ to toggle focus between the current and previous window; \fullscreen\ to toggle native fullscreen; \join-with\ to group two windows; \layout\ to change tiling layout or orientation; \list-apps\, \list-modes\, \list-monitors\, \list-windows\, and \list-workspaces\ to query system state with optional JSON output and count mode; \macos-native-fullscreen\ to toggle macOS native fullscreen; \macos-native-minimize\ to toggle macOS native minimize; \mode\ to switch to a named mode; \move-node-to-monitor\ and \move-node-to-workspace\ to move windows; \move-workspace-to-monitor\ to move workspaces between monitors; \on-window-detected\ to run commands when windows appear; \reload-config\ to reload configuration; \resize\ to change window sizes; \run-callback\ to run callbacks; \search\ to find windows; \set\ to modify configuration at runtime; \skip\ to mark windows as non-focusable; \split\ to split a window's container; \swap\ to exchange two windows; \test\ to evaluate conditions; \true\ to return a success exit code; \workspace\ to switch workspaces; and \workspace-back-and-forth\ to toggle between current and previous workspace. Additionally, \list-windows\, \list-workspaces\, \list-monitors\, and \list-apps\ now support a \--json\ flag for JSON output and a \--count\ flag to output only the count of items.

Sources/AppBundle/command/impl · high confidence

New experimental UI settings and UI components

The application now includes a new UI folder containing several components: an AppearanceTheme enum for light/dark mode detection, an ExperimentalUISettings struct with a MenuBarStyle enum for customizing the menu bar display (e.g., monospaced text, system text, squares, i3 styles), and a MenuBarLabel view that renders the menu bar content. Additionally, a MessageView is introduced for displaying config errors and warnings, a SecureInputView/Panel for informing users about Secure Input restrictions, and a VolumeView/Panel for displaying volume changes. The TrayMenuModel is updated to support these new UI elements, including the ability to select different menu bar styles in the experimental settings.

Sources/AppBundle/ui · high confidence

Standardize development environment with new build and linting scripts

The project now includes a suite of new shell scripts to standardize the development workflow. A new makefile allows building and testing via the :make command in Vim. Build scripts (build-debug.sh, build-release.sh, build-docs.sh, build-shell-completion.sh) automate the compilation of the app and CLI, documentation generation, and shell completion generation. A format.sh script runs SwiftFormat, while lint.sh enforces SwiftLint and Periphery rules. Additional scripts (run-cli.sh, run-debug.sh, swift-test.sh, test.sh) streamline running the CLI, the app, and tests. Configuration files (.editorconfig, .gitattributes, .gitignore, .swift-version, .swiftformat, .swiftlint.yml) are added to enforce consistent formatting, ignore generated files, and define Swift tooling versions.

(repo-wide) · high confidence

Removals

Removed macOS window manager Swift CLI entry point

The main.swift file, which previously served as the entry point for a macOS window manager written in Swift, has been removed from the project. This change eliminates the CLI application structure, indicating a shift away from the initial command-line interface implementation.

macos-window-manager-swift · high confidence

Behavioural changes

Add window state caching for screen lock/unlock recovery

The application now caches the entire window state (workspaces, monitors, and window IDs) when a window is closed. This cache is used to restore the previous layout after the screen is unlocked, preventing the application from incorrectly assuming all windows were closed during the lock screen state. The cache is reset when layout changes occur to ensure the most recent state is preserved.

Sources/AppBundle/tree/frozen · medium confidence

Comprehensive CLI argument parsing and command structure overhaul

The command-line interface has been refactored to use a new, type-safe argument parsing system. Each command (such as \focus\, \move\, \layout\, and various \list-\*\ commands) now has a dedicated struct (e.g., \FocusCmdArgs\, \LayoutCmdArgs\) that defines its specific flags, positional arguments, and validation rules. This change introduces several new capabilities and behavioral shifts: query commands (\list-windows\, \list-workspaces\, \list-monitors\, \list-apps\) now support \--json\ and \--count\ flags for easier scripting and integration; many commands now accept a \--window-id\ or \--workspace\ flag to target specific objects; and commands like \focus\ and \move\ gain new options such as \--boundaries\ and \--fail-if-fullscreen\ to control edge-case behavior. The refactoring also standardizes error handling and help message generation, ensuring consistent user experience across all subcommands.

Sources/Common/cmdArgs/impl · high confidence

Configure Bundler to install gems locally

The project now includes a .bundle/config file that sets BUNDLE\_PATH to .deps/bundler-path and disables shared gems. This ensures that Ruby gems are installed into a local directory within the repository rather than the global system path, which helps keep the environment consistent and isolated.

.bundle · high confidence

Improved window and monitor model with stricter heuristics and new event streaming

The application's window management logic has been refined to better distinguish between regular windows, dialogs, and popups, reducing the chance of incorrectly managing transient UI elements. This includes stricter heuristics for identifying windows from specific applications (like Firefox, Chrome, and Emacs child frames) and excluding non-window elements from tiling. Additionally, the model now exposes monitor information via a new \ServerEvent\ type, enabling real-time event streaming for focus changes, workspace changes, and mode updates.

Sources/AppBundle/model · high confidence

Introduce new CLI entry point and version mismatch warnings

The CLI now uses a new \\_main.swift\ entry point that handles argument parsing, stdin processing, and client-server communication. A key addition is a version mismatch warning: when the client and server versions do not match, the CLI prints a warning suggesting to restart the AeroSpace.app server or reinstall the application. The \--version\ flag now explicitly shows both the client and server versions, and the \subscribe\ command is handled specially to stream real-time events. Additionally, the CLI now supports reading from stdin for commands like \workspace\ and \move-node-to-workspace\, with an explicit \--stdin\/\--no-stdin\ flag to control this behavior.

Sources/Cli · high confidence

Major refactoring of focus management and window state tracking

The application's internal architecture for tracking the currently focused window and workspace has been completely rewritten. A new \LiveFocus\/\FrozenFocus\ model replaces the previous global state, ensuring that commands and callbacks access the correct focus context rather than a shared global variable. This change introduces \on-focus-changed\ and \on-focused-monitor-changed\ callbacks, and ensures that the \AEROSpace\_WINDOW\_ID\ and \AEROSpace\_WORKSPACE\ environment variables are correctly forwarded to these callbacks. The refactoring also includes a new \GlobalObserver\ to handle system-level notifications (like app hide/unhide and mouse clicks) and a \windowLevelCache\ to efficiently track macOS window levels. These changes improve the reliability of focus management, fix several crashes related to focus state, and provide a more robust foundation for future features.

Sources/AppBundle · high confidence

New hand-written shell lexer, parser, and execution engine

The shell implementation has been completely rewritten from scratch, replacing the previous generated lexer and parser with a new hand-written Swift implementation. This introduces a new \Shell\ enum representing the command structure (supporting pipes, AND/OR/SEQ operators) and a dedicated lexer (\shellLexer.swift\) and parser (\shellParser.swift\) to process shell-like syntax. The execution logic has also been updated to run commands within this new shell environment, meaning shell scripts and command chains defined in configurations will now be interpreted by this new engine.

Sources/AppBundle/shell · high confidence

PrivateApi module exposed via SPM module map

The PrivateApi target is now fully supported by Swift Package Manager through a new module map and header files. This change replaces the previous bridging header approach, allowing the private C API (specifically the \_AXUIElementGetWindow function) to be imported directly into Swift code without needing an intermediate header or bridging header configuration.

Sources/PrivateApi · medium confidence

Redesigned window and application model with thread-safe containers

The internal tree structure for managing windows and applications has been refactored to improve thread safety and separation of concerns. A new \AbstractApp\ protocol and \MacApp\ class encapsulate macOS-specific window management, moving away from a shared \Workspace\-centric model to a more granular \TreeNode\ hierarchy. This introduces dedicated containers for different window states—such as \MacosMinimizedWindowsContainer\, \MacosFullscreenWindowsContainer\, and \MacosHiddenAppsWindowsContainer\—allowing the application to handle native macOS behaviors like fullscreen, minimize, and hidden app windows more robustly. The \TreeNode\ base class and its extensions now provide a unified way to navigate and manipulate the window tree, ensuring that operations like focusing, resizing, and closing windows are handled through a consistent, thread-safe interface.

Sources/AppBundle/tree · medium confidence

Refactor window layout and refresh logic

The layout logic has been restructured into a new \layoutRecursive\ file, introducing a recursive layout pass that handles tiling containers, floating windows, and fullscreen states. The refresh mechanism has been split into \runLightSession\ for quick updates and \runHeavyCompleteRefreshSession\ for full state synchronization, with the latter now supporting cancellation and optimistic pre-layout. This change improves performance by reducing the refresh complexity from O(n^2) to O(n) and ensures that window coordinates are correctly calculated relative to the target workspace's bounds.

Sources/AppBundle/layout · high confidence

Refactored command execution model with dedicated environment and I/O abstractions

The command execution infrastructure has been restructured to improve safety and clarity. A new \CmdEnv\ struct manages the execution environment, explicitly passing window and workspace context to commands. I/O operations are now handled through the \CmdIo\ protocol and \CmdStdin\ struct, decoupling input/output logic from the command implementations. Additionally, \CmdResult\ and \ExitCode\ types have been introduced to standardize command outcomes and error handling.

Sources/AppBundle/command · medium confidence

Refactored common utility library with new data structures and concurrency support

The common utility module was restructured and expanded to support Swift 6 concurrency and modernize the codebase. A new \ArrSlice\ type was introduced to replace standard \ArraySlice\ for better encapsulation and zero-based indexing. Several extension files were added or updated (\AeroAny\, \BoolEx\, \CaseInsensitiveRegex\, \CollectionEx\, \ConvenienceMutable\, \DictionaryEx\, \JsonEncoderEx\, \MainActorEx\, \NWConnectionEx\, \Nullable\, \OptionalEx\, \ResultEx\, \SequenceEx\, \StringEx\, \TaskEx\, \commonUtil\), adding functional helpers like \apply\, \also\, \takeIf\, \andAsync\/\orAsync\, \partition\, \sortedBy\, \interpolate\, and \bugPrompt\. The \NWConnection\ extension was rewritten to use the \Network\ framework with atomic writes and versioned protocol handshakes. Error handling was improved with \EquatableNoop\, \Lateinit\, and \Nullable\ types, while \die\/\dieT\ functions were consolidated for crash reporting.

Sources/Common/util · high confidence

Removed macOS CLI project configuration

The Xcode project file (project.pbxproj) for the 'macos-window-manager-swift' target has been deleted. This removes the build configuration for the macOS command-line tool, indicating a shift away from the previous CLI-based implementation.

macos-window-manager-swift.xcodeproj · high confidence

Removed stale Xcode scheme configuration

The user-specific Xcode scheme management file (xcschememanagement.plist) has been removed from the project. This change eliminates local development settings that were previously stored in the repository, ensuring that Xcode run/debug configurations are no longer tracked in version control.

macos-window-manager-swift.xcodeproj/xcuserdata · medium confidence

Rewrite CLI argument parsing to a functional, type-safe architecture

The command-line interface parsing has been completely rewritten to use a functional, type-safe approach. This introduces new types like \ArgParser\, \ParsedCliArgs\, and \ParsedCmd\ to handle argument validation and state transitions. The change adds support for conflicting command-line options, explicit \--stdin\ flag handling, and better error messages for invalid arguments. Users will see more robust validation of CLI inputs, with specific exit codes (e.g., exit code 2 for generic errors) and improved help generation from adoc files.

Sources/Common/cmdArgs · high confidence

Updated app icon and accent color resources

The app's visual assets have been updated: a new AppIcon is now defined for all standard Mac sizes (16px to 512px), and an AccentColor resource has been added to the asset catalog. Additionally, the project's entitlements have been reorganized, moving the configuration to a dedicated file and disabling the app sandbox.

resources · medium confidence

Xcode project restructured for git worktree compatibility

The Xcode project files have been moved into a dedicated \xcode\ directory and reorganized to support git worktrees. This change improves the development workflow by allowing the Xcode project to coexist with other git worktrees without path conflicts, while maintaining the same build configuration and target structure.

xcode · high confidence

Test coverage

Add comprehensive config parsing tests; Added test infrastructure for window detection and tree normalization; Added tests for ClientRequest and ServerEvent serialization; Added tests for shell lexer, parser, and command execution; Expanded test coverage and improved test infrastructure; Expanded test coverage for window management commands.

Dependencies

Upgrade to Swift 6 and modernize package dependencies

The project has been upgraded to Swift 6, enabling strict memory safety and the NonisolatedNonsendingByDefault concurrency feature. Several dependencies have been updated or migrated: TOMLKit has been replaced with TOMLDecoder, and the codebase now relies on specific versions of swift-collections (1.3.0), HotKey (0.2.1), and ISSoundAdditions (2.0.1). The Package.swift manifest has been restructured to explicitly define targets and products, and the Package.resolved file has been added to lock dependency states.

(dependencies) · medium confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Baseline

  • First survey — no prior run to compare against. CAI 62.

Lenses

  • Architecture 92
  • Maturity 57
  • Readiness 52
  • Security 74
  • Domain Modelling 100

Changes since last survey

  • 300 commits — 259 feature/other, 41 fixes

By area

  • Sources/AppBundle — 165 commits
  • Sources/Common — 40 commits
  • (root) — 34 commits
  • Sources/AppBundleTests — 26 commits
  • docs/guide.adoc — 5 commits
  • docs/goodies.adoc — 4 commits
  • .github/workflows — 3 commits
  • docs/config-examples — 3 commits
  • .github/pull_request_template.md — 2 commits
  • Sources/Cli — 2 commits
  • grammar/commands-bnf-grammar.txt — 2 commits
  • (repo) — 1 commit
  • AeroSpace.xcodeproj/project.pbxproj — 1 commit
  • axDumps/about_this_mac.json5 — 1 commit
  • axDumps/archiveutility.json5 — 1 commit
  • axDumps/codex.json5 — 1 commit
  • axDumps/ghostty.json5 — 1 commit
  • axDumps/kitty_quick_access.json5 — 1 commit
  • axDumps/raycast.json5 — 1 commit
  • axDumps/wisprFlow1.json5 — 1 commit

Notable commits

  • fix: 2/2 Fix swift warnings
  • fix: 2/2 Fix the regression introduce by the previous commit: errors in config are reported again at startup
  • fix: 2/2 Fix wisprFlow popup detection
  • fix: Add regression tests for cleanshotx
  • fix: Cleanup: fix Equatable for HotkeyBinding. Introduce zipIfCountsAreEqual
  • fix: Fix 'Ambiguous config error' crash while loading the built-in default-config.toml
  • fix: Fix GH actions: don't run periphery on macos 14
  • fix: Fix GitHub Actions CI
  • fix: Fix GitHub Actions CI #2
  • fix: Fix GitHub Actions CI #3
  • fix: Fix GitHub actions
  • fix: Fix bug, workspace next/prev: land on first workspace when current isn't in --stdin list
  • fix: Fix bug: do not read stdin in client if explicitly asked not to
  • fix: Fix bug: execOnWorkspaceChange error message
  • fix: Fix bug: floating windows get nudged away from right/bottom edges on unhide
  • fix: Fix bug: menu bar clicks steal focus when 'Displays have separate spaces' is off
  • fix: Fix client-server protocol
  • fix: Fix codex pet window detection
  • fix: Fix crash on startup when afterStartupCommand couldn't be run because AeroSpace is disabled
  • fix: Fix crash when built-in config couldn't be loaded
  • …and 280 more

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

nikitabobko/AeroSpace was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 3 August 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit d56e1637c3a1ed660d0cadd7534e94fb3218d1c3 — the exact code this score is about.
  • Scored under rubric-2026.08.18 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer latest.