Cormac is a macOS AppKit terminal host that embeds libghostty via a locally built GhosttyKit.xcframework.
Cormac runs unsandboxed (it spawns user shells, like any terminal emulator) with the Hardened Runtime enabled. See SECURITY.md for the full security model, including how agent file access is confined to the workspace.

Vendor/ghostty: source checkout of ghostty-org/ghosttyVendor/ghostty/macos/GhosttyKit.xcframework: native macOS Ghostty binary built from that sourceCormac.xcodeproj: canonical development project for the macOS app, signing, and SwiftUI previewsSources/Cormac: the minimal AppKit host applicationSources/CormacACP: Agent Client Protocol card supportSources/CormacAgentHook: helper used by terminal-agent notification hooksScripts/build-ghosttykit.sh: helper to rebuild the local Ghostty xcframeworkScripts/build-mlx-metallib.sh: helper used by Xcode and the SwiftPM bundler to build mlx.metallibScripts/make-app-bundle.sh: packages the SwiftPM executable as Build/Cormac.app with Ghostty resourcesCormac is currently set up for Apple Silicon macOS development. The project targets macOS 14.0 and Package.swift uses Swift tools 6.2, so use an Xcode release that includes the Swift 6.2 toolchain.
Install the external tools used by the checked-in project and build scripts:
brew install libgit2 zig@0.15
xcode-select points at it:sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
xcrun -sdk macosx metal --version fails, install the component:xcodebuild -downloadComponent MetalToolchain
Package.swift and Cormac.xcodeproj link -lgit2 from /opt/homebrew/opt/libgit2/lib. If Homebrew is installed somewhere else, update the library search paths in both places.Scripts/build-ghosttykit.sh automatically prefers /opt/homebrew/opt/zig@0.15/bin/zig; set ZIG_BIN=/path/to/zig if you need a different install.Rust is not needed for normal Cormac development. Cormac consumes VikerKit 0.1.5 or newer from https://github.com/terhechte/VikerKit.git as a Swift package dependency; VikerKit provides the release-hosted editor engine xcframework and the reusable editor autosuggestion UI.
Clone with submodules:
git clone --recurse-submodules <repo-url>
cd Cormac
If you already cloned without submodules or LFS, fix the checkout in place:
git submodule update --init --recursive
Vendor/ghostty is the only top-level git submodule. SwiftPM dependencies such as VikerKit, MLX, Swift ACP, Markdown UI, and Hugging Face Transformers are resolved later by Xcode or swift build.
Build the native Ghostty library before opening or building Cormac:
./Scripts/build-ghosttykit.sh
This runs Ghostty's Zig build with:
zig build -Demit-xcframework=true -Demit-macos-app=false -Dxcframework-target=native -Doptimize=ReleaseFast
The script also checks that Zig is new enough and that Xcode's Metal compiler is available. The important outputs for Cormac are:
Vendor/ghostty/macos/GhosttyKit.xcframeworkVendor/ghostty/zig-out/share/terminfoVendor/ghostty/zig-out/share/ghosttyRe-run this script when Vendor/ghostty changes or when you need to rebuild the embedded Ghostty binary. You do not need to run it for every Swift edit.
The preferred development flow is Xcode:
open Cormac.xcodeproj
Use the Cormac scheme to build, run, archive, or open SwiftUI previews. Xcode resolves Swift package dependencies into DerivedData automatically on first build.
The Xcode app target has two important run script phases:
Cormac.app/Contents/MacOS/.Scripts/build-mlx-metallib.sh and writes mlx.metallib into the app resources.So for Xcode builds, you do not manually compile the MLX Metal library. Let the build phase do it. The first build after package resolution can take longer because it has to compile the MLX kernels; incremental builds skip the work when the existing mlx.metallib is newer than the kernel sources.
SwiftPM is useful for command-line builds, tests, and local bundling:
./Scripts/build-ghosttykit.sh
swift build
swift test
Bare swift build compiles the Swift products, but it does not produce a complete .app bundle with Ghostty resources. To create a runnable development bundle, use:
./Scripts/make-app-bundle.sh
open Build/Cormac.app
make-app-bundle.sh builds Cormac, builds CormacAgentHook, invokes Scripts/build-mlx-metallib.sh, and copies Ghostty's terminfo and shell-integration resources into the app bundle.
Running the bundled app gives Ghostty access to its terminfo database and shell-integration resources. The package intentionally starts as a single-window, single-surface terminal so it stays small and easy to customize. The host runtime and surface view live in Sources/Cormac/GhosttyRuntime.swift and Sources/Cormac/GhosttySurfaceView.swift.
ld: library 'git2' not found: install libgit2 with brew install libgit2, or update the project/package library search paths if your Homebrew prefix is not /opt/homebrew.Ghostty checkout not found: run git submodule update --init --recursive.zig ... is missing, broken, or older than 0.15.2: run brew install zig@0.15, or set ZIG_BIN to a Zig 0.15.2+ binary.cannot execute tool 'metal' due to missing Metal Toolchain: run xcodebuild -downloadComponent MetalToolchain.MLX Metal kernels not found: let Xcode resolve packages once, or run swift build before calling Scripts/build-mlx-metallib.sh directly.Package.resolved, then rerun swift package resolve.Scripts/release-github.sh archives the Xcode app, extracts Cormac.app, signs it with a Developer ID Application identity, notarizes and staples it, zips the final app, and uploads the zip to a GitHub release with gh.
NOTARY_PROFILE=cormac-notary Scripts/release-github.sh v0.1.0 --draft
The script auto-selects the first valid Developer ID Application identity in the Keychain unless SIGNING_IDENTITY is set, then infers DEVELOPMENT_TEAM from that identity for the Xcode archive step. NOTARY_PROFILE must name a notarytool keychain profile unless --skip-notarize is used. Use --skip-upload to stop after creating Build/Release/Cormac-<tag>.zip.
Cormac supports two different ways to work with AI coding agents.
Terminal cards can run any CLI tool, but Cormac's notification hook integration is currently implemented for claude and codex when they are launched by command name from a Cormac terminal. Enable it in Settings > Agent Alerts > Enable CLI notification hooks, then open a new terminal card and run:
claude
codex
New terminal cards get Cormac-specific environment variables and wrapper directories prepended to PATH. The agent wrapper installs Cormac hooks into the agent's normal config, then launches the real CLI outside the wrapper path. Existing terminal cards keep their old environment, so open a fresh terminal after changing the setting.
Cormac also installs cormac and cedit wrappers inside Cormac's Application Support directory and exposes them to new terminal/ACP agent sessions through their environment. The commands are shell executables, so agents should invoke them through Bash:
cormac browser open https://slashdot.org
cormac browser state
cormac new_web_card --url https://example.com
cormac terminal_insert_text --text "ls -la"
cedit Sources/App.swift
cormac-browser and cormac-action remain available as legacy aliases. ACP coding-agent cards receive this environment directly and do not require personal skill files. Terminal-launched CLI agents can optionally discover the command through cormac skills; that write is disabled by default and must be enabled in Settings > Agent Alerts > Cormac Tool Discovery. When enabled, Cormac writes only under agent config directories that already exist: ~/.claude/skills/cormac/SKILL.md, ~/.codex/skills/cormac/SKILL.md, and ~/.config/opencode/skills/cormac/SKILL.md.
The helper can surface permission prompts, questions, idle/replied events, denied requests, and stop events as notifications and in-app attention highlights. By default Cormac uses macOS banners; enable Settings > Agent Alerts > Use Cormac floating notifications instead of macOS banners to show Cormac's own floating windows for both terminal hooks and ACP cards. Informational floating notifications offer OK to dismiss or Open to bring Cormac forward, select the originating workspace/card/pane, and scroll the card strip to it. Use Settings > Agent Alerts > Show Test Prompt to verify the floating prompt UI.
Current limits:
claude and codex have built-in wrappers.npx, or another wrapper can bypass Cormac's wrapper.ACP cards run agents through the Agent Client Protocol instead of a terminal shell.
Settings > Coding Agents.Refresh Registry to install from the ACP registry, or Add Existing... to point at an ACP executable.File > New Coding Agent... or the command palette entry New Coding Agent....The card launches the ACP client over stdio, creates or loads an ACP session, and renders the transcript natively. Permission requests appear both inside the card and through Cormac's agent attention system. Agent replies can produce a notification/highlight when the turn completes, using either macOS banners or Cormac floating notifications depending on the Agent Alerts delivery setting.
Vim bindings are optional. Enable them in Settings > General > Enable Vim bindings for non-terminal cards. Terminal cards are never intercepted.
Use Ctrl+; to toggle between Insert and Normal mode. In Insert mode, keys pass through to the active card. In Normal mode:
j / k / h / l move or scroll; counts work, such as 5j.gg jumps to the top, G to the bottom, 0 to the left/start, and $ to the right/end.d pages down on navigable cards, and u pages up.Enter activates the current item, i returns to Insert mode, and o focuses a card's primary input when it has one.v enters Visual mode on cards that support selection, and y copies the selected content.Card-specific bindings:
H / L go back/forward, r reloads, and o focuses the address bar.j / k moves the current file/hunk/line selection, s stages, S stashes, x or d discards with confirmation, c comments, y copies the prompt summary, and r refreshes.h goes up a directory, l or Enter opens the selected item, Visual mode selects multiple rows, and y copies selected paths.Enter resets zoom.o or Enter focuses the composer.Swift
94.6%
HTML
2.0%
CSS
1.6%
JavaScript
1.0%
Cormac is a macOS AppKit terminal host that embeds libghostty via a locally built GhosttyKit.xcframework.
Cormac runs unsandboxed (it spawns user shells, like any terminal emulator) with the Hardened Runtime enabled. See SECURITY.md for the full security model, including how agent file access is confined to the workspace.

Vendor/ghostty: source checkout of ghostty-org/ghosttyVendor/ghostty/macos/GhosttyKit.xcframework: native macOS Ghostty binary built from that sourceCormac.xcodeproj: canonical development project for the macOS app, signing, and SwiftUI previewsSources/Cormac: the minimal AppKit host applicationSources/CormacACP: Agent Client Protocol card supportSources/CormacAgentHook: helper used by terminal-agent notification hooksScripts/build-ghosttykit.sh: helper to rebuild the local Ghostty xcframeworkScripts/build-mlx-metallib.sh: helper used by Xcode and the SwiftPM bundler to build mlx.metallibScripts/make-app-bundle.sh: packages the SwiftPM executable as Build/Cormac.app with Ghostty resourcesCormac is currently set up for Apple Silicon macOS development. The project targets macOS 14.0 and Package.swift uses Swift tools 6.2, so use an Xcode release that includes the Swift 6.2 toolchain.
Install the external tools used by the checked-in project and build scripts:
brew install libgit2 zig@0.15
xcode-select points at it:sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
xcrun -sdk macosx metal --version fails, install the component:xcodebuild -downloadComponent MetalToolchain
Package.swift and Cormac.xcodeproj link -lgit2 from /opt/homebrew/opt/libgit2/lib. If Homebrew is installed somewhere else, update the library search paths in both places.Scripts/build-ghosttykit.sh automatically prefers /opt/homebrew/opt/zig@0.15/bin/zig; set ZIG_BIN=/path/to/zig if you need a different install.Rust is not needed for normal Cormac development. Cormac consumes VikerKit 0.1.5 or newer from https://github.com/terhechte/VikerKit.git as a Swift package dependency; VikerKit provides the release-hosted editor engine xcframework and the reusable editor autosuggestion UI.
Clone with submodules:
git clone --recurse-submodules <repo-url>
cd Cormac
If you already cloned without submodules or LFS, fix the checkout in place:
git submodule update --init --recursive
Vendor/ghostty is the only top-level git submodule. SwiftPM dependencies such as VikerKit, MLX, Swift ACP, Markdown UI, and Hugging Face Transformers are resolved later by Xcode or swift build.
Build the native Ghostty library before opening or building Cormac:
./Scripts/build-ghosttykit.sh
This runs Ghostty's Zig build with:
zig build -Demit-xcframework=true -Demit-macos-app=false -Dxcframework-target=native -Doptimize=ReleaseFast
The script also checks that Zig is new enough and that Xcode's Metal compiler is available. The important outputs for Cormac are:
Vendor/ghostty/macos/GhosttyKit.xcframeworkVendor/ghostty/zig-out/share/terminfoVendor/ghostty/zig-out/share/ghosttyRe-run this script when Vendor/ghostty changes or when you need to rebuild the embedded Ghostty binary. You do not need to run it for every Swift edit.
The preferred development flow is Xcode:
open Cormac.xcodeproj
Use the Cormac scheme to build, run, archive, or open SwiftUI previews. Xcode resolves Swift package dependencies into DerivedData automatically on first build.
The Xcode app target has two important run script phases:
Cormac.app/Contents/MacOS/.Scripts/build-mlx-metallib.sh and writes mlx.metallib into the app resources.So for Xcode builds, you do not manually compile the MLX Metal library. Let the build phase do it. The first build after package resolution can take longer because it has to compile the MLX kernels; incremental builds skip the work when the existing mlx.metallib is newer than the kernel sources.
SwiftPM is useful for command-line builds, tests, and local bundling:
./Scripts/build-ghosttykit.sh
swift build
swift test
Bare swift build compiles the Swift products, but it does not produce a complete .app bundle with Ghostty resources. To create a runnable development bundle, use:
./Scripts/make-app-bundle.sh
open Build/Cormac.app
make-app-bundle.sh builds Cormac, builds CormacAgentHook, invokes Scripts/build-mlx-metallib.sh, and copies Ghostty's terminfo and shell-integration resources into the app bundle.
Running the bundled app gives Ghostty access to its terminfo database and shell-integration resources. The package intentionally starts as a single-window, single-surface terminal so it stays small and easy to customize. The host runtime and surface view live in Sources/Cormac/GhosttyRuntime.swift and Sources/Cormac/GhosttySurfaceView.swift.
ld: library 'git2' not found: install libgit2 with brew install libgit2, or update the project/package library search paths if your Homebrew prefix is not /opt/homebrew.Ghostty checkout not found: run git submodule update --init --recursive.zig ... is missing, broken, or older than 0.15.2: run brew install zig@0.15, or set ZIG_BIN to a Zig 0.15.2+ binary.cannot execute tool 'metal' due to missing Metal Toolchain: run xcodebuild -downloadComponent MetalToolchain.MLX Metal kernels not found: let Xcode resolve packages once, or run swift build before calling Scripts/build-mlx-metallib.sh directly.Package.resolved, then rerun swift package resolve.Scripts/release-github.sh archives the Xcode app, extracts Cormac.app, signs it with a Developer ID Application identity, notarizes and staples it, zips the final app, and uploads the zip to a GitHub release with gh.
NOTARY_PROFILE=cormac-notary Scripts/release-github.sh v0.1.0 --draft
The script auto-selects the first valid Developer ID Application identity in the Keychain unless SIGNING_IDENTITY is set, then infers DEVELOPMENT_TEAM from that identity for the Xcode archive step. NOTARY_PROFILE must name a notarytool keychain profile unless --skip-notarize is used. Use --skip-upload to stop after creating Build/Release/Cormac-<tag>.zip.
Cormac supports two different ways to work with AI coding agents.
Terminal cards can run any CLI tool, but Cormac's notification hook integration is currently implemented for claude and codex when they are launched by command name from a Cormac terminal. Enable it in Settings > Agent Alerts > Enable CLI notification hooks, then open a new terminal card and run:
claude
codex
New terminal cards get Cormac-specific environment variables and wrapper directories prepended to PATH. The agent wrapper installs Cormac hooks into the agent's normal config, then launches the real CLI outside the wrapper path. Existing terminal cards keep their old environment, so open a fresh terminal after changing the setting.
Cormac also installs cormac and cedit wrappers inside Cormac's Application Support directory and exposes them to new terminal/ACP agent sessions through their environment. The commands are shell executables, so agents should invoke them through Bash:
cormac browser open https://slashdot.org
cormac browser state
cormac new_web_card --url https://example.com
cormac terminal_insert_text --text "ls -la"
cedit Sources/App.swift
cormac-browser and cormac-action remain available as legacy aliases. ACP coding-agent cards receive this environment directly and do not require personal skill files. Terminal-launched CLI agents can optionally discover the command through cormac skills; that write is disabled by default and must be enabled in Settings > Agent Alerts > Cormac Tool Discovery. When enabled, Cormac writes only under agent config directories that already exist: ~/.claude/skills/cormac/SKILL.md, ~/.codex/skills/cormac/SKILL.md, and ~/.config/opencode/skills/cormac/SKILL.md.
The helper can surface permission prompts, questions, idle/replied events, denied requests, and stop events as notifications and in-app attention highlights. By default Cormac uses macOS banners; enable Settings > Agent Alerts > Use Cormac floating notifications instead of macOS banners to show Cormac's own floating windows for both terminal hooks and ACP cards. Informational floating notifications offer OK to dismiss or Open to bring Cormac forward, select the originating workspace/card/pane, and scroll the card strip to it. Use Settings > Agent Alerts > Show Test Prompt to verify the floating prompt UI.
Current limits:
claude and codex have built-in wrappers.npx, or another wrapper can bypass Cormac's wrapper.ACP cards run agents through the Agent Client Protocol instead of a terminal shell.
Settings > Coding Agents.Refresh Registry to install from the ACP registry, or Add Existing... to point at an ACP executable.File > New Coding Agent... or the command palette entry New Coding Agent....The card launches the ACP client over stdio, creates or loads an ACP session, and renders the transcript natively. Permission requests appear both inside the card and through Cormac's agent attention system. Agent replies can produce a notification/highlight when the turn completes, using either macOS banners or Cormac floating notifications depending on the Agent Alerts delivery setting.
Vim bindings are optional. Enable them in Settings > General > Enable Vim bindings for non-terminal cards. Terminal cards are never intercepted.
Use Ctrl+; to toggle between Insert and Normal mode. In Insert mode, keys pass through to the active card. In Normal mode:
j / k / h / l move or scroll; counts work, such as 5j.gg jumps to the top, G to the bottom, 0 to the left/start, and $ to the right/end.d pages down on navigable cards, and u pages up.Enter activates the current item, i returns to Insert mode, and o focuses a card's primary input when it has one.v enters Visual mode on cards that support selection, and y copies the selected content.Card-specific bindings:
H / L go back/forward, r reloads, and o focuses the address bar.j / k moves the current file/hunk/line selection, s stages, S stashes, x or d discards with confirmation, c comments, y copies the prompt summary, and r refreshes.h goes up a directory, l or Enter opens the selected item, Visual mode selects multiple rows, and y copies selected paths.Enter resets zoom.o or Enter focuses the composer.Swift
94.6%
HTML
2.0%
CSS
1.6%
JavaScript
1.0%