RepoPilotOpen in app →

ianyh/Amethyst

Automatic tiling window manager for macOS à la xmonad.

Healthy

Healthy across the board

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 5w ago
  • 26+ active contributors
  • MIT licensed
Show 3 more →
  • CI configured
  • Tests present
  • Concentrated ownership — top contributor handles 70% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/ianyh/amethyst)](https://repopilot.app/r/ianyh/amethyst)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/ianyh/amethyst on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: ianyh/Amethyst

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/ianyh/Amethyst shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 5w ago
  • 26+ active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Concentrated ownership — top contributor handles 70% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live ianyh/Amethyst repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/ianyh/Amethyst.

What it runs against: a local clone of ianyh/Amethyst — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in ianyh/Amethyst | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch development exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 65 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>ianyh/Amethyst</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of ianyh/Amethyst. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/ianyh/Amethyst.git
#   cd Amethyst
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of ianyh/Amethyst and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "ianyh/Amethyst(\\.git)?\\b" \\
  && ok "origin remote is ianyh/Amethyst" \\
  || miss "origin remote is not ianyh/Amethyst (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify development >/dev/null 2>&1 \\
  && ok "default branch development exists" \\
  || miss "default branch development no longer exists"

# 4. Critical files exist
test -f "Amethyst/AppDelegate.swift" \\
  && ok "Amethyst/AppDelegate.swift" \\
  || miss "missing critical file: Amethyst/AppDelegate.swift"
test -f "Amethyst/Managers/WindowManager.swift" \\
  && ok "Amethyst/Managers/WindowManager.swift" \\
  || miss "missing critical file: Amethyst/Managers/WindowManager.swift"
test -f "Amethyst/Managers/ScreenManager.swift" \\
  && ok "Amethyst/Managers/ScreenManager.swift" \\
  || miss "missing critical file: Amethyst/Managers/ScreenManager.swift"
test -f "Amethyst/Layout/Layout.swift" \\
  && ok "Amethyst/Layout/Layout.swift" \\
  || miss "missing critical file: Amethyst/Layout/Layout.swift"
test -f "Amethyst/Events/HotKeyManager.swift" \\
  && ok "Amethyst/Events/HotKeyManager.swift" \\
  || miss "missing critical file: Amethyst/Events/HotKeyManager.swift"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 65 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~35d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/ianyh/Amethyst"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Amethyst is an automatic tiling window manager for macOS written in Swift that mimics xmonad's behavior, allowing users to organize and resize windows automatically into predefined layouts (tall, wide, fullscreen, etc.) via keyboard shortcuts rather than manual dragging. It solves the macOS gap in productivity-focused, keyboard-driven window management for developers and power users accustomed to tiling managers on Linux. Single Xcode project (Amethyst.xcodeproj) with workspace structure. Core logic in Amethyst/ folder organized by concern: Categories/ for extensions, Events/ for HotKeyManager, Debug/ for introspection tools, and Base.lproj/ for UI. Configuration via .amethyst.sample.yml. Debug CLI variant available (xcschemes show 'Amethyst Debug CLI').

👥Who it's for

Software developers and power users on macOS who use keyboard-driven workflows (often coming from Linux/xmonad backgrounds) and want to eliminate repetitive window resizing and positioning tasks through automated, layout-based window organization.

🌱Maturity & risk

Production-ready and actively maintained. The codebase is 595KB Swift (primary language), has CI/CD via GitHub Actions (tests.yml), uses Xcode project structure with workspace, and supports macOS 10.15+. Recent activity visible in Git workflow files and test plan configuration suggests ongoing development, though exact commit recency is not shown in provided data.

Low-to-moderate risk: single-maintainer project (ianyh), requires macOS Accessibility API permissions (potential OS compatibility surface), and depends on system-level window manipulation which can break across macOS updates. No public dependency lock file visible (Package.resolved exists but dependencies aren't listed), making transitive dependency risk unclear. Swift 5+ requirement limits backwards compatibility.

Active areas of work

Actively maintained with GitHub Discussions enabled, SwiftLint enforced (.swiftlint.yml), and Hound code review automation integrated. Test infrastructure in place (Amethyst.xctestplan, tests.yml workflow). Debug tooling recently added (AppsInfo.swift, ScreensInfo.swift, WindowsInfo.swift under Debug/ folder suggests recent introspection capability expansion).

🚀Get running

git clone https://github.com/ianyh/Amethyst.git
cd Amethyst
open Amethyst.xcworkspace
# In Xcode: Product > Scheme > Amethyst > Run

Requires Xcode 12+ and macOS 10.15+. Build via Xcode GUI or xcodebuild -workspace Amethyst.xcworkspace -scheme Amethyst.

Daily commands: Open Amethyst.xcworkspace in Xcode and press Product > Run, or: xcodebuild -workspace Amethyst.xcworkspace -scheme Amethyst -configuration Debug build. Debug CLI available via 'Amethyst Debug CLI' scheme. App runs as menu bar application once built.

🗺️Map of the codebase

  • Amethyst/AppDelegate.swift — Application entry point and lifecycle manager; initializes the window manager, hot key system, and app state.
  • Amethyst/Managers/WindowManager.swift — Core engine managing window layouts, reflow operations, and accessibility-based window manipulation; all tiling logic flows through here.
  • Amethyst/Managers/ScreenManager.swift — Handles multi-monitor support and workspace management; critical for tracking screens and delegating layouts per display.
  • Amethyst/Layout/Layout.swift — Abstract layout protocol and base implementation; all layout algorithms inherit from or conform to this interface.
  • Amethyst/Events/HotKeyManager.swift — Keyboard shortcut registration and dispatch system; bridges user input to all window/layout operations.
  • Amethyst/Managers/AppManager.swift — Monitors running applications, tracks windowless apps, and manages application-level focus state.

🛠️How to make changes

Add a New Tiling Layout Algorithm

  1. Create a new Swift file in Amethyst/Layout/Layouts/ named YourLayout.swift (Amethyst/Layout/Layouts/YourLayout.swift)
  2. Conform to Layout protocol from Amethyst/Layout/Layout.swift and implement reflowOperationForLayout(windows:screenFrame:index:) (Amethyst/Layout/Layout.swift)
  3. Register your layout in the layout manager by adding it to the supported layouts list in Amethyst/Managers/LayoutType.swift (Amethyst/Managers/LayoutType.swift)
  4. Add hotkey bindings for layout selection in Amethyst/Events/HotKeyManager.swift if desired (Amethyst/Events/HotKeyManager.swift)

Add a New Global Hotkey Command

  1. Define the command enum case in Amethyst/Managers/LayoutType.swift or create a new command enum (Amethyst/Managers/LayoutType.swift)
  2. Implement the command logic in Amethyst/Managers/WindowManager.swift as a new method (e.g., focusNextWindow(), shrinkMaster()) (Amethyst/Managers/WindowManager.swift)
  3. Register the hotkey binding and map it to your command in Amethyst/Events/HotKeyManager.swift (Amethyst/Events/HotKeyManager.swift)
  4. Store the binding preference in Amethyst/Managers/HotKeyRegistrar.swift for persistence across sessions (Amethyst/Managers/HotKeyRegistrar.swift)

Extend Window Filtering or Exclusion Logic

  1. Check current window filtering rules in Amethyst/Managers/AppManager.swift (e.g., isManageable) (Amethyst/Managers/AppManager.swift)
  2. Enhance filtering criteria in Amethyst/Categories/NSRunningApplication+Manageable.swift (Amethyst/Categories/NSRunningApplication+Manageable.swift)
  3. Update window reflow logic in Amethyst/Managers/WindowManager.swift to skip windows matching your new criteria (Amethyst/Managers/WindowManager.swift)
  4. Add configuration option in .amethyst.sample.yml if user should control this behavior (.amethyst.sample.yml)

🔧Why these technologies

  • Swift + Cocoa (macOS SDK) — Native macOS development required for accessibility APIs, window introspection, and system integration; Cocoa provides NSRunningApplication, AXUIElement, and accessibility permissions.
  • macOS Accessibility Framework (AXUIElement) — Only API available on macOS to introspect and manipulate windows; requires explicit user permission; essential for reading window frames and repositioning them.
  • Global hotkey registration (Cocoa events) — Necessary for intercepting keyboard shortcuts even when Amethyst is not in focus; enables background tiling operations.
  • Xcode project (not Swift Package Manager) — Supports UI building with XIB files, asset catalogs, app icons, entitlements, and code signing required for macOS app distribution.

⚖️Trade-offs already made

  • Accessibility API for window manipulation instead of custom window server

    • Why: macOS does not expose low-level window server APIs; Accessibility Framework is the only public API.
    • Consequence: Window operations are slower (~50–100ms per window) than xmonad on Linux; subject to system performance and accessibility permissions.
  • Per-screen layout state instead of workspace-aware state

    • Why: Simpler mental model and implementation; aligns with macOS multi-monitor conventions.
    • Consequence: Virtual workspace switching (e.g., Mission Control) requires re-tiling on return; Amethyst cannot track layouts across Space transitions.
  • Hotkey-driven UI instead of mouse-driven tiling

    • Why: Mirrors xmonad philosophy; reduces reliance on pointer precision.
    • Consequence: Steep learning curve for mouse-first macOS users; requires memorizing key bindings.
  • Global focus-follows-mouse optional feature

    • Why: macOS users expect click-to-focus; configurable behavior allows opt-in for power users.
    • Consequence: Adds complexity to focus tracking and FocusTransitionCoordinator logic.

🚫Non-goals (don't propose these)

  • Does not manage floating windows or modal dialogs—Amethyst skips windows without AXWindow role
  • Does not sync layouts across macOS Spaces/Virtual Desktops—per-space state is lost on Space switch
  • Does not provide IDE-style tiling (e.g., vertical split editor panes)—operates at OS window level only
  • Does not work on systems without accessibility permissions enabled—requires user opt

🪤Traps & gotchas

Accessibility permission requirement: Amethyst must be granted Accessibility API access in System Preferences → Security & Privacy → Accessibility; silently fails without it. Space rearrangement conflict: macOS setting 'Automatically rearrange Spaces based on most recent use' (defaults write com.apple.dock workspaces-auto-swoosh) breaks keyboard space navigation; users must disable manually. Window server timing: Accessing window information via Accessibility APIs can be slow/unreliable; see Debug/ folder code for workarounds. Entitlements: AmethystDebug.entitlements vs Amethyst.entitlements suggests debug build needs special permissions; ensure correct one is used for signing.

🏗️Architecture

💡Concepts to learn

  • Tiling Window Manager — Core architectural paradigm — Amethyst's entire design is built around automatically subdividing screen space into non-overlapping tiles per layout algorithm, unlike macOS's default stacking/floating window model
  • Layout Algorithms (Haskell/xmonad style) — Amethyst implements xmonad-compatible layout compositors (tall, wide, fullscreen, grid, etc.); understanding how layouts calculate window geometries from screen dimensions is essential for adding new layouts or debugging window positioning
  • macOS Accessibility API (AXUIElement) — Amethyst's entire window manipulation capability depends on the private/undocumented Accessibility API to observe windows and send window-move/resize commands; permission failures and API stability issues are common pain points
  • Event-Driven Keyboard Hooking — HotKeyManager.swift implements global keyboard event interception without blocking other apps; understanding Carbon Event Manager or modern alternatives is needed to add/modify keybindings
  • Screen Space Topology (Spaces & Displays) — Amethyst manages windows across multiple displays and Spaces (virtual desktops); layout algorithms must account for dynamic screen geometry and Space switching behavior, which conflicts with macOS's Space auto-rearrange feature
  • YAML Configuration Parsing & Hotkey Binding DSL — Amethyst's .amethyst.yml file defines all user customization; understanding how YAML maps to keybindings (mod1/mod2/mod3/mod4 + key combos) is essential for configuration and feature additions
  • koekeishiya/yabai — Modern tiling window manager for macOS with more aggressive window manipulation; direct competitor with larger feature set but steeper learning curve
  • tmux/tmux — Terminal tiling window manager that Amethyst users often combine with for full terminal + GUI tiling workflow
  • xmonad/xmonad — Original Haskell tiling window manager for X11/Linux that Amethyst's layout algorithms and keybindings explicitly mimic; reference implementation for layout semantics
  • ianyh/Amethyst-Debug-CLI — Companion debug CLI tool for Amethyst (mentioned in xcscheme); useful for testing and troubleshooting window manager behavior from terminal

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for Layout engines

The repo has an Amethyst.xctestplan but the file structure shows no visible test files in the Amethyst/ directory for core layout logic. Given that Amethyst is a tiling window manager with multiple layout strategies (mentioned in the xmonad comparison), there should be tests for layout computation, window positioning, and screen management logic. This is critical since layout bugs directly impact user experience.

  • [ ] Create Tests/ directory structure mirroring Amethyst/ source
  • [ ] Add unit tests for Layout protocol implementations (currently no visible test files)
  • [ ] Add tests for ScreenManager and WindowManager coordination in Amethyst/
  • [ ] Reference the existing Amethyst.xctestplan configuration
  • [ ] Test edge cases: empty screens, single window, overlapping display layouts

Add GitHub Action workflow for macOS code signing and notarization

The .github/workflows/tests.yml exists but there's no visible workflow for building signed/notarized binaries for release distribution. Since Amethyst is distributed via Homebrew cask and direct downloads, automating code signing and notarization in CI would prevent manual release bottlenecks and improve security. The Amethyst/ directory contains entitlements files (Amethyst.entitlements, AmethystDebug.entitlements) which suggests this is already configured but not automated.

  • [ ] Review .github/workflows/tests.yml for existing build steps
  • [ ] Create new .github/workflows/release.yml for macOS app signing
  • [ ] Reference Amethyst.entitlements and AmethystDebug.entitlements in workflow
  • [ ] Add notarization step for Gatekeeper compatibility
  • [ ] Configure secrets for Apple Developer certificates in GitHub

Create integration test suite for HotKeyManager and event handling

Amethyst/Events/HotKeyManager.swift handles critical user input for window management, but there are no visible integration tests. Testing hotkey registration, conflict detection, and event propagation across different scenarios (multiple screens, app focus changes) is essential for reliability. This would catch regressions when refactoring input handling.

  • [ ] Create Tests/Events/ directory
  • [ ] Add integration tests in Tests/Events/HotKeyManagerTests.swift
  • [ ] Test hotkey binding, triggering, and modifier key combinations
  • [ ] Test focus change events with NSRunningApplication+Manageable.swift integration
  • [ ] Test screen change scenarios (monitor connect/disconnect) affecting hotkey scope

🌿Good first issues

  • Add unit tests for Categories/NSRunningApplication+Manageable.swift — currently no visible test coverage for window manipulation logic; stub tests should verify that window move/resize operations produce correct geometry
  • Expand Debug/ introspection tools (AppsInfo.swift, ScreensInfo.swift, WindowsInfo.swift) with human-readable output formats (JSON export, pretty-print options) to help users diagnose accessibility issues; currently structure exists but output formatting may be minimal
  • Create comprehensive configuration migration docs and validator for .amethyst.yml — users upgrading between versions may have stale configs; a migration tool that validates and upgrades YAML would reduce support burden

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 34e3562 — Amethyst 0.24.3 (#1852) (ianyh)
  • 86310fb — Take value snapshots instead of dynamic values (#1850) (ianyh)
  • 9d87018 — Amethyst 0.24.2 (#1841) (ianyh)
  • 3299ceb — Fix issues with tab swapping and change distribution (#1831) (ianyh)
  • a18a32b — Add Layouts Submenu to Application Menu (#1804) (rgeraskin)
  • f0f2e46 — add configurable small-window-size threshold (#1833) (aliir74)
  • d943580 — Fix: Stabilize reflow during Space transitions and window tracking order (#1839) (RyoZaizen)
  • d34119c — Pull in Silica memory safety changes (#1829) (ianyh)
  • 40bef89 — Add Hotkeys and HUD for Adjusting Maximum Window Count Setting (#1802) (rgeraskin)
  • 8a48f15 — Add "Open Custom Layouts Folder" button to Layouts preferences (#1805) (rgeraskin)

🔒Security observations

Amethyst is a macOS tiling window manager with moderate security posture. Primary security concerns relate to the privileged nature of the application (Accessibility API access, window management) and the need for proper code signing and entitlements validation. No obvious hardcoded secrets, SQL injection, or XSS vulnerabilities are apparent from the file structure. The main recommendations focus on: (1) ensuring proper code signing and distribution only through verified channels, (2) minimizing and auditing Accessibility API permissions, (3) preventing debug builds from reaching users, and (4) comprehensive input validation for hotkey handling. The lack of visible dependency files (Package.swift, Podfile, etc.) prevents assessment of third-party library vulnerabilities, but overall the architecture suggests a relatively contained system with limited external dependencies.

  • Medium · Missing Code Signing Verification — Amethyst/Amethyst.entitlements, Amethyst/AmethystDebug.entitlements. The application is a macOS window manager with extensive system access (managing windows, keyboard events, screen access). No visible evidence of code signing validation or entitlements review in the provided file structure. The presence of both standard and debug entitlements files suggests different permission levels that should be carefully audited. Fix: Ensure all releases are properly code-signed with a valid Apple Developer certificate. Implement signature verification at runtime. Regularly audit and minimize entitlements to the least privilege required.
  • Medium · Potential Accessibility API Misuse — Amethyst/Categories/NSRunningApplication+Manageable.swift, Amethyst/Events/HotKeyManager.swift. The application manages windows and requires Accessibility API permissions on macOS. Files like NSRunningApplication+Manageable.swift suggest direct manipulation of application windows and events. Improper use of these APIs could allow unauthorized window manipulation or information disclosure. Fix: Implement strict access controls for Accessibility API usage. Validate all window operations. Request only necessary permissions. Document all API interactions and regularly audit for unauthorized access patterns.
  • Low · Configuration File in Repository — .amethyst.sample.yml. Sample configuration file (.amethyst.sample.yml) is present in the repository. While this is a sample file, ensure that no production configuration files with sensitive settings are committed. Fix: Ensure production configuration files are never committed to version control. Use environment variables or secure configuration management for sensitive settings. Document the configuration schema securely.
  • Low · Debug Build Configuration Present — Amethyst/Debug/, Amethyst/AmethystDebug.entitlements. Presence of debug-specific files (Amethyst/Debug/, AmethystDebug.entitlements) indicates debug builds with potentially elevated privileges. Debug builds should not be distributed to end users. Fix: Ensure debug builds are never distributed. Implement build-time checks to prevent debug entitlements in release builds. Use compiler directives to strip debug code from production releases.
  • Low · No Visible Input Validation Documentation — Amethyst/Events/HotKeyManager.swift. The codebase includes keyboard event handling and hot key management, but without visible source code, input validation for these features cannot be verified. Risk of injection attacks if user input is not properly sanitized. Fix: Implement comprehensive input validation for all keyboard and mouse event handlers. Sanitize any user-provided configuration data. Use allowlisting for acceptable key combinations.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · ianyh/Amethyst — RepoPilot