nikitabobko/AeroSpace/main 396k tokens More Tools
```
├── .bundle/
   ├── config
├── .editorconfig (omitted)
├── .gitattributes (omitted)
├── .github/
   ├── DISCUSSION_TEMPLATE/
      ├── potential-bugs.yml (100 tokens)
   ├── FUNDING.yml
   ├── ISSUE_TEMPLATE/
      ├── config.yml
      ├── new-issue.yml (100 tokens)
   ├── gh-actions-runner-xcode-select.sh (100 tokens)
   ├── pull_request_template.md (200 tokens)
   ├── workflows/
      ├── build.yml (500 tokens)
      ├── close-third-party-issues.yml (200 tokens)
      ├── label-incoming-prs.yml (200 tokens)
├── .gitignore (100 tokens)
├── .idea/
   ├── codeStyles/
      ├── Project.xml (100 tokens)
      ├── codeStyleConfig.xml
   ├── inspectionProfiles/
      ├── Project_Default.xml (100 tokens)
├── .swift-version
├── .swiftformat (300 tokens)
├── .swiftlint.yml (400 tokens)
├── CONTRIBUTING.md (400 tokens)
├── Gemfile (100 tokens)
├── LICENSE.txt (200 tokens)
├── Package.resolved (200 tokens)
├── Package.swift (600 tokens)
├── README.md (2.1k tokens)
├── Sources/
   ├── AeroSpaceApp/
      ├── AeroSpaceApp.swift (100 tokens)
   ├── AppBundle/
      ├── GlobalObserver.swift (900 tokens)
      ├── command/
         ├── CmdEnv.swift (200 tokens)
         ├── CmdIo.swift (300 tokens)
         ├── Command.swift (200 tokens)
         ├── cmdManifest.swift (1000 tokens)
         ├── cmdResolveTargetOrReportError.swift (300 tokens)
         ├── format.swift (2.1k tokens)
         ├── formatToJson.swift (200 tokens)
         ├── impl/
            ├── BalanceSizesCommand.swift (200 tokens)
            ├── CloseAllWindowsButCurrentCommand.swift (200 tokens)
            ├── CloseCommand.swift (200 tokens)
            ├── ConfigCommand.swift (1400 tokens)
            ├── DebugWindowsCommand.swift (1200 tokens)
            ├── EchoCommand.swift (300 tokens)
            ├── EnableCommand.swift (300 tokens)
            ├── EvalCommand.swift (100 tokens)
            ├── ExecAndForgetCommand.swift (100 tokens)
            ├── FalseCommand.swift
            ├── FlattenWorkspaceTreeCommand.swift (100 tokens)
            ├── FocusBackAndForthCommand.swift (100 tokens)
            ├── FocusCommand.swift (1900 tokens)
            ├── FocusMonitorCommand.swift (700 tokens)
            ├── FullscreenCommand.swift (300 tokens)
            ├── JoinWithCommand.swift (300 tokens)
            ├── LayoutCommand.swift (1200 tokens)
            ├── ListAppsCommand.swift (200 tokens)
            ├── ListExecEnvVarsCommand.swift (100 tokens)
            ├── ListModesCommand.swift (100 tokens)
            ├── ListMonitorsCommand.swift (300 tokens)
            ├── ListWindowsCommand.swift (600 tokens)
            ├── ListWorkspacesCommand.swift (500 tokens)
            ├── MacosNativeFullscreenCommand.swift (500 tokens)
            ├── MacosNativeMinimizeCommand.swift (200 tokens)
            ├── ModeCommand.swift (100 tokens)
            ├── MoveCommand.swift (1700 tokens)
            ├── MoveMouseCommand.swift (600 tokens)
            ├── MoveNodeToMonitorCommand.swift (300 tokens)
            ├── MoveNodeToWorkspaceCommand.swift (400 tokens)
            ├── MoveWorkspaceToMonitorCommand.swift (300 tokens)
            ├── ReloadConfigCommand.swift (600 tokens)
            ├── ResizeCommand.swift (500 tokens)
            ├── RunCallbackCommand.swift (200 tokens)
            ├── SplitCommand.swift (500 tokens)
            ├── SummonWorkspaceCommand.swift (300 tokens)
            ├── SwapCommand.swift (400 tokens)
            ├── TestCommand.swift (500 tokens)
            ├── TestNotCommand.swift (100 tokens)
            ├── TriggerBindingCommand.swift (200 tokens)
            ├── TrueCommand.swift (100 tokens)
            ├── VolumeCommand.swift (200 tokens)
            ├── WorkspaceBackAndForthCommand.swift (100 tokens)
            ├── WorkspaceCommand.swift (600 tokens)
         ├── parseCommand.swift (300 tokens)
      ├── config/
         ├── Config.swift (600 tokens)
         ├── ConfigFile.swift (300 tokens)
         ├── ConfigFileWatcher.swift (300 tokens)
         ├── DynamicConfigValue.swift (700 tokens)
         ├── HotkeyBinding.swift (1000 tokens)
         ├── Mode.swift (300 tokens)
         ├── keysMap.swift (1900 tokens)
         ├── parseConfig.swift (4.4k tokens)
         ├── parseExecEnvVariables.swift (500 tokens)
         ├── parseFocusFollowsMouse.swift (100 tokens)
         ├── parseGaps.swift (800 tokens)
         ├── parseKeyMapping.swift (500 tokens)
         ├── parseOnWindowDetected.swift (1200 tokens)
         ├── parseWorkspaceToMonitorAssignment.swift (300 tokens)
         ├── startAtLogin.swift (200 tokens)
      ├── focus.swift (1600 tokens)
      ├── focusCache.swift (100 tokens)
      ├── getNativeFocusedWindow.swift (100 tokens)
      ├── initAppBundle.swift (800 tokens)
      ├── layout/
         ├── layoutRecursive.swift (1800 tokens)
         ├── refresh.swift (1600 tokens)
      ├── model/
         ├── AxUiElementWindowType.swift (1900 tokens)
         ├── Json.swift (500 tokens)
         ├── KnownBundleId.swift (300 tokens)
         ├── MonitorDescriptionEx.swift (100 tokens)
         ├── MonitorEx.swift (200 tokens)
         ├── MonitorInfo.swift (800 tokens)
         ├── OrderedJson.swift (500 tokens)
         ├── Rect.swift (400 tokens)
         ├── ServerEvent.swift (500 tokens)
      ├── mouse/
         ├── focusFollowsMouse.swift (600 tokens)
         ├── mouse.swift (100 tokens)
         ├── moveWithMouse.swift (900 tokens)
         ├── resizeWithMouse.swift (1000 tokens)
      ├── normalizeLayoutReason.swift (700 tokens)
      ├── runLoop.swift (600 tokens)
      ├── server.swift (1200 tokens)
      ├── shell/
         ├── Shell.swift (1300 tokens)
         ├── shellLexer.swift (1500 tokens)
         ├── shellParser.swift (900 tokens)
      ├── subscriptions.swift (400 tokens)
      ├── tree/
         ├── AbstractApp.swift (100 tokens)
         ├── FloatingWindowsContainer.swift
         ├── MacApp.swift (3.8k tokens)
         ├── MacWindow.swift (2.9k tokens)
         ├── MacosUnconventionalWindowsContainer.swift (300 tokens)
         ├── TilingContainer.swift (500 tokens)
         ├── TreeNode.swift (1300 tokens)
         ├── TreeNodeCases.swift (1900 tokens)
         ├── TreeNodeEx.swift (800 tokens)
         ├── Window.swift (600 tokens)
         ├── Workspace.swift (1600 tokens)
         ├── WorkspaceEx.swift (500 tokens)
         ├── frozen/
            ├── FrozenTreeNode.swift (300 tokens)
            ├── FrozenWorld.swift (100 tokens)
            ├── closedWindowsCache.swift (1100 tokens)
         ├── normalizeContainers.swift (300 tokens)
      ├── ui/
         ├── AppearanceTheme.swift (100 tokens)
         ├── ExperimentalUISettings.swift (400 tokens)
         ├── MenuBar.swift (1300 tokens)
         ├── MenuBarLabel.swift (1300 tokens)
         ├── MessageView.swift (1000 tokens)
         ├── NSPanelHud.swift (100 tokens)
         ├── SecureInputView.swift (600 tokens)
         ├── TrayMenuModel.swift (800 tokens)
         ├── VolumeView.swift (600 tokens)
      ├── util/
         ├── AwaitableOneTimeBroadcastLatch.swift (300 tokens)
         ├── AxSubscription.swift (400 tokens)
         ├── AxUiElementMock.swift (100 tokens)
         ├── CompletableFuture.swift (100 tokens)
         ├── LazySequenceProtocolEx.swift
         ├── MruStack.swift (300 tokens)
         ├── NSRunningApplicationEx.swift
         ├── NsApplicationEx.swift (100 tokens)
         ├── SetEx.swift (100 tokens)
         ├── ThreadGuardedValue.swift (200 tokens)
         ├── UniqueToken.swift (100 tokens)
         ├── accessibility.swift (2.5k tokens)
         ├── appBundleUtil.swift (1000 tokens)
         ├── axTrustedCheckOptionPrompt.swift
         ├── dumpAxRecursive.swift (1000 tokens)
      ├── windowLevelCache.swift (400 tokens)
   ├── AppBundleTests/
      ├── AwaitableOneTimeBroadcastLatchTest.swift (800 tokens)
      ├── AxUiElementWindowTypeTest.swift (600 tokens)
      ├── assert.swift (800 tokens)
      ├── command/
         ├── BalanceSizesCommandTest.swift (200 tokens)
         ├── CloseCommandTest.swift (300 tokens)
         ├── ConfigCommandTest.swift (2.1k tokens)
         ├── EchoCommandTest.swift (1100 tokens)
         ├── EvalCommandTest.swift (800 tokens)
         ├── ExecCommandTest.swift (100 tokens)
         ├── FalseCommandTest.swift (100 tokens)
         ├── FlattenWorkspaceTreeCommandTest.swift (200 tokens)
         ├── FocusCommandTest.swift (2.5k tokens)
         ├── FocusMonitorCommandTest.swift (300 tokens)
         ├── FormatTest.swift (4.3k tokens)
         ├── JoinWithCommandTest.swift (200 tokens)
         ├── LayoutCommandTest.swift (3.1k tokens)
         ├── ListAppsTest.swift (100 tokens)
         ├── ListModesTest.swift (600 tokens)
         ├── ListMonitorsTest.swift (100 tokens)
         ├── ListWindowsTest.swift (2.1k tokens)
         ├── ListWorkspacesTest.swift (1200 tokens)
         ├── ModeCommandTest.swift (200 tokens)
         ├── MoveCommandTest.swift (2.8k tokens)
         ├── MoveNodeToMonitorCommandTest.swift (300 tokens)
         ├── MoveNodeToWorkspaceCommandTest.swift (1700 tokens)
         ├── MoveWorkspaceToMonitorCommandTest.swift (200 tokens)
         ├── ResizeCommandTest.swift (1500 tokens)
         ├── RunCallbackCommandTest.swift (500 tokens)
         ├── SplitCommandTest.swift (500 tokens)
         ├── SubscribeCmdArgsTest.swift (500 tokens)
         ├── SummonWorkspaceCommandTest.swift (200 tokens)
         ├── SwapCommandTest.swift (1300 tokens)
         ├── TestCommandTest.swift (2000 tokens)
         ├── TriggerBindingCommandTest.swift (200 tokens)
         ├── TrueCommandTest.swift (100 tokens)
         ├── WorkspaceCommandTest.swift (1800 tokens)
      ├── config/
         ├── ConfigTest.swift (5.6k tokens)
         ├── ParseEnvVariablesTest.swift (500 tokens)
      ├── model/
         ├── ClientServerTest.swift (1000 tokens)
      ├── shell/
         ├── ShellLexerTest.swift (1600 tokens)
         ├── ShellParserTest.swift (1400 tokens)
         ├── ShellRunTest.swift (1100 tokens)
      ├── testUtil.swift (700 tokens)
      ├── tree/
         ├── OnWindowDetectedTest.swift (400 tokens)
         ├── TestApp.swift (200 tokens)
         ├── TestWindow.swift (300 tokens)
         ├── TilingContainer.swift (100 tokens)
         ├── TreeNodeTest.swift (700 tokens)
   ├── Cli/
      ├── _main.swift (1500 tokens)
      ├── cliUtil.swift
      ├── subcommandDescriptionsGenerated.swift (700 tokens)
   ├── Common/
      ├── appMetadata.swift (100 tokens)
      ├── cmdArgs/
         ├── ArgParser.swift (700 tokens)
         ├── ArgParserInput.swift (200 tokens)
         ├── ExitCode.swift (300 tokens)
         ├── ParsedCliArgs.swift (200 tokens)
         ├── ParsedCmd.swift (300 tokens)
         ├── SubArgParser.swift (300 tokens)
         ├── cmdArgsManifest.swift (1400 tokens)
         ├── impl/
            ├── BalanceSizesCmdArgs.swift (100 tokens)
            ├── CloseAllWindowsButCurrentCmdArgs.swift (100 tokens)
            ├── CloseCmdArgs.swift (100 tokens)
            ├── ConfigCmdArgs.swift (500 tokens)
            ├── DebugWindowsCmdArgs.swift (100 tokens)
            ├── EchoCmdArgs.swift (200 tokens)
            ├── EnableCmdArgs.swift (300 tokens)
            ├── EvalCmdArgs.swift (200 tokens)
            ├── ExecAndForgetCmdArgs.swift (100 tokens)
            ├── FalseCmdArgs.swift (100 tokens)
            ├── FlattenWorkspaceTreeCmdArgs.swift (100 tokens)
            ├── FocusBackAndForthCmdArgs.swift (100 tokens)
            ├── FocusCmdArgs.swift (1200 tokens)
            ├── FocusMonitorCmdArgs.swift (500 tokens)
            ├── FullscreenCmdArgs.swift (200 tokens)
            ├── JoinWithCmdArgs.swift (100 tokens)
            ├── LayoutCmdArgs.swift (700 tokens)
            ├── ListAppsCmdArgs.swift (400 tokens)
            ├── ListExecEnvVarsCmdArgs.swift (100 tokens)
            ├── ListModesCmdArgs.swift (200 tokens)
            ├── ListMonitorsCmdArgs.swift (300 tokens)
            ├── ListWindowsCmdArgs.swift (2.2k tokens)
            ├── ListWorkspacesCmdArgs.swift (800 tokens)
            ├── MacosNativeFullscreenCmdArgs.swift (300 tokens)
            ├── MacosNativeMinimizeCmdArgs.swift (100 tokens)
            ├── ModeCmdArgs.swift (100 tokens)
            ├── MoveCmdArgs.swift (500 tokens)
            ├── MoveMouseCmdArgs.swift (300 tokens)
            ├── MoveNodeToMonitorCmdArgs.swift (300 tokens)
            ├── MoveNodeToWorkspaceCmdArgs.swift (400 tokens)
            ├── MoveWorkpsaceToMonitorCmdArgs.swift (200 tokens)
            ├── ReloadConfigCmdArgs.swift (100 tokens)
            ├── ResizeCmdArgs.swift (400 tokens)
            ├── RunCallbackCmdArgs.swift (400 tokens)
            ├── SplitCmdArgs.swift (200 tokens)
            ├── SubscribeCmdArgs.swift (500 tokens)
            ├── SummonWorkspaceCmdArgs.swift (200 tokens)
            ├── SwapCmdArgs.swift (200 tokens)
            ├── TestCmdArgs.swift (500 tokens)
            ├── TestNotCmdArgs.swift (100 tokens)
            ├── TriggerBindingCmdArgs.swift (200 tokens)
            ├── TrueCmdArgs.swift (100 tokens)
            ├── VolumeCmdArgs.swift (300 tokens)
            ├── WorkspaceBackAndForthCmdArgs.swift (100 tokens)
            ├── WorkspaceCmdArgs.swift (600 tokens)
         ├── joinArgs.swift (200 tokens)
         ├── parseCmdArgs.swift (600 tokens)
         ├── parseSpecificCmdArgs.swift (600 tokens)
         ├── subcommandParsers.swift (100 tokens)
      ├── cmdHelpGenerated.swift (1700 tokens)
      ├── gitHashGenerated.swift
      ├── model/
         ├── AeroSpaceEnvVars.swift
         ├── AxAppThreadToken.swift (100 tokens)
         ├── CardinalDirection.swift (100 tokens)
         ├── CardinalOrDfsDirection.swift (200 tokens)
         ├── DfsNextPrev.swift
         ├── Init.swift (100 tokens)
         ├── MonitorDescription.swift (200 tokens)
         ├── NextPrev.swift
         ├── Orientation.swift (100 tokens)
         ├── WorkspaceName.swift (300 tokens)
         ├── clientServer.swift (500 tokens)
         ├── sponsorshipPrompts.swift (100 tokens)
      ├── util/
         ├── AeroAny.swift (200 tokens)
         ├── ArrSlice.swift (700 tokens)
         ├── ArrayEx.swift (300 tokens)
         ├── BoolEx.swift (100 tokens)
         ├── CaseInsensitiveRegex.swift (200 tokens)
         ├── CollectionEx.swift (100 tokens)
         ├── ComparableEx.swift
         ├── ConvenienceMutable.swift
         ├── DictionaryEx.swift (200 tokens)
         ├── EquatableNoop.swift (100 tokens)
         ├── JsonEncoderEx.swift (100 tokens)
         ├── Lateinit.swift (100 tokens)
         ├── MainActorEx.swift (100 tokens)
         ├── NWConnectionEx.swift (1000 tokens)
         ├── NonCopyable.swift (100 tokens)
         ├── Nullable.swift (100 tokens)
         ├── OptionalEx.swift (200 tokens)
         ├── ResultEx.swift (500 tokens)
         ├── SequenceEx.swift (1000 tokens)
         ├── StringEx.swift (1400 tokens)
         ├── StringLogicalSegments.swift (300 tokens)
         ├── TaskEx.swift (200 tokens)
         ├── commonUtil.swift (1400 tokens)
         ├── showMessageInGui.swift (200 tokens)
      ├── versionGenerated.swift
   ├── PrivateApi/
      ├── include/
         ├── module.modulemap
         ├── private.h (200 tokens)
         ├── private.m
├── axDumps/
   ├── 1password.json5 (1200 tokens)
   ├── 1password_large_type_window.json5 (1200 tokens)
   ├── 1password_mini_window.json5 (1200 tokens)
   ├── about_this_mac.json5 (1100 tokens)
   ├── alacritty_decorations_buttonless.json5 (1000 tokens)
   ├── apple_calendar.json5 (1300 tokens)
   ├── apple_calendar_settings.json5 (1100 tokens)
   ├── apple_followup_sign_in_to_a_new_device_confirmation.json5 (1000 tokens)
   ├── apple_mail.json5 (1500 tokens)
   ├── apple_mail_new_email.json5 (1200 tokens)
   ├── apple_mail_settings.json5 (1100 tokens)
   ├── archiveutility.json5 (1300 tokens)
   ├── brave.json5 (1200 tokens)
   ├── brave_pip.json5 (1100 tokens)
   ├── calculator.json5 (1000 tokens)
   ├── choose_1_5_0.json5 (700 tokens)
   ├── chrome.json5 (1100 tokens)
   ├── chrome_choose_what_to_share_popup.json5 (1200 tokens)
   ├── chrome_extensions_popup.json5 (600 tokens)
   ├── chrome_find_in_page.json5 (600 tokens)
   ├── chrome_pip.json5 (600 tokens)
   ├── chrome_sharing_is_in_progress_popup.json5 (600 tokens)
   ├── cleanshotx_monitor_1.json5 (700 tokens)
   ├── cleanshotx_monitor_2.json5 (700 tokens)
   ├── codex.json5 (1200 tokens)
   ├── codex_pet_window.json5 (700 tokens)
   ├── drracket.json5 (1300 tokens)
   ├── emacs.json5 (1300 tokens)
   ├── emacs_child_frame_corfu.json5 (600 tokens)
   ├── emacs_child_frame_posframe.json5 (600 tokens)
   ├── finder.json5 (1300 tokens)
   ├── finder_quick_look.json5 (900 tokens)
   ├── firefox.json5 (1100 tokens)
   ├── firefox_extensions_popup.json5 (700 tokens)
   ├── firefox_mouse_hover_over_extensions_button.json5 (600 tokens)
   ├── firefox_mouse_hover_over_tab.json5 (600 tokens)
   ├── firefox_non_native_fullscreen.json5 (600 tokens)
   ├── firefox_normal_window_when_non_native_fullscreen_in_background.json5 (1100 tokens)
   ├── firefox_pinterest_sign_in_with_google.json5 (1100 tokens)
   ├── firefox_pip.json5 (1100 tokens)
   ├── ghostty.json5 (1100 tokens)
   ├── ghostty_about.json5 (900 tokens)
   ├── ghostty_check_for_updates_1_dialog.json5 (700 tokens)
   ├── ghostty_check_for_updates_2_alert.json5 (800 tokens)
   ├── ghostty_config_error.json5 (1000 tokens)
   ├── ghostty_quick_terminal.json5 (800 tokens)
   ├── ghostty_window_decorations_false.json5 (600 tokens)
   ├── intellij.json5 (1500 tokens)
   ├── intellij_background_tasks.json5 (900 tokens)
   ├── intellij_context_menu.json5 (800 tokens)
   ├── intellij_native_open_window.json5 (800 tokens)
   ├── intellij_quick_doc_popup.json5 (900 tokens)
   ├── intellij_rebase_dialog.json5 (1200 tokens)
   ├── iphonesimulator.json5 (1300 tokens)
   ├── iterm2.json5 (1200 tokens)
   ├── iterm2_hotkey_window.json5 (1100 tokens)
   ├── iterm2_no_title_bar.json5 (1200 tokens)
   ├── jetbrains_toolbox.json5 (800 tokens)
   ├── karabiner_event_viewer.json5 (1300 tokens)
   ├── karabiner_settings.json5 (1600 tokens)
   ├── kitty_quick_access.json5 (700 tokens)
   ├── macos_capslock_popup_safari.json5 (700 tokens)
   ├── macos_capslock_popup_textedit.json5 (700 tokens)
   ├── macos_join_network.json5 (1200 tokens)
   ├── macos_share_window_purple_pill_sublime.json5 (800 tokens)
   ├── marta.json5 (1100 tokens)
   ├── microsoft_edge.json5 (1600 tokens)
   ├── microsoft_edge_pip.json5 (1100 tokens)
   ├── mpv_fullscreen.json5 (700 tokens)
   ├── mpv_windowed.json5 (1300 tokens)
   ├── nomachine_session_1.json5 (600 tokens)
   ├── nomachine_session_2.json5 (1000 tokens)
   ├── nomachine_welcome_window_1.json5 (800 tokens)
   ├── nomachine_welcome_window_2.json5 (1200 tokens)
   ├── outlook_reminder.json5 (1200 tokens)
   ├── qutebrowser.json5 (1300 tokens)
   ├── qutebrowser_context_menu.json5 (700 tokens)
   ├── qutebrowser_hide_decoration.json5 (800 tokens)
   ├── raycast.json5 (700 tokens)
   ├── raycast_settings.json5 (1100 tokens)
   ├── safari.json5 (1100 tokens)
   ├── safari_pinterest_sign_in_with_google.json5 (1400 tokens)
   ├── scenario_firefox_google_meet_share_window/
      ├── 01_firefox.json5 (300 tokens)
      ├── 02_firefox.json5 (600 tokens)
      ├── 03_firefox.json5 (300 tokens)
      ├── 04_firefox.json5 (600 tokens)
      ├── 05_apple_controlcenter.json5 (300 tokens)
      ├── 06_firefox.json5 (400 tokens)
      ├── 07_firefox.json5 (600 tokens)
      ├── README.md (100 tokens)
   ├── slack.json5 (1300 tokens)
   ├── slack_chat_in_a_separate_window.json5 (1300 tokens)
   ├── slack_huddle_share_screen_draw_on_screen_fake_window.json5 (1100 tokens)
   ├── slack_huddle_share_screen_floating_popup.json5 (1100 tokens)
   ├── slack_huddle_share_screen_target_picker.json5 (700 tokens)
   ├── spotify.json5 (1100 tokens)
   ├── spotify_miniplayer.json5 (1100 tokens)
   ├── steam_1.json5 (800 tokens)
   ├── steam_2.json5 (700 tokens)
   ├── sublime_text_4.json5 (1000 tokens)
   ├── system_settings.json5 (1200 tokens)
   ├── telegram.json5 (1100 tokens)
   ├── telegram_image_viewer.json5 (600 tokens)
   ├── terminal_app.json5 (1100 tokens)
   ├── transmission.json5 (1100 tokens)
   ├── transmission_torrent_inspector.json5 (1200 tokens)
   ├── vlc_empty.json5 (1100 tokens)
   ├── vlc_fullscreen.json5 (700 tokens)
   ├── vlc_video_playing.json5 (1100 tokens)
   ├── vs_code.json5 (1300 tokens)
   ├── vs_code_nativeFullScreen_false.json5 (1200 tokens)
   ├── vs_codium.json5 (1300 tokens)
   ├── vs_codium_nativeFullScreen_false.json5 (1200 tokens)
   ├── wisprFlow1.json5 (800 tokens)
   ├── wisprFlow2.json5 (800 tokens)
   ├── xcode.json5 (1300 tokens)
   ├── xcode_build_succeeded_popup.json5 (800 tokens)
   ├── xcode_installing_system_components.json5 (500 tokens)
   ├── xcode_open_quickly.json5 (1100 tokens)
   ├── xcode_quick_actions.json5 (1100 tokens)
   ├── xcode_settings.json5 (1300 tokens)
   ├── xcode_welcome_window.json5 (700 tokens)
   ├── zebar.json5 (600 tokens)
   ├── zed.json5 (1100 tokens)
   ├── zen_browser.json5 (1200 tokens)
   ├── zen_browser_pip.json5 (1300 tokens)
├── build-debug.sh (100 tokens)
├── build-docs.sh (400 tokens)
├── build-release.sh (900 tokens)
├── build-shell-completion.sh (100 tokens)
├── dev-docs/
   ├── architecture.md (500 tokens)
   ├── development.md (900 tokens)
├── docs/
   ├── aerospace-balance-sizes.adoc (200 tokens)
   ├── aerospace-close-all-windows-but-current.adoc (200 tokens)
   ├── aerospace-close.adoc (200 tokens)
   ├── aerospace-config.adoc (500 tokens)
   ├── aerospace-debug-windows.adoc (300 tokens)
   ├── aerospace-echo.adoc (400 tokens)
   ├── aerospace-enable.adoc (200 tokens)
   ├── aerospace-eval.adoc (300 tokens)
   ├── aerospace-exec-and-forget.adoc (300 tokens)
   ├── aerospace-false.adoc (200 tokens)
   ├── aerospace-flatten-workspace-tree.adoc (200 tokens)
   ├── aerospace-focus-back-and-forth.adoc (300 tokens)
   ├── aerospace-focus-monitor.adoc (300 tokens)
   ├── aerospace-focus.adoc (700 tokens)
   ├── aerospace-fullscreen.adoc (300 tokens)
   ├── aerospace-join-with.adoc (300 tokens)
   ├── aerospace-layout.adoc (500 tokens)
   ├── aerospace-list-apps.adoc (500 tokens)
   ├── aerospace-list-exec-env-vars.adoc (200 tokens)
   ├── aerospace-list-modes.adoc (200 tokens)
   ├── aerospace-list-monitors.adoc (500 tokens)
   ├── aerospace-list-windows.adoc (1000 tokens)
   ├── aerospace-list-workspaces.adoc (700 tokens)
   ├── aerospace-macos-native-fullscreen.adoc (300 tokens)
   ├── aerospace-macos-native-minimize.adoc (200 tokens)
   ├── aerospace-mode.adoc (200 tokens)
   ├── aerospace-move-mouse.adoc (400 tokens)
   ├── aerospace-move-node-to-monitor.adoc (400 tokens)
   ├── aerospace-move-node-to-workspace.adoc (400 tokens)
   ├── aerospace-move-workspace-to-monitor.adoc (400 tokens)
   ├── aerospace-move.adoc (600 tokens)
   ├── aerospace-reload-config.adoc (300 tokens)
   ├── aerospace-resize.adoc (300 tokens)
   ├── aerospace-run-callback.adoc (500 tokens)
   ├── aerospace-split.adoc (300 tokens)
   ├── aerospace-subscribe.adoc (500 tokens)
   ├── aerospace-summon-workspace.adoc (300 tokens)
   ├── aerospace-swap.adoc (300 tokens)
   ├── aerospace-test-not.adoc (200 tokens)
   ├── aerospace-test.adoc (800 tokens)
   ├── aerospace-trigger-binding.adoc (300 tokens)
   ├── aerospace-true.adoc (200 tokens)
   ├── aerospace-volume.adoc (200 tokens)
   ├── aerospace-workspace-back-and-forth.adoc (200 tokens)
   ├── aerospace-workspace.adoc (400 tokens)
   ├── aerospace.adoc (100 tokens)
   ├── assets/
      ├── h_accordion.png
      ├── h_tiles.png
      ├── icon.png
      ├── monitor-arrangement-1-bad.svg (19.8k tokens)
      ├── monitor-arrangement-1-good.svg (11.6k tokens)
      ├── monitor-arrangement-2-bad.svg (12.4k tokens)
      ├── monitor-arrangement-2-good.svg (7.5k tokens)
      ├── tree.png
      ├── v_accordion.png
   ├── commands.adoc (1600 tokens)
   ├── config-examples/
      ├── default-config.toml (1900 tokens)
      ├── i3-like-config-example.toml (600 tokens)
   ├── docinfo-footer.html (400 tokens)
   ├── goodies.adoc (1900 tokens)
   ├── guide.adoc (8.2k tokens)
   ├── index.html (100 tokens)
   ├── util/
      ├── all-monitors-option.adoc (100 tokens)
      ├── conditional-arguments-header.adoc
      ├── conditional-examples-header.adoc
      ├── conditional-exit-code-header.adoc
      ├── conditional-interpolation-variables-header.adoc
      ├── conditional-operators-header.adoc
      ├── conditional-options-header.adoc
      ├── conditional-output-format-header.adoc
      ├── header.adoc (100 tokens)
      ├── man-attributes.adoc
      ├── man-footer.adoc (100 tokens)
      ├── monitor-option.adoc (100 tokens)
      ├── site-attributes.adoc
      ├── window-id-flag-desc.adoc
      ├── workspace-flag-desc.adoc
├── format.sh
├── generate.sh (400 tokens)
├── grammar/
   ├── commands-bnf-grammar.txt (1500 tokens)
├── install-from-sources.sh (200 tokens)
├── legal/
   ├── LICENSE.txt
   ├── README.md (200 tokens)
   ├── third-party-license/
      ├── LICENSE-HotKey.txt (200 tokens)
      ├── LICENSE-ISSoundAdditions.txt (200 tokens)
      ├── LICENSE-TOMLDecoder.txt (200 tokens)
      ├── LICENSE-swift-collections.txt (2.4k tokens)
      ├── LICENSE-tomlplusplus.txt (200 tokens)
├── lint.sh (300 tokens)
├── makefile (100 tokens)
├── resources/
   ├── AeroSpace.entitlements
   ├── Assets.xcassets/
      ├── AccentColor.colorset/
         ├── Contents.json
      ├── AppIcon.appiconset/
         ├── Contents.json (200 tokens)
         ├── icon.png
      ├── Contents.json
├── run-cli.sh
├── run-debug.sh
├── script/
   ├── build-brew-cask.sh (600 tokens)
   ├── check-uncommitted-files.sh (100 tokens)
   ├── clean-project.sh
   ├── clean-xcode.sh
   ├── generate-cmd-help.sh (200 tokens)
   ├── install-dep.sh (800 tokens)
   ├── publish-release.sh (300 tokens)
   ├── reset-accessibility-permission-for-debug.sh (100 tokens)
   ├── setup.sh (600 tokens)
├── swift-test.sh (100 tokens)
├── test.sh (100 tokens)
├── xcode/
   ├── AeroSpace.xcodeproj/
      ├── project.pbxproj (2.7k tokens)
      ├── project.xcworkspace/
         ├── contents.xcworkspacedata
   ├── aerospace-package-symlink
   ├── project.yml (400 tokens)
```


## /.bundle/config

```bundle/config path="/.bundle/config" 
---
BUNDLE_PATH: ".deps/bundler-path"
BUNDLE_DISABLE_SHARED_GEMS: "1"

```

## /.github/DISCUSSION_TEMPLATE/potential-bugs.yml

```yml path="/.github/DISCUSSION_TEMPLATE/potential-bugs.yml" 
body:
  - type: textarea
    id: body
    attributes:
      label: Body
      value: |
        Steps to reproduce:
        1.
        2.
        3.

        Expected result:
        Actual result:

        ### Additional info

        \`\`\`shell
        $ aerospace -v
        \`\`\`
    validations:
      required: true

```

## /.github/FUNDING.yml

```yml path="/.github/FUNDING.yml" 
github: [nikitabobko]

```

## /.github/ISSUE_TEMPLATE/config.yml

```yml path="/.github/ISSUE_TEMPLATE/config.yml" 
blank_issues_enabled: false

```

## /.github/ISSUE_TEMPLATE/new-issue.yml

```yml path="/.github/ISSUE_TEMPLATE/new-issue.yml" 
name: New Issue
description: New Issue
body:
  - type: markdown
    attributes:
      value: |
        AeroSpace project doesn't accept Issues directly. Please prefer GitHub Discussions. See: https://github.com/nikitabobko/AeroSpace/issues/947
  - type: checkboxes
    id: checkbox
    attributes:
      label: 'Sanity check'
      options:
        - label: |
            I read https://github.com/nikitabobko/AeroSpace/issues/947
          required: true
  - type: textarea
    id: body
    attributes:
      label: Body
      value: |
        YOUR ISSUE WILL BE IMMEDIATELY CLOSED BY BOT, DON'T OPEN NEW ISSUES DIRECTLY, USE DISCUSSIONS INSTEAD
    validations:
      required: true

```

## /.github/gh-actions-runner-xcode-select.sh

```sh path="/.github/gh-actions-runner-xcode-select.sh" 
#!/usr/bin/env bash
set -e # Exit if one of commands exit with non-zero exit code
set -u # Treat unset variables and parameters other than the special parameters ‘@’ or ‘*’ as an error
set -o pipefail # Any command failed in the pipe fails the whole pipe
# set -x # Print shell commands as they are executed (or you can try -v which is less verbose)

sw_vers -productVersion
# Xcode version affects the target macOS SDK that we compile against + different Xcodes bundle different Swift verions
if sw_vers -productVersion | grep -q "^14"; then # macOS 14
  sudo xcode-select -s "$XCODE_16_DEVELOPER_DIR"
else
  sudo xcode-select -s "$XCODE_26_DEVELOPER_DIR"
fi

```

## /.github/pull_request_template.md

## PR checklist

- [ ] Explain your changes in the relevant commit messages rather than in the PR description. The PR description must not contain more information than the commit messages (except for images and other media).
- [ ] Each commit must explain what/why/how and motivation in its description. https://cbea.ms/git-commit/
- [ ] Don't forget to link the appropriate issues/discussions in commit messages (if applicable).
- [ ] Each commit must be an atomic change (a PR may contain several commits). Don't introduce new functional changes together with refactorings in the same commit.
- [ ] `./test.sh` exits with non-zero exit code.
- [ ] Avoid merge commits, always rebase and force push.

Failure to follow the checklist with no apparent reasons will result in silent PR rejection.


## /.github/workflows/build.yml

```yml path="/.github/workflows/build.yml" 
name: build

on:
  push:
    branches:
      - 'main'
      - 'rr/**' # "rr" stands for "remote run"
  pull_request:
    branches: [ "main" ]
  schedule:
    - cron: '0 0 * * *' # every day at 00:00

jobs:

  build-debug:
    strategy:
      # fail-fast: false # Disable fail-fast in matrix
      matrix:
        # https://docs.github.com/en/actions/reference/runners/github-hosted-runners#standard-github-hosted-runners-for-public-repositories
        # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-arm64-Readme.md
        # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-arm64-Readme.md
        # https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md
        #
        # Xcode versions:
        # - https://en.wikipedia.org/wiki/Xcode
        # - https://xcodereleases.com/?scope=release
        os: [macos-14, macos-15, macos-26]
    name: build-debug
    runs-on: ${{ matrix.os }}
    steps:
      - run: env # Debug
      - uses: actions/checkout@v6
      - run: ./.github/gh-actions-runner-xcode-select.sh
      - run: brew install swiftly bash
      - run: swiftly init --skip-install --assume-yes --verbose && swiftly install
      - run: swiftly run swift --version
      - run: ./build-debug.sh
      - run: ./test.sh

  # We build release artifacts only on the latest macOS versions because:
  # 1. It cuts the build time twice on GH Actions
  # 2. The latest Xcode version is not available on old macOS, and old Xcode versions bundle too old Swift version
  build-release:
    strategy:
      # fail-fast: false # Disable fail-fast in matrix
      matrix:
        os: [macos-15, macos-26]
    name: build-release
    runs-on: ${{ matrix.os }}
    steps:
      - run: env # Debug
      - uses: actions/checkout@v6
      - run: ./.github/gh-actions-runner-xcode-select.sh
      - run: brew install bash fish xcbeautify swiftly
      - run: swiftly init --skip-install --assume-yes --verbose && swiftly install
      - run: swiftly run swift --version
      - name: './build-release.sh'
        run: |
          # "-" means "Sign to run locally". There is no aerospace-codesign-certificate on GH Actions
          ./build-release.sh --codesign-identity -
          brew trust nikitabobko/tap
          ./install-from-sources.sh --dont-rebuild
      - name: cat ./.release/xcodebuild.log
        if: ${{ always() }}
        run: 'if test -f ./.release/xcodebuild.log; then cat ./.release/xcodebuild.log; fi'

```

## /.github/workflows/close-third-party-issues.yml

```yml path="/.github/workflows/close-third-party-issues.yml" 
name: close-third-party-issues

on:
  issues:
    types: [opened]

jobs:
  close-third-party-issues:
    name: Close third party issues
    runs-on: ubuntu-latest
    permissions:
      issues: write
    steps:
    - name: Close third party issues
      run: |
        set -e # Exit if one of commands exit with non-zero exit code
        set -u # Treat unset variables and parameters other than the special parameters ‘@’ or ‘*’ as an error
        set -o pipefail # Any command failed in the pipe fails the whole pipe

        author="$(gh issue view "$ISSUE" --json author --jq '.author.login')"

        close() {
          gh issue edit "$ISSUE" --add-label bin
          gh issue close "$ISSUE" --comment "Please don't open issues directly, use GitHub Discussions instead. See: https://github.com/nikitabobko/AeroSpace/issues/947"
          gh issue lock "$ISSUE"
        }

        test "$author" = nikitabobko || test "$author" = mobile-ar || test "$author" = rickyz || close
      env:
        GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        GH_REPO: ${{ github.repository }}
        ISSUE: ${{ github.event.issue.number }}

```

## /.github/workflows/label-incoming-prs.yml

```yml path="/.github/workflows/label-incoming-prs.yml" 
name: label-incoming-prs

on:
  pull_request_target:
    types: [opened]

jobs:
  label-incoming-prs:
    name: Label incoming PRs
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
    steps:
    - name: Add not-actionable label
      run: |
        set -e # Exit if one of commands exit with non-zero exit code
        set -u # Treat unset variables and parameters other than the special parameters ‘@’ or ‘*’ as an error
        set -o pipefail # Any command failed in the pipe fails the whole pipe

        author="$(gh pr view "$PR" --json author --jq '.author.login')"

        label() {
          gh pr edit "$PR" --add-label not-actionable
        }

        test "$author" = nikitabobko || test "$author" = mobile-ar || test "$author" = rickyz || label
      env:
        GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        GH_REPO: ${{ github.repository }}
        PR: ${{ github.event.number }}

```

## /.gitignore

```gitignore path="/.gitignore" 
/.idea
/.debug
/.release
/.shell-completion
/.site
/.man
/Gemfile.lock
# IDK, AppCode randomly creates this EMPTY file. I have no idea what this is
/default.profraw
.DS_Store
/xcode/.xcode-build
# Swift package manager
/.build
/.swiftpm
/.vscode
# External dependencies
/.deps

# For whatever local files that developers might want to keep there (I personally keep a separate `generated-html` git worktree here)
/.local

# XCode User settings
xcuserdata/
xcshareddata/

```

## /.idea/codeStyles/Project.xml

```xml path="/.idea/codeStyles/Project.xml" 
<component name="ProjectCodeStyleConfiguration">
  <code_scheme name="Project" version="173">
    <SwiftCodeStyleSettings>
      <option name="METHOD_CHAIN_INDENT" value="4" />
    </SwiftCodeStyleSettings>
    <codeStyleSettings language="Swift">
      <option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" />
      <option name="KEEP_SIMPLE_BLOCKS_IN_ONE_LINE" value="true" />
      <option name="KEEP_SIMPLE_METHODS_IN_ONE_LINE" value="true" />
      <option name="KEEP_SIMPLE_CLASSES_IN_ONE_LINE" value="true" />
      <indentOptions>
        <option name="CONTINUATION_INDENT_SIZE" value="4" />
      </indentOptions>
    </codeStyleSettings>
  </code_scheme>
</component>
```

## /.idea/codeStyles/codeStyleConfig.xml

```xml path="/.idea/codeStyles/codeStyleConfig.xml" 
<component name="ProjectCodeStyleConfiguration">
  <state>
    <option name="USE_PER_PROJECT_SETTINGS" value="true" />
  </state>
</component>
```

## /.idea/inspectionProfiles/Project_Default.xml

```xml path="/.idea/inspectionProfiles/Project_Default.xml" 
<component name="InspectionProjectProfileManager">
  <profile version="1.0">
    <option name="myName" value="Project Default" />
    <inspection_tool class="SwiftUnnecessarySelfQualifier" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
  </profile>
</component>
```

## /.swift-version

```swift-version path="/.swift-version" 
6.3.2

```

## /.swiftformat

```swiftformat path="/.swiftformat" 
# https://github.com/nicklockwood/SwiftFormat/blob/main/Rules.md
--indentcase true
--patternlet inline
--indentstrings true

# https://github.com/nicklockwood/SwiftFormat/issues/483 fix indentation for expressions nested in ternary
--wrapternary before-operators

--disable all

# --enable docComments

--enable anyObjectProtocol
--enable blankLineAfterImports
--enable blankLinesAtEndOfScope
--enable blankLinesBetweenImports
--enable conditionalAssignment
--enable docCommentsBeforeModifiers
--enable duplicateImports
--enable elseOnSameLine
--enable emptyBraces
--enable emptyExtensions
--enable enumNamespaces
--enable fileMacro
--enable genericExtensions
--enable indent
--enable leadingDelimiters
--enable linebreakAtEndOfFile
--enable linebreaks
--enable numberFormatting
--enable preferCountWhere
--enable preferFinalClasses
--enable redundantAsync
--enable redundantBackticks
--enable redundantBreak
--enable redundantClosure
--enable redundantEquatable
--enable redundantFileprivate
--enable redundantGet
--enable redundantLet
--enable redundantLetError
--enable redundantMemberwiseInit
--enable redundantObjc
--enable redundantOptionalBinding
--enable redundantThrows
--enable redundantTypedThrows
--enable redundantVoidReturnType
--enable semicolons
--enable spaceAroundBraces
--enable spaceAroundBrackets
--enable spaceAroundGenerics
--enable spaceAroundOperators
--enable spaceAroundParens
--enable spaceInsideBraces
--enable spaceInsideBrackets
--enable spaceInsideGenerics
--enable spaceInsideParens
--enable strongOutlets
--enable trailingClosures
--enable trailingCommas
--enable trailingSpace
--enable urlMacro
--enable wrapMultilineStatementBraces

--enable extensionAccessControl
--extensionacl on-declarations

```

## /.swiftlint.yml

```yml path="/.swiftlint.yml" 
excluded:
  - .build
  - xcode

# https://realm.github.io/SwiftLint/rule-directory.html
only_rules:
  # - line_length # todo fix it
  - colon
  - computed_accessors_order
  - dynamic_inline # Avoid using ‘dynamic’ and ‘@inline(__always)’ together
  - empty_enum_arguments
  - empty_parameters # Prefer () -> over Void ->
  - empty_string # Prefer checking isEmpty over comparing string to an empty string literal
  - file_name_no_space
  - first_where
  - implicit_getter
  - is_disjoint
  - last_where # Prefer using .last(where:) over .filter { }.last in collections
  - legacy_constant
  - legacy_constructor # Swift constructors are preferred over legacy convenience functions
  - legacy_hashing # Prefer using the hash(into:) function instead of overriding hashValue
  - legacy_nsgeometry_functions # Struct extension properties and methods are preferred over legacy functions
  - legacy_random # Prefer using type.random(in:) over legacy functions
  - local_doc_comment # Prefer regular comments over doc comments in local scopes
  - no_fallthrough_only
  - no_space_in_method_call
  - nsobject_prefer_isequal # NSObject subclasses should implement isEqual instead of ==
  - function_name_whitespace
  - optional_enum_case_matching
  - redundant_discardable_let
  - redundant_nil_coalescing # nil coalescing operator is only evaluated if the lhs is nil, coalescing operator with nil as rhs is redundant
  - switch_case_alignment
  - toggle_bool
  - trailing_newline
  - trailing_semicolon # Lines should not have trailing semicolons
  - trailing_whitespace # Lines should not have trailing whitespace
  - unavailable_condition # Use #unavailable/#available instead of #available/#unavailable with an empty body.
  - unneeded_break_in_switch # Avoid using unneeded break statements
  - unneeded_override # Remove overridden functions that don’t do anything except call their super
  # - unused_closure_parameter
  - unused_control_flow_label
  - unused_enumerated # When the index or the item is not used, .enumerated() can be removed.
  - unused_setter_value
  - weak_delegate # Delegates should be weak to avoid reference cycles

switch_case_alignment:
  indented_cases: true

strict: true
# quiet: true

```

## /CONTRIBUTING.md

# Contributing

The main and the most important rule: **read the room!**

* Does your patch look like typical commit in the repo?
* Does your commit message look like typical commit message in the repo?
* Does your test look like typical test in the repo?
* etc.

## Submiting bugs and feature ideas

Submit bugs to https://github.com/nikitabobko/AeroSpace/discussions/categories/potential-bugs

Submit feature ideas to https://github.com/nikitabobko/AeroSpace/discussions/categories/feature-ideas

Rules:
* Search for duplicates (in GitHub Issues and Discussions) before creating a new discussion
* Upvote for issues/discussions that you find useful

**Consider including in bug reports**

* `aerospace debug-windows` output, if the problem is about handling some windows
* Screenshots of problematic windows
* Videos of problematic windows
* What did you try to resolve the issue?
* Your config
* AeroSpace version
* macOS version

**Consider including in feature request**

* Use cases!
* Alternative approaches
* Links to docs of similar features in other window managers that you know
* Synopsis, if you suggest a new command
* Mental model description

## Submiting code

There are 2 options:
1. Send email patches to: `echo YWVyb3NwYWNlLXBhdGNoZXNAYm9ia28ueHl6Cg== | base64 --decode`
2. Send GitHub PRs

**License Agreement**. By contributing changes to this repository, you agree to license your contributions under the MIT license.

Maintainers can apply your patch with arbitrary modifications.

## Spread the word

Do you like the project? Does AeroSpace finally fix your problems with windows management on macOS? Good to hear it!

* Spread the word in social networks! (Don't forget to share the link :) )
* Talk about AeroSpace to your colleagues and friends
* Write a blogpost about your workflows
* Record a YouTube video

## Share your workflow and tips

Submit your tips to [the Goodies page](https://nikitabobko.github.io/AeroSpace/goodies). The source code of the page can be found in `./docs` directory

## Support the project financially

Supporting the project financially counts as a contribution (even if it's just a $1/month).
You can sponsor the project on GitHub Sponsors page: https://github.com/sponsors/nikitabobko


## /Gemfile

``` path="/Gemfile" 
# frozen_string_literal: true
ruby '~> 3.0' # >= 3.0 and < 4.0

source "https://rubygems.org"

# https://github.com/asciidoctor/asciidoctor/releases
gem 'asciidoctor', '2.0.23'

# https://github.com/pygments/pygments.rb/releases
# https://github.com/pygments/pygments/releases
gem 'pygments.rb', git: 'https://github.com/nikitabobko/pygments.rb.git', ref: '1a4e502ee49c3fd93dae4abb171fea49f9d52561'

```

## /LICENSE.txt

MIT License

Copyright (c) 2023 Nikita Bobko

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


## /Package.resolved

```resolved path="/Package.resolved" 
{
  "originHash" : "6466a3de6b03a7f9499cc6ad528be037cd42ee688a16c00bd96a3fa208099b1e",
  "pins" : [
    {
      "identity" : "hotkey",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/soffes/HotKey",
      "state" : {
        "revision" : "a3cf605d7a96f6ff50e04fcb6dea6e2613cfcbe4",
        "version" : "0.2.1"
      }
    },
    {
      "identity" : "issoundadditions",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/InerziaSoft/ISSoundAdditions",
      "state" : {
        "revision" : "4b555f0354e6c280917bae8a598a258efe87ab98",
        "version" : "2.0.1"
      }
    },
    {
      "identity" : "swift-collections",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-collections",
      "state" : {
        "revision" : "7b847a3b7008b2dc2f47ca3110d8c782fb2e5c7e",
        "version" : "1.3.0"
      }
    },
    {
      "identity" : "tomldecoder",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/dduan/TOMLDecoder",
      "state" : {
        "revision" : "fa1103a62b1c08cc08eabc58dda8b55887ff1622",
        "version" : "0.4.4"
      }
    }
  ],
  "version" : 3
}

```

## /Package.swift

```swift path="/Package.swift" 
// swift-tools-version: 6.2
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let swiftSettings: [SwiftSetting] = [
    .enableUpcomingFeature("NonisolatedNonsendingByDefault"),
    .strictMemorySafety(),
]

let package = Package(
    name: "AeroSpacePackage",
    // Runtime support for parameterized protocol types is only available in macOS 13.0.0 or newer
    // And it specifies deploymentTarget for CLI
    platforms: [.macOS(.v13)],
    // Products define the executables and libraries a package produces, making them visible to other packages.
    products: [
        .executable(name: "aerospace", targets: ["Cli"]),
        // Don't use this build for release, use xcode instead
        .executable(name: "AeroSpaceApp", targets: ["AeroSpaceApp"]),
        // We only need to expose this as a product for xcode
        .library(name: "AppBundle", targets: ["AppBundle"]),
    ],
    dependencies: [
        .package(url: "https://github.com/InerziaSoft/ISSoundAdditions.git", exact: "2.0.1"),
        .package(url: "https://github.com/dduan/TOMLDecoder", exact: "0.4.4"),
        .package(url: "https://github.com/apple/swift-collections.git", exact: "1.3.0"),
        .package(url: "https://github.com/soffes/HotKey.git", exact: "0.2.1"),
    ],
    // Targets are the basic building blocks of a package, defining a module or a test suite.
    // Targets can depend on other targets in this package and products from dependencies.
    targets: [
        // Exposes the private _AXUIElementGetWindow function to swift
        .target(
            name: "PrivateApi",
            path: "Sources/PrivateApi",
            publicHeadersPath: "include",
        ),
        .target(
            name: "Common",
            dependencies: [
                .product(name: "Collections", package: "swift-collections"),
            ],
            swiftSettings: swiftSettings,
        ),
        .target(
            name: "AppBundle",
            dependencies: [
                .product(name: "Collections", package: "swift-collections"),
                .product(name: "HotKey", package: "HotKey"),
                .product(name: "ISSoundAdditions", package: "ISSoundAdditions"),
                .product(name: "TOMLDecoder", package: "TOMLDecoder"),
                .target(name: "Common"),
                .target(name: "PrivateApi"),
            ],
            swiftSettings: swiftSettings,
        ),
        .executableTarget(
            name: "AeroSpaceApp",
            dependencies: [
                .target(name: "AppBundle"),
            ],
            swiftSettings: swiftSettings,
        ),
        .executableTarget(
            name: "Cli",
            dependencies: [
                .target(name: "Common"),
            ],
            swiftSettings: swiftSettings,
        ),
        .testTarget(
            name: "AppBundleTests",
            dependencies: [
                .target(name: "AppBundle"),
            ],
            swiftSettings: swiftSettings,
        ),
    ],
)

```

## /README.md

# AeroSpace Beta [![Build](https://github.com/nikitabobko/AeroSpace/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/nikitabobko/AeroSpace/actions/workflows/build.yml)

<img src="./resources/Assets.xcassets/AppIcon.appiconset/icon.png" width="40%" align="right">

AeroSpace is an i3-like tiling window manager for macOS

Videos:
- [YouTube 91 sec Demo](https://www.youtube.com/watch?v=UOl7ErqWbrk)
- [YouTube Guide by Josean Martinez](https://www.youtube.com/watch?v=-FoWClVHG5g)

Docs:
- [AeroSpace Guide](https://nikitabobko.github.io/AeroSpace/guide)
- [AeroSpace Commands](https://nikitabobko.github.io/AeroSpace/commands)
- [AeroSpace Goodies](https://nikitabobko.github.io/AeroSpace/goodies)

## Key features

- Tiling window manager based on a [tree paradigm](https://nikitabobko.github.io/AeroSpace/guide#tree)
- [i3](https://i3wm.org/) inspired
- Fast workspaces switching without animations and without the necessity to disable SIP
- AeroSpace employs its [own emulation of virtual workspaces](https://nikitabobko.github.io/AeroSpace/guide#emulation-of-virtual-workspaces) instead of relying on native macOS Spaces due to [their considerable limitations](https://nikitabobko.github.io/AeroSpace/guide#emulation-of-virtual-workspaces)
- Plain text configuration (dotfiles friendly). See: [default-config.toml](https://nikitabobko.github.io/AeroSpace/guide#default-config)
- CLI first (manpages and shell completion included)
- Doesn't require disabling SIP (System Integrity Protection)
- [Proper multi-monitor support](https://nikitabobko.github.io/AeroSpace/guide#multiple-monitors) (i3-like paradigm)

## Installation

Install via [Homebrew](https://brew.sh/) to get autoupdates (Preferred)

```
brew install --cask nikitabobko/tap/aerospace
```

In multi-monitor setup please make sure that monitors [are properly arranged](https://nikitabobko.github.io/AeroSpace/guide#proper-monitor-arrangement).

Other installation options: https://nikitabobko.github.io/AeroSpace/guide#installation

> [!NOTE]
> By using AeroSpace, you acknowledge that it's not [notarized](https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution).
>
> Notarization is a "security" feature by Apple.
> You send binaries to Apple, and they either approve them or not.
> In reality, notarization is about building binaries the way Apple likes it.
>
> I don't have anything against notarization as a concept.
> I specifically don't like the way Apple does notarization.
> I don't have time to deal with Apple.
>
> [Homebrew installation script](https://github.com/nikitabobko/homebrew-tap/blob/main/Casks/aerospace.rb) is configured to
> automatically delete `com.apple.quarantine` attribute, that's why the app should work out of the box, without any warnings that
> "Apple cannot check AeroSpace for malicious software"

## Community, discussions, issues

AeroSpace project doesn't accept Issues directly - we ask you to create a [Discussion](https://github.com/nikitabobko/AeroSpace/discussions) first.
Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for more details.

Community discussions happen at GitHub Discussions.
There you can discuss bugs, propose new features, ask your questions, show off your setup, or just chat.

There are 7 channels:
-   [#all](https://github.com/nikitabobko/AeroSpace/discussions).
    [RSS](https://github.com/nikitabobko/AeroSpace/discussions.atom?discussions_q=sort%3Adate_created).
    Feed with all discussions.
-   [#announcements](https://github.com/nikitabobko/AeroSpace/discussions/categories/announcements).
    [RSS](https://github.com/nikitabobko/AeroSpace/discussions/categories/announcements.atom?discussions_q=category%3Aannouncements+sort%3Adate_created).
    Only maintainers can post here.
    Highly moderated traffic.
-   [#announcements-releases](https://github.com/nikitabobko/AeroSpace/discussions/categories/announcements-releases).
    [RSS](https://github.com/nikitabobko/AeroSpace/discussions/categories/announcements-releases.atom?discussions_q=category%3Aannouncements-releases+sort%3Adate_created).
    Announcements about non-patch releases.
    Only maintainers can post here.
-   [#feature-ideas](https://github.com/nikitabobko/AeroSpace/discussions/categories/feature-ideas).
    [RSS](https://github.com/nikitabobko/AeroSpace/discussions/categories/feature-ideas.atom?discussions_q=category%3Afeature-ideas+sort%3Adate_created).
-   [#general](https://github.com/nikitabobko/AeroSpace/discussions/categories/general).
    [RSS](https://github.com/nikitabobko/AeroSpace/discussions/categories/general.atom?discussions_q=sort%3Adate_created+category%3Ageneral).
-   [#potential-bugs](https://github.com/nikitabobko/AeroSpace/discussions/categories/potential-bugs).
    [RSS](https://github.com/nikitabobko/AeroSpace/discussions/categories/potential-bugs.atom?discussions_q=category%3Apotential-bugs+sort%3Adate_created).
    If you think that you have encountered a bug, you can discuss your bugs here.
-   [#questions-and-answers](https://github.com/nikitabobko/AeroSpace/discussions/categories/questions-and-answers).
    [RSS](https://github.com/nikitabobko/AeroSpace/discussions/categories/questions-and-answers.atom?discussions_q=category%3Aquestions-and-answers+sort%3Adate_created).
    Everyone is welcome to ask questions.
    Everyone is encouraged to answer other people's questions.

## Project status

Public Beta. AeroSpace can be used as a daily driver, but expect breaking changes until 1.0 is reached.

What stops us from 1.0 release:
- [x] https://github.com/nikitabobko/AeroSpace/issues/131 Performance. Implement thread-per-application to circumvent macOS blocking AX API.
- [ ] https://github.com/nikitabobko/AeroSpace/issues/1215 _Big refactoring_. Rewrite mutable double-linked core tree data structure to immutable single-linked persistent tree.
  Important for: stability and potential performance
  - [ ] https://github.com/nikitabobko/AeroSpace/issues/1216 The big refactoring will help us to fix stability issue that windows may randomly jump to the focused workspace
  - [ ] https://github.com/nikitabobko/AeroSpace/issues/68 The big refactoring will help us to support macOS native tabs
- [x] https://github.com/nikitabobko/AeroSpace/issues/278 Implement shell-like combinators.
  Ignore a lot of crazy fuss in the issue,
  We are most probably going with the minimal approach to only introduce common shell-combinators: `||`, `&&`, `;` and `eval` command to send multiple commands in one go.
- [ ] https://github.com/nikitabobko/AeroSpace/issues/1012 Investigate a possibility to use `CGEvent.tapCreate` API for global hotkeys
  - [ ] https://github.com/nikitabobko/AeroSpace/issues/28 Maybe it will allow to distinguish left and right modifiers. Maybe not

Big and important issues which will go after 1.0 release:
- [ ] https://github.com/nikitabobko/AeroSpace/issues/2 sticky windows
- [ ] https://github.com/nikitabobko/AeroSpace/issues/260 Dynamic TWM

## Development

A notes on how to setup the project, build it, how to run the tests, etc. can be found here: [dev-docs/development.md](./dev-docs/development.md)

## Project values

**Values**
- AeroSpace is targeted at advanced users and developers
- Keyboard centric
- Breaking changes (configuration files, CLI, behavior) are avoided as much as possible, but it must not let the software stagnate.
  Thus breaking changes can happen, but with careful considerations and helpful message.
  [Semver](https://semver.org/) major version is bumped in case of a breaking change (It's all guaranteed once AeroSpace reaches 1.0 version, until then breaking changes just happen)
- AeroSpace doesn't use GUI, unless necessarily
  - AeroSpace will never provide a GUI for configuration.
    For advanced users, it's easier to edit a configuration file in text editor rather than navigating through checkboxes in GUI.
  - Status menu icon is ok, because visual feedback is needed
- Provide _practical_ features. Fancy appearance features are not _practical_ (e.g. window borders, transparency, animations, etc.)
- "dark magic" (aka "private APIs", "code injections", etc.) must be avoided as much as possible
  - Right now, AeroSpace uses only a single private API to get window ID of accessibility object `_AXUIElementGetWindow`.
    Everything else is [macOS public accessibility API](https://developer.apple.com/documentation/applicationservices/axuielement_h).
  - AeroSpace will never require you to disable SIP (System Integrity Protection).
  - The goal is to make AeroSpace easily maintainable, and resistant to macOS updates.

**Non Values**
- Play nicely with existing macOS features.
  If limitations are imposed then AeroSpace won't play nicely with existing macOS features
  (For example, AeroSpace doesn't acknowledge the existence of macOS Spaces, and it uses [emulation of its own workspaces](https://nikitabobko.github.io/AeroSpace/guide#emulation-of-virtual-workspaces))
- Ricing.
  AeroSpace provides only a very minimal support for ricing - gaps and a few callbacks for integrations with bars.
  The current maintainer doesn't care about ricing.
  Ricing issues are not a priority, and they are mostly ignored.
  The ricing stance can change only with the appearance of more maintainers.

## macOS compatibility table

* AeroSpace binary runs on: macOS 13+
* AeroSpace debug build from sources is supported on: macOS 14+
* AeroSpace release build from sources is supported on: macOS 15+ (Requires Xcode 26+)

## Sponsorship

AeroSpace is developed and maintained in my free time.
If you find it useful, [consider sponsoring](https://github.com/sponsors/nikitabobko#sponsors).

## People who have write access

In alphabetical order:

- [@mobile-ar](https://github.com/mobile-ar)
- [@nikitabobko](https://github.com/nikitabobko)
- [@rickyz](https://github.com/rickyz)

## Tip of the day

```bash
defaults write -g NSWindowShouldDragOnGesture -bool true
```

Now, you can move windows by holding `ctrl`+`cmd` and dragging any part of the window (not necessarily the window title)

Source: [reddit](https://www.reddit.com/r/MacOS/comments/k6hiwk/keyboard_modifier_to_simplify_click_drag_of/)

## Related projects

- [Amethyst](https://github.com/ianyh/Amethyst) - tiling window manager à la xmonad
- [InstantSpaceSwitcher](https://github.com/jurplel/InstantSpaceSwitcher) - Instant space switching by synthesizing trackpad gesture with an artificially high velocity
- [yabai](https://github.com/koekeishiya/yabai) - a tiling window manager for macOS based on binary space partitioning


## /Sources/AeroSpaceApp/AeroSpaceApp.swift

```swift path="/Sources/AeroSpaceApp/AeroSpaceApp.swift" 
import AppBundle
import SwiftUI

// This file is shared between SPM and xcode project

@main
struct AeroSpaceApp: App {
    @StateObject var viewModel = TrayMenuModel.shared
    @StateObject var messageModel = MessageModel.shared
    @Environment(\.openWindow) var openWindow: OpenWindowAction

    init() {
        initAppBundle()
    }

    var body: some Scene {
        menuBar(viewModel: viewModel)
        getMessageWindow(messageModel: messageModel)
            .onChange(of: messageModel.message) { message in
                if message != nil {
                    openWindow(id: messageWindowId)
                }
            }
    }
}

```

## /Sources/AppBundle/GlobalObserver.swift

```swift path="/Sources/AppBundle/GlobalObserver.swift" 
import AppKit
import Common

enum GlobalObserver {
    private static func onNotif(_ notification: Notification) {
        // Third line of defence against lock screen window. See: closedWindowsCache
        // Second and third lines of defence are technically needed only to avoid potential flickering
        if (notification.userInfo?[NSWorkspace.applicationUserInfoKey] as? NSRunningApplication)?.bundleIdentifier == lockScreenAppBundleId {
            return
        }
        let notifName = notification.name.rawValue
        Task.startUnstructured { @MainActor in
            if !TrayMenuModel.shared.isEnabled { return }
            if notifName == NSWorkspace.didActivateApplicationNotification.rawValue {
                scheduleCancellableCompleteRefreshSession(.globalObserver(notifName), optimisticallyPreLayoutWorkspaces: true)
            } else {
                scheduleCancellableCompleteRefreshSession(.globalObserver(notifName))
            }
        }
    }

    private static func onHideApp(_ notification: Notification) {
        let notifName = notification.name.rawValue
        Task.startUnstructured { @MainActor in
            guard let token: RunSessionGuard = .isServerEnabled else { return }
            try await runLightSession(.globalObserver(notifName), token) {
                if config.automaticallyUnhideMacosHiddenApps {
                    if let w = prevFocus?.windowOrNil,
                       w.macAppUnsafe.nsApp.isHidden,
                       // "Hide others" (cmd-alt-h) -> don't force focus
                       // "Hide app" (cmd-h) -> force focus
                       MacApp.allAppsMap.values.count(where: { $0.nsApp.isHidden }) == 1
                    {
                        // Force focus
                        _ = w.focusWindow()
                        w.nativeFocus()
                    }
                    for app in MacApp.allAppsMap.values {
                        app.nsApp.unhide()
                    }
                }
            }
        }
    }

    @MainActor
    static func initObserver() {
        let nc = NSWorkspace.shared.notificationCenter
        nc.addObserver(forName: NSWorkspace.didLaunchApplicationNotification, object: nil, queue: .main, using: onNotif)
        nc.addObserver(forName: NSWorkspace.didActivateApplicationNotification, object: nil, queue: .main, using: onNotif)
        nc.addObserver(forName: NSWorkspace.didHideApplicationNotification, object: nil, queue: .main, using: onHideApp)
        nc.addObserver(forName: NSWorkspace.didUnhideApplicationNotification, object: nil, queue: .main, using: onNotif)
        nc.addObserver(forName: NSWorkspace.activeSpaceDidChangeNotification, object: nil, queue: .main, using: onNotif)
        nc.addObserver(forName: NSWorkspace.didTerminateApplicationNotification, object: nil, queue: .main, using: onNotif)

        NSEvent.addGlobalMonitorForEvents(matching: .leftMouseUp) { _ in
            // todo reduce number of refreshSession in the callback
            //  resetManipulatedWithMouseIfPossible might call its own refreshSession
            //  The end of the callback calls refreshSession
            Task.startUnstructured { @MainActor in
                guard let token: RunSessionGuard = .isServerEnabled else { return }
                try await resetManipulatedWithMouseIfPossible()
                let mouseLocation = mouseLocation
                let clickedMonitor = mouseLocation.monitorApproximation
                switch true {
                    // Detect clicks on desktop of different monitors
                    case clickedMonitor.visibleRect.contains(mouseLocation) && clickedMonitor.activeWorkspace != focus.workspace:
                        _ = try await runLightSession(.globalObserverLeftMouseUp, token) {
                            clickedMonitor.activeWorkspace.focusWorkspace()
                        }
                    // Detect close button clicks for unfocused windows. Yes, kAXUIElementDestroyedNotification is that unreliable
                    //  And trigger new window detection that could be delayed due to mouseDown event
                    default:
                        scheduleCancellableCompleteRefreshSession(.globalObserverLeftMouseUp)
                }
            }
        }
    }
}

```

## /Sources/AppBundle/command/CmdEnv.swift

```swift path="/Sources/AppBundle/command/CmdEnv.swift" 
import Common

struct CmdEnv {
    var windowId: UInt32? = nil
    var workspaceName: String? = nil

    static let defaultEnv: CmdEnv = .init()

    consuming func withFocus(_ focus: LiveFocus) -> Self {
        return switch focus.asLeaf {
            case .window(let wd): withWindowId(wd.windowId)
            case .emptyWorkspace(let ws): withWorkspaceName(ws.name)
        }
    }

    consuming func withWindowId(_ windowId: UInt32) -> CmdEnv {
        self.windowId = windowId
        self.workspaceName = nil
        return self
    }

    consuming func withWorkspaceName(_ workspaceName: String) -> CmdEnv {
        self.windowId = nil
        self.workspaceName = workspaceName
        return self
    }

    var asMap: [String: String] {
        var result = [String: String]()
        if let windowId {
            result[AEROSPACE_WINDOW_ID] = windowId.description
        }
        if let workspaceName {
            result[AEROSPACE_WORKSPACE] = workspaceName.description
        }
        return result
    }
}

```

## /Sources/AppBundle/command/CmdIo.swift

```swift path="/Sources/AppBundle/command/CmdIo.swift" 
import Common

struct CmdStdin: ~Copyable {
    private var input: String = ""
    init(_ input: String) {
        self.input = input
    }
    static var emptyStdin: CmdStdin { .init("") }

    mutating func readAll() -> String {
        let result = input
        input = ""
        return result
    }
}

protocol CmdIo: AnyObject {
    var stdout: [String] { get set }
    var stderr: [String] { get set }
    func readStdin() -> String
}

extension CmdIo {
    @discardableResult func out(_ msg: String) -> IoSideEffect { stdout.append(msg); return .instance }
    @discardableResult func err(_ msg: String) -> IoSideEffect { stderr.append(msg); return .instance }
    @discardableResult func out(_ msg: [String]) -> IoSideEffect { stdout += msg; return .instance }
    // periphery:ignore
    @discardableResult func err(_ msg: [String]) -> IoSideEffect { stderr += msg; return .instance }
}

final class CmdIoImpl: CmdIo {
    private var stdin: CmdStdin
    var stdout: [String] = []
    var stderr: [String] = []

    init(stdin: consuming CmdStdin) { self.stdin = stdin }
    func readStdin() -> String { stdin.readAll() }

    static var emptyStdinIgnoringOut: CmdIo { CmdIoImpl(stdin: .emptyStdin) }
}

final class CmdIoForwardingStdin: CmdIo {
    private var stdin: CmdIo
    var stdout: [String] = []
    var stderr: [String] = []

    init(stdin: CmdIo) { self.stdin = stdin }
    func readStdin() -> String { stdin.readStdin() }
}

struct CmdResult: Equatable {
    let stdout: [String]
    let stderr: [String]
    let exitCode: Int32ExitCode
}

```

## /Sources/AppBundle/command/Command.swift

```swift path="/Sources/AppBundle/command/Command.swift" 
import AppKit
import Common

protocol Command: AeroAny, Equatable, Sendable {
    associatedtype T: CmdArgs

    var args: T { get }
    @MainActor
    func run(_ env: CmdEnv, _ io: CmdIo) async -> T.ExitCodeType

    /// We should reset closedWindowsCache when the command can potentially change the tree
    var shouldResetClosedWindowsCache: Bool { get }
}

extension Command {
    static func == (lhs: Self, rhs: Self) -> Bool {
        return lhs.args.equals(rhs.args)
    }

    nonisolated func equals(_ other: any Command) -> Bool {
        (other as? Self).flatMap { self == $0 } ?? false
    }
}

extension Command {
    var info: CmdStaticInfo { T.info }
}

extension Command {
    @MainActor
    @discardableResult
    func run(_ env: CmdEnv, _ stdin: consuming CmdStdin) async -> CmdResult {
        return await Shell.cmd(self).run(env, stdin)
    }
}

```

## /Sources/AppBundle/command/cmdManifest.swift

```swift path="/Sources/AppBundle/command/cmdManifest.swift" 
import Common

extension CmdArgs {
    func toCommand() -> ParsedCmd<any Command> {
        let command: any Command
        switch Self.info.kind {
            case ._false:
                command = FalseCommand(args: self as! FalseCmdArgs)
            case ._true:
                command = TrueCommand(args: self as! TrueCmdArgs)
            case .balanceSizes:
                command = BalanceSizesCommand(args: self as! BalanceSizesCmdArgs)
            case .close:
                command = CloseCommand(args: self as! CloseCmdArgs)
            case .closeAllWindowsButCurrent:
                command = CloseAllWindowsButCurrentCommand(args: self as! CloseAllWindowsButCurrentCmdArgs)
            case .config:
                command = ConfigCommand(args: self as! ConfigCmdArgs)
            case .debugWindows:
                command = DebugWindowsCommand(args: self as! DebugWindowsCmdArgs)
            case .echo:
                command = EchoCommand(args: self as! EchoCmdArgs)
            case .enable:
                command = EnableCommand(args: self as! EnableCmdArgs)
            case .eval:
                command = EvalCommand(args: self as! EvalCmdArgs)
            case .execAndForget:
                return .failure("exec-and-forget is not a real command and it's NOT allowed in the shell", EXIT_CODE_TWO)
            case .flattenWorkspaceTree:
                command = FlattenWorkspaceTreeCommand(args: self as! FlattenWorkspaceTreeCmdArgs)
            case .focus:
                command = FocusCommand(args: self as! FocusCmdArgs)
            case .focusBackAndForth:
                command = FocusBackAndForthCommand(args: self as! FocusBackAndForthCmdArgs)
            case .focusMonitor:
                command = FocusMonitorCommand(args: self as! FocusMonitorCmdArgs)
            case .fullscreen:
                command = FullscreenCommand(args: self as! FullscreenCmdArgs)
            case .joinWith:
                command = JoinWithCommand(args: self as! JoinWithCmdArgs)
            case .layout:
                command = LayoutCommand(args: self as! LayoutCmdArgs)
            case .listApps:
                command = ListAppsCommand(args: self as! ListAppsCmdArgs)
            case .listExecEnvVars:
                command = ListExecEnvVarsCommand(args: self as! ListExecEnvVarsCmdArgs)
            case .listModes:
                command = ListModesCommand(args: self as! ListModesCmdArgs)
            case .listMonitors:
                command = ListMonitorsCommand(args: self as! ListMonitorsCmdArgs)
            case .listWindows:
                command = ListWindowsCommand(args: self as! ListWindowsCmdArgs)
            case .listWorkspaces:
                command = ListWorkspacesCommand(args: self as! ListWorkspacesCmdArgs)
            case .macosNativeFullscreen:
                command = MacosNativeFullscreenCommand(args: self as! MacosNativeFullscreenCmdArgs)
            case .macosNativeMinimize:
                command = MacosNativeMinimizeCommand(args: self as! MacosNativeMinimizeCmdArgs)
            case .mode:
                command = ModeCommand(args: self as! ModeCmdArgs)
            case .move:
                command = MoveCommand(args: self as! MoveCmdArgs)
            case .moveMouse:
                command = MoveMouseCommand(args: self as! MoveMouseCmdArgs)
            case .moveNodeToMonitor:
                command = MoveNodeToMonitorCommand(args: self as! MoveNodeToMonitorCmdArgs)
            case .moveNodeToWorkspace:
                command = MoveNodeToWorkspaceCommand(args: self as! MoveNodeToWorkspaceCmdArgs)
            case .moveWorkspaceToMonitor:
                command = MoveWorkspaceToMonitorCommand(args: self as! MoveWorkspaceToMonitorCmdArgs)
            case .reloadConfig:
                command = ReloadConfigCommand(args: self as! ReloadConfigCmdArgs)
            case .resize:
                command = ResizeCommand(args: self as! ResizeCmdArgs)
            case .runCallback:
                command = RunCallbackCommand(args: self as! RunCallbackCmdArgs)
            case .split:
                command = SplitCommand(args: self as! SplitCmdArgs)
            case .subscribe:
                return .failure("subscribe is not supported in the eval", EXIT_CODE_TWO)
            case .summonWorkspace:
                command = SummonWorkspaceCommand(args: self as! SummonWorkspaceCmdArgs)
            case .swap:
                command = SwapCommand(args: self as! SwapCmdArgs)
            case .test:
                command = TestCommand(args: self as! TestCmdArgs)
            case .testNot:
                command = TestNotCommand(args: self as! TestNotCmdArgs)
            case .triggerBinding:
                command = TriggerBindingCommand(args: self as! TriggerBindingCmdArgs)
            case .volume:
                command = VolumeCommand(args: self as! VolumeCmdArgs)
            case .workspace:
                command = WorkspaceCommand(args: self as! WorkspaceCmdArgs)
            case .workspaceBackAndForth:
                command = WorkspaceBackAndForthCommand(args: self as! WorkspaceBackAndForthCmdArgs)
        }
        check(command.info == Self.info)
        return .cmd(command)
    }
}

```

## /Sources/AppBundle/command/cmdResolveTargetOrReportError.swift

```swift path="/Sources/AppBundle/command/cmdResolveTargetOrReportError.swift" 
import Common

extension CmdArgs {
    @MainActor
    var workspace: Workspace? {
        if let workspaceName { Workspace.get(byName: workspaceName.raw) } else { nil }
    }

    @MainActor
    func resolveTargetOrReportError(_ env: CmdEnv, _ io: CmdIo) -> LiveFocus? {
        // Flags
        if let windowId {
            if let wi = Window.get(byId: windowId) {
                return wi.toLiveFocusOrReportError(io)
            } else {
                io.err("Invalid <window-id> \(windowId) passed to --window-id")
                return nil
            }
        }
        if let workspace {
            return workspace.toLiveFocus()
        }
        // Env
        if let windowId = env.windowId {
            if let wi = Window.get(byId: windowId) {
                return wi.toLiveFocusOrReportError(io)
            } else {
                io.err("Invalid <window-id> \(windowId) specified in \(AEROSPACE_WINDOW_ID) env variable")
                return nil
            }
        }
        if let wsName = env.workspaceName {
            return Workspace.get(byName: wsName).toLiveFocus()
        }
        // Real Focus
        return focus
    }
}

extension Window {
    @MainActor
    func toLiveFocusOrReportError(_ io: CmdIo) -> LiveFocus? {
        if let result = toLiveFocusOrNil() {
            return result
        } else {
            io.err("Window \(windowId) doesn't belong to any monitor. And thus can't even define a focused workspace")
            return nil
        }
    }
}

```

## /Sources/AppBundle/command/format.swift

```swift path="/Sources/AppBundle/command/format.swift" 
import Common
import Foundation

struct WindowWithPrefetchedTitle {
    let window: Window
    let title: String?

    private init(window: Window, title: String?) {
        self.window = window
        self.title = title
    }

    static func resolveWindow(_ window: Window, for formatVar: FormatVar, _ cm: CancellationMode) async throws -> Self {
        try await resolveWindow(window, needsTitle: formatVar == .window(.windowTitle), cm)
    }

    static func resolveWindow(_ window: Window, for format: [InterToken<InterVar>], _ cm: CancellationMode) async throws -> Self {
        let needsTitle = format.contains { $0 == .interVar(.formatVar(.window(.windowTitle))) }
        return try await resolveWindow(window, needsTitle: needsTitle, cm)
    }

    private static func resolveWindow(_ window: Window, needsTitle: Bool, _ cm: CancellationMode) async throws -> Self {
        let title = needsTitle ? try await window.getTitle(cm) : nil
        return .init(window: window, title: title)
    }

    static func forTest(window: Window, title: String?) -> Self {
        .init(window: window, title: title)
    }
}

enum AeroObj {
    case window(WindowWithPrefetchedTitle)
    case workspace(Workspace)
    case app(any AbstractApp)
    case monitor(MonitorInfo)

    var kind: AeroObjKind {
        switch self {
            case .window: .window
            case .workspace: .workspace
            case .app: .app
            case .monitor: .monitor
        }
    }
}

extension [AeroObj] {
    @MainActor
    func format(_ format: [InterToken<InterVar>]) -> Result<[String], [InterVarExpansionError]> {
        var cellTable: [[Cell<String>]] = []
        for obj in self {
            var line: [Cell<String>] = []
            var curCell: String = ""
            var errors = [InterVarExpansionError]()
            for token in format {
                switch token {
                    case .interVar(.plainInterVar(.rightPadding)):
                        line.append(Cell(value: curCell, rightPadding: true))
                        curCell = ""
                    case .literal(let literal):
                        curCell += literal
                    case .interVar(let value):
                        switch value.expandFormatVar(obj: obj) {
                            case .success(let expanded): curCell += expanded.toString()
                            case .failure(let error): errors.append(error)
                        }
                }
            }
            if !errors.isEmpty { return .failure(errors) }
            line.append(Cell(value: curCell, rightPadding: false))
            cellTable.append(line)
        }
        let result = cellTable
            .transposed()
            .map { column in
                let columndWidth = column.map { $0.value.count }.max().orDie()
                return column.map {
                    $0.rightPadding
                        ? $0.value + String(repeating: " ", count: columndWidth - $0.value.count)
                        : $0.value
                }
            }
            .transposed()
            .map { line in line.joined(separator: "") }
        return .success(result)
    }
}

enum Primitive: Encodable {
    case bool(Bool)
    case int(Int64)
    case string(String)

    enum Kind: String {
        case bool = "Bool"
        case int = "Int"
        case string = "String"
    }

    var kind: Kind {
        switch self {
            case .bool: .bool
            case .int: .int
            case .string: .string
        }
    }

    func toString() -> String {
        switch self {
            case .bool(let x): x.description
            case .int(let x): x.description
            case .string(let x): x
        }
    }

    func encode(to encoder: any Encoder) throws {
        let value: Encodable = switch self {
            case .bool(let x): x
            case .int(let x): x
            case .string(let x): x
        }
        var container = encoder.singleValueContainer()
        try container.encode(value)
    }

    public static func int(_ int: UInt32) -> Self { .int(Int64(exactly: int).orDie()) }
    public static func int(_ int: Int32) -> Self { .int(Int64(exactly: int).orDie()) }
    public static func int(_ int: Int) -> Self { .int(Int64(exactly: int).orDie()) }
}

private struct Cell<T> {
    let value: T
    let rightPadding: Bool
}

extension FormatVar {
    @MainActor func expandFormatVar(obj: AeroObj) -> Result<Primitive, InterVarExpansionError> {
        switch (obj, self) {
            case (.window(let w), .workspace):
                return w.window.nodeWorkspace.flatMap(AeroObj.workspace).map(expandFormatVar) ?? .success(.string("NULL-WORKSPACE"))
            case (.window(let w), .monitor):
                return w.window.nodeMonitor.flatMap(AeroObj.monitor).map(expandFormatVar) ?? .success(.string("NULL-MONITOR"))
            case (.window(let w), .app):
                return expandFormatVar(obj: .app(w.window.app))
            case (.window(_), .window): break

            case (.workspace(let ws), .monitor):
                return expandFormatVar(obj: AeroObj.monitor(ws.workspaceMonitor))
            case (.workspace, _): break

            case (.app(_), _): break
            case (.monitor(_), _): break
        }

        switch (obj, self) {
            case (.window(let w), .window(let f)):
                return switch f {
                    case .windowId: .success(.int(w.window.windowId))
                    case .windowIsFullscreen: .success(.bool(w.window.isFullscreen))
                    case .windowTitle: .success(.string(w.title.orDie("Title wasn't prefetched")))
                    case .windowLayout, .windowParentContainerLayout: toLayoutResult(w: w.window)
                }
            case (.workspace(let w), .workspace(let f)):
                return switch f {
                    case .workspaceName: .success(.string(w.name))
                    case .workspaceVisible: .success(.bool(w.isVisible))
                    case .workspaceFocused: .success(.bool(focus.workspace == w))
                    case .workspaceRootContainerLayout: .success(.string(toLayoutString(tc: w.rootTilingContainer)))
                }
            case (.monitor(let m), .monitor(let f)):
                return switch f {
                    case .monitorId_oneBased: .success(m.monitorId_oneBased.map { .int($0) } ?? .string("NULL-MONITOR-ID"))
                    case .monitorAppKitNsScreenScreensId: .success(.int(m.monitorAppKitNsScreenScreensId))
                    case .monitorName: .success(.string(m.name))
                    case .monitorIsMain: .success(.bool(m.isMain))
                }
            case (.app(let a), .app(let f)):
                return switch f {
                    case .appBundleId: .success(.string(a.rawAppBundleId ?? "NULL-APP-BUNDLE-ID"))
                    case .appName: .success(.string(a.name ?? "NULL-APP-NAME"))
                    case .appPid: .success(.int(a.pid))
                    case .appExecPath: .success(.string(a.execPath ?? "NULL-APP-EXEC-PATH"))
                    case .appBundlePath: .success(.string(a.bundlePath ?? "NULL-APP-BUNDLE-PATH"))
                }
            default: break
        }
        return .failure(.unknownInterpolationVariable(unknownInterpolationVariable(variable: rawValue, obj)))
    }
}

enum InterVarExpansionError: LocalizedError, CustomStringConvertible {
    case unknownInterpolationVariable(String)
    case nullParent(String)
    case notPossible(String)
    case windowParentIllegalRelation(String)
    case rightPaddingCannotBeExpanded(String)

    public var description: String {
        switch self {
            case .unknownInterpolationVariable(let msg): msg
            case .nullParent(let msg): msg
            case .notPossible(let msg): msg
            case .windowParentIllegalRelation(let msg): msg
            case .rightPaddingCannotBeExpanded(let msg): msg
        }
    }

    public var errorDescription: String? { description }
}

extension PlainInterVar {
    @MainActor func expandFormatVar() -> Result<Primitive, InterVarExpansionError> {
        switch self {
            case .newline: .success(.string("\n"))
            case .tab: .success(.string("\t"))
            case .rightPadding:
                .failure(.rightPaddingCannotBeExpanded("\(PlainInterVar.rightPadding.rawValue.singleQuoted) interpolation variable cannot be expanded"))
        }
    }
}

extension InterVar {
    @MainActor func expandFormatVar(obj: AeroObj) -> Result<Primitive, InterVarExpansionError> {
        switch self {
            case .formatVar(let it): it.expandFormatVar(obj: obj)
            case .plainInterVar(let it): it.expandFormatVar()
        }
    }
}

func unknownInterpolationVariable(variable: String, _ obj: AeroObj) -> String {
    "Unknown interpolation variable '\(variable)'. " +
        "Possible values:\n\(getAvailableInterVars(for: obj.kind).joined(separator: "\n").prependLines("  "))"
}

private func toLayoutString(tc: TilingContainer) -> String {
    switch (tc.layout, tc.orientation) {
        case (.tiles, .h): return LayoutCmdArgs.LayoutDescription.h_tiles.rawValue
        case (.tiles, .v): return LayoutCmdArgs.LayoutDescription.v_tiles.rawValue
        case (.accordion, .h): return LayoutCmdArgs.LayoutDescription.h_accordion.rawValue
        case (.accordion, .v): return LayoutCmdArgs.LayoutDescription.v_accordion.rawValue
    }
}

private func toLayoutResult(w: Window) -> Result<Primitive, InterVarExpansionError> {
    guard let parent = w.parent else { return .failure(.nullParent("NULL-PARENT")) }
    return switch getChildParentRelation(child: w, parent: parent) {
        case .tiling(let tc): .success(.string(toLayoutString(tc: tc)))
        case .floatingWindow: .success(.string(LayoutCmdArgs.LayoutDescription.floating.rawValue))
        case .macosNativeFullscreenWindow: .success(.string("macos_native_fullscreen"))
        case .macosNativeHiddenAppWindow: .success(.string("macos_native_window_of_hidden_app"))
        case .macosNativeMinimizedWindow: .success(.string("macos_native_minimized"))
        case .macosPopupWindow: .success(.string("NULL-WINDOW-LAYOUT"))

        case .rootTilingContainer: .failure(.notPossible("Not possible"))
        case .shimContainerRelation: .failure(.windowParentIllegalRelation("Window cannot have a shim container relation"))
    }
}

```

## /Sources/AppBundle/command/formatToJson.swift

```swift path="/Sources/AppBundle/command/formatToJson.swift" 
import Common
import Foundation

extension [AeroObj] {
    @MainActor
    func formatToJson(_ format: [InterToken<InterVar>], ignoreRightPaddingVar: Bool) -> Result<String, String> {
        var list: [[String: Primitive]] = []
        for richObj in self {
            var rawObj: [String: Primitive] = [:]
            for token in format {
                switch token {
                    case .interVar(.plainInterVar(.rightPadding)) where ignoreRightPaddingVar:
                        break
                    case .literal:
                        break // should be spaces
                    case .interVar(let varName):
                        switch varName.expandFormatVar(obj: richObj) {
                            case .success(let expanded): rawObj[varName.rawValue] = expanded
                            case .failure(let error): return .failure(error.description)
                        }
                }
            }
            list.append(rawObj)
        }
        return JSONEncoder.aeroSpaceDefault.encodeToString(list).toResult("Can't encode '\(list)' to JSON")
    }
}

```

## /Sources/AppBundle/command/impl/BalanceSizesCommand.swift

```swift path="/Sources/AppBundle/command/impl/BalanceSizesCommand.swift" 
import AppKit
import Common
import Foundation

struct BalanceSizesCommand: Command {
    let args: BalanceSizesCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        balance(target.workspace.rootTilingContainer)
        return .succ
    }
}

@MainActor
private func balance(_ parent: TilingContainer) {
    for child in parent.children {
        switch parent.layout {
            case .tiles: child.setWeight(parent.orientation, 1)
            case .accordion: break // Do nothing
        }
        if let child = child as? TilingContainer {
            balance(child)
        }
    }
}

```

## /Sources/AppBundle/command/impl/CloseAllWindowsButCurrentCommand.swift

```swift path="/Sources/AppBundle/command/impl/CloseAllWindowsButCurrentCommand.swift" 
import AppKit
import Common

struct CloseAllWindowsButCurrentCommand: Command {
    let args: CloseAllWindowsButCurrentCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> BinaryExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        guard let focused = target.windowOrNil else {
            return .fail(io.err("Empty workspace"))
        }
        guard let workspace = focused.nodeWorkspace else {
            return .fail(io.err("Focused window '\(focused.windowId)' doesn't belong to workspace"))
        }
        var result = BinaryExitCode.succ
        for window in workspace.allLeafWindowsRecursive where window != focused {
            result = await CloseCommand(args: args.closeArgs).run(env.withWindowId(window.windowId), io).and(result)
        }
        return result
    }
}

```

## /Sources/AppBundle/command/impl/CloseCommand.swift

```swift path="/Sources/AppBundle/command/impl/CloseCommand.swift" 
import AppKit
import Common

struct CloseCommand: Command {
    let args: CloseCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> BinaryExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        guard let window = target.windowOrNil else {
            return .fail(io.err("Empty workspace"))
        }
        // Access ax directly. Not cool :(
        if await args.quitIfLastWindow.andAsync({ @MainActor @Sendable in (try? await window.macAppUnsafe.getAxWindowsCount(.nonCancellable)) == 1 }) {
            let app = window.macAppUnsafe
            if app.nsApp.terminate() {
                for workspace in Workspace.all {
                    for window in workspace.allLeafWindowsRecursive where window.app.pid == app.pid {
                        (window as! MacWindow).garbageCollect(skipClosedWindowsCache: true)
                    }
                }
                return .succ
            } else {
                return .fail(io.err("Failed to quit '\(window.app.name ?? "Unknown app")'"))
            }
        } else {
            window.closeAxWindow()
            return .succ
        }
    }
}

```

## /Sources/AppBundle/command/impl/ConfigCommand.swift

```swift path="/Sources/AppBundle/command/impl/ConfigCommand.swift" 
import AppKit
import Common

struct ConfigCommand: Command {
    let args: ConfigCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        switch args.mode {
            case .getKey(let key):
                return getKey(io, args: args, key: key)
            case .majorKeys:
                let out = """
                    .
                    mode
                    \(config.modes.keys.map { "mode.\($0).binding" }.joined(separator: "\n"))
                    """
                return .succ(io.out(out))
            case .allKeys:
                let configMap = buildConfigMap()
                var allKeys: [String] = []
                configMap.dumpAllKeysRecursive(path: ".", result: &allKeys)
                return .succ(io.out(allKeys.joined(separator: "\n")))
            case .configPath:
                return .succ(io.out(configUrl.absoluteURL.path))
        }
    }
}

extension String {
    fileprivate func toKeyPath() -> Result<[String], String> {
        if self == "." { return .success([]) }
        if isEmpty { return .failure("Invalid empty key") }
        if self.contains("..") { return .failure("Invalid key '\(self)'") }
        if self.hasSuffix(".") { return .failure("Invalid key '\(self)'") }
        return .success(self.split(separator: ".", omittingEmptySubsequences: false).map(String.init))
    }
}

@MainActor private func getKey(_ io: CmdIo, args: ConfigCmdArgs, key: String) -> BinaryExitCode {
    guard let keyPath = key.toKeyPath().getOrNil(appendErrorTo: &io.stderr) else { return .fail }
    guard var configMap = buildConfigMap().find(keyPath: keyPath.slice).getOrNil(appendErrorTo: &io.stderr) else { return .fail }
    if args.keys {
        switch configMap {
            case .scalar(let scalar):
                return .fail(io.err("--keys flag cannot be applied to scalar object '\(scalar)'"))
            case .map(let map):
                configMap = .array(map.keys.map { .scalar(.string($0)) })
            case .array(let array):
                configMap = .array((0 ..< array.count).map { .scalar(.int($0)) })
        }
    }
    if args.json {
        return switch JSONEncoder.aeroSpaceDefault.encodeToString(configMap) {
            case let json?: .succ(io.out(json))
            case nil: .fail(io.err("Can't convert json Data to String"))
        }
    } else {
        switch configMap {
            case .scalar(let scalar):
                return .succ(io.out(scalar.describe))
            case .map:
                let msg = "Complicated objects can be printed only with --json flag. Alternatively, you can try to inspect keys of the object with --keys flag"
                return .fail(io.err(msg))
            case .array(let array):
                let plainArray: Result<[String], String> = array.mapAllOrFailure {
                    switch $0 {
                        case .scalar(let scalar): .success(scalar.describe)
                        default: .failure("Printing array of non-string objects is supported only with --json flag." +
                                "Alternatively, you can try to inspect keys of the object with --keys flag")
                    }
                }
                return switch plainArray {
                    case .success(let array): .succ(io.out(array.sorted().joined(separator: "\n")))
                    case .failure(let error): .fail(io.err(error))
                }
        }
    }
}

extension ConfigMapValue {
    func find(keyPath: StrArrSlice) -> Result<ConfigMapValue, String> {
        if let key = keyPath.first {
            switch self {
                case .scalar(let scalar):
                    return .failure("Can't dereference scalar value '\(scalar.describe)'")
                case .map(let map):
                    return switch map[key] {
                        case let child?: child.find(keyPath: keyPath.slice(1...).orDie())
                        case nil: .failure("No value at key token '\(key)'")
                    }
                case .array(let array):
                    if let key = Int(key) {
                        return switch array.getOrNil(atIndex: key) {
                            case let child?: child.find(keyPath: keyPath.slice(1...).orDie())
                            case nil: .failure("Index out of bounds. Index: \(key), Size: \(array.count)")
                        }
                    } else {
                        return .failure("Can't convert key token '\(key)' to Int")
                    }
            }
        } else {
            return .success(self)
        }
    }

    func dumpAllKeysRecursive(path: String, result: inout [String]) {
        result.append(path)
        switch self {
            case .scalar: break
            case .map(let map):
                for (key, value) in map {
                    let path = path == "." ? key : path + "." + key
                    value.dumpAllKeysRecursive(path: path, result: &result)
                }
            case .array(let array):
                for (index, value) in array.enumerated() {
                    let path = path == "." ? String(index) : path + "." + String(index)
                    value.dumpAllKeysRecursive(path: path, result: &result)
                }
        }
    }
}

extension Shell<any Command> {
    var shellOfCommandsDescription: String { buildDescription { $0.args.description } }
}

@MainActor func buildConfigMap() -> ConfigMapValue {
    let mode = config.modes.mapValues { (mode: Mode) -> ConfigMapValue in
        var keyNotationToScript: [String: ConfigMapValue] = [:]
        for binding in mode.bindings.values {
            keyNotationToScript[binding.descriptionWithKeyNotation] =
                .scalar(.string(binding.commands.shellOfCommandsDescription))
        }
        return .map(["binding": .map(keyNotationToScript)])
    }
    return .map(["mode": .map(mode)])
}

enum ConfigScalarValue: Encodable {
    case string(String)
    case int(Int)

    var describe: String {
        return switch self {
            case .string(let string): string
            case .int(let int): String(int)
        }
    }

    func encode(to encoder: Encoder) throws {
        let value: Encodable = switch self {
            case .string(let string): string
            case .int(let int): int
        }
        var container = encoder.singleValueContainer()
        try container.encode(value)
    }
}

enum ConfigMapValue: Encodable {
    case scalar(ConfigScalarValue)
    case map([String: ConfigMapValue])
    case array([ConfigMapValue])

    func encode(to encoder: Encoder) throws {
        let value: Encodable = switch self {
            case .scalar(let scalar): scalar
            case .map(let map): map
            case .array(let array): array
        }
        var container = encoder.singleValueContainer()
        try container.encode(value)
    }
}

```

## /Sources/AppBundle/command/impl/DebugWindowsCommand.swift

```swift path="/Sources/AppBundle/command/impl/DebugWindowsCommand.swift" 
import AppKit
import Common
import OrderedCollections

private let disclaimer =
    """
    !!! DISCLAIMER !!!
    !!! 'debug-windows' command is not stable API. Please don't rely on the command existence and output format !!!
    !!! The only intended use case is to report bugs about incorrect windows handling !!!
    """

@MainActor private var debugWindowsState: DebugWindowsState = .notRecording
@MainActor private var debugWindowsLog: OrderedDictionary<UInt32, String> = [:]
private let debugWindowsLimit = 10

enum DebugWindowsState {
    case recording
    case notRecording
    case recordingAborted
}

struct DebugWindowsCommand: Command {
    let args: DebugWindowsCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> BinaryExitCode {
        if let windowId = args.windowId {
            guard let window = Window.get(byId: windowId) else {
                return .fail(io.err("Can't find window with the specified window-id: \(windowId)"))
            }
            guard let a = try? await dumpWindowDebugInfo(window, .nonCancellable) else { return .fail(io.err(bugPrompt())) }
            io.out(a + "\n")
            io.out(disclaimer)
            return .succ
        }
        switch debugWindowsState {
            case .recording:
                debugWindowsState = .notRecording
                io.out(debugWindowsLog.values.joined(separator: "\n\n"))
                io.out("\n" + disclaimer + "\n")
                io.out("Debug session finished" + "\n")
                debugWindowsLog = [:]
                return .succ
            case .notRecording:
                debugWindowsState = .recording
                debugWindowsLog = [:]
                io.out(
                    """
                    Debug windows session has started
                    1. Focus the problematic window
                    2. Run 'aerospace debug-windows' once again to finish the session and get the results
                    """,
                )
                // Make sure that the Terminal window that started the recording is recorded first
                guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
                if let window = target.windowOrNil {
                    do {
                        try await debugWindowsIfRecording(window, .nonCancellable)
                    } catch {
                        return .fail(io.err(bugPrompt(String(describing: error))))
                    }
                }
                return .succ
            case .recordingAborted:
                io.out(
                    """
                    Recording of the previous session was aborted after \(debugWindowsLimit) windows has been focused
                    Run the command one more time to start new debug session
                    """,
                )
                debugWindowsState = .notRecording
                debugWindowsLog = [:]
                return .fail
        }
    }
}

@MainActor
private func dumpWindowDebugInfo(_ window: Window, _ cm: CancellationMode) async throws -> String {
    let window = window as! MacWindow
    let appInfoDic = window.macApp.nsApp.bundleURL.flatMap { Bundle.init(url: $0) }?.infoDictionary ?? [:]

    var result: [String: Json] = try await window.dumpAxInfo(cm)

    let windowLevel = getWindowLevel(for: window.windowId)
    let windowLevelJson = windowLevel?.toJson() ?? .null
    result["Aero.windowLevel"] = windowLevelJson
    result["Aero.axWindowId"] = .int(window.windowId)
    result["Aero.workspace"] = .stringOrNull(window.nodeWorkspace?.name)
    result["Aero.treeNodeParent"] = .string(String(describing: window.parent))
    result["Aero.macOS.version"] = .string(ProcessInfo().operatingSystemVersionString) // because built-in apps might behave differently depending on the OS version
    result["Aero.App.appBundleId"] = .stringOrNull(window.app.rawAppBundleId)
    result["Aero.App.pid"] = .int(Int(window.app.pid))
    result["Aero.App.versionShort"] = .stringOrNull(appInfoDic["CFBundleShortVersionString"] as? String)
    result["Aero.App.version"] = .stringOrNull(appInfoDic["CFBundleVersion"] as? String)
    result["Aero.App.nsApp.activationPolicy"] = .string(window.macApp.nsApp.activationPolicy.prettyDescription)
    result["Aero.App.nsApp.execPath"] = .stringOrNull(window.macApp.nsApp.executableURL?.description)
    result["Aero.App.nsApp.appBundlePath"] = .stringOrNull(window.macApp.nsApp.bundleURL?.description)
    result["Aero.AXApp"] = .dict(try await window.macApp.dumpAppAxInfo(cm))

    let isDialog = try await window.isDialogHeuristic(windowLevel, cm)
    let isWindow = try await window.isWindowHeuristic(windowLevel, cm)
    result["Aero.AxUiElementWindowType"] = .string(AxUiElementWindowType.new(isWindow: isWindow, isDialog: { isDialog }).rawValue)
    result["Aero.AxUiElementWindowType_isDialogHeuristic"] = .bool(isDialog)

    var matchingCallbacks: [Json] = []
    for callback in config.onWindowDetected where await callback.matches(window) {
        matchingCallbacks.append(callback.debugJson)
    }
    result["Aero.on-window-detected"] = .array(matchingCallbacks)

    return JSONEncoder.aeroSpaceDefault.encodeToString(result).prettyDescription
        .prefixLines(with: "\(window.app.rawAppBundleId ?? "nil-bundle-id").\(window.windowId) ||| ")
}

@MainActor
func debugWindowsIfRecording(_ window: Window, _ cm: CancellationMode) async throws {
    switch debugWindowsState {
        case .recording: break
        case .notRecording, .recordingAborted: return
    }
    if debugWindowsLog.count > debugWindowsLimit {
        debugWindowsState = .recordingAborted
        debugWindowsLog = [:]
    }
    if debugWindowsLog.keys.contains(window.windowId) {
        return
    }
    debugWindowsLog[window.windowId] = try await dumpWindowDebugInfo(window, cm)
}

```

## /Sources/AppBundle/command/impl/EchoCommand.swift

```swift path="/Sources/AppBundle/command/impl/EchoCommand.swift" 
import Common

struct EchoCommand: Command {
    let args: EchoCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> BinaryExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        var obj = [AeroObj]()
        if let window = target.windowOrNil {
            guard let a: WindowWithPrefetchedTitle = try? await .resolveWindow(window, for: args.args.val.flatMap { $0 }, .nonCancellable) else { return .fail(io.err(bugPrompt())) }
            obj.append(AeroObj.window(a))
        } else {
            obj.append(AeroObj.workspace(target.workspace))
        }
        for argWithInterVars in args.args.val {
            guard let strs = obj.format(argWithInterVars).getOrNil(onFailure: { errs in
                for err in errs {
                    switch err {
                        case .unknownInterpolationVariable: io.err(noWindowIsFocused)
                        case .notPossible, .nullParent,
                             .rightPaddingCannotBeExpanded, .windowParentIllegalRelation: io.err(err.description)
                    }
                }
            }) else { return .fail }
            for str in strs {
                switch args.isStderr {
                    case true: io.err(str)
                    case false: io.out(str)
                }
            }
        }
        return .succ
    }
}

```

## /Sources/AppBundle/command/impl/EnableCommand.swift

```swift path="/Sources/AppBundle/command/impl/EnableCommand.swift" 
import AppKit
import Common

struct EnableCommand: Command {
    let args: EnableCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> BinaryExitCode {
        let prevState = TrayMenuModel.shared.isEnabled
        let newState: Bool = switch args.targetState.val {
            case .on: true
            case .off: false
            case .toggle: !TrayMenuModel.shared.isEnabled
        }
        if newState == prevState {
            switch args.failIfNoop {
                case true: return .fail
                case false:
                    let msg = newState
                        ? "Already enabled. Tip: use --fail-if-noop to exit with non-zero code"
                        : "Already disabled. Tip: use --fail-if-noop to exit with non-zero code"
                    return .succ(io.err(msg))
            }
        }

        TrayMenuModel.shared.isEnabled = newState
        if newState {
            for workspace in Workspace.all {
                for window in workspace.allLeafWindowsRecursive where window.isFloating {
                    window.lastFloatingSize = (try? await window.getAxSize(.nonCancellable)) ?? window.lastFloatingSize
                }
            }
            await activateMode_nonCancellable(mainModeId)
        } else {
            await activateMode_nonCancellable(nil)
        }
        return .succ
    }
}

```

## /Sources/AppBundle/command/impl/EvalCommand.swift

```swift path="/Sources/AppBundle/command/impl/EvalCommand.swift" 
import Common

struct EvalCommand: Command {
    let args: EvalCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = true

    func run(_ env: CmdEnv, _ io: CmdIo) async -> Int32ExitCode {
        switch parseCommand(args.shellExpr.val, allowExecAndForget: false, allowEval: false) {
            case .failure(let cmdParsingFailure):
                io.err(cmdParsingFailure.msg)
                return Int32ExitCode(rawValue: cmdParsingFailure.exitCode)
            case .help:
                io.err("--help is not supported inside eval command")
                return .init(rawValue: EXIT_CODE_TWO)
            case .cmd(let cmd):
                return await cmd.run(env, io)
        }
    }
}

```

## /Sources/AppBundle/command/impl/ExecAndForgetCommand.swift

```swift path="/Sources/AppBundle/command/impl/ExecAndForgetCommand.swift" 
import AppKit
import Common

struct ExecAndForgetCommand: Command {
    let args: ExecAndForgetCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        // todo shall exec-and-forget fork exec session?
        // It doesn't throw if exit code is non-zero
        let process = Process()
        process.environment = config.execConfig.envVariables + env.asMap
        process.executableURL = URL(filePath: "/bin/bash")
        process.arguments = ["-c", args.bashScript]
        return .from(bool: Result { try process.run() }.isSuccess)
    }
}

```

## /Sources/AppBundle/command/impl/FalseCommand.swift

```swift path="/Sources/AppBundle/command/impl/FalseCommand.swift" 
import AppKit
import Common

struct FalseCommand: Command {
    let args: FalseCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache: Bool = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> ConditionalExitCode { ._false }
}

```

## /Sources/AppBundle/command/impl/FlattenWorkspaceTreeCommand.swift

```swift path="/Sources/AppBundle/command/impl/FlattenWorkspaceTreeCommand.swift" 
import AppKit
import Common

struct FlattenWorkspaceTreeCommand: Command {
    let args: FlattenWorkspaceTreeCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache: Bool = true

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        let workspace = target.workspace
        let windows = workspace.rootTilingContainer.allLeafWindowsRecursive
        for window in windows {
            window.bind(to: workspace.rootTilingContainer, adaptiveWeight: 1, index: INDEX_BIND_LAST)
        }
        return .succ
    }
}

```

## /Sources/AppBundle/command/impl/FocusBackAndForthCommand.swift

```swift path="/Sources/AppBundle/command/impl/FocusBackAndForthCommand.swift" 
import AppKit
import Common

struct FocusBackAndForthCommand: Command {
    let args: FocusBackAndForthCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        switch prevFocus {
            case let prevFocus?: .from(bool: setFocus(to: prevFocus))
            case nil: .fail(io.err("Prev window has been closed"))
        }
    }
}

```

## /Sources/AppBundle/command/impl/FocusCommand.swift

```swift path="/Sources/AppBundle/command/impl/FocusCommand.swift" 
import AppKit
import Common

struct FocusCommand: Command {
    let args: FocusCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> BinaryExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        if let window = target.windowOrNil, await shouldFailBecauseFullscreen_nonCancellable(
            window: window,
            failIfFullscreen: args.failIfFullscreen,
            failIfMacosNativeFullscreen: args.failIfMacosNativeFullscreen,
        ) {
            return .fail
        }
        // todo bug: floating windows break mru
        let floatingWindows = args.floatingAsTiling ? await makeFloatingWindowsSeenAsTiling(workspace: target.workspace) : []
        defer {
            if args.floatingAsTiling {
                restoreFloatingWindows(floatingWindows: floatingWindows, workspace: target.workspace)
            }
        }

        switch args.target {
            case .direction(let direction):
                let window = target.windowOrNil
                if let (parent, ownIndex) = window?.closestParent(hasChildrenInDirection: direction, withLayout: nil) {
                    guard let windowToFocus = parent.children[ownIndex + direction.focusOffset]
                        .findLeafWindowRecursive(snappedTo: direction.opposite) else { return .fail(io.err(bugPrompt())) }
                    return .from(bool: windowToFocus.focusWindow())
                } else {
                    return hitWorkspaceBoundaries(target, io, args, direction)
                }
            case .windowId(let windowId):
                if let windowToFocus = Window.get(byId: windowId) {
                    return .from(bool: windowToFocus.focusWindow())
                } else {
                    return .fail(io.err("Can't find window with ID \(windowId)"))
                }
            case .dfsIndex(let dfsIndex):
                if let windowToFocus = target.workspace.rootTilingContainer.allLeafWindowsRecursive.getOrNil(atIndex: Int(dfsIndex)) {
                    return .from(bool: windowToFocus.focusWindow())
                } else {
                    return .fail(io.err("Can't find window with DFS index \(dfsIndex)"))
                }
            case .dfsRelative(let nextPrev):
                let windows = target.workspace.rootTilingContainer.allLeafWindowsRecursive
                guard let currentIndex = windows.firstIndex(where: { $0 == target.windowOrNil }) else {
                    return .fail
                }
                var targetIndex = switch nextPrev {
                    case .dfsNext: currentIndex + 1
                    case .dfsPrev: currentIndex - 1
                }
                if !(0 ..< windows.count).contains(targetIndex) {
                    switch args.boundariesAction {
                        case .stop: return .succ
                        case .fail: return .fail
                        case .wrapAroundTheWorkspace: targetIndex = (targetIndex + windows.count) % windows.count
                        case .wrapAroundAllMonitors: return .fail(io.err(bugPrompt("Must be discarded by args parser")))
                    }
                }
                return .from(bool: windows[targetIndex].focusWindow())
        }
    }
}

@MainActor private func hitWorkspaceBoundaries(
    _ target: LiveFocus,
    _ io: CmdIo,
    _ args: FocusCmdArgs,
    _ direction: CardinalDirection,
) -> BinaryExitCode {
    switch args.boundaries {
        case .workspace:
            return switch args.boundariesAction {
                case .stop: .succ
                case .fail: .fail
                case .wrapAroundTheWorkspace: wrapAroundTheWorkspace(target, io, direction)
                case .wrapAroundAllMonitors: .fail(io.err("Must be discarded by args parser"))
            }
        case .allMonitorsOuterFrame:
            let currentMonitor = target.workspace.workspaceMonitor
            guard let (monitors, index) = currentMonitor.findRelativeMonitor(inDirection: direction) else {
                return .fail(io.err(bugPrompt("Should never happen. Can't find the current monitor")))
            }

            if let targetMonitor = monitors.getOrNil(atIndex: index) {
                return .from(bool: targetMonitor.activeWorkspace.focusWorkspace())
            } else {
                guard let wrapped = monitors.get(wrappingIndex: index) else { return .fail(io.err(bugPrompt("\(index) \(monitors)"))) }
                return hitAllMonitorsOuterFrameBoundaries(target, io, args, direction, wrapped)
            }
    }
}

@MainActor private func hitAllMonitorsOuterFrameBoundaries(
    _ target: LiveFocus,
    _ io: CmdIo,
    _ args: FocusCmdArgs,
    _ direction: CardinalDirection,
    _ wrappedMonitor: MonitorInfo,
) -> BinaryExitCode {
    switch args.boundariesAction {
        case .stop:
            return .succ
        case .fail:
            return .fail
        case .wrapAroundTheWorkspace:
            return wrapAroundTheWorkspace(target, io, direction)
        case .wrapAroundAllMonitors:
            wrappedMonitor.activeWorkspace.findLeafWindowRecursive(snappedTo: direction.opposite)?.markAsMostRecentChild()
            return .from(bool: wrappedMonitor.activeWorkspace.focusWorkspace())
    }
}

@MainActor private func wrapAroundTheWorkspace(_ target: LiveFocus, _ io: CmdIo, _ direction: CardinalDirection) -> BinaryExitCode {
    guard let windowToFocus = target.workspace.findLeafWindowRecursive(snappedTo: direction.opposite) else {
        return .fail(io.err(noWindowIsFocused))
    }
    return .from(bool: windowToFocus.focusWindow())
}

@MainActor private func makeFloatingWindowsSeenAsTiling(workspace: Workspace) async -> [FloatingWindowData] {
    let mruBefore = workspace.mostRecentWindowRecursive
    defer {
        mruBefore?.markAsMostRecentChild()
    }
    var _floatingWindows: [FloatingWindowData] = []
    for window in workspace.floatingWindows {
        // todo bug: we shouldn't access ax api here. What if the window was moved but it wasn't committed to ax yet?
        guard let center = try? await window.getCenter(.nonCancellable) else { continue }

        let tilingParent: TilingContainer
        let index: Int
        if let target = center.coerce(in: workspace.workspaceMonitor.visibleRectPaddedByOuterGaps)?
            .findWindowRecursively(in: workspace.rootTilingContainer, virtual: true, fullscreenCoversAll: false)
        {
            guard let targetCenter = try? await target.getCenter(.nonCancellable) else { continue }
            guard let _tilingParent = target.parent as? TilingContainer else { continue }
            tilingParent = _tilingParent
            index = switch tilingParent.layout {
                case .tiles:
                    center.getProjection(tilingParent.orientation) >= targetCenter.getProjection(tilingParent.orientation)
                        ? target.ownIndex.orDie() + 1
                        : target.ownIndex.orDie()
                case .accordion:
                    center.getProjection(tilingParent.orientation) >= targetCenter.getProjection(tilingParent.orientation)
                        ? tilingParent.children.count
                        : 0
            }
        } else {
            index = 0
            tilingParent = workspace.rootTilingContainer
        }

        let data = window.unbindFromParent()
        let floatingWindowData = FloatingWindowData(
            window: window,
            center: center,
            tilingParent: tilingParent,
            adaptiveWeight: data.adaptiveWeight,
            index: index,
        )
        _floatingWindows.append(floatingWindowData)
    }
    let floatingWindows: [FloatingWindowData] = _floatingWindows.sortedBy { $0.center.getProjection($0.tilingParent.orientation) }.reversed()

    for floating in floatingWindows { // Make floating windows be seen as tiling
        floating.window.bind(to: floating.tilingParent, adaptiveWeight: 1, index: floating.index)
    }
    return floatingWindows
}

@MainActor private func restoreFloatingWindows(floatingWindows: [FloatingWindowData], workspace: Workspace) {
    let mruBefore = workspace.mostRecentWindowRecursive
    defer {
        mruBefore?.markAsMostRecentChild()
    }
    for floating in floatingWindows {
        floating.window.bind(to: workspace.floatingWindowsContainer, adaptiveWeight: floating.adaptiveWeight, index: INDEX_BIND_LAST)
    }
}

private struct FloatingWindowData {
    let window: Window
    let center: CGPoint

    let tilingParent: TilingContainer
    let adaptiveWeight: CGFloat
    let index: Int
}

extension TreeNode {
    @MainActor
    func findLeafWindowRecursive(snappedTo direction: CardinalDirection) -> Window? {
        switch nodeCases {
            case .workspace(let workspace):
                return workspace.rootTilingContainer.findLeafWindowRecursive(snappedTo: direction)
            case .window(let window):
                return window
            case .tilingContainer(let container):
                if direction.orientation == container.orientation {
                    return (direction.isPositive ? container.children.last : container.children.first)?
                        .findLeafWindowRecursive(snappedTo: direction)
                } else {
                    return mostRecentChild?.findLeafWindowRecursive(snappedTo: direction)
                }
            case .macosMinimizedWindowsContainer, .macosFullscreenWindowsContainer,
                 .macosPopupWindowsContainer, .macosHiddenAppsWindowsContainer,
                 .floatingWindowsContainer:
                die("Impossible")
        }
    }
}

```

## /Sources/AppBundle/command/impl/FocusMonitorCommand.swift

```swift path="/Sources/AppBundle/command/impl/FocusMonitorCommand.swift" 
import AppKit
import Common

struct FocusMonitorCommand: Command {
    let args: FocusMonitorCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        return switch args.target.val.resolve(target.workspace.workspaceMonitor, wrapAround: args.wrapAround) {
            case .success(let targetMonitor): .from(bool: targetMonitor.activeWorkspace.focusWorkspace())
            case .failure(let msg): .fail(io.err(msg))
        }
    }
}

extension MonitorTarget {
    @MainActor func resolve(_ currentMonitor: MonitorInfo, wrapAround: Bool) -> Result<MonitorInfo, String> {
        switch self {
            case .direction(let direction):
                guard let (monitorsInDirection, index) = currentMonitor.findRelativeMonitor(inDirection: direction) else {
                    return .failure("Should never happen. Can't find the current monitor")
                }
                let targetMonitor = wrapAround ? monitorsInDirection.get(wrappingIndex: index) : monitorsInDirection.getOrNil(atIndex: index)
                guard let targetMonitor else {
                    return .failure("No monitors in direction \(direction)")
                }
                return .success(targetMonitor)
            case .relative(let nextPrev):
                let monitors = sortedMonitorInfos
                guard let curIndex = monitors.firstIndex(where: { $0.rect.topLeftCorner == currentMonitor.rect.topLeftCorner }) else {
                    return .failure("Can't find current monitor")
                }
                let targetIndex = nextPrev == .next ? curIndex + 1 : curIndex - 1
                let targetMonitor = wrapAround ? monitors.get(wrappingIndex: targetIndex) : monitors.getOrNil(atIndex: targetIndex)
                guard let targetMonitor else {
                    return .failure("Can't find target monitor")
                }
                return .success(targetMonitor)
            case .patterns(let patterns):
                let monitors = sortedMonitorInfos
                guard let targetMonitor = patterns.lazy.compactMap({ $0.resolveMonitor(sortedMonitors: monitors) }).first else {
                    return .failure("None of the monitors match the pattern(s)")
                }
                return .success(targetMonitor)
        }
    }
}

extension MonitorInfo {
    func relation(to monitor: MonitorInfo) -> Orientation {
        guard let otherYRange = monitor.rect.minY.until(excl: monitor.rect.maxY) else { return .h }
        guard let myYRange = rect.minY.until(excl: rect.maxY) else { return .h }
        return myYRange.overlaps(otherYRange) ? .h : .v
    }

    func findRelativeMonitor(inDirection direction: CardinalDirection) -> (monitorsInDirection: [MonitorInfo], index: Int)? {
        let currentMonitor = self
        let monitors = sortedMonitorInfos.filter {
            currentMonitor.rect.topLeftCorner == $0.rect.topLeftCorner ||
                $0.relation(to: currentMonitor) == direction.orientation
        }
        guard let index = monitors.firstIndex(where: { $0.rect.topLeftCorner == currentMonitor.rect.topLeftCorner }) else { return nil }
        return (monitors, index + direction.focusOffset)
    }
}

```

## /Sources/AppBundle/command/impl/FullscreenCommand.swift

```swift path="/Sources/AppBundle/command/impl/FullscreenCommand.swift" 
import AppKit
import Common

struct FullscreenCommand: Command {
    let args: FullscreenCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        guard let window = target.windowOrNil else {
            return .fail(io.err(noWindowIsFocused))
        }
        let newState: Bool = switch args.toggle {
            case .on: true
            case .off: false
            case .toggle: !window.isFullscreen
        }
        if newState == window.isFullscreen {
            switch args.failIfNoop {
                case true: return .fail
                case false:
                    let msg = newState
                        ? "Already fullscreen. Tip: use --fail-if-noop to exit with non-zero code"
                        : "Already not fullscreen. Tip: use --fail-if-noop to exit with non-zero code"
                    return .succ(io.err(msg))
            }
        }
        window.isFullscreen = newState
        window.noOuterGapsInFullscreen = args.noOuterGaps

        // Focus on its own workspace
        window.markAsMostRecentChild()
        return .succ
    }
}

let noWindowIsFocused = "No window is focused"

```

## /Sources/AppBundle/command/impl/JoinWithCommand.swift

```swift path="/Sources/AppBundle/command/impl/JoinWithCommand.swift" 
import AppKit
import Common

struct JoinWithCommand: Command {
    let args: JoinWithCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = true

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        let direction = args.direction.val
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        guard let currentWindow = target.windowOrNil else {
            return .fail(io.err(noWindowIsFocused))
        }
        guard let (parent, ownIndex) = currentWindow.closestParent(hasChildrenInDirection: direction, withLayout: nil) else {
            return .fail(io.err("No windows in the specified direction"))
        }
        let joinWithTarget = parent.children[ownIndex + direction.focusOffset]
        let prevBinding = joinWithTarget.unbindFromParent()
        let newParent = TilingContainer(
            parent: parent,
            adaptiveWeight: prevBinding.adaptiveWeight,
            parent.orientation.opposite,
            .tiles,
            index: prevBinding.index,
        )
        currentWindow.unbindFromParent()

        joinWithTarget.bind(to: newParent, adaptiveWeight: WEIGHT_AUTO, index: 0)
        currentWindow.bind(to: newParent, adaptiveWeight: WEIGHT_AUTO, index: direction.isPositive ? 0 : INDEX_BIND_LAST)
        return .succ
    }
}

```

## /Sources/AppBundle/command/impl/LayoutCommand.swift

```swift path="/Sources/AppBundle/command/impl/LayoutCommand.swift" 
import AppKit
import Common

struct LayoutCommand: Command {
    let args: LayoutCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = true

    func run(_ env: CmdEnv, _ io: CmdIo) async -> BinaryExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }

        let node: ConventionalWindowParentCases
        switch args.root ? nil : target.windowOrNil {
            case let window?:
                switch window.windowParentCases {
                    case .floatingWindowsContainer(let it):
                        node = .floatingWindowsContainer(it)
                    case .tilingContainer(let it):
                        node = .tilingContainer(it)
                    case .macosFullscreenWindowsContainer,
                         .macosHiddenAppsWindowsContainer,
                         .macosMinimizedWindowsContainer:
                        let msg = "Can't change layout for macOS minimized, fullscreen windows or windows or hidden apps. " +
                            "This behavior is subject to change"
                        return .fail(io.err(msg))
                    case .unbound, .macosPopupWindowsContainer:
                        return .fail(io.err(bugPrompt()))
                }
            case nil:
                node = .tilingContainer(target.workspace.rootTilingContainer)
        }

        let targetDescription = args.toggleBetween.val.first(where: { !node.matchesDescription($0) })
            ?? args.toggleBetween.val.first.orDie()
        if node.matchesDescription(targetDescription) {
            switch args.failIfNoop {
                case true: return .fail
                case false:
                    let msg = "Already in the requested \(targetDescription.rawValue) mode. " +
                        "Tip: use --fail-if-noop to exit with non-zero exit code"
                    return .succ(io.err(msg))
            }
        }
        switch targetDescription {
            case .h_accordion:
                return changeTilingLayout(io, targetLayout: .accordion, targetOrientation: .h, node: node)
            case .v_accordion:
                return changeTilingLayout(io, targetLayout: .accordion, targetOrientation: .v, node: node)
            case .h_tiles:
                return changeTilingLayout(io, targetLayout: .tiles, targetOrientation: .h, node: node)
            case .v_tiles:
                return changeTilingLayout(io, targetLayout: .tiles, targetOrientation: .v, node: node)
            case .accordion:
                return changeTilingLayout(io, targetLayout: .accordion, targetOrientation: nil, node: node)
            case .tiles:
                return changeTilingLayout(io, targetLayout: .tiles, targetOrientation: nil, node: node)
            case .horizontal:
                return changeTilingLayout(io, targetLayout: nil, targetOrientation: .h, node: node)
            case .vertical:
                return changeTilingLayout(io, targetLayout: nil, targetOrientation: .v, node: node)
            case .tiling:
                guard let window = target.windowOrNil else { return .fail(io.err(noWindowIsFocused)) }
                switch node {
                    case .tilingContainer:
                        return .succ // Nothing to do
                    case .floatingWindowsContainer(let container):
                        window.lastFloatingSize = (try? await window.getAxSize(.nonCancellable)) ?? window.lastFloatingSize
                        guard let workspace = container.nodeWorkspace else { return .fail(io.err(bugPrompt())) }
                        do {
                            try await window.relayoutWindow(on: workspace, .nonCancellable, forceTile: true)
                        } catch {
                            return .fail(io.err(bugPrompt()))
                        }
                        return .succ
                }
            case .floating:
                guard let window = target.windowOrNil else { return .fail(io.err(noWindowIsFocused)) }
                let workspace = target.workspace
                window.bindAsFloatingWindow(to: workspace)
                if let size = window.lastFloatingSize { window.setAxFrame(nil, size) }
                return .succ
        }
    }
}

@MainActor private func changeTilingLayout(
    _ io: CmdIo,
    targetLayout: Layout?,
    targetOrientation: Orientation?,
    node: ConventionalWindowParentCases,
) -> BinaryExitCode {
    switch node {
        case .floatingWindowsContainer:
            return .fail(io.err("The window is non-tiling"))
        case .tilingContainer(let parent):
            let targetOrientation = targetOrientation ?? parent.orientation
            let targetLayout = targetLayout ?? parent.layout
            parent.layout = targetLayout
            parent.changeOrientation(targetOrientation)
            return .succ
    }
}

extension ConventionalWindowParentCases {
    fileprivate func matchesDescription(_ layout: LayoutCmdArgs.LayoutDescription) -> Bool {
        return switch layout {
            case .accordion:   tilingContainerOrNil?.layout == .accordion
            case .tiles:       tilingContainerOrNil?.layout == .tiles
            case .horizontal:  tilingContainerOrNil?.orientation == .h
            case .vertical:    tilingContainerOrNil?.orientation == .v
            case .h_accordion: tilingContainerOrNil.map { $0.layout == .accordion && $0.orientation == .h } == true
            case .v_accordion: tilingContainerOrNil.map { $0.layout == .accordion && $0.orientation == .v } == true
            case .h_tiles:     tilingContainerOrNil.map { $0.layout == .tiles && $0.orientation == .h } == true
            case .v_tiles:     tilingContainerOrNil.map { $0.layout == .tiles && $0.orientation == .v } == true
            case .tiling:      tilingContainerOrNil != nil
            case .floating:    floatingWindowsContainerOrNil != nil
        }
    }
}

```

## /Sources/AppBundle/command/impl/ListAppsCommand.swift

```swift path="/Sources/AppBundle/command/impl/ListAppsCommand.swift" 
import AppKit
import Common

struct ListAppsCommand: Command {
    let args: ListAppsCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        var result = Array(MacApp.allAppsMap.values)
        if let hidden = args.macosHidden {
            result = result.filter { $0.nsApp.isHidden == hidden }
        }

        lazy var list = result.map(AeroObj.app)
        return switch true {
            case args.outputOnlyCount:
                .succ(io.out("\(result.count)"))
            case args.json:
                switch list.formatToJson(args.format, ignoreRightPaddingVar: args._format.isEmpty) {
                    case .success(let json): .succ(io.out(json))
                    case .failure(let msg): .fail(io.err(msg))
                }
            default:
                switch list.format(args.format) {
                    case .success(let lines): .succ(io.out(lines))
                    case .failure(let msg): .fail(io.err(msg.map(\.description).joinErrors()))
                }
        }
    }
}

```

## /Sources/AppBundle/command/impl/ListExecEnvVarsCommand.swift

```swift path="/Sources/AppBundle/command/impl/ListExecEnvVarsCommand.swift" 
import AppKit
import Common

struct ListExecEnvVarsCommand: Command {
    let args: ListExecEnvVarsCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        for (key, value) in config.execConfig.envVariables {
            io.out("\(key)=\(value)")
        }
        return .succ
    }
}

```

## /Sources/AppBundle/command/impl/ListModesCommand.swift

```swift path="/Sources/AppBundle/command/impl/ListModesCommand.swift" 
import AppKit
import Common

struct ListModesCommand: Command {
    let args: ListModesCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        let modes: [String] = args.current ? [activeMode ?? mainModeId] : config.modes.keys.sorted()
        return switch true {
            case args.outputOnlyCount:
                .succ(io.out("\(modes.count)"))
            case args.json:
                JSONEncoder.aeroSpaceDefault.encodeToString(modes.map { ["mode-id": $0] }).map { .succ(io.out($0)) }
                    ?? .fail(io.err("Failed to encode JSON"))
            default:
                .succ(io.out(modes))
        }
    }
}

```

## /Sources/AppBundle/command/impl/ListMonitorsCommand.swift

```swift path="/Sources/AppBundle/command/impl/ListMonitorsCommand.swift" 
import AppKit
import Common

struct ListMonitorsCommand: Command {
    let args: ListMonitorsCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        let focus = focus
        var result = sortedMonitorInfos
        if let focused = args.focused {
            result = result.filter { (monitor) in (monitor.activeWorkspace == focus.workspace) == focused }
        }
        if let mouse = args.mouse {
            let mouseWorkspace = mouseLocation.monitorApproximation.activeWorkspace
            result = result.filter { (monitor) in (monitor.activeWorkspace == mouseWorkspace) == mouse }
        }

        lazy var list = result.map(AeroObj.monitor)
        return switch true {
            case args.outputOnlyCount:
                .succ(io.out("\(result.count)"))
            case args.json:
                switch list.formatToJson(args.format, ignoreRightPaddingVar: args._format.isEmpty) {
                    case .success(let json): .succ(io.out(json))
                    case .failure(let msg): .fail(io.err(msg))
                }
            default:
                switch list.format(args.format) {
                    case .success(let lines): .succ(io.out(lines))
                    case .failure(let msg): .fail(io.err(msg.map(\.description).joinErrors()))
                }
        }
    }
}

```

## /Sources/AppBundle/command/impl/ListWindowsCommand.swift

```swift path="/Sources/AppBundle/command/impl/ListWindowsCommand.swift" 
import AppKit
import Common

struct ListWindowsCommand: Command {
    let args: ListWindowsCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> BinaryExitCode {
        let focus = focus
        var windows: [Window] = []

        if args.filteringOptions.focused {
            switch focus.windowOrNil {
                case let window?: windows = [window]
                case nil: return .fail(io.err(noWindowIsFocused))
            }
        } else {
            var workspaces: Set<Workspace> = args.filteringOptions.workspaces.isEmpty
                ? Workspace.all.toSet()
                : args.filteringOptions.workspaces
                    .flatMap { filter in
                        switch filter {
                            case .focused: [focus.workspace]
                            case .visible: Workspace.all.filter(\.isVisible)
                            case .name(let name): [Workspace.get(byName: name.raw)]
                        }
                    }
                    .toSet()
            if !args.filteringOptions.monitors.isEmpty {
                let monitors: Set<CGPoint> = args.filteringOptions.monitors.resolveMonitors(io)
                if monitors.isEmpty { return .fail }
                workspaces = workspaces.filter { monitors.contains($0.workspaceMonitor.rect.topLeftCorner) }
            }
            windows = workspaces.flatMap(\.allLeafWindowsRecursive)
            if let pid = args.filteringOptions.pidFilter {
                windows = windows.filter { $0.app.pid == pid }
            }
            if let appId = args.filteringOptions.appIdFilter {
                windows = windows.filter { $0.app.rawAppBundleId == appId }
            }
        }

        if args.outputOnlyCount {
            return .succ(io.out("\(windows.count)"))
        } else {
            var _list: [WindowWithPrefetchedTitle] = [] // todo cleanup
            for window in windows {
                guard let window = try? await WindowWithPrefetchedTitle.resolveWindow(window, for: args.format, .nonCancellable) else { return .fail(io.err(bugPrompt())) }
                _list.append(window)
            }
            _list = _list.filter { $0.window.isBound }
            _list = _list.sortedBy([{ $0.window.app.name ?? "" }, { $0.title ?? "" }])

            let list = _list.map { AeroObj.window($0) }
            if args.json {
                return switch list.formatToJson(args.format, ignoreRightPaddingVar: args._format.isEmpty) {
                    case .success(let json): .succ(io.out(json))
                    case .failure(let msg): .fail(io.err(msg))
                }
            } else {
                return switch list.format(args.format) {
                    case .success(let lines): .succ(io.out(lines))
                    case .failure(let msg): .fail(io.err(msg.map(\.description).joinErrors()))
                }
            }
        }
    }
}

```

## /Sources/AppBundle/command/impl/ListWorkspacesCommand.swift

```swift path="/Sources/AppBundle/command/impl/ListWorkspacesCommand.swift" 
import AppKit
import Common

struct ListWorkspacesCommand: Command {
    let args: ListWorkspacesCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        var result: [Workspace] = Workspace.all
        if let visible = args.filteringOptions.visible {
            result = result.filter { $0.isVisible == visible }
        }
        if !args.filteringOptions.onMonitors.isEmpty {
            let monitors: Set<CGPoint> = args.filteringOptions.onMonitors.resolveMonitors(io)
            if monitors.isEmpty { return .fail }
            result = result.filter { monitors.contains($0.workspaceMonitor.rect.topLeftCorner) }
        }
        if let empty = args.filteringOptions.empty {
            result = result.filter { $0.isEffectivelyEmpty == empty }
        }

        lazy var list = result.map() { AeroObj.workspace($0) }
        return switch true {
            case args.outputOnlyCount:
                .succ(io.out("\(result.count)"))
            case args.json:
                switch list.formatToJson(args.format, ignoreRightPaddingVar: args._format.isEmpty) {
                    case .success(let json): .succ(io.out(json))
                    case .failure(let msg): .fail(io.err(msg))
                }
            default:
                switch list.format(args.format) {
                    case .success(let lines): .succ(io.out(lines))
                    case .failure(let msg): .fail(io.err(msg.map(\.description).joinErrors()))
                }
        }
    }
}

extension [MonitorId] {
    @MainActor func resolveMonitors(_ io: CmdIo) -> Set<CGPoint> {
        var requested: Set<CGPoint> = []
        let sortedMonitors = sortedMonitorInfos
        for id in self {
            let resolved = id.resolve(io, sortedMonitors: sortedMonitors)
            if resolved.isEmpty {
                return []
            }
            for monitor in resolved {
                requested.insert(monitor.rect.topLeftCorner)
            }
        }
        return requested
    }
}

extension MonitorId {
    @MainActor func resolve(_ io: CmdIo, sortedMonitors: [MonitorInfo]) -> [MonitorInfo] {
        switch self {
            case .focused:
                return [focus.workspace.workspaceMonitor]
            case .mouse:
                return [mouseLocation.monitorApproximation]
            case .all:
                return monitorInfos
            case .index(let index):
                if let monitor = sortedMonitors.getOrNil(atIndex: index) {
                    return [monitor]
                } else {
                    io.err("Invalid monitor ID: \(index + 1)")
                    return []
                }
        }
    }
}

```

## /Sources/AppBundle/command/impl/MacosNativeFullscreenCommand.swift

```swift path="/Sources/AppBundle/command/impl/MacosNativeFullscreenCommand.swift" 
import AppKit
import Common

/// Problem ID-B6E178F2: It's not first-class citizen command in AeroSpace model, since it interacts with macOS API directly.
/// Consecutive macos-native-fullscreen commands may not works as expected (because macOS may report correct state with a
/// delay), or may flicker
///
/// The same applies to macos-native-minimize command
struct MacosNativeFullscreenCommand: Command {
    let args: MacosNativeFullscreenCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> BinaryExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        guard let window = target.windowOrNil else {
            return .fail(io.err(noWindowIsFocused))
        }
        guard let prevState = try? await window.isMacosFullscreen(.nonCancellable) else { return .fail(io.err(bugPrompt())) }
        let newState: Bool = switch args.toggle {
            case .on: true
            case .off: false
            case .toggle: !prevState
        }
        if newState == prevState {
            return switch args.failIfNoop {
                case true: .fail
                case false:
                    .succ(io.err((newState ? "Already fullscreen. " : "Already not fullscreen. ") +
                            "Tip: use --fail-if-noop to exit with non-zero exit code"))
            }
        }
        window.asMacWindow().setNativeFullscreen(newState)
        guard let workspace = window.visualWorkspace else {
            return .fail(io.err(windowIsntPartOfTree(window)))
        }
        if newState { // Enter fullscreen
            window.bind(to: workspace.macOsNativeFullscreenWindowsContainer, adaptiveWeight: 1, index: INDEX_BIND_LAST)
        } else { // Exit fullscreen
            switch window.layoutReason {
                case .macos(let prevParentKind):
                    do {
                        try await exitMacOsNativeUnconventionalState(
                            window: window,
                            prevParentKind: prevParentKind,
                            workspace: workspace,
                            .nonCancellable,
                        )
                    } catch {
                        return .fail(io.err(bugPrompt()))
                    }
                default:
                    do {
                        try await window.relayoutWindow(on: workspace, .nonCancellable)
                    } catch {
                        return .fail(io.err(bugPrompt()))
                    }
            }
        }
        return .succ
    }
}

```

## /Sources/AppBundle/command/impl/MacosNativeMinimizeCommand.swift

```swift path="/Sources/AppBundle/command/impl/MacosNativeMinimizeCommand.swift" 
import AppKit
import Common

/// See: MacosNativeFullscreenCommand. Problem ID-B6E178F2
struct MacosNativeMinimizeCommand: Command {
    let args: MacosNativeMinimizeCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> BinaryExitCode {
        // resolveTargetOrReportError on already minimized windows will always fail
        // It would be easier if minimized windows were part of the workspace in tree hierarchy
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        guard let window = target.windowOrNil else {
            return .fail(io.err(noWindowIsFocused))
        }
        guard let newState: Bool = try? await !window.isMacosMinimized(.nonCancellable) else { return .fail(io.err(bugPrompt())) }
        window.asMacWindow().setNativeMinimized(newState)
        if newState { // minimize
            window.bind(to: macosMinimizedWindowsContainer, adaptiveWeight: 1, index: INDEX_BIND_LAST)
            return .succ
        } else { // unminimize
            return .fail(io.err("The command is uncapable of unminimizing windows yet. Sorry")) // dead code. should never be possible, see the comment above
        }
    }
}

```

## /Sources/AppBundle/command/impl/ModeCommand.swift

```swift path="/Sources/AppBundle/command/impl/ModeCommand.swift" 
import AppKit
import Common

struct ModeCommand: Command {
    let args: ModeCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> BinaryExitCode {
        await activateMode_nonCancellable(args.targetMode.val)
        return .succ
    }
}

```

## /Sources/AppBundle/command/impl/MoveCommand.swift

```swift path="/Sources/AppBundle/command/impl/MoveCommand.swift" 
import AppKit
import Common

struct MoveCommand: Command {
    let args: MoveCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = true

    func run(_ env: CmdEnv, _ io: CmdIo) async -> BinaryExitCode {
        let direction = args.direction.val
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        guard let currentWindow = target.windowOrNil else {
            return .fail(io.err(noWindowIsFocused))
        }
        if await shouldFailBecauseFullscreen_nonCancellable(
            window: currentWindow,
            failIfFullscreen: args.failIfFullscreen,
            failIfMacosNativeFullscreen: args.failIfMacosNativeFullscreen,
        ) {
            return .fail
        }
        switch currentWindow.windowParentCases {
            case .unbound: return .fail
            case .tilingContainer(let parent):
                guard let indexOfCurrent = currentWindow.ownIndex else { return .fail(io.err(bugPrompt())) }
                let indexOfSiblingTarget = indexOfCurrent + direction.focusOffset
                if parent.orientation == direction.orientation && parent.children.indices.contains(indexOfSiblingTarget) {
                    switch parent.children[indexOfSiblingTarget].tilingTreeNodeCasesOrDie() {
                        case .tilingContainer(let topLevelSiblingTargetContainer):
                            return deepMoveIn(window: currentWindow, into: topLevelSiblingTargetContainer, moveDirection: direction, io)
                        case .window: // "swap windows"
                            let prevBinding = currentWindow.unbindFromParent()
                            currentWindow.bind(to: parent, adaptiveWeight: prevBinding.adaptiveWeight, index: indexOfSiblingTarget)
                            return .succ
                    }
                } else {
                    return moveOut(tilingWindow: currentWindow, direction: direction, io, args, env)
                }
            case .floatingWindowsContainer: // floating window
                return .fail(io.err("moving floating windows isn't yet supported")) // todo
            case .macosMinimizedWindowsContainer, .macosFullscreenWindowsContainer, .macosHiddenAppsWindowsContainer:
                return .fail(io.err(moveOutMacosUnconventionalWindow))
            case .macosPopupWindowsContainer:
                return .fail(io.err(bugPrompt())) // Impossible
        }
    }
}

@MainActor private func hitWorkspaceBoundaries(
    _ window: Window,
    _ workspace: Workspace,
    _ io: CmdIo,
    _ args: MoveCmdArgs,
    _ direction: CardinalDirection,
    _ env: CmdEnv,
) -> BinaryExitCode {
    switch args.boundaries {
        case .workspace:
            switch args.boundariesAction {
                case .stop: return .succ
                case .fail: return .fail
                case .createImplicitContainer:
                    createImplicitContainerAndMoveWindow(window, workspace, direction)
                    return .succ
            }
        case .allMonitorsOuterFrame:
            guard let (monitors, index) = window.nodeMonitor?.findRelativeMonitor(inDirection: direction) else {
                return .fail(io.err("Should never happen. Can't find the current monitor"))
            }

            if monitors.indices.contains(index) {
                let moveNodeToMonitorArgs = MoveNodeToMonitorCmdArgs(target: .direction(direction))
                    .copy(\.windowId, window.windowId)
                    .copy(\.focusFollowsWindow, focus.windowOrNil == window)

                return MoveNodeToMonitorCommand(args: moveNodeToMonitorArgs).run(env, io)
            } else {
                return hitAllMonitorsOuterFrameBoundaries(window, workspace, args, direction)
            }
    }
}

@MainActor private func hitAllMonitorsOuterFrameBoundaries(
    _ window: Window,
    _ workspace: Workspace,
    _ args: MoveCmdArgs,
    _ direction: CardinalDirection,
) -> BinaryExitCode {
    switch args.boundariesAction {
        case .stop: return .succ
        case .fail: return .fail
        case .createImplicitContainer:
            createImplicitContainerAndMoveWindow(window, workspace, direction)
            return .succ
    }
}

private let moveOutMacosUnconventionalWindow = "moving macOS fullscreen, minimized windows and windows of hidden apps isn't yet supported. This behavior is subject to change"

@MainActor private func moveOut(
    tilingWindow window: Window,
    direction: CardinalDirection,
    _ io: CmdIo,
    _ args: MoveCmdArgs,
    _ env: CmdEnv,
) -> BinaryExitCode {
    let innerMostTilingContainer = window.parents.first(where: {
        return switch $0.parent?.cases {
            case .tilingContainer(let parent): parent.orientation == direction.orientation
            // Stop searching: we have hit the workspace
            case nil, .workspace: true
            // Impossible: tilingContainer's parent can only be a workspace or tilingContainer
            case .floatingWindowsContainer,
                 .macosMinimizedWindowsContainer,
                 .macosFullscreenWindowsContainer,
                 .macosHiddenAppsWindowsContainer,
                 .macosPopupWindowsContainer: true
        }
    }) as? TilingContainer
    guard let innerMostTilingContainer else { return .fail(io.err(bugPrompt())) } // Impossible
    switch innerMostTilingContainer.tilingContainerParentCases {
        case .unbound: return .fail
        case .tilingContainer(let parent):
            check(parent.orientation == direction.orientation)
            guard let ownIndex = innerMostTilingContainer.ownIndex else { return .fail(io.err(bugPrompt())) }
            window.bind(to: parent, adaptiveWeight: WEIGHT_AUTO, index: ownIndex + direction.insertionOffset)
            return .succ
        case .workspace(let parent):
            return hitWorkspaceBoundaries(window, parent, io, args, direction, env)
    }
}

@MainActor private func createImplicitContainerAndMoveWindow(
    _ window: Window,
    _ workspace: Workspace,
    _ direction: CardinalDirection,
) {
    let prevRoot = workspace.rootTilingContainer
    prevRoot.unbindFromParent()
    // Force tiles layout
    _ = TilingContainer(parent: workspace, adaptiveWeight: WEIGHT_AUTO, direction.orientation, .tiles, index: 0)
    check(prevRoot != workspace.rootTilingContainer)
    prevRoot.bind(to: workspace.rootTilingContainer, adaptiveWeight: WEIGHT_AUTO, index: 0)
    window.bind(to: workspace.rootTilingContainer, adaptiveWeight: WEIGHT_AUTO, index: direction.insertionOffset)
}

@MainActor private func deepMoveIn(window: Window, into container: TilingContainer, moveDirection: CardinalDirection, _ io: CmdIo) -> BinaryExitCode {
    let deepTarget = container.tilingTreeNodeCasesOrDie().findDeepMoveInTargetRecursive(moveDirection.orientation)
    switch deepTarget {
        case .tilingContainer(let deepTarget):
            window.bind(to: deepTarget, adaptiveWeight: WEIGHT_AUTO, index: 0)
        case .window(let deepTarget):
            guard let parent = deepTarget.parent as? TilingContainer else { return .fail(io.err(bugPrompt())) }
            guard let deepTargetIndex = deepTarget.ownIndex else { return .fail(io.err(bugPrompt())) }
            window.bind(to: parent, adaptiveWeight: WEIGHT_AUTO, index: deepTargetIndex + 1)
    }
    return .succ
}

extension TilingTreeNodeCases {
    @MainActor fileprivate func findDeepMoveInTargetRecursive(_ orientation: Orientation) -> TilingTreeNodeCases {
        switch self {
            case .window:
                self
            case .tilingContainer(let container) where container.orientation == orientation:
                .tilingContainer(container)
            case .tilingContainer(let container):
                container.mostRecentChild.orDie("Empty containers must be detached during normalization")
                    .tilingTreeNodeCasesOrDie()
                    .findDeepMoveInTargetRecursive(orientation)
        }
    }
}

func shouldFailBecauseFullscreen_nonCancellable(
    window: Window,
    failIfFullscreen: Bool,
    failIfMacosNativeFullscreen: Bool,
) async -> Bool {
    if failIfFullscreen && window.isFullscreen {
        return true
    }
    if failIfMacosNativeFullscreen {
        if true == (try? await window.isMacosFullscreen(.nonCancellable)) {
            return true
        }
    }
    return false
}

```

## /Sources/AppBundle/command/impl/MoveMouseCommand.swift

```swift path="/Sources/AppBundle/command/impl/MoveMouseCommand.swift" 
import AppKit
import Common

struct MoveMouseCommand: Command {
    let args: MoveMouseCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> BinaryExitCode {
        let mouse = mouseLocation
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        switch args.mouseTarget.val {
            case .windowLazyCenter:
                guard let rect = await windowSubjectRectOrReportError(target, io) else { return .fail }
                if rect.contains(mouse) {
                    return switch args.failIfNoop {
                        case true: .fail
                        case false:
                            .succ(io.err("The mouse already belongs to the window. Tip: use --fail-if-noop to exit with non-zero code"))
                    }
                }
                return moveMouse(io, rect.center)
            case .windowForceCenter:
                guard let rect = await windowSubjectRectOrReportError(target, io) else { return .fail }
                return moveMouse(io, rect.center)
            case .monitorLazyCenter:
                let rect = target.workspace.workspaceMonitor.rect
                if rect.contains(mouse) {
                    return switch args.failIfNoop {
                        case true: .fail
                        case false:
                            .succ(io.err("The mouse already belongs to the monitor. Tip: use --fail-if-noop to exit with non-zero code"))
                    }
                }
                return moveMouse(io, rect.center)
            case .monitorForceCenter:
                return moveMouse(io, target.workspace.workspaceMonitor.rect.center)
        }
    }
}

private func moveMouse(_ io: CmdIo, _ point: CGPoint) -> BinaryExitCode {
    let event = CGEvent(
        mouseEventSource: nil,
        mouseType: CGEventType.mouseMoved,
        mouseCursorPosition: point,
        mouseButton: CGMouseButton.left,
    )
    switch event {
        case nil: return .fail(io.err("Failed to move mouse"))
        case let event?:
            event.post(tap: CGEventTapLocation.cghidEventTap)
            return .succ
    }
}

@MainActor
private func windowSubjectRectOrReportError(_ target: LiveFocus, _ io: CmdIo) async -> Rect? {
    // todo bug it's bad that we operate on the "ax physical" state directly. command seq won't work correctly
    //      focus <direction> command has the similar problem
    if let window: Window = target.windowOrNil {
        if let rect = window.lastAppliedLayoutPhysicalRect {
            return rect
        } else if let rect = try? await window.getAxRect(.nonCancellable) {
            return rect
        } else {
            io.err("Failed to get rect of window '\(window.windowId)'")
            return nil
        }
    } else {
        io.err(noWindowIsFocused)
        return nil
    }
}

```

## /Sources/AppBundle/command/impl/MoveNodeToMonitorCommand.swift

```swift path="/Sources/AppBundle/command/impl/MoveNodeToMonitorCommand.swift" 
import AppKit
import Common

struct MoveNodeToMonitorCommand: Command {
    let args: MoveNodeToMonitorCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = true

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        guard let window = target.windowOrNil else {
            return .fail(io.err(noWindowIsFocused))
        }
        guard let currentMonitor = window.nodeMonitor else {
            return .fail(io.err(windowIsntPartOfTree(window)))
        }
        switch args.target.val.resolve(currentMonitor, wrapAround: args.wrapAround) {
            case .success(let targetMonitor):
                let targetWs = targetMonitor.activeWorkspace
                let index = true == args.target.val.directionOrNil
                    .map { dir in dir.isPositive && targetWs.rootTilingContainer.orientation == dir.orientation }
                    ? 0
                    : INDEX_BIND_LAST
                return moveWindowToWorkspace(
                    window,
                    targetWs,
                    io,
                    focusFollowsWindow: args.focusFollowsWindow,
                    failIfNoop: args.failIfNoop,
                    index: index,
                )
            case .failure(let msg):
                return .fail(io.err(msg))
        }
    }
}

func windowIsntPartOfTree(_ window: Window) -> String {
    "Window \(window.windowId) is not part of tree (minimized or hidden)"
}

```

## /Sources/AppBundle/command/impl/MoveNodeToWorkspaceCommand.swift

```swift path="/Sources/AppBundle/command/impl/MoveNodeToWorkspaceCommand.swift" 
import Common

struct MoveNodeToWorkspaceCommand: Command {
    let args: MoveNodeToWorkspaceCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache: Bool = true

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        guard let window = target.windowOrNil else { return .fail(io.err(noWindowIsFocused)) }
        let subjectWs = window.nodeWorkspace
        let targetWorkspace: Workspace
        switch args.target.val {
            case .relative(let nextPrev):
                guard let subjectWs else { return .fail(io.err("Window \(window.windowId) doesn't belong to any workspace")) }
                let ws = getNextPrevWorkspace(
                    current: subjectWs,
                    isNext: nextPrev == .next,
                    wrapAround: args.wrapAround,
                    stdin: args.useStdin ? io.readStdin() : nil,
                    target: target,
                )
                guard let ws = ws.getOrNil(appendErrorTo: &io.stderr) else { return .fail }
                targetWorkspace = ws
            case .direct(let name):
                targetWorkspace = Workspace.get(byName: name.raw)
        }
        return moveWindowToWorkspace(window, targetWorkspace, io, focusFollowsWindow: args.focusFollowsWindow, failIfNoop: args.failIfNoop)
    }
}

@MainActor
func moveWindowToWorkspace(_ window: Window, _ targetWorkspace: Workspace, _ io: CmdIo, focusFollowsWindow: Bool, failIfNoop: Bool, index: Int = INDEX_BIND_LAST) -> BinaryExitCode {
    if window.nodeWorkspace == targetWorkspace {
        return switch failIfNoop {
            case true: .fail
            case false:
                .succ(io.err("Window '\(window.windowId)' already belongs to workspace '\(targetWorkspace.name)'. Tip: use --fail-if-noop to exit with non-zero code"))
        }
    }
    let targetContainer: NonLeafTreeNodeObject = window.isFloating
        ? targetWorkspace.floatingWindowsContainer
        : targetWorkspace.rootTilingContainer
    window.bind(to: targetContainer, adaptiveWeight: WEIGHT_AUTO, index: index)
    return .from(bool: focusFollowsWindow ? window.focusWindow() : true)
}

```

## /Sources/AppBundle/command/impl/MoveWorkspaceToMonitorCommand.swift

```swift path="/Sources/AppBundle/command/impl/MoveWorkspaceToMonitorCommand.swift" 
import AppKit
import Common

struct MoveWorkspaceToMonitorCommand: Command {
    let args: MoveWorkspaceToMonitorCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = true

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        let focusedWorkspace = target.workspace
        let prevMonitor = focusedWorkspace.workspaceMonitor

        switch args.target.val.resolve(target.workspace.workspaceMonitor, wrapAround: args.wrapAround) {
            case .success(let targetMonitor):
                if targetMonitor.monitorId_oneBased == prevMonitor.monitorId_oneBased {
                    return .succ
                }
                if targetMonitor.setActiveWorkspace(focusedWorkspace) {
                    let stubWorkspace = getStubWorkspace(for: prevMonitor)
                    check(
                        prevMonitor.setActiveWorkspace(stubWorkspace),
                        "getStubWorkspace generated incompatible stub workspace (\(stubWorkspace)) for the monitor (\(prevMonitor)",
                    )
                    return .succ
                } else {
                    return .fail(io.err(
                        "Can't move workspace '\(focusedWorkspace.name)' to monitor '\(targetMonitor.name)'. workspace-to-monitor-force-assignment doesn't allow it",
                    ))
                }
            case .failure(let msg):
                return .fail(io.err(msg))
        }
    }
}

```

## /Sources/AppBundle/command/impl/ReloadConfigCommand.swift

```swift path="/Sources/AppBundle/command/impl/ReloadConfigCommand.swift" 
import AppKit
import Common

struct ReloadConfigCommand: Command {
    let args: ReloadConfigCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> BinaryExitCode {
        let result = await reloadConfig_nonCancellable(args: args)
        if !result.stdout.isEmpty {
            io.out(result.stdout)
        }
        if !result.stderr.isEmpty {
            io.err(result.stderr)
        }
        return .from(bool: result.isOk)
    }
}

struct ReloadConfigResult {
    let isOk: Bool
    let stdout: String
    let stderr: String
}

@MainActor func reloadConfig_nonCancellable(
    args: ReloadConfigCmdArgs = ReloadConfigCmdArgs(rawArgs: []),
    forceConfigUrl: URL? = nil,
) async -> ReloadConfigResult {
    let result = readConfig(forceConfigUrl: forceConfigUrl)
    let parseResult = result.parseConfigResult
    let warningsAsErrors = args.warningsAsErrors

    var errors = parseResult.errors.map { $0.description(.error) }
    var warnings = parseResult.warnings.map { $0.description(.warning) }
    let containsWarnings = !parseResult.warnings.isEmpty

    if !args.noGui {
        let lines = errors + warnings
        switch true {
            case !errors.isEmpty:
                let msg = failedToParseMsg(configUrl: result.configUrl, errorsCount: parseResult.errors.count, warningsCount: parseResult.warnings.count, lines: lines)
                MessageModel.shared.message = Message(body: msg, containsWarnings: containsWarnings)
            case warningsAsErrors && !warnings.isEmpty:
                let msg = parsedWithWarningsMsg(configUrl: result.configUrl, warningsCount: parseResult.warnings.count, lines: lines)
                MessageModel.shared.message = Message(body: msg, containsWarnings: containsWarnings)
            default:
                MessageModel.shared.message = nil
        }
    }
    if parseResult.allowReloadConfig && !args.dryRun {
        TrayMenuModel.shared.lastReloadConfigContainedWarnings = containsWarnings
        resetHotKeys()
        config = parseResult.config
        configUrl = result.configUrl
        await activateMode_nonCancellable(activeMode)
        syncStartAtLogin()
        syncFocusFollowsMouse(config)
        syncConfigFileWatcher()
    }

    if warningsAsErrors {
        errors += warnings
        warnings = []
    }

    return ReloadConfigResult(
        isOk: errors.isEmpty,
        stdout: errors.joined(separator: "\n\n"),
        stderr: warnings.joined(separator: "\n\n"),
    )
}

private func failedToParseMsg(configUrl: URL, errorsCount: Int, warningsCount: Int, lines: [String]) -> String {
    let path = configUrl.absoluteURL.path.singleQuoted
    let header = "Failed to parse \(path). \(errorsCount) error(s). \(warningsCount) warning(s)"
    return "\(header)\n\n\(lines.joined(separator: "\n\n"))"
}

private func parsedWithWarningsMsg(configUrl: URL, warningsCount: Int, lines: [String]) -> String {
    let path = configUrl.absoluteURL.path.singleQuoted
    let header = "Parsed \(path) with \(warningsCount) warning(s). Feel free to close this window."
    return "\(header)\n\n\(lines.joined(separator: "\n\n"))"
}

```

## /Sources/AppBundle/command/impl/ResizeCommand.swift

```swift path="/Sources/AppBundle/command/impl/ResizeCommand.swift" 
import AppKit
import Common

struct ResizeCommand: Command {
    let args: ResizeCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = true

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }

        let candidates = target.windowOrNil?.parentsWithSelf
            .filter { ($0.parent as? TilingContainer)?.layout == .tiles }
            ?? []

        let orientation: Orientation?
        let parent: TilingContainer?
        let node: TreeNode?
        switch args.dimension.val {
            case .width:
                orientation = .h
                node = candidates.first(where: { ($0.parent as? TilingContainer)?.orientation == orientation })
                parent = node?.parent as? TilingContainer
            case .height:
                orientation = .v
                node = candidates.first(where: { ($0.parent as? TilingContainer)?.orientation == orientation })
                parent = node?.parent as? TilingContainer
            case .smart:
                node = candidates.first
                parent = node?.parent as? TilingContainer
                orientation = parent?.orientation
            case .smartOpposite:
                orientation = (candidates.first?.parent as? TilingContainer)?.orientation.opposite
                node = candidates.first(where: { ($0.parent as? TilingContainer)?.orientation == orientation })
                parent = node?.parent as? TilingContainer
        }
        guard let parent else {
            return .fail(io.err("resize command doesn't support floating windows yet https://github.com/nikitabobko/AeroSpace/issues/9"))
        }
        guard let orientation else { return .fail }
        guard let node else { return .fail }
        let diff: CGFloat = switch args.units.val {
            case .set(let unit): CGFloat(unit) - node.getWeight(orientation)
            case .add(let unit): CGFloat(unit)
            case .subtract(let unit): -CGFloat(unit)
        }

        guard let childDiff = diff.div(parent.children.count - 1) else { return .fail }
        parent.children.lazy
            .filter { $0 != node }
            .forEach { $0.setWeight(parent.orientation, $0.getWeight(parent.orientation) - childDiff) }

        node.setWeight(orientation, node.getWeight(orientation) + diff)
        return .succ
    }
}

```

## /Sources/AppBundle/command/impl/RunCallbackCommand.swift

```swift path="/Sources/AppBundle/command/impl/RunCallbackCommand.swift" 
import AppKit
import Common

struct RunCallbackCommand: Command {
    let args: RunCallbackCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = true

    func run(_ env: CmdEnv, _ io: CmdIo) async -> Int32ExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        switch args.callback.val {
            case .onWindowDetected where args.forEveryWindow:
                var exitCode = Int32ExitCode.succ
                for window in MacWindow.allWindows {
                    exitCode = await onWindowDetected(env, io, window)
                }
                return exitCode
            case .onWindowDetected:
                guard let window = target.windowOrNil else { return .fail(io.err(noWindowIsFocused)) }
                return await onWindowDetected(env, io, window)
            case .onFocusChanged:
                return await onFocusChanged(env, io, target)
            case .onFocusedMonitorChanged:
                return await onFocusedMonitorChanged(env, io, target)
        }
    }
}

```

## /Sources/AppBundle/command/impl/SplitCommand.swift

```swift path="/Sources/AppBundle/command/impl/SplitCommand.swift" 
import AppKit
import Common

struct SplitCommand: Command {
    let args: SplitCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = true

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        if config.enableNormalizationFlattenContainers {
            return .fail(io.err("'split' has no effect when 'enable-normalization-flatten-containers' normalization enabled. My recommendation: keep the normalizations enabled, and prefer 'join-with' over 'split'."))
        }
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        guard let window = target.windowOrNil else {
            return .fail(io.err(noWindowIsFocused))
        }
        guard let parent = window.parent else { return .fail(io.err(bugPrompt())) }
        switch parent.cases {
            case .floatingWindowsContainer:
                // Nothing to do for floating and macOS native fullscreen windows
                return .fail(io.err("Can't split floating windows"))
            case .tilingContainer(let parent):
                let orientation: Orientation = switch args.arg.val {
                    case .vertical: .v
                    case .horizontal: .h
                    case .opposite: parent.orientation.opposite
                }
                if parent.children.count == 1 {
                    parent.changeOrientation(orientation)
                } else {
                    let data = window.unbindFromParent()
                    let newParent = TilingContainer(
                        parent: parent,
                        adaptiveWeight: data.adaptiveWeight,
                        orientation,
                        .tiles,
                        index: data.index,
                    )
                    window.bind(to: newParent, adaptiveWeight: WEIGHT_AUTO, index: 0)
                }
                return .succ
            case .macosMinimizedWindowsContainer, .macosFullscreenWindowsContainer, .macosHiddenAppsWindowsContainer:
                return .fail(io.err("Can't split macos fullscreen, minimized windows and windows of hidden apps. This behavior may change in the future"))
            case .macosPopupWindowsContainer, .workspace:
                return .fail(io.err(bugPrompt())) // Impossible
        }
    }
}

```

## /Sources/AppBundle/command/impl/SummonWorkspaceCommand.swift

```swift path="/Sources/AppBundle/command/impl/SummonWorkspaceCommand.swift" 
import AppKit
import Common

struct SummonWorkspaceCommand: Command {
    let args: SummonWorkspaceCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = true

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        let workspace = Workspace.get(byName: args.target.val.raw)
        let monitor = focus.workspace.workspaceMonitor
        if monitor.activeWorkspace == workspace {
            return switch args.failIfNoop {
                case true: .fail
                case false:
                    .succ(io.err("Workspace '\(workspace.name)' is already visible on the focused monitor. Tip: use --fail-if-noop to exit with non-zero code"))
            }
        }
        let prevMonitor = workspace.isVisible ? workspace.workspaceMonitor : nil
        if monitor.setActiveWorkspace(workspace) {
            if let prevMonitor {
                let stubWorkspace = getStubWorkspace(for: prevMonitor)
                check(
                    prevMonitor.setActiveWorkspace(stubWorkspace),
                    "getStubWorkspace generated incompatible stub workspace (\(stubWorkspace)) for the monitor (\(prevMonitor)",
                )
            }
            return .from(bool: workspace.focusWorkspace())
        } else {
            return .fail(io.err("Can't move workspace '\(workspace.name)' to monitor '\(monitor.name)'. workspace-to-monitor-force-assignment doesn't allow it"))
        }
    }
}

```

## /Sources/AppBundle/command/impl/SwapCommand.swift

```swift path="/Sources/AppBundle/command/impl/SwapCommand.swift" 
import AppKit
import Common

struct SwapCommand: Command {
    let args: SwapCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache: Bool = true

    func run(_ env: CmdEnv, _ io: CmdIo) async -> BinaryExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else {
            return .fail
        }

        guard let currentWindow = target.windowOrNil else {
            return .fail(io.err(noWindowIsFocused))
        }

        let targetWindow: Window?
        switch args.target.val {
            case .direction(let direction):
                switch currentWindow.closestParent(hasChildrenInDirection: direction, withLayout: nil) {
                    case let (parent, ownIndex)?:
                        targetWindow = parent.children[ownIndex + direction.focusOffset].findLeafWindowRecursive(snappedTo: direction.opposite)
                    case nil where args.wrapAround:
                        targetWindow = target.workspace.findLeafWindowRecursive(snappedTo: direction.opposite)
                    case nil:
                        return .fail
                }
            case .dfsRelative(let nextPrev):
                let windows = target.workspace.rootTilingContainer.allLeafWindowsRecursive
                guard let currentIndex = windows.firstIndex(where: { $0 == target.windowOrNil }) else {
                    return .fail
                }
                var targetIndex = switch nextPrev {
                    case .dfsNext: currentIndex + 1
                    case .dfsPrev: currentIndex - 1
                }
                if !(0 ..< windows.count).contains(targetIndex) {
                    if !args.wrapAround {
                        return .fail
                    }
                    targetIndex = (targetIndex + windows.count) % windows.count
                }
                targetWindow = windows[targetIndex]
        }

        guard let targetWindow else {
            return .fail
        }

        swapWindows(mruDominant: currentWindow, targetWindow)

        if args.swapFocus {
            return .from(bool: targetWindow.focusWindow())
        }
        return .succ
    }
}

```

## /Sources/AppBundle/command/impl/TestCommand.swift

```swift path="/Sources/AppBundle/command/impl/TestCommand.swift" 
import AppKit
import Common

struct TestCommand: Command {
    let args: TestCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache: Bool = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> ConditionalExitCode {
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }

        let lhs: Result<Primitive, InterVarExpansionError>
        switch target.windowOrNil {
            case let window?:
                guard let window = try? await WindowWithPrefetchedTitle.resolveWindow(window, for: args.lhs.val, .nonCancellable) else { return .fail(io.err(bugPrompt())) }
                lhs = args.lhs.val.expandFormatVar(obj: .window(window))
            case nil:
                lhs = args.lhs.val.expandFormatVar(obj: .workspace(target.workspace))
        }

        guard let lhs = lhs.getOrNil(onFailure: { err in
            switch err {
                case .unknownInterpolationVariable: io.err(noWindowIsFocused)
                case .notPossible, .nullParent,
                     .rightPaddingCannotBeExpanded, .windowParentIllegalRelation: io.err(err.description)
            }
        }) else { return .fail }

        let infixOperator = args.infixOperator.val
        let rhs = args.rhs.val
        let lhsType = lhs.kind.rawValue
        let incompatibleLhsAndOperatorMsg = """
            Interpolation variable: \(args.lhs.val.rawValue.singleQuoted) has a type of \(lhsType). The \(lhsType) type is not compatible with \(args.infixOperator.val.rawValue.singleQuoted) operator.
            """

        let result: Result<Bool, String> = switch (lhs, infixOperator) {
            case (.bool(let lhs), .equals):
                Bool(rhs).toResult("Can't convert String \(rhs.singleQuoted) to Bool").map { rhs in lhs == rhs }
            case (.bool, .matchesRegex):
                .failure(incompatibleLhsAndOperatorMsg)
            case (.int(let lhs), .equals):
                Int64(rhs).toResult("Can't convert String \(rhs.singleQuoted) to Int").map { rhs in lhs == rhs }
            case (.int, .matchesRegex):
                .failure(incompatibleLhsAndOperatorMsg)
            case (.string(let lhs), .equals):
                .success(lhs == rhs)
            case (.string(let lhs), .matchesRegex):
                CaseInsensitiveRegex.new(rhs).map { rhs in lhs.contains(caseInsensitiveRegex: rhs) }
        }

        return switch result {
            case .success(let result): result ? ._true : ._false
            case .failure(let err): .fail(io.err(err))
        }
    }
}

```

## /Sources/AppBundle/command/impl/TestNotCommand.swift

```swift path="/Sources/AppBundle/command/impl/TestNotCommand.swift" 
import AppKit
import Common

struct TestNotCommand: Command {
    let args: TestNotCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache: Bool = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> ConditionalExitCode {
        switch await TestCommand(args: args.testArgs).run(env, io) {
            case ._false: ._true
            case ._true: ._false
            case .fail: .fail
        }
    }
}

```

## /Sources/AppBundle/command/impl/TriggerBindingCommand.swift

```swift path="/Sources/AppBundle/command/impl/TriggerBindingCommand.swift" 
import AppKit
import Common

struct TriggerBindingCommand: Command {
    let args: TriggerBindingCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> Int32ExitCode {
        return if let mode = config.modes[args.mode] {
            if let binding = mode.bindings.values.first(where: { $0.descriptionWithKeyNotation == args.binding.val }) {
                // refreshSession is not needed since commands are already run in refreshSession
                await binding.commands.run(env, io)
            } else {
                .fail(io.err("Binding '\(args.binding.val)' is not presented in mode '\(args.mode)'"))
            }
        } else {
            .fail(io.err("Mode '\(args.mode)' doesn't exist. " +
                    "Available modes: \(config.modes.keys.joined(separator: ","))"))
        }
    }
}

```

## /Sources/AppBundle/command/impl/TrueCommand.swift

```swift path="/Sources/AppBundle/command/impl/TrueCommand.swift" 
import AppKit
import Common

struct TrueCommand: Command {
    let args: TrueCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache: Bool = false

    func run(_ env: CmdEnv, _ io: CmdIo) async -> ConditionalExitCode { ._true }

    static let instance = TrueCommand(args: TrueCmdArgs(rawArgs: []))
}

```

## /Sources/AppBundle/command/impl/VolumeCommand.swift

```swift path="/Sources/AppBundle/command/impl/VolumeCommand.swift" 
import AppKit
import Common
import ISSoundAdditions

struct VolumeCommand: Command {
    let args: VolumeCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        switch args.action.val {
            case .up:
                Sound.output.increaseVolume(by: 0.0625, autoMuteUnmute: true)
            case .down:
                Sound.output.decreaseVolume(by: 0.0625, autoMuteUnmute: true)
            case .muteToggle:
                Sound.output.isMuted.toggle()
            case .muteOn:
                Sound.output.isMuted = true
            case .muteOff:
                Sound.output.isMuted = false
            case .set(let int):
                Sound.output.setVolume(Float(int) / 100, autoMuteUnmute: true)
        }
        if args.gui {
            do {
                VolumePanel.shared.update(with: Sound.output.isMuted ? 0 : try Sound.output.readVolume())
            } catch {
                return .fail(io.err(bugPrompt(String(describing: error))))
            }
        }
        return .succ
    }
}

```

## /Sources/AppBundle/command/impl/WorkspaceBackAndForthCommand.swift

```swift path="/Sources/AppBundle/command/impl/WorkspaceBackAndForthCommand.swift" 
import AppKit
import Common

struct WorkspaceBackAndForthCommand: Command {
    let args: WorkspaceBackAndForthCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode {
        return .from(bool: prevFocusedWorkspace?.focusWorkspace() != nil)
    }
}

```

## /Sources/AppBundle/command/impl/WorkspaceCommand.swift

```swift path="/Sources/AppBundle/command/impl/WorkspaceCommand.swift" 
import AppKit
import Common
import Foundation

struct WorkspaceCommand: Command {
    let args: WorkspaceCmdArgs
    /*conforms*/ let shouldResetClosedWindowsCache = false

    func run(_ env: CmdEnv, _ io: CmdIo) -> BinaryExitCode { // todo refactor
        guard let target = args.resolveTargetOrReportError(env, io) else { return .fail }
        let focusedWs = target.workspace
        let workspaceName: String
        switch args.target.val {
            case .relative(let nextPrev):
                let workspace = getNextPrevWorkspace(
                    current: focusedWs,
                    isNext: nextPrev == .next,
                    wrapAround: args.wrapAround,
                    stdin: args.useStdin ? io.readStdin() : nil,
                    target: target,
                )
                guard let workspace = workspace.getOrNil(appendErrorTo: &io.stderr) else { return .fail }
                workspaceName = workspace.name
            case .direct(let name):
                workspaceName = name.raw
                if args.autoBackAndForth && focusedWs.name == workspaceName {
                    return WorkspaceBackAndForthCommand(args: WorkspaceBackAndForthCmdArgs(rawArgs: [])).run(env, io)
                }
        }
        if focusedWs.name == workspaceName {
            return switch args.failIfNoop {
                case true: .fail
                case false:
                    .succ(io.err("Workspace '\(workspaceName)' is already focused. Tip: use --fail-if-noop to exit with non-zero code"))
            }
        } else {
            return .from(bool: Workspace.get(byName: workspaceName).focusWorkspace())
        }
    }
}

@MainActor func getNextPrevWorkspace(current: Workspace, isNext: Bool, wrapAround: Bool, stdin: String?, target: LiveFocus) -> ResOrStr<Workspace> {
    Result { () throws(String) in
        let stdinWorkspaces: [WorkspaceName] = try stdin?.split(whereSeparator: \.isWhitespace)
            .map { String($0).trim() }
            .filter { !$0.isEmpty }
            .mapAllOrFailure(WorkspaceName.parse)
            .get()
            ?? []
        let currentMonitor = current.workspaceMonitor
        let workspaces: [Workspace] = stdin != nil
            ? stdinWorkspaces.map { Workspace.get(byName: $0.raw) }
            : Workspace.all.filter { $0.workspaceMonitor.rect.topLeftCorner == currentMonitor.rect.topLeftCorner }
                .toSet()
                .union([current])
                .sorted()
        if workspaces.isEmpty { throw "The list of workspaces is empty" }
        let index = workspaces.firstIndex(where: { $0 == target.workspace })
            .map { index in isNext ? index + 1 : index - 1 }
            ?? 0
        return wrapAround
            ? try workspaces.get(wrappingIndex: index).toResult("List of workspaces is empty").get()
            : try workspaces.getOrNil(atIndex: index)
                .toResult(
                    index >= workspaces.count
                        ? "Reached the end of the supplied workspaces list"
                        : "Rached the beginning of the supplied workspaces list",
                )
                .get()
    }
}

```

## /Sources/AppBundle/command/parseCommand.swift

```swift path="/Sources/AppBundle/command/parseCommand.swift" 
import Common

func parseCommand(
    _ raw: String,
    allowExecAndForget: Bool,
    allowEval: Bool,
) -> ParsedCmd<Shell<any Command>> {
    if allowExecAndForget && raw.starts(with: "exec-and-forget") {
        return .cmd(.cmd(ExecAndForgetCommand(args: ExecAndForgetCmdArgs(bashScript: raw.removePrefix("exec-and-forget")))))
    }
    return switch raw.lexAndParseShell() {
        case .success(let it):
            it.flatMap { args in
                switch parseCommand(args) {
                    case .cmd(_ as EvalCommand) where !allowEval: .failure("Illegal eval (Tip: nested evals are forbidden)", EXIT_CODE_TWO)
                    case .cmd(let it): .cmd(it)
                    case .failure(let it): .failure(it)
                    case .help(let it): .help(it)
                }
            }
        case .failure(let it): ParsedCmd.failure(it, EXIT_CODE_TWO)
    }
}

func parseCommand(_ args: [String]) -> ParsedCmd<any Command> {
    parseCmdArgs(args.slice).flatMap { $0.toCommand() }
}

func expectedActualTypeError(expected: TomlType, actual: TomlType) -> String {
    "Expected type is \(expected.rawValue.singleQuoted). But actual type is \(actual.rawValue.singleQuoted)"
}

func expectedActualTypeError(expected: [TomlType], actual: TomlType) -> String {
    switch expected.singleOrNil() {
        case let single?: expectedActualTypeError(expected: single, actual: actual)
        case nil: "Expected types are \(expected.map { "'\($0)'" }.joined(separator: " or ")). But actual type is '\(actual)'"
    }
}

```

## /Sources/AppBundle/config/Config.swift

```swift path="/Sources/AppBundle/config/Config.swift" 
import AppKit
import Common
import HotKey
import OrderedCollections

func getDefaultConfigUrlFromProject() -> URL {
    var url = URL(filePath: #filePath)
    check(FileManager.default.fileExists(atPath: url.path))
    while !FileManager.default.fileExists(atPath: url.appending(component: ".git").path) {
        url.deleteLastPathComponent()
    }
    let projectRoot: URL = url
    return projectRoot.appending(component: "docs/config-examples/default-config.toml")
}

var defaultConfigUrl: URL {
    if isUnitTest {
        return getDefaultConfigUrlFromProject()
    } else {
        return Bundle.main.url(forResource: "default-config", withExtension: "toml")
            // Useful for debug builds that are not app bundles
            ?? getDefaultConfigUrlFromProject()
    }
}
@MainActor let defaultConfig: Config = {
    let parsedConfig = parseConfig(Result { try String(contentsOf: defaultConfigUrl, encoding: .utf8) }.getOrDie())
    if !parsedConfig.errors.isEmpty {
        die("Can't parse default config: \(parsedConfig.errors)")
    }
    return parsedConfig.config
}()
@MainActor var config: Config = defaultConfig // todo move to Ctx?
@MainActor var configUrl: URL = defaultConfigUrl

struct Config: ConvenienceMutable {
    var configVersion: ConfigVersion = ._1
    var _afterLoginCommand: [any Command] = []
    var afterStartupCommand: Shell<any Command> = .empty
    var _indentForNestedContainersWithTheSameOrientation: Void = ()
    var enableNormalizationFlattenContainers: Bool = true
    var _nonEmptyWorkspacesRootContainersLayoutOnStartup: Void = ()
    var defaultRootContainerLayout: Layout = .tiles
    var defaultRootContainerOrientation: DefaultContainerOrientation = .auto
    var startAtLogin: Bool = false
    var autoReloadConfig: Bool = false
    var automaticallyUnhideMacosHiddenApps: Bool = false
    var accordionPadding: Int = 30
    var enableNormalizationOppositeOrientationForNestedContainers: Bool = true
    var persistentWorkspaces: OrderedSet<String> = []
    var execOnWorkspaceChange: [String] = [] // todo deprecate
    var keyMapping = KeyMapping()
    var execConfig: ExecConfig = ExecConfig()
    var focusFollowsMouse: FocusFollowsMouse = FocusFollowsMouse()

    var onFocusChanged: Shell<any Command> = .empty
    // var onFocusedWorkspaceChanged: [any Command] = []
    var onFocusedMonitorChanged: Shell<any Command> = .empty

    var gaps: Gaps = .zero
    var workspaceToMonitorForceAssignment: [String: [MonitorDescription]] = [:]
    var modes: [String: Mode] = [:]
    var onWindowDetected: [WindowDetectedCallback] = []
    var onModeChanged: Shell<any Command> = .empty
}

struct FocusFollowsMouse: ConvenienceMutable {
    var enabled: Bool = false
}

enum ConfigVersion: Int, Comparable, CaseIterable, Sendable, CustomStringConvertible {
    case _1 = 1
    case _2 = 2

    static let max = allCases.max().orDie()
    static let min = allCases.min().orDie()
    static func < (lhs: ConfigVersion, rhs: ConfigVersion) -> Bool { lhs.rawValue < rhs.rawValue }

    var description: String { rawValue.description }
}

enum DefaultContainerOrientation: String {
    case horizontal, vertical, auto
}

```

## /Sources/AppBundle/config/ConfigFile.swift

```swift path="/Sources/AppBundle/config/ConfigFile.swift" 
import Common
import Foundation

let configDotfileName = ".aerospace.toml"
func findCustomConfigUrl() -> ConfigFile {
    let xdgConfigHome = ProcessInfo.processInfo.environment["XDG_CONFIG_HOME"].map { URL(filePath: $0) }
        ?? FileManager.default.homeDirectoryForCurrentUser.appending(path: ".config/")
    let candidates: [URL] = switch serverArgs.configLocation {
        case let configLocation?: [URL(filePath: configLocation)]
        case nil:
            [
                FileManager.default.homeDirectoryForCurrentUser.appending(path: configDotfileName),
                xdgConfigHome.appending(path: "aerospace").appending(path: "aerospace.toml"),
            ]
    }
    let existingCandidates: [URL] = candidates.filter { (candidate: URL) in FileManager.default.fileExists(atPath: candidate.path) }
    let count = existingCandidates.count
    return switch count {
        case 0: .noCustomConfigExists
        case 1: .file(existingCandidates.first.orDie())
        default: .ambiguousConfigError(existingCandidates)
    }
}

enum ConfigFile {
    case file(URL), ambiguousConfigError(_ candidates: [URL]), noCustomConfigExists

    var urlOrNil: URL? {
        return switch self {
            case .file(let url): url
            case .ambiguousConfigError, .noCustomConfigExists: nil
        }
    }
}

```

## /Sources/AppBundle/config/ConfigFileWatcher.swift

```swift path="/Sources/AppBundle/config/ConfigFileWatcher.swift" 
import Common
import Foundation

private struct ConfigFileWatcher: ~Copyable {
    private let source: DispatchSourceFileSystemObject
    private let fd: Int32

    init?(url: URL, onChange: @escaping @MainActor () -> Void) {
        fd = unsafe open(url.path, O_EVTONLY)
        if fd < 0 { return nil }
        source = DispatchSource.makeFileSystemObjectSource(
            fileDescriptor: fd,
            eventMask: [.write, .delete, .rename, .revoke],
            queue: .main,
        )
        source.setEventHandler { MainActor.checkIsolated { onChange() } }
        source.setCancelHandler { [fd] in close(fd) }
        source.activate()
    }

    deinit {
        source.cancel()
    }
}

@MainActor private var currentWatcher: ConfigFileWatcher? = nil
@MainActor private var debounceTask: Task<Void, any Error>? = nil

private let debounceDelay: Duration = .milliseconds(200)

@MainActor func syncConfigFileWatcher() {
    currentWatcher = nil
    if !config.autoReloadConfig { return }
    currentWatcher = ConfigFileWatcher(url: configUrl) {
        debounceTask?.cancel()
        debounceTask = Task.startUnstructured {
            try await Task.sleep(for: debounceDelay)
            if let token: RunSessionGuard = .isServerEnabled {
                try await runLightSession(.configAutoReload, token) {
                    _ = await reloadConfig_nonCancellable()
                }
            }
        }
    }
}

```

## /Sources/AppBundle/config/DynamicConfigValue.swift

```swift path="/Sources/AppBundle/config/DynamicConfigValue.swift" 
import Common

struct PerMonitorValue<Value: Equatable>: Equatable {
    let description: MonitorDescription
    let value: Value
}
extension PerMonitorValue: Sendable where Value: Sendable {}

enum DynamicConfigValue<Value: Equatable>: Equatable {
    case constant(Value)
    case perMonitor([PerMonitorValue<Value>], default: Value)
}
extension DynamicConfigValue: Sendable where Value: Sendable {}

extension DynamicConfigValue {
    @MainActor func getValue(for monitor: any MonitorInfo) -> Value {
        switch self {
            case .constant(let value): return value
            case .perMonitor(let array, let defaultValue):
                let sortedMonitors = sortedMonitorInfos
                return array
                    .lazy
                    .compactMap {
                        $0.description.resolveMonitor(sortedMonitors: sortedMonitors)?.rect.topLeftCorner == monitor.rect.topLeftCorner
                            ? $0.value
                            : nil
                    }
                    .first ?? defaultValue
        }
    }
}

func parseDynamicValue<T>(
    _ raw: OrderedJson,
    ofType valueType: T.Type,
    _ fallback: T,
    _ backtrace: ConfigBacktrace,
    _ c: inout ConfigParserContext,
) -> DynamicConfigValue<T> {
    if let simpleValue = parseSimpleType(raw, ofType: T.self) {
        return .constant(simpleValue)
    } else if let array = raw.asArrayOrNil {
        if array.isEmpty {
            c.errors.append(.init(backtrace, "The array must not be empty"))
            return .constant(fallback)
        }

        guard let defaultValue = array.last.flatMap({ parseSimpleType($0, ofType: T.self) }) else {
            c.errors.append(.init(backtrace, "The last item in the array must be of type \(T.self)"))
            return .constant(fallback)
        }

        if array.dropLast().isEmpty {
            c.errors.append(.init(backtrace, "The array must contain at least one monitor pattern"))
            return .constant(fallback)
        }

        let rules: [PerMonitorValue<T>] = parsePerMonitorValues(array.dropLast(), backtrace, &c)

        return .perMonitor(rules, default: defaultValue)
    } else {
        c.errors.append(.init(backtrace, "Unsupported type: \(raw.tomlType), expected: \(valueType) or array"))
        return .constant(fallback)
    }
}

func parsePerMonitorValues<T>(_ array: OrderedJson.JsonArray, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> [PerMonitorValue<T>] {
    array.enumerated().compactMap { (index: Int, raw: OrderedJson) -> PerMonitorValue<T>? in
        var backtrace = backtrace + .index(index)

        guard let (key, value) = raw.unwrapTableWithSingleKey(expectedKey: "monitor", &backtrace)
            .flatMap({ $0.value.unwrapTableWithSingleKey(expectedKey: nil, &backtrace) })
            .getOrNil(appendErrorTo: &c.errors)
        else {
            return nil
        }

        let monitorDescriptionResult = parseMonitorDescription(.string(key), backtrace)

        guard let monitorDescription = monitorDescriptionResult.getOrNil(appendErrorTo: &c.errors) else { return nil }

        guard let value = parseSimpleType(value, ofType: T.self) else {
            c.errors.append(.init(backtrace, "Expected type is '\(T.self)'. But actual type is '\(value.tomlType)'"))
            return nil
        }

        return PerMonitorValue(description: monitorDescription, value: value)
    }
}

```

## /Sources/AppBundle/config/HotkeyBinding.swift

```swift path="/Sources/AppBundle/config/HotkeyBinding.swift" 
import AppKit
import Common
import Foundation
import HotKey

@MainActor private var hotkeys: [String: HotKey] = [:]

@MainActor func resetHotKeys() {
    // Explicitly unregister all hotkeys. We cannot always rely on destruction of the HotKey object to trigger
    // unregistration because we might be running inside a hotkey handler that is keeping its HotKey object alive.
    for (_, key) in hotkeys {
        key.isEnabled = false
    }
    hotkeys = [:]
}

extension HotKey {
    var isEnabled: Bool {
        get { !isPaused }
        set {
            if isEnabled != newValue {
                isPaused = !newValue
            }
        }
    }
}

@MainActor var activeMode: String? = mainModeId
@MainActor func activateMode_nonCancellable(_ targetMode: String?) async {
    let targetBindings = targetMode.flatMap { config.modes[$0] }?.bindings ?? [:]
    for binding in targetBindings.values where !hotkeys.keys.contains(binding.descriptionWithKeyCode) {
        hotkeys[binding.descriptionWithKeyCode] = HotKey(key: binding.keyCode, modifiers: binding.modifiers, keyDownHandler: {
            Task.startUnstructured {
                if let activeMode {
                    broadcastEvent(.bindingTriggered(
                        mode: activeMode,
                        binding: binding.descriptionWithKeyNotation,
                    ))
                    try await runLightSession(.hotkeyBinding, .checkServerIsEnabledOrDie()) { () throws in
                        _ = await config.modes[activeMode]?.bindings[binding.descriptionWithKeyCode]?.commands
                            .run(.defaultEnv, .emptyStdin)
                    }
                }
            }
        })
    }
    for (binding, key) in hotkeys {
        key.isEnabled = targetBindings.keys.contains(binding)
    }
    let oldMode = activeMode
    activeMode = targetMode
    if oldMode != targetMode {
        broadcastEvent(.modeChanged(mode: targetMode))
        _ = await config.onModeChanged.run(.defaultEnv, .emptyStdin)
    }
}

struct HotkeyBinding: Equatable, Sendable {
    let modifiers: NSEvent.ModifierFlags
    let keyCode: Key
    let commands: Shell<any Command>
    let descriptionWithKeyCode: String
    let descriptionWithKeyNotation: String

    init(_ modifiers: NSEvent.ModifierFlags, _ keyCode: Key, _ commands: Shell<any Command>, descriptionWithKeyNotation: String) {
        self.modifiers = modifiers
        self.keyCode = keyCode
        self.commands = commands
        self.descriptionWithKeyCode = modifiers.isEmpty
            ? keyCode.toString()
            : modifiers.toString() + "-" + keyCode.toString()
        self.descriptionWithKeyNotation = descriptionWithKeyNotation
    }

    static func == (lhs: HotkeyBinding, rhs: HotkeyBinding) -> Bool {
        lhs.modifiers == rhs.modifiers &&
            lhs.keyCode == rhs.keyCode &&
            lhs.descriptionWithKeyCode == rhs.descriptionWithKeyCode &&
            lhs.commands.strictEquals(rhs.commands)
    }
}

func parseBindings(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext, _ mapping: [String: Key]) -> [String: HotkeyBinding] {
    guard let rawTable = raw.asDictOrNil else {
        c.errors += [expectedActualTypeDiagnostic(expected: .table, actual: raw.tomlType, backtrace)]
        return [:]
    }
    var result: [String: HotkeyBinding] = [:]
    for (binding, rawCommand): (String, OrderedJson) in rawTable {
        let backtrace = backtrace + .key(binding)
        let binding = parseBinding(binding, backtrace, mapping)
            .map { modifiers, key -> HotkeyBinding in
                let commands = parseShellOfCommandsForConfig(rawCommand, backtrace, &c)
                return HotkeyBinding(modifiers, key, commands, descriptionWithKeyNotation: binding)
            }
            .getOrNil(appendErrorTo: &c.errors)
        if let binding {
            if result.keys.contains(binding.descriptionWithKeyCode) {
                c.errors.append(.init(backtrace, "'\(binding.descriptionWithKeyCode)' Binding redeclaration"))
            }
            result[binding.descriptionWithKeyCode] = binding
        }
    }
    return result
}

func parseBinding(_ raw: String, _ backtrace: ConfigBacktrace, _ mapping: [String: Key]) -> ResOrConfigParseDiagnostic<(NSEvent.ModifierFlags, Key)> {
    let rawKeys = raw.split(separator: "-")
    let modifiers: ResOrConfigParseDiagnostic<NSEvent.ModifierFlags> = rawKeys.dropLast()
        .mapAllOrFailure {
            modifiersMap[String($0)].toResult(.init(backtrace, "Can't parse modifiers in '\(raw)' binding"))
        }
        .map { NSEvent.ModifierFlags($0) }
    let key: ResOrConfigParseDiagnostic<Key> = rawKeys.last.flatMap { mapping[String($0)] }
        .toResult(.init(backtrace, "Can't parse the key in '\(raw)' binding"))
    return modifiers.flatMap { modifiers -> ResOrConfigParseDiagnostic<(NSEvent.ModifierFlags, Key)> in
        key.flatMap { key -> ResOrConfigParseDiagnostic<(NSEvent.ModifierFlags, Key)> in
            .success((modifiers, key))
        }
    }
}

```

## /Sources/AppBundle/config/Mode.swift

```swift path="/Sources/AppBundle/config/Mode.swift" 
import Common
import HotKey

struct Mode: ConvenienceMutable, Equatable, Sendable {
    var bindings: [String: HotkeyBinding]

    static let zero = Mode(bindings: [:])
}

func parseModes(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext, _ mapping: [String: Key]) -> [String: Mode] {
    guard let rawTable = raw.asDictOrNil else {
        c.errors += [expectedActualTypeDiagnostic(expected: .table, actual: raw.tomlType, backtrace)]
        return [:]
    }
    var result: [String: Mode] = [:]
    for (key, value) in rawTable {
        result[key] = parseMode(value, backtrace + .key(key), &c, mapping)
    }
    if !result.keys.contains(mainModeId) {
        c.errors += [.init(backtrace, "Please specify '\(mainModeId)' mode")]
    }
    return result
}

func parseMode(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext, _ mapping: [String: Key]) -> Mode {
    guard let rawTable: OrderedJson.JsonDict = raw.asDictOrNil else {
        c.errors += [expectedActualTypeDiagnostic(expected: .table, actual: raw.tomlType, backtrace)]
        return .zero
    }

    var result: Mode = .zero
    for (key, value) in rawTable {
        let backtrace = backtrace + .key(key)
        switch key {
            case "binding":
                result.bindings = parseBindings(value, backtrace, &c, mapping)
            default:
                c.errors += [unknownKeyDiagnostic(backtrace)]
        }
    }
    return result
}

```

## /Sources/AppBundle/config/keysMap.swift

```swift path="/Sources/AppBundle/config/keysMap.swift" 
import AppKit
import Common
import HotKey

private let minus = "minus"
private let equal = "equal"

private let q = "q"
private let w = "w"
private let e = "e"
private let r = "r"
private let t = "t"
private let y = "y"
private let u = "u"
private let i = "i"
private let o = "o"
private let p = "p"
private let leftSquareBracket = "leftSquareBracket"
private let rightSquareBracket = "rightSquareBracket"
private let backslash = "backslash"
private let sectionSign = "sectionSign"

private let a = "a"
private let s = "s"
private let d = "d"
private let f = "f"
private let g = "g"
private let h = "h"
private let j = "j"
private let k = "k"
private let l = "l"
private let semicolon = "semicolon"
private let quote = "quote"

private let z = "z"
private let x = "x"
private let c = "c"
private let v = "v"
private let b = "b"
private let n = "n"
private let m = "m"
private let comma = "comma"
private let period = "period"
private let slash = "slash"

func getKeysPreset(_ layout: KeyMapping.Preset) -> [String: Key] {
    return switch layout {
        case .qwerty: keyNotationToKeyCode
        case .dvorak: dvorakMap
        case .colemak: colemakMap
    }
}

extension Key: @unchecked @retroactive Sendable {}

let keyNotationToKeyCode: [String: Key] = [
    sectionSign: .section,
    "0": .zero,
    "1": .one,
    "2": .two,
    "3": .three,
    "4": .four,
    "5": .five,
    "6": .six,
    "7": .seven,
    "8": .eight,
    "9": .nine,
    minus: .minus,
    equal: .equal,

    q: .q,
    w: .w,
    e: .e,
    r: .r,
    t: .t,
    y: .y,
    u: .u,
    i: .i,
    o: .o,
    p: .p,
    leftSquareBracket: .leftBracket,
    rightSquareBracket: .rightBracket,
    backslash: .backslash,

    a: .a,
    s: .s,
    d: .d,
    f: .f,
    g: .g,
    h: .h,
    j: .j,
    k: .k,
    l: .l,
    semicolon: .semicolon,
    quote: .quote,

    z: .z,
    x: .x,
    c: .c,
    v: .v,
    b: .b,
    n: .n,
    m: .m,
    comma: .comma,
    period: .period,
    slash: .slash,

    "keypad0": .keypad0,
    "keypad1": .keypad1,
    "keypad2": .keypad2,
    "keypad3": .keypad3,
    "keypad4": .keypad4,
    "keypad5": .keypad5,
    "keypad6": .keypad6,
    "keypad7": .keypad7,
    "keypad8": .keypad8,
    "keypad9": .keypad9,
    "keypadClear": .keypadClear,
    "keypadDecimalMark": .keypadDecimal,
    "keypadDivide": .keypadDivide,
    "keypadEnter": .keypadEnter,
    "keypadEqual": .keypadEquals,
    "keypadMinus": .keypadMinus,
    "keypadMultiply": .keypadMultiply,
    "keypadPlus": .keypadPlus,

    "pageUp": .pageUp,
    "pageDown": .pageDown,
    "home": .home,
    "end": .end,
    "forwardDelete": .forwardDelete,

    "f1": .f1,
    "f2": .f2,
    "f3": .f3,
    "f4": .f4,
    "f5": .f5,
    "f6": .f6,
    "f7": .f7,
    "f8": .f8,
    "f9": .f9,
    "f10": .f10,
    "f11": .f11,
    "f12": .f12,
    "f13": .f13,
    "f14": .f14,
    "f15": .f15,
    "f16": .f16,
    "f17": .f17,
    "f18": .f18,
    "f19": .f19,
    "f20": .f20,

    "backtick": .grave,
    "space": .space,
    "enter": .return,
    "esc": .escape,
    "backspace": .delete,
    "tab": .tab,

    "left": .leftArrow,
    "down": .downArrow,
    "up": .upArrow,
    "right": .rightArrow,
]

private let dvorakMap: [String: Key] = keyNotationToKeyCode + [
    leftSquareBracket: .minus,
    rightSquareBracket: .equal,

    quote: .q,
    comma: .w,
    period: .e,
    p: .r,
    y: .t,
    f: .y,
    g: .u,
    c: .i,
    r: .o,
    l: .p,
    slash: .leftBracket, // leftBracket -> leftSquareBracket
    equal: .rightBracket, // rightBracket -> rightSquareBracket
    backslash: .backslash,

    a: .a,
    o: .s,
    e: .d,
    u: .f,
    i: .g,
    d: .h,
    h: .j,
    t: .k,
    n: .l,
    s: .semicolon,
    minus: .quote,

    semicolon: .z,
    q: .x,
    j: .c,
    k: .v,
    x: .b,
    b: .n,
    m: .m,
    w: .comma,
    v: .period,
    z: .slash,
]

private let colemakMap: [String: Key] = keyNotationToKeyCode + [
    q: .q,
    w: .w,
    f: .e,
    p: .r,
    g: .t,
    j: .y,
    l: .u,
    u: .i,
    y: .o,
    semicolon: .p,
    leftSquareBracket: .leftBracket,
    rightSquareBracket: .rightBracket,
    backslash: .backslash,

    a: .a,
    r: .s,
    s: .d,
    t: .f,
    d: .g,
    h: .h,
    n: .j,
    e: .k,
    i: .l,
    o: .semicolon,
    quote: .quote,

    z: .z,
    x: .x,
    c: .c,
    v: .v,
    b: .b,
    k: .n,
    m: .m,
    comma: .comma,
    period: .period,
    slash: .slash,
]

let modifiersMap: [String: NSEvent.ModifierFlags] = [
    "shift": .shift,
    "alt": .option,
    "ctrl": .control,
    "cmd": .command,
]

extension NSEvent.ModifierFlags {
    func toString() -> String {
        var result: [String] = []
        if contains(.option) { result.append("alt") }
        if contains(.control) { result.append("ctrl") }
        if contains(.command) { result.append("cmd") }
        if contains(.shift) { result.append("shift") }
        return result.joined(separator: "-")
    }
}

extension Key {
    func toString() -> String {
        switch self {
            case .a: "a"
            case .b: "b"
            case .c: "c"
            case .d: "d"
            case .e: "e"
            case .f: "f"
            case .g: "g"
            case .h: "h"
            case .i: "i"
            case .j: "j"
            case .k: "k"
            case .l: "l"
            case .m: "m"
            case .n: "n"
            case .o: "o"
            case .p: "p"
            case .q: "q"
            case .r: "r"
            case .s: "s"
            case .t: "t"
            case .u: "u"
            case .v: "v"
            case .w: "w"
            case .x: "x"
            case .y: "y"
            case .z: "z"

            case .zero: "0"
            case .one: "1"
            case .two: "2"
            case .three: "3"
            case .four: "4"
            case .five: "5"
            case .six: "6"
            case .seven: "7"
            case .eight: "8"
            case .nine: "9"

            case .period: "period"
            case .quote: "quote"
            case .leftBracket: "leftSquareBracket"
            case .rightBracket: "rightSquareBracket"
            case .semicolon: "semicolon"
            case .slash: "slash"
            case .backslash: "backslash"
            case .comma: "comma"
            case .equal: "equal"
            case .grave: "backtick"
            case .minus: "minus"
            case .space: "space"
            case .tab: "tab"
            case .return: "enter"
            case .pageUp: "pageUp"
            case .pageDown: "pageDown"
            case .home: "home"
            case .end: "end"
            case .leftArrow: "left"
            case .downArrow: "down"
            case .upArrow: "up"
            case .rightArrow: "right"
            case .escape: "esc"
            case .delete: "backspace"
            case .section: "sectionSign"

            case .f1: "f1"
            case .f2: "f2"
            case .f3: "f3"
            case .f4: "f4"
            case .f5: "f5"
            case .f6: "f6"
            case .f7: "f7"
            case .f8: "f8"
            case .f9: "f9"
            case .f10: "f10"
            case .f11: "f11"
            case .f12: "f12"
            case .f13: "f13"
            case .f14: "f14"
            case .f15: "f15"
            case .f16: "f16"
            case .f17: "f17"
            case .f18: "f18"
            case .f19: "f19"
            case .f20: "f20"

            case .keypad0: "keypad0"
            case .keypad1: "keypad1"
            case .keypad2: "keypad2"
            case .keypad3: "keypad3"
            case .keypad4: "keypad4"
            case .keypad5: "keypad5"
            case .keypad6: "keypad6"
            case .keypad7: "keypad7"
            case .keypad8: "keypad8"
            case .keypad9: "keypad9"
            case .keypadClear: "keypadClear"
            case .keypadDecimal: "keypadDecimalMark"
            case .keypadDivide: "keypadDivide"
            case .keypadEnter: "keypadEnter"
            case .keypadEquals: "keypadEqual"
            case .keypadMinus: "keypadMinus"
            case .keypadMultiply: "keypadMultiply"
            case .keypadPlus: "keypadPlus"

            // wtf
            case .command: "cmd"
            case .rightCommand: "rCmd"
            case .option: "alt"
            case .rightOption: "rAlt"
            case .control: "ctrl"
            case .rightControl: "rCtrl"
            case .shift: "shift"
            case .rightShift: "rShift"
            case .function: "function"
            case .capsLock: "capsLock"
            case .forwardDelete: "forwardDelete"
            case .help: "help"
            case .volumeUp: "volumeUp"
            case .volumeDown: "volumeDown"
            case .mute: "mute"
        }
    }
}

// doesn't work :(
//extension NSEvent.ModifierFlags {
//    static let lOption = NSEvent.ModifierFlags(rawValue: 1 << 1)
//    static let rOption = NSEvent.ModifierFlags(rawValue: 1 << 2)
//    static let lShift = NSEvent.ModifierFlags(rawValue: 0x00000002)
//    static let rShift = NSEvent.ModifierFlags(rawValue: 0x00000004)
//    static let lCommand = NSEvent.ModifierFlags(rawValue: 1 << 7)
//    static let rCommand = NSEvent.ModifierFlags(rawValue: 0x00000010)
//}

// NSEvent.ModifierFlags.command.rawValue // 1 << 20
// NSEvent.ModifierFlags.option.rawValue // 1 << 19
// NSEvent.ModifierFlags.control.rawValue // 1 << 18
// NSEvent.ModifierFlags.shift.rawValue // 1 << 17
// https://github.com/koekeishiya/skhd/blob/master/src/hotkey.h

```

## /Sources/AppBundle/config/parseConfig.swift

```swift path="/Sources/AppBundle/config/parseConfig.swift" 
import AppKit
import Common
import HotKey
import TOMLDecoder
import OrderedCollections

struct ReadConfigResult {
    let configUrl: URL
    let parseConfigResult: ParseConfigResult

    @MainActor static func fatal(configUrl: URL, message: String) -> Self {
        ReadConfigResult(
            configUrl: configUrl,
            parseConfigResult: ParseConfigResult(
                config: defaultConfig,
                errors: [.init(.emptyRoot, message, preventConfigReload: true)],
                warnings: [],
            ),
        )
    }
}

@MainActor
func readConfig(forceConfigUrl: URL?) -> ReadConfigResult {
    let configUrl: URL
    if let forceConfigUrl {
        configUrl = forceConfigUrl
    } else {
        switch findCustomConfigUrl() {
            case .file(let url): configUrl = url
            case .noCustomConfigExists: configUrl = defaultConfigUrl
            case .ambiguousConfigError(let candidates):
                let msg = """
                    Ambiguous config error. Several configs found:
                    \(candidates.map(\.path).joined(separator: "\n"))
                    """
                return .fatal(configUrl: defaultConfigUrl, message: msg)
        }
    }
    let configStr: String
    do {
        configStr = try String(contentsOf: configUrl, encoding: .utf8)
    } catch {
        let msg = "Can't read contents of \(configUrl.path.singleQuoted) as a utf8 string: \(error.localizedDescription)"
        return .fatal(configUrl: configUrl, message: msg)
    }
    return ReadConfigResult(configUrl: configUrl, parseConfigResult: parseConfig(configStr))
}

struct ConfigParseDiagnostic: Error, Equatable {
    let backtrace: ConfigBacktrace
    let message: String
    let preventConfigReload: Bool // for severe config errors (like TOML parse error)

    public init(_ backtrace: ConfigBacktrace, _ message: String, preventConfigReload: Bool = false) {
        check(!message.isEmpty)
        self.backtrace = backtrace
        self.message = message
        self.preventConfigReload = preventConfigReload
    }

    func description(_ severity: Severity) -> String {
        let backtraceDesc = backtrace.description
        // todo Make 'split' + flatten normalization prettier
        return switch backtraceDesc.isEmpty {
            case true: "[\(severity.rawValue)] \(message)"
            case false: "[\(severity.rawValue)] \(backtraceDesc): \(message)"
        }
    }

    enum Severity: String {
        case warning = "WARNING"
        case error = "ERROR"
    }
}

typealias ResOrConfigParseDiagnostic<T> = Result<T, ConfigParseDiagnostic>

extension ParserProtocol {
    func transformRawConfig(_ raw: S,
                            _ value: OrderedJson,
                            _ backtrace: ConfigBacktrace,
                            _ c: inout ConfigParserContext) -> S
    {
        if let value = parse(value, backtrace, &c).getOrNil(appendErrorTo: &c.errors) {
            return raw.copy(keyPath, value)
        }
        return raw
    }
}

struct ConfigParserContext {
    var configVersion: ConfigVersion
    var errors: [ConfigParseDiagnostic]
    var warnings: [ConfigParseDiagnostic]
}

protocol ParserProtocol<S>: Sendable {
    associatedtype T
    associatedtype S where S: ConvenienceMutable
    var keyPath: SendableWritableKeyPath<S, T> { get }
    var parse: @Sendable (OrderedJson, ConfigBacktrace, inout ConfigParserContext) -> ResOrConfigParseDiagnostic<T> { get }
}

struct Parser<S: ConvenienceMutable, T>: ParserProtocol {
    let keyPath: SendableWritableKeyPath<S, T>
    let parse: @Sendable (OrderedJson, ConfigBacktrace, inout ConfigParserContext) -> ResOrConfigParseDiagnostic<T>

    init(_ keyPath: SendableWritableKeyPath<S, T>, _ parse: @escaping @Sendable (OrderedJson, ConfigBacktrace, inout ConfigParserContext) -> T) {
        self.keyPath = keyPath
        self.parse = { raw, backtrace, errors -> ResOrConfigParseDiagnostic<T> in .success(parse(raw, backtrace, &errors)) }
    }

    init(_ keyPath: SendableWritableKeyPath<S, T>, _ parse: @escaping @Sendable (OrderedJson, ConfigBacktrace) -> ResOrConfigParseDiagnostic<T>) {
        self.keyPath = keyPath
        self.parse = { raw, backtrace, _ -> ResOrConfigParseDiagnostic<T> in parse(raw, backtrace) }
    }
}

private let keyMappingConfigRootKey = "key-mapping"
private let configVersionConfigRootKey = "config-version"
private let modeConfigRootKey = "mode"
private let persistentWorkspacesKey = "persistent-workspaces"

// For every new config option you add, think:
// 1. Does it make sense to have different value
// 2. Prefer commands and commands flags over toml options if possible
private let configParser: [String: any ParserProtocol<Config>] = [
    configVersionConfigRootKey: Parser(\.configVersion, skipParsing(Config().configVersion)), // Parsed manually

    "after-login-command": Parser(\._afterLoginCommand, parseDeprecatedAfterLoginCommand),
    "after-startup-command": Parser(\.afterStartupCommand, parseShellOfCommandsForConfig),

    "on-focus-changed": Parser(\.onFocusChanged, parseShellOfCommandsForConfig),
    "on-mode-changed": Parser(\.onModeChanged, parseShellOfCommandsForConfig),
    "on-focused-monitor-changed": Parser(\.onFocusedMonitorChanged, parseShellOfCommandsForConfig),
    // "on-focused-workspace-changed": Parser(\.onFocusedWorkspaceChanged, { parseCommandOrCommands($0).toParsedConfig($1) }),

    "enable-normalization-flatten-containers": Parser(\.enableNormalizationFlattenContainers, parseBool),
    "enable-normalization-opposite-orientation-for-nested-containers": Parser(\.enableNormalizationOppositeOrientationForNestedContainers, parseBool),

    "default-root-container-layout": Parser(\.defaultRootContainerLayout, parseLayout),
    "default-root-container-orientation": Parser(\.defaultRootContainerOrientation, parseDefaultContainerOrientation),

    "start-at-login": Parser(\.startAtLogin, parseBool),
    "auto-reload-config": Parser(\.autoReloadConfig, parseBool),
    "automatically-unhide-macos-hidden-apps": Parser(\.automaticallyUnhideMacosHiddenApps, parseBool),
    "accordion-padding": Parser(\.accordionPadding, parseInt),
    persistentWorkspacesKey: Parser(\.persistentWorkspaces, parsePersistentWorkspaces),
    "exec-on-workspace-change": Parser(\.execOnWorkspaceChange, parseArrayOfStrings),
    "exec": Parser(\.execConfig, parseExecConfig),

    keyMappingConfigRootKey: Parser(\.keyMapping, skipParsing(Config().keyMapping)), // Parsed manually
    modeConfigRootKey: Parser(\.modes, skipParsing(Config().modes)), // Parsed manually

    "gaps": Parser(\.gaps, parseGaps),
    "focus-follows-mouse": Parser(\.focusFollowsMouse, parseFocusFollowsMouse),
    "workspace-to-monitor-force-assignment": Parser(\.workspaceToMonitorForceAssignment, parseWorkspaceToMonitorAssignment),
    "on-window-detected": Parser(\.onWindowDetected, parseOnWindowDetectedArray),

    // Deprecated
    "non-empty-workspaces-root-containers-layout-on-startup": Parser(\._nonEmptyWorkspacesRootContainersLayoutOnStartup, parseStartupRootContainerLayout),
    "indent-for-nested-containers-with-the-same-orientation": Parser(\._indentForNestedContainersWithTheSameOrientation, parseIndentForNestedContainersWithTheSameOrientation),
]

extension ParsedCmd {
    func toResult() -> ResOrStr<T> {
        return switch self {
            case .cmd(let a): .success(a)
            case .help(let a): .failure(a)
            case .failure(let a): .failure(a.msg)
        }
    }
}

func parseDeprecatedAfterLoginCommand(_ raw: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<[any Command]> {
    if let array = raw.asArrayOrNil, array.count == 0 {
        return .success([])
    }
    let msg = "after-login-command is deprecated since AeroSpace 0.19.0. https://github.com/nikitabobko/AeroSpace/issues/1482"
    return .failure(.init(backtrace, msg))
}

func parseShellOfCommandsForConfig(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> Shell<any Command> {
    if let rawString = raw.asStringOrNil {
        return parseCommand(rawString, allowExecAndForget: true, allowEval: false).toResult().toParsedConfig(backtrace).getOrNil(appendErrorTo: &c.errors) ?? .empty
    } else if let rawArray = raw.asArrayOrNil {
        var result = [Shell<any Command>]()
        for (index, elem) in rawArray.enumerated() {
            let backtrace = backtrace + .index(index)
            if let elem = elem.asStringOrNil {
                result.append(parseCommand(elem, allowExecAndForget: true, allowEval: false).toResult().toParsedConfig(backtrace).getOrNil(appendErrorTo: &c.errors) ?? .empty)
            } else {
                c.errors.append(.init(backtrace, expectedActualTypeError(expected: .string, actual: elem.tomlType)))
            }
        }
        return .newCompound(result, Shell<any Command>.seq)
    } else {
        c.errors.append(.init(backtrace, expectedActualTypeError(expected: [.string, .array], actual: raw.tomlType)))
        return .empty
    }
}

func tomlAnyToOrderedJsonRecursive(
    any: Any,
    _ backtrace: ConfigBacktrace,
    _ errors: inout [ConfigParseDiagnostic],
) -> OrderedJson? {
    switch any {
        case let dict as [String: Any]:
            var json = OrderedJson.JsonDict()
            for (key, tomlValue) in dict.sortedEntries {
                json[key] = tomlAnyToOrderedJsonRecursive(any: tomlValue, backtrace + .key(key), &errors)
            }
            return .dict(json)
        case let array as [Any]:
            var json = OrderedJson.JsonArray()
            for (index, tomlValue) in array.enumerated() {
                let element = tomlAnyToOrderedJsonRecursive(any: tomlValue, backtrace + .index(index), &errors)
                guard let element else { continue }
                json.append(element)
            }
            return .array(json)
        default:
            if let value = OrderedJson.newScalarOrNil(any) { return value }
            errors.append(.init(backtrace, "Unsupported TOML type: \(type(of: any))"))
            return nil
    }
}

struct ParseConfigResult {
    let config: Config
    let errors: [ConfigParseDiagnostic]
    let warnings: [ConfigParseDiagnostic]

    var allowReloadConfig: Bool { errors.allSatisfy { !$0.preventConfigReload } }
}

@MainActor func parseConfig(_ rawToml: String) -> ParseConfigResult {
    var errors = NonCopyable([ConfigParseDiagnostic]())

    let rawTable: OrderedJson.JsonDict
    do {
        let dict: [String: Any] = try .init(try TOMLTable(source: rawToml))
        let json = tomlAnyToOrderedJsonRecursive(any: dict, .emptyRoot, &errors.value)
        switch json {
            case .dict(let dict): rawTable = dict
            default: // dead code
                let msg = "Config parsing error: the top level type must be a TOML Table. But got: \((json ?? .null).tomlType)"
                errors.value.append(.init(.emptyRoot, msg, preventConfigReload: true))
                rawTable = [:]
        }
    } catch {
        errors.value.append(.init(.emptyRoot, error.description, preventConfigReload: true))
        rawTable = [:]
    }

    let configVersion: ConfigVersion = rawTable[configVersionConfigRootKey]
        .flatMap { parseConfigVersion($0, .rootKey(configVersionConfigRootKey)).getOrNil(appendErrorTo: &errors.value) }
        ?? .min

    var c = ConfigParserContext(configVersion: configVersion, errors: errors.consume(), warnings: [ConfigParseDiagnostic]())

    var config = rawTable.parseTable(Config(), configParser, .emptyRoot, &c)
    config.configVersion = configVersion

    if let mapping = rawTable[keyMappingConfigRootKey].flatMap({ parseKeyMapping($0, .rootKey(keyMappingConfigRootKey), &c) }) {
        config.keyMapping = mapping
    }

    // Parse modeConfigRootKey after keyMappingConfigRootKey
    if let modes = rawTable[modeConfigRootKey].flatMap({ parseModes($0, .rootKey(modeConfigRootKey), &c, config.keyMapping.resolve()) }) {
        config.modes = modes
    }

    if config.configVersion <= ._1 {
        if rawTable.keys.contains(persistentWorkspacesKey) {
            c.errors += [.init(.rootKey(persistentWorkspacesKey), "This config option is only available since 'config-version = 2'")]
        }
        config.persistentWorkspaces = (config.modes.values.lazy
            .flatMap { (mode: Mode) -> [HotkeyBinding] in Array(mode.bindings.values) }
            .flatMap { (binding: HotkeyBinding) -> [String] in
                let commands = binding.commands.flatten()
                return commands.filterIsInstance(of: WorkspaceCommand.self).compactMap { $0.args.target.val.workspaceNameOrNil()?.raw } +
                    commands.filterIsInstance(of: MoveNodeToWorkspaceCommand.self).compactMap { $0.args.target.val.workspaceNameOrNil()?.raw }
            }
            + (config.workspaceToMonitorForceAssignment).keys)
            .toOrderedSet()
    }

    if config.enableNormalizationFlattenContainers {
        let containsSplitCommand = config.modes.values.lazy.flatMap { $0.bindings.values }
            .flatMap { $0.commands.flatten() }
            .contains { $0 is SplitCommand }
        if containsSplitCommand {
            c.errors += [.init(
                .emptyRoot, // todo Make 'split' + flatten normalization prettier
                """
                The config contains:
                1. usage of 'split' command
                2. enable-normalization-flatten-containers = true
                These two settings don't play nicely together. 'split' command has no effect when enable-normalization-flatten-containers is disabled.

                My recommendation: keep the normalizations enabled, and prefer 'join-with' over 'split'.
                """,
            )]
        }
    }
    if config.configVersion < .max {
        let msg = "The current 'config-version = \(config.configVersion)' is outdated. " +
            "Please consider migrating to 'config-version = \(ConfigVersion.max)'. " +
            "See https://nikitabobko.github.io/AeroSpace/guide#config-version for the migration guide."
        c.warnings.append(.init(.emptyRoot, msg))
    }
    return ParseConfigResult(config: config, errors: c.errors, warnings: c.warnings)
}

func parseIndentForNestedContainersWithTheSameOrientation(_ _: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<Void> {
    let msg = "Deprecated. Please drop it from the config. See https://github.com/nikitabobko/AeroSpace/issues/96"
    return .failure(.init(backtrace, msg))
}

func parseConfigVersion(_ raw: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<ConfigVersion> {
    parseInt(raw, backtrace)
        .flatMap { ConfigVersion.init(rawValue: $0).toResult(.init(backtrace, "config-version must be in [\(ConfigVersion.min), \(ConfigVersion.max)] range")) }
}

func parseInt(_ raw: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<Int> {
    raw.asIntOrNil.toResult(expectedActualTypeDiagnostic(expected: .int, actual: raw.tomlType, backtrace))
}

func parseString(_ raw: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<String> {
    raw.asStringOrNil.toResult(expectedActualTypeDiagnostic(expected: .string, actual: raw.tomlType, backtrace))
}

func parseSimpleType<T>(_ raw: OrderedJson, ofType: T.Type) -> T? {
    (raw.asIntOrNil as? T) ?? (raw.asStringOrNil as? T) ?? (raw.asBoolOrNil as? T)
}

extension OrderedJson {
    func unwrapTableWithSingleKey(expectedKey: String? = nil, _ backtrace: inout ConfigBacktrace) -> ResOrConfigParseDiagnostic<(key: String, value: OrderedJson)> {
        guard let asDictOrNil else {
            return .failure(expectedActualTypeDiagnostic(expected: .table, actual: tomlType, backtrace))
        }
        let singleKeyError: ConfigParseDiagnostic = .init(
            backtrace,
            expectedKey != nil
                ? "The table is expected to have a single key '\(expectedKey.orDie())'"
                : "The table is expected to have a single key",
        )
        guard let (actualKey, value): (String, OrderedJson) = asDictOrNil.count == 1 ? asDictOrNil.first : nil else {
            return .failure(singleKeyError)
        }
        if expectedKey != nil && expectedKey != actualKey {
            return .failure(singleKeyError)
        }
        backtrace = backtrace + .key(actualKey)
        return .success((actualKey, value))
    }
}

func parseTomlArray(_ raw: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<OrderedJson.JsonArray> {
    raw.asArrayOrNil.toResult(expectedActualTypeDiagnostic(expected: .array, actual: raw.tomlType, backtrace))
}

func parseTable<T: ConvenienceMutable>(
    _ raw: OrderedJson,
    _ initial: T,
    _ fieldsParser: [String: any ParserProtocol<T>],
    _ backtrace: ConfigBacktrace,
    _ c: inout ConfigParserContext,
) -> T {
    switch raw {
        case .dict(let table):
            return table.parseTable(initial, fieldsParser, backtrace, &c)
        default:
            c.errors.append(expectedActualTypeDiagnostic(expected: .table, actual: raw.tomlType, backtrace))
            return initial
    }
}

private func parseStartupRootContainerLayout(_ raw: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<Void> {
    parseString(raw, backtrace)
        .filter(.init(backtrace, "'non-empty-workspaces-root-containers-layout-on-startup' is deprecated. Please drop it from your config")) { raw in raw == "smart" }
        .map { _ in () }
}

private func parseLayout(_ raw: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<Layout> {
    parseString(raw, backtrace)
        .flatMap { $0.parseLayout().toResult(.init(backtrace, "Can't parse layout '\($0)'")) }
}

private func skipParsing<T: Sendable>(_ value: T) -> @Sendable (_ raw: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<T> {
    { _, _ in .success(value) }
}

private func parsePersistentWorkspaces(_ raw: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<OrderedSet<String>> {
    parseArrayOfStrings(raw, backtrace)
        .flatMap { arr in
            let set = arr.toOrderedSet()
            return set.count == arr.count ? .success(set) : .failure(.init(backtrace, "Contains duplicated workspace names"))
        }
}

private func parseArrayOfStrings(_ raw: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<[String]> {
    parseTomlArray(raw, backtrace)
        .flatMap { arr in
            arr.enumerated().mapAllOrFailure { (index, elem) in
                parseString(elem, backtrace + .index(index))
            }
        }
}

private func parseDefaultContainerOrientation(_ raw: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<DefaultContainerOrientation> {
    parseString(raw, backtrace).flatMap {
        DefaultContainerOrientation(rawValue: $0)
            .toResult(.init(backtrace, "Can't parse default container orientation '\($0)'"))
    }
}

extension ResOrStr where Failure == String {
    func toParsedConfig(_ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<Success> {
        mapError { .init(backtrace, $0) }
    }
}

func parseBool(_ raw: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<Bool> {
    raw.asBoolOrNil.toResult(expectedActualTypeDiagnostic(expected: .bool, actual: raw.tomlType, backtrace))
}

struct ConfigBacktrace: CustomStringConvertible, Equatable {
    private var path: [TomlBacktraceItem] = []
    private init(_ path: [TomlBacktraceItem]) {
        check(path.first?.isKey != false, "Tried to construct invalid TOML path: \(path)")
        self.path = path
    }

    static func rootKey(_ key: String) -> Self { .init([.key(key)]) }
    static let emptyRoot: Self = .init([])

    var description: String {
        var result = ""
        for (i, elem) in path.enumerated() {
            switch elem {
                case .key(let rootKey) where i == 0: result += rootKey
                case .key(let key): result += ".\(key)"
                case .index(let index): result += "[\(index)]"
            }
        }
        return result
    }

    var isRootKey: Bool { path.singleOrNil().map(\.isKey) == true }

    static func + (lhs: consuming Self, rhs: TomlBacktraceItem) -> Self {
        lhs.path += [rhs]
        return lhs
    }
}

enum TomlBacktraceItem: Equatable {
    case key(String)
    case index(Int)

    var isKey: Bool {
        switch self {
            case .key: true
            case .index: false
        }
    }
}

extension OrderedJson.JsonDict {
    func parseTable<T: ConvenienceMutable>(
        _ initial: T,
        _ fieldsParser: [String: any ParserProtocol<T>],
        _ backtrace: ConfigBacktrace,
        _ c: inout ConfigParserContext,
    ) -> T {
        var raw = initial

        for (key, value) in self {
            let backtrace: ConfigBacktrace = backtrace + .key(key)
            switch fieldsParser[key] {
                case let parser?: raw = parser.transformRawConfig(raw, value, backtrace, &c)
                case nil: c.errors.append(unknownKeyDiagnostic(backtrace))
            }
        }

        return raw
    }
}

func unknownKeyDiagnostic(_ backtrace: ConfigBacktrace) -> ConfigParseDiagnostic {
    .init(backtrace, backtrace.isRootKey ? "Unknown top-level key" : "Unknown key")
}

func expectedActualTypeDiagnostic(expected: TomlType, actual: TomlType, _ backtrace: ConfigBacktrace) -> ConfigParseDiagnostic {
    .init(backtrace, expectedActualTypeError(expected: expected, actual: actual))
}

func expectedActualTypeDiagnostic(expected: [TomlType], actual: TomlType, _ backtrace: ConfigBacktrace) -> ConfigParseDiagnostic {
    .init(backtrace, expectedActualTypeError(expected: expected, actual: actual))
}

```

## /Sources/AppBundle/config/parseExecEnvVariables.swift

```swift path="/Sources/AppBundle/config/parseExecEnvVariables.swift" 
import AppKit
import Common

let testEnv = ["PATH": "AEROSPACE_TEST_PATH", "AEROSPACE_INHERITED_TEST_ENV": "inherited"]
private var env: [String: String] {
    isUnitTest ? testEnv : ProcessInfo.processInfo.environment
}

private let rawExecConfigParser: [String: any ParserProtocol<RawExecConfig>] = [
    "inherit-env-vars": Parser(\.inheritEnvVariables, parseBool),
    "env-vars": Parser(\.overriddenVars, parseEnvVariables),
]

let defaultOverriddenEnvVars = ["PATH": "/opt/homebrew/bin:/opt/homebrew/sbin:\(env["PATH"] ?? "")"]

struct ExecConfig: Equatable {
    var envVariables: [String: String] = env + defaultOverriddenEnvVars
}

struct RawExecConfig: ConvenienceMutable, Equatable {
    var inheritEnvVariables = true
    // Already interpolated value of overridden vars
    var overriddenVars: [String: String] = [:]

    func expand() -> ExecConfig {
        let base: [String: String] = inheritEnvVariables ? env : [:]
        return ExecConfig(envVariables: base + overriddenVars)
    }
}

func parseExecConfig(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> ExecConfig {
    parseTable(raw, RawExecConfig(), rawExecConfigParser, backtrace, &c).expand()
}

private func parseEnvVariables(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> [String: String] {
    guard let table = raw.asDictOrNil else {
        c.errors.append(expectedActualTypeDiagnostic(expected: .array, actual: raw.tomlType, backtrace))
        return [:]
    }
    let mutated = table.keys
    let fullEnv: [String: String] = env
    let baseEnv: [String: String] = fullEnv.filter { (key, _) -> Bool in !mutated.contains(key) }
    var result: [String: String] = [:]
    for (key, value) in table {
        let backtrace = backtrace + .key(key)
        if key == "PWD" { c.errors.append(.init(backtrace, "Changing 'PWD' is not allowed")) }
        guard let rawStr = parseString(value, backtrace).getOrNil(appendErrorTo: &c.errors) else { continue }
        var env = baseEnv
        if let add: String = fullEnv[key] {
            env[key] = add
        }
        switch rawStr.interpolate(with: env) {
            case .success(let interpolated): result[key] = interpolated
            case .failure(let _errros): c.errors += _errros.map { .init(backtrace, $0) }
        }
    }
    return result
}

```

## /Sources/AppBundle/config/parseFocusFollowsMouse.swift

```swift path="/Sources/AppBundle/config/parseFocusFollowsMouse.swift" 
private let focusFollowsMouseParserTable: [String: any ParserProtocol<FocusFollowsMouse>] = [
    "enabled": Parser(\.enabled, parseBool),
]

func parseFocusFollowsMouse(_ rawConfig: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> FocusFollowsMouse {
    parseTable(rawConfig, FocusFollowsMouse(), focusFollowsMouseParserTable, backtrace, &c)
}

```

## /Sources/AppBundle/config/parseGaps.swift

```swift path="/Sources/AppBundle/config/parseGaps.swift" 
import Common

struct Gaps: ConvenienceMutable, Equatable, Sendable {
    var inner: Inner
    var outer: Outer

    static let zero = Gaps(inner: .zero, outer: .zero)

    struct Inner: ConvenienceMutable, Equatable, Sendable {
        var vertical: DynamicConfigValue<Int>
        var horizontal: DynamicConfigValue<Int>

        static let zero = Inner(vertical: 0, horizontal: 0)

        init(vertical: Int, horizontal: Int) {
            self.vertical = .constant(vertical)
            self.horizontal = .constant(horizontal)
        }

        init(vertical: DynamicConfigValue<Int>, horizontal: DynamicConfigValue<Int>) {
            self.vertical = vertical
            self.horizontal = horizontal
        }
    }

    struct Outer: ConvenienceMutable, Equatable, Sendable {
        var left: DynamicConfigValue<Int>
        var bottom: DynamicConfigValue<Int>
        var top: DynamicConfigValue<Int>
        var right: DynamicConfigValue<Int>

        static let zero = Outer(left: 0, bottom: 0, top: 0, right: 0)

        init(left: Int, bottom: Int, top: Int, right: Int) {
            self.left = .constant(left)
            self.bottom = .constant(bottom)
            self.top = .constant(top)
            self.right = .constant(right)
        }

        init(left: DynamicConfigValue<Int>, bottom: DynamicConfigValue<Int>, top: DynamicConfigValue<Int>, right: DynamicConfigValue<Int>) {
            self.left = left
            self.bottom = bottom
            self.top = top
            self.right = right
        }
    }
}

struct ResolvedGaps {
    let inner: Inner
    let outer: Outer

    struct Inner {
        let vertical: Int
        let horizontal: Int

        func get(_ orientation: Orientation) -> Int {
            orientation == .h ? horizontal : vertical
        }
    }

    struct Outer {
        let left: Int
        let bottom: Int
        let top: Int
        let right: Int
    }

    @MainActor init(gaps: Gaps, monitor: any MonitorInfo) {
        inner = .init(
            vertical: gaps.inner.vertical.getValue(for: monitor),
            horizontal: gaps.inner.horizontal.getValue(for: monitor),
        )

        outer = .init(
            left: gaps.outer.left.getValue(for: monitor),
            bottom: gaps.outer.bottom.getValue(for: monitor),
            top: gaps.outer.top.getValue(for: monitor),
            right: gaps.outer.right.getValue(for: monitor),
        )
    }
}

private let gapsParser: [String: any ParserProtocol<Gaps>] = [
    "inner": Parser(\.inner, parseInner),
    "outer": Parser(\.outer, parseOuter),
]

private let innerParser: [String: any ParserProtocol<Gaps.Inner>] = [
    "vertical": Parser(\.vertical, parseIntDynamicValue),
    "horizontal": Parser(\.horizontal, parseIntDynamicValue),
]

private let outerParser: [String: any ParserProtocol<Gaps.Outer>] = [
    "left": Parser(\.left, parseIntDynamicValue),
    "bottom": Parser(\.bottom, parseIntDynamicValue),
    "top": Parser(\.top, parseIntDynamicValue),
    "right": Parser(\.right, parseIntDynamicValue),
]

private func parseIntDynamicValue(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> DynamicConfigValue<Int> {
    parseDynamicValue(raw, ofType: Int.self, 0, backtrace, &c)
}

func parseGaps(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> Gaps {
    parseTable(raw, .zero, gapsParser, backtrace, &c)
}

func parseInner(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> Gaps.Inner {
    parseTable(raw, Gaps.Inner.zero, innerParser, backtrace, &c)
}

func parseOuter(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> Gaps.Outer {
    parseTable(raw, Gaps.Outer.zero, outerParser, backtrace, &c)
}

```

## /Sources/AppBundle/config/parseKeyMapping.swift

```swift path="/Sources/AppBundle/config/parseKeyMapping.swift" 
import Common
import HotKey

private let keyMappingParser: [String: any ParserProtocol<KeyMapping>] = [
    "preset": Parser(\.preset, parsePreset),
    "key-notation-to-key-code": Parser(\.rawKeyNotationToKeyCode, parseKeyNotationToKeyCode),
]

struct KeyMapping: ConvenienceMutable, Equatable, Sendable {
    enum Preset: String, CaseIterable, Sendable {
        case qwerty, dvorak, colemak
    }

    init(
        preset: Preset = .qwerty,
        rawKeyNotationToKeyCode: [String: Key] = [:],
    ) {
        self.preset = preset
        self.rawKeyNotationToKeyCode = rawKeyNotationToKeyCode
    }

    fileprivate var preset: Preset = .qwerty
    fileprivate var rawKeyNotationToKeyCode: [String: Key] = [:]

    func resolve() -> [String: Key] {
        getKeysPreset(preset) + rawKeyNotationToKeyCode
    }
}

func parseKeyMapping(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> KeyMapping {
    parseTable(raw, KeyMapping(), keyMappingParser, backtrace, &c)
}

private func parsePreset(_ raw: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<KeyMapping.Preset> {
    parseString(raw, backtrace).flatMap { parseEnum($0, KeyMapping.Preset.self).toParsedConfig(backtrace) }
}

private func parseKeyNotationToKeyCode(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> [String: Key] {
    var result: [String: Key] = [:]
    guard let table = raw.asDictOrNil else {
        c.errors.append(expectedActualTypeDiagnostic(expected: .table, actual: raw.tomlType, backtrace))
        return result
    }
    for (key, value): (String, OrderedJson) in table {
        if isValidKeyNotation(key) {
            let backtrace = backtrace + .key(key)
            if let value = parseString(value, backtrace).getOrNil(appendErrorTo: &c.errors) {
                switch keyNotationToKeyCode[value] {
                    case let value?: result[key] = value
                    case nil: c.errors.append(.init(backtrace, "\(value.singleQuoted) is invalid key code"))
                }
            }
        } else {
            c.errors.append(.init(backtrace, "\(key.singleQuoted) is invalid key notation"))
        }
    }
    return result
}

private func isValidKeyNotation(_ str: String) -> Bool {
    str.rangeOfCharacter(from: .whitespacesAndNewlines) == nil && !str.contains("-")
}

```

## /Sources/AppBundle/config/parseOnWindowDetected.swift

```swift path="/Sources/AppBundle/config/parseOnWindowDetected.swift" 
import Common

struct WindowDetectedCallback: ConvenienceMutable, Equatable {
    var matcher: WindowDetectedCallbackMatcher = .command(.empty)
    var checkFurtherCallbacks: Bool = false
    var rawRun: Shell<any Command>? = nil

    var run: Shell<any Command> {
        rawRun ?? dieT("ID-46D063B2 should have discarded nil")
    }

    var debugJson: Json {
        var result: [String: Json] = [:]
        result["matcher"] = switch matcher {
            case .command(let command): .string(command.shellOfCommandsDescription)
            case .legacy(let legacy): legacy.debugJson
        }
        if let commands = rawRun {
            result["commands"] = .string(commands.shellOfCommandsDescription)
        }
        return .dict(result)
    }

    static func == (lhs: WindowDetectedCallback, rhs: WindowDetectedCallback) -> Bool {
        lhs.matcher == rhs.matcher && lhs.checkFurtherCallbacks == rhs.checkFurtherCallbacks && lhs.run.strictEquals(rhs.run)
    }
}

struct LegacyWindowDetectedCallbackMatcher: ConvenienceMutable, Equatable {
    var appId: String?
    var appNameRegexSubstring: CaseInsensitiveRegex?
    var windowTitleRegexSubstring: CaseInsensitiveRegex?
    var workspace: String?
    var duringAeroSpaceStartup: Bool?

    var debugJson: Json {
        var resultParts: [String] = []
        if let appId {
            resultParts.append("appId=\"\(appId)\"")
        }
        if let appNameRegexSubstring {
            resultParts.append("appNameRegexSubstring=\"\(appNameRegexSubstring.origin)\"")
        }
        if let windowTitleRegexSubstring {
            resultParts.append("windowTitleRegexSubstring=\"\(windowTitleRegexSubstring.origin)\"")
        }
        if let workspace {
            resultParts.append("workspace=\"\(workspace)\"")
        }
        if let duringAeroSpaceStartup {
            resultParts.append("duringAeroSpaceStartup=\(duringAeroSpaceStartup)")
        }
        return .string(resultParts.joined(separator: ", "))
    }
}

enum WindowDetectedCallbackMatcher: Equatable {
    case command(Shell<any Command>)
    case legacy(LegacyWindowDetectedCallbackMatcher)

    static func == (lhs: WindowDetectedCallbackMatcher, rhs: WindowDetectedCallbackMatcher) -> Bool {
        switch (lhs, rhs) {
            case (.command(let command1), .command(let command2)): command1.strictEquals(command2)
            case (.legacy(let matcher1), .legacy(let matcher2)): matcher1 == matcher2
            default: false
        }
    }
}

private let windowDetectedParser: [String: any ParserProtocol<WindowDetectedCallback>] = [
    "if": Parser(\.matcher, parseMatcher),
    "check-further-callbacks": Parser(\.checkFurtherCallbacks, parseBool),
    "run": Parser(\.rawRun, parseShellOfCommandsForConfig),
]

private let matcherParsers: [String: any ParserProtocol<LegacyWindowDetectedCallbackMatcher>] = [
    "app-id": Parser(\.appId, upcast(parseString)),
    "workspace": Parser(\.workspace, upcast(parseString)),
    "app-name-regex-substring": Parser(\.appNameRegexSubstring, upcast(parseCasInsensitiveRegex)),
    "window-title-regex-substring": Parser(\.windowTitleRegexSubstring, upcast(parseCasInsensitiveRegex)),
    "during-aerospace-startup": Parser(\.duringAeroSpaceStartup, upcast(parseBool)),
]

private func upcast<T>(
    _ fun: @escaping @Sendable (OrderedJson, ConfigBacktrace) -> ResOrConfigParseDiagnostic<T>,
) -> @Sendable (OrderedJson, ConfigBacktrace) -> ResOrConfigParseDiagnostic<T?> {
    { fun($0, $1).map(Optional.init) }
}

func parseOnWindowDetectedArray(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> [WindowDetectedCallback] {
    if let array = raw.asArrayOrNil {
        return array.enumerated().map { (index, raw) in parseWindowDetectedCallback(raw, backtrace + .index(index), &c) }.filterNotNil()
    } else {
        c.errors += [expectedActualTypeDiagnostic(expected: .array, actual: raw.tomlType, backtrace)]
        return []
    }
}

private func parseCasInsensitiveRegex(_ raw: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<CaseInsensitiveRegex> {
    parseString(raw, backtrace).flatMap { CaseInsensitiveRegex.new($0).toParsedConfig(backtrace) }
}

private func parseMatcher(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> WindowDetectedCallbackMatcher {
    switch raw {
        case .dict(let raw):
            return .legacy(raw.parseTable(LegacyWindowDetectedCallbackMatcher(), matcherParsers, backtrace, &c))
        case .string(let raw):
            return .command(parseCommand(raw, allowExecAndForget: false, allowEval: false).toResult().toParsedConfig(backtrace).getOrNil(appendErrorTo: &c.errors) ?? .empty)
        default:
            // Intentionally skip Table type from the list of expected types
            c.errors.append(.init(backtrace, expectedActualTypeError(expected: .string, actual: raw.tomlType)))
            return .command(.empty)
    }
}

private func parseWindowDetectedCallback(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> WindowDetectedCallback? {
    var myContext = ConfigParserContext(configVersion: c.configVersion, errors: [], warnings: [])
    let callback = parseTable(raw, WindowDetectedCallback(), windowDetectedParser, backtrace, &myContext)

    if callback.matcher == .command(.empty) && !callback.checkFurtherCallbacks {
        let msg = "Omitting 'if' is error prone. You can use `if = 'true'` to preserve the previous behavior.\n" +
            "But heads up! You may have missed 'check-further-callbacks = true'"
        myContext.errors.append(.init(backtrace, msg))
    }

    if callback.rawRun == nil { // ID-46D063B2
        myContext.errors.append(.init(backtrace, "'run' is mandatory key"))
    }

    if !myContext.errors.isEmpty {
        c.errors += myContext.errors
        c.warnings += myContext.warnings
        return nil
    }

    return callback
}

```

## /Sources/AppBundle/config/parseWorkspaceToMonitorAssignment.swift

```swift path="/Sources/AppBundle/config/parseWorkspaceToMonitorAssignment.swift" 
import Common

func parseWorkspaceToMonitorAssignment(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> [String: [MonitorDescription]] {
    guard let rawTable = raw.asDictOrNil else {
        c.errors += [expectedActualTypeDiagnostic(expected: .table, actual: raw.tomlType, backtrace)]
        return [:]
    }
    var result: [String: [MonitorDescription]] = [:]
    for (workspaceName, rawMonitorDescription) in rawTable {
        result[workspaceName] = parseMonitorDescriptions(rawMonitorDescription, backtrace + .key(workspaceName), &c)
    }
    return result
}

func parseMonitorDescriptions(_ raw: OrderedJson, _ backtrace: ConfigBacktrace, _ c: inout ConfigParserContext) -> [MonitorDescription] {
    if let array = raw.asArrayOrNil {
        return array.enumerated()
            .map { (index, rawDesc) in parseMonitorDescription(rawDesc, backtrace + .index(index)).getOrNil(appendErrorTo: &c.errors) }
            .filterNotNil()
    } else {
        return parseMonitorDescription(raw, backtrace).getOrNil(appendErrorTo: &c.errors).asList()
    }
}

func parseMonitorDescription(_ raw: OrderedJson, _ backtrace: ConfigBacktrace) -> ResOrConfigParseDiagnostic<MonitorDescription> {
    let rawString: String
    if let string = raw.asStringOrNil {
        rawString = string
    } else if let int = raw.asIntOrNil {
        rawString = String(int)
    } else {
        return .failure(expectedActualTypeDiagnostic(expected: [.string, .int], actual: raw.tomlType, backtrace))
    }

    return parseMonitorDescription(rawString).toParsedConfig(backtrace)
}

```

## /Sources/AppBundle/config/startAtLogin.swift

```swift path="/Sources/AppBundle/config/startAtLogin.swift" 
import AppKit
import Common
import ServiceManagement

@MainActor
func syncStartAtLogin() {
    cleanupPlistFromPrevVersions()
    let service = SMAppService.mainApp
    switch true {
        case !config.startAtLogin: _ = try? service.unregister()
        case isDebug: print("'start-at-login = true' has no effect in debug builds")
        default: _ = try? service.register()
    }
}

private func cleanupPlistFromPrevVersions() { // todo Drop after a couple of versions
    let launchAgentsDir = FileManager.default.homeDirectoryForCurrentUser.appending(component: "Library/LaunchAgents/")
    Result { try FileManager.default.createDirectory(at: launchAgentsDir, withIntermediateDirectories: true) }.getOrDie()
    let url: URL = launchAgentsDir.appending(path: "bobko.aerospace.plist")
    try? FileManager.default.removeItem(at: url)
}

```

## /Sources/AppBundle/focus.swift

```swift path="/Sources/AppBundle/focus.swift" 
import AppKit
import Common

enum EffectiveLeaf {
    case window(Window)
    case emptyWorkspace(Workspace)
}
extension LiveFocus {
    var asLeaf: EffectiveLeaf {
        if let windowOrNil { .window(windowOrNil) } else { .emptyWorkspace(workspace) }
    }
}

/// This object should be only passed around but never memorized
/// Alternative name: ResolvedFocus
struct LiveFocus: AeroAny, Equatable {
    let windowOrNil: Window?
    var workspace: Workspace

    @MainActor fileprivate var frozen: FrozenFocus {
        return FrozenFocus(
            windowId: windowOrNil?.windowId,
            workspaceName: workspace.name,
            monitorId_oneBased: workspace.workspaceMonitor.monitorId_oneBased ?? 0,
        )
    }
}

/// "old", "captured", "frozen in time" Focus
/// It's safe to keep a hard reference to this object.
/// Unlike in LiveFocus, information inside FrozenFocus isn't guaranteed to be self-consistent.
/// window - workspace - monitor relation could change since the moment object was created
private struct FrozenFocus: AeroAny, Equatable, Sendable {
    let windowId: UInt32?
    let workspaceName: String
    // monitorId is not part of the focus. We keep it here only for 'on-focused-monitor-changed' to work
    let monitorId_oneBased: Int

    @MainActor var live: LiveFocus { // Important: don't access focus.monitorId here. monitorId is not part of the focus. Always prefer workspace
        let window: Window? = windowId.flatMap { Window.get(byId: $0) }
        let workspace = Workspace.get(byName: workspaceName)

        let workspaceFocus = workspace.toLiveFocus()
        let windowFocus = window?.toLiveFocusOrNil() ?? workspaceFocus

        return workspaceFocus.workspace != windowFocus.workspace
            ? workspaceFocus // If window and workspace become separated prefer workspace
            : windowFocus
    }
}

@MainActor private var _focus: FrozenFocus = {
    let monitor = mainMonitorInfo
    return FrozenFocus(windowId: nil, workspaceName: monitor.activeWorkspace.name, monitorId_oneBased: monitor.monitorId_oneBased ?? 0)
}()

/// Global focus.
/// Commands must be cautious about accessing this property directly. There are legitimate cases.
/// But, in general, commands must firstly check --window-id, --workspace, AEROSPACE_WINDOW_ID env and
/// AEROSPACE_WORKSPACE env before accessing the global focus.
@MainActor var focus: LiveFocus { _focus.live }

@MainActor func setFocus(to newFocus: LiveFocus) -> Bool {
    if _focus == newFocus.frozen { return true }
    let oldFocus = focus
    // Normalize mruWindow when focus away from a workspace
    if oldFocus.workspace != newFocus.workspace {
        oldFocus.windowOrNil?.markAsMostRecentChild()
    }

    _focus = newFocus.frozen
    let status = newFocus.workspace.workspaceMonitor.setActiveWorkspace(newFocus.workspace)

    newFocus.windowOrNil?.markAsMostRecentChild()
    return status
}
extension Window {
    @MainActor func focusWindow() -> Bool {
        if let focus = toLiveFocusOrNil() {
            return setFocus(to: focus)
        } else {
            // todo We should also exit-native-hidden/unminimize[/exit-native-fullscreen?] window if we want to fix ID-B6E178F2
            //      and retry to focus the window. Otherwise, it's not possible to focus minimized/hidden windows
            return false
        }
    }

    @MainActor func toLiveFocusOrNil() -> LiveFocus? { visualWorkspace.map { LiveFocus(windowOrNil: self, workspace: $0) } }
}
extension Workspace {
    @MainActor func focusWorkspace() -> Bool { setFocus(to: toLiveFocus()) }

    func toLiveFocus() -> LiveFocus {
        // todo unfortunately mostRecentWindowRecursive may recursively reach empty rootTilingContainer
        //      while floating or macos unconventional windows might be presented
        if let wd = mostRecentWindowRecursive ?? anyLeafWindowRecursive {
            LiveFocus(windowOrNil: wd, workspace: self)
        } else {
            LiveFocus(windowOrNil: nil, workspace: self) // emptyWorkspace
        }
    }
}

@MainActor private var _lastKnownFocus: FrozenFocus = _focus

// Used by workspace-back-and-forth
@MainActor var _prevFocusedWorkspaceName: String? = nil {
    didSet {
        prevFocusedWorkspaceDate = .now
    }
}
@MainActor var prevFocusedWorkspaceDate: Date = .distantPast
@MainActor var prevFocusedWorkspace: Workspace? { _prevFocusedWorkspaceName.map { Workspace.get(byName: $0) } }

// Used by focus-back-and-forth
@MainActor private var _prevFocus: FrozenFocus? = nil
@MainActor var prevFocus: LiveFocus? { _prevFocus?.live.takeIf { $0 != focus } }

@MainActor private var onFocusChangedRecursionGuard = false
// Should be called in refreshSession
@MainActor func checkOnFocusChangedCallbacks_nonCancellable() async {
    if refreshSessionEvent?.isStartup == true {
        return
    }
    let focus = focus
    let frozenFocus = focus.frozen
    var hasFocusChanged = false
    var hasFocusedWorkspaceChanged = false
    var hasFocusedMonitorChanged = false
    if frozenFocus != _lastKnownFocus {
        _prevFocus = _lastKnownFocus
        hasFocusChanged = true
    }
    if frozenFocus.workspaceName != _lastKnownFocus.workspaceName {
        _prevFocusedWorkspaceName = _lastKnownFocus.workspaceName
        hasFocusedWorkspaceChanged = true
    }
    if frozenFocus.monitorId_oneBased != _lastKnownFocus.monitorId_oneBased {
        hasFocusedMonitorChanged = true
    }
    _lastKnownFocus = frozenFocus

    if onFocusChangedRecursionGuard { return }
    onFocusChangedRecursionGuard = true
    defer { onFocusChangedRecursionGuard = false }
    if hasFocusChanged {
        _ = await onFocusChanged(.defaultEnv, CmdIoImpl.emptyStdinIgnoringOut, focus)
    }
    if let _prevFocusedWorkspaceName, hasFocusedWorkspaceChanged {
        onWorkspaceChanged(_prevFocusedWorkspaceName, frozenFocus.workspaceName, focus)
    }
    if hasFocusedMonitorChanged {
        _ = await onFocusedMonitorChanged(.defaultEnv, CmdIoImpl.emptyStdinIgnoringOut, focus)
    }
}

@MainActor func onFocusedMonitorChanged(_ env: CmdEnv, _ io: CmdIo, _ focus: LiveFocus) async -> Int32ExitCode {
    broadcastEvent(.focusedMonitorChanged(
        workspace: focus.workspace.name,
        monitorId_oneBased: focus.workspace.workspaceMonitor.monitorId_oneBased ?? 0,
    ))
    return await config.onFocusedMonitorChanged.run(env.withFocus(focus), io)
}

@MainActor func onFocusChanged(_ env: CmdEnv, _ io: CmdIo, _ focus: LiveFocus) async -> Int32ExitCode {
    broadcastEvent(.focusChanged(
        windowId: focus.windowOrNil?.windowId,
        workspace: focus.workspace.name,
    ))
    return await config.onFocusChanged.run(env.withFocus(focus), io)
}

@MainActor private func onWorkspaceChanged(_ oldWorkspace: String, _ newWorkspace: String, _ focus: LiveFocus) {
    broadcastEvent(.workspaceChanged(
        workspace: newWorkspace,
        prevWorkspace: oldWorkspace,
    ))
    if let exec = config.execOnWorkspaceChange.first {
        let process = Process()
        process.executableURL = URL(filePath: exec)
        process.arguments = Array(config.execOnWorkspaceChange.dropFirst())
        var environment = config.execConfig.envVariables
        environment[AEROSPACE_FOCUSED_WORKSPACE] = newWorkspace
        environment[AEROSPACE_PREV_WORKSPACE] = oldWorkspace
        switch focus.asLeaf {
            case .emptyWorkspace(let w):
                environment[AEROSPACE_WORKSPACE] = w.name
                environment[AEROSPACE_WINDOW_ID] = nil
            case .window(let w):
                environment[AEROSPACE_WORKSPACE] = nil
                environment[AEROSPACE_WINDOW_ID] = w.windowId.description
        }
        process.environment = environment
        _ = Result { try process.run() }
    }
}

```

## /Sources/AppBundle/focusCache.swift

```swift path="/Sources/AppBundle/focusCache.swift" 
@MainActor private var lastKnownNativeFocusedWindowId: UInt32? = nil

/// The data should flow (from nativeFocused to focused) and
///                      (from nativeFocused to lastKnownNativeFocusedWindowId)
/// Alternative names: takeFocusFromMacOs, syncFocusFromMacOs
@MainActor func updateFocusCache(_ nativeFocused: Window?) {
    if nativeFocused?.parent is MacosPopupWindowsContainer {
        return
    }
    if nativeFocused?.windowId != lastKnownNativeFocusedWindowId {
        _ = nativeFocused?.focusWindow()
        lastKnownNativeFocusedWindowId = nativeFocused?.windowId
    }
    nativeFocused?.macAppUnsafe.lastNativeFocusedWindowId = nativeFocused?.windowId
}

```

## /Sources/AppBundle/getNativeFocusedWindow.swift

```swift path="/Sources/AppBundle/getNativeFocusedWindow.swift" 
import AppKit
import Common

@MainActor
var appForTests: (any AbstractApp)? = nil

@MainActor
private var focusedApp: (any AbstractApp)? {
    get async throws {
        if isUnitTest {
            return appForTests
        } else {
            check(appForTests == nil)
            return switch NSWorkspace.shared.frontmostApplication {
                case let frontmostApplication?: try await MacApp.getOrRegister(frontmostApplication)
                case nil: nil
            }
        }
    }
}

@MainActor
func getNativeFocusedWindow(_ cm: CancellationMode) async throws -> Window? {
    try await focusedApp?.getFocusedWindow(cm)
}

```

## /Sources/AppBundle/initAppBundle.swift

```swift path="/Sources/AppBundle/initAppBundle.swift" 
import AppKit
import Common
import Foundation

@MainActor public func initAppBundle() {
    Task.startUnstructured {
        initTerminationHandler()
        unsafe _isCli = false
        initServerArgs()
        await waitForAccessibilityPermission_nonCancellable()
        if isDebug {
            await toggleReleaseServerIfDebug(.off)
            interceptTermination(SIGINT)
            interceptTermination(SIGKILL)
        }

        await bootstrapConfig_nonCancellable()
        _ = await reloadConfig_nonCancellable()

        startUnixSocketServer()
        GlobalObserver.initObserver()
        Workspace.garbageCollectUnusedWorkspaces() // init workspaces
        _ = Workspace.all.first?.focusWorkspace()
        await runHeavyCompleteRefreshSession(
            .startup,
            // It's important for the first initialization to be non cancellable
            // to make sure that isStartup propagates to all places
            assumeCancellable: false,
            layoutWorkspaces: false,
        )
        try await runLightSession(.startup, .forceRun) {
            smartLayoutAtStartup()
            _ = await config.afterStartupCommand.run(.defaultEnv, .emptyStdin)
        }
    }
}

@MainActor private func bootstrapConfig_nonCancellable() async {
    let result = await reloadConfig_nonCancellable(forceConfigUrl: defaultConfigUrl)
    let msg = """
        Can't load default config. Your installation is probably corrupted.
        Please don't modify \(defaultConfigUrl.description.singleQuoted)

        \(result.stdout)
        """
    check(result.isOk, msg)
}

@MainActor
private func smartLayoutAtStartup() {
    let workspace = focus.workspace
    let root = workspace.rootTilingContainer
    switch root.children.count <= 3 {
        case true: root.layout = .tiles
        case false: root.layout = .accordion
    }
}

var isStartup: Bool { refreshSessionEvent?.isStartup == true }

struct ServerArgs: Sendable {
    var configLocation: String? = nil
    var isReadOnly: Bool = false
}

private let serverHelp = """
    USAGE: \(CommandLine.arguments.first ?? "AeroSpace.app/Contents/MacOS/AeroSpace") [<options>]

    OPTIONS:
      -h, --help              Print help
      -v, --version           Print AeroSpace.app version
      --config-path <path>    Config path. It will take priority over ~/.aerospace.toml
                              and ${XDG_CONFIG_HOME}/aerospace/aerospace.toml
      --read-only             Disable window management.
                              Useful if you want to use only debug-windows or other query commands.
    """

nonisolated(unsafe) private var _serverArgs = ServerArgs()
var serverArgs: ServerArgs { unsafe _serverArgs }
private func initServerArgs() {
    let args = CommandLine.arguments.slice(1...) ?? []
    if args.contains(where: { $0 == "-h" || $0 == "--help" }) {
        exit(EXIT_CODE_ZERO, out: serverHelp)
    }
    var index = 0
    while index < args.count {
        let current = args[index]
        index += 1
        switch current {
            case "--version", "-v":
                exit(EXIT_CODE_ZERO, out: "\(aeroSpaceAppVersion) \(gitHash)")
            case "--config-path":
                switch args.getOrNil(atIndex: index) {
                    case let arg?: unsafe _serverArgs.configLocation = arg
                    case nil: exit(EXIT_CODE_TWO, err: "Missing <path> in --config-path flag")
                }
                index += 1
            case "--read-only": // todo rename to '--disabled' and unite with disabled feature
                unsafe _serverArgs.isReadOnly = true
            case "-NSDocumentRevisionsDebugMode" where isDebug:
                // Skip Xcode CLI args.
                // Usually it's '-NSDocumentRevisionsDebugMode NO'/'-NSDocumentRevisionsDebugMode YES'
                while args.getOrNil(atIndex: index)?.starts(with: "-") == false { index += 1 }
            default:
                exit(EXIT_CODE_TWO, err: "Unrecognized flag \(args.first.orDie().singleQuoted)")
        }
    }
    if let path = serverArgs.configLocation, !FileManager.default.fileExists(atPath: path) {
        exit(EXIT_CODE_TWO, err: "\(path) doesn't exist")
    }
}

```

## /Sources/AppBundle/model/Json.swift

```swift path="/Sources/AppBundle/model/Json.swift" 
import AppKit
import Common

enum Json: Encodable, Equatable { // todo rename to Dto? (data transfer object)
    // vector
    case dict(JsonDict)
    case array(JsonArray)

    // scalar
    case null
    case string(String)
    case int(Int64)
    case bool(Bool)

    typealias JsonDict = [String: Json]
    typealias JsonArray = [Json]

    func encode(to encoder: any Encoder) throws {
        switch self {
            case .array(let value): try value.encode(to: encoder)
            case .dict(let value): try value.encode(to: encoder)
            case .string(let value): try value.encode(to: encoder)
            case .int(let value): try value.encode(to: encoder)
            case .bool(let value): try value.encode(to: encoder)
            case .null: try (nil as String?).encode(to: encoder)
        }
    }

    static func newOrDieRecursive(_ value: Any?) -> Json {
        switch value {
            case let value as [String: Any?]: .dict(value.mapValues(newOrDieRecursive))
            case let value as [Any?]: .array(value.map(newOrDieRecursive))
            default:
                newScalarOrNil(value)
                    ?? dieT("Can't parse \(String(describing: value)) (\(Swift.type(of: value))) to JSON")
        }
    }

    static func newScalarOrNil(_ value: Any?) -> Json? {
        switch value {
            case let value as Int64: .int(value)
            case let value as Int: .int(Int64(value))
            case let value as UInt32: .int(Int64(value))
            case let value as UInt: .int(Int64(value))
            case let value as Bool: .bool(value)
            case let value as String: .string(value)
            case nil, is NSNull: .null
            default: nil
        }
    }

    static func stringOrNull(_ str: String?) -> Json { str.map(Json.string) ?? .null }

    static func int(_ int: Int) -> Json { .int(Int64(exactly: int).orDie()) }
    static func int(_ int: UInt32) -> Json { .int(Int64(exactly: int).orDie()) }

    var rawValue: Any? {
        switch self {
            case .null: nil

            case .array(let x): x
            case .dict(let x): x

            case .bool(let x): x
            case .int(let x): x
            case .string(let x): x
        }
    }

    var asDictOrDie: [String: Json] { asDictOrNil.orDie("\(self) is not a dict") }

    var asInt64OrNil: Int64? {
        if case .int(let value) = self { value } else { nil }
    }

    var asDictOrNil: JsonDict? {
        if case .dict(let value) = self { value } else { nil }
    }
}

```

## /Sources/AppBundle/model/KnownBundleId.swift

```swift path="/Sources/AppBundle/model/KnownBundleId.swift" 
enum KnownBundleId: String, Equatable {

    case _1password = "com.1password.1password"
    case activityMonitor = "com.apple.ActivityMonitor"
    case alacritty = "org.alacritty"
    case braveBrowser = "com.brave.Browser"
    case chrome = "com.google.Chrome"
    case cleanshotx = "pl.maketheweb.cleanshotx"
    case codex = "com.openai.codex"
    case emacs = "org.gnu.Emacs"
    case finder = "com.apple.finder"
    case ghostty = "com.mitchellh.ghostty"
    case gimp = "org.gimp.gimp-2.10"
    case iphonesimulator = "com.apple.iphonesimulator"
    case iterm2 = "com.googlecode.iterm2"
    case kitty = "net.kovidgoyal.kitty"
    case outlook = "com.microsoft.Outlook"
    case photoBooth = "com.apple.PhotoBooth"
    case qutebrowser = "org.qutebrowser.qutebrowser"
    case screenstudio = "com.timpler.screenstudio"
    case slack = "com.tinyspeck.slackmacgap"
    case steam = "com.valvesoftware.steam.helper"
    case wezterm = "com.github.wez.wezterm"
    case wisprFlow = "com.electron.wispr-flow"
    case xcode = "com.apple.dt.Xcode"
    case zenBrowser = "app.zen-browser.zen"
    case zoom = "us.zoom.xos"

    case mozillaFirefox = "org.mozilla.firefox"
    case mozillaFirefoxDeveloperEdition = "org.mozilla.firefoxdeveloperedition"
    case mozillaFirefoxNightly = "org.mozilla.nightly"

    case vscode = "com.microsoft.VSCode"
    case vscodium = "com.vscodium"

    var isFirefox: Bool {
        self == .mozillaFirefox
            || self == .mozillaFirefoxDeveloperEdition
            || self == .mozillaFirefoxNightly
            || self == .zenBrowser
    }

    var isVscode: Bool {
        self == .vscode || self == .vscodium
    }
}

```

## /Sources/AppBundle/model/MonitorDescriptionEx.swift

```swift path="/Sources/AppBundle/model/MonitorDescriptionEx.swift" 
import Common

extension MonitorDescription {
    @MainActor func resolveMonitor(sortedMonitors: [MonitorInfo]) -> MonitorInfo? {
        switch self {
            case .sequenceNumber(let number): sortedMonitors.getOrNil(atIndex: number - 1)
            case .main: mainMonitorInfo
            case .pattern(let regex): sortedMonitors.first { $0.name.contains(caseInsensitiveRegex: regex) }
            case .secondary:
                sortedMonitors.takeIf { $0.count == 2 }?
                    .first { $0.rect.topLeftCorner != mainMonitorInfo.rect.topLeftCorner }
        }
    }
}

```

## /Sources/AppBundle/model/MonitorEx.swift

```swift path="/Sources/AppBundle/model/MonitorEx.swift" 
extension MonitorInfo {
    @MainActor
    var visibleRectPaddedByOuterGaps: Rect {
        let topLeft = visibleRect.topLeftCorner
        let gaps = ResolvedGaps(gaps: config.gaps, monitor: self)
        return Rect(
            topLeftX: topLeft.x + gaps.outer.left.toDouble(),
            topLeftY: topLeft.y + gaps.outer.top.toDouble(),
            width: visibleRect.width - gaps.outer.left.toDouble() - gaps.outer.right.toDouble(),
            height: visibleRect.height - gaps.outer.top.toDouble() - gaps.outer.bottom.toDouble(),
        )
    }

    var monitorId_oneBased: Int? {
        let sorted = sortedMonitorInfos
        let origin = self.rect.topLeftCorner
        return sorted.firstIndex { $0.rect.topLeftCorner == origin }.map { $0 + 1 }
    }
}

```

## /Sources/AppBundle/mouse/mouse.swift

```swift path="/Sources/AppBundle/mouse/mouse.swift" 
import AppKit

@MainActor var currentlyManipulatedWithMouseWindowId: UInt32? = nil
var isLeftMouseButtonDown: Bool { NSEvent.pressedMouseButtons == 1 }

@MainActor
func isManipulatedWithMouse(_ window: Window) async throws -> Bool {
    try await (!window.isHiddenInCorner && // Don't allow to resize/move windows of hidden workspaces
        isLeftMouseButtonDown &&
        (currentlyManipulatedWithMouseWindowId == nil || window.windowId == currentlyManipulatedWithMouseWindowId))
        .andAsync { @Sendable @MainActor in try await getNativeFocusedWindow(.cancellable) == window }
}

/// Same motivation as in monitorFrameNormalized
var mouseLocation: CGPoint { NSEvent.mouseLocation.withYAxisFlipped }

```


The content has been capped at 50000 tokens. The user could consider applying other filters to refine the result. The better and more specific the context, the better the LLM can follow instructions. If the context seems verbose, the user can refine the filter using uithub. Thank you for using https://uithub.com - Perfect LLM context for any GitHub repo.
Copied!