Skip to content
simotaPublic

About

GPU-accelerated terminal emulator for macOS, independently implemented in Rust with winit and wgpu, aiming for observable Ghostty compatibility.

Topics

Resources

Stars

6 stars

Watchers

0 watching

Forks

Repository files navigation

Noa

Noa

Noa is a GPU-accelerated terminal emulator for macOS and Linux, implemented independently in Rust with winit and wgpu. It is built to be the fastest terminal at swallowing output floods — cat huge.log, build logs, CI streams — and aims for observable compatibility with Ghostty while keeping the core terminal model reusable and testable.

Noa is under active development and is currently built from source. The macOS app bundle targets macOS 13 or later. Fixture-based regression tests cover terminal behavior; automated differential comparison against Ghostty is still planned.

Quick start

Use a current stable Rust toolchain with Rust 2024 edition support.

cargo run -p noa

To build a double-clickable macOS app:

scripts/bundle-macos.sh
open target/release/Noa.app

The bundle script creates a local ad-hoc-signed app. It is not a notarized distribution workflow.

Install with Homebrew

Noa currently supports Apple Silicon Macs. Install the cask from this source repository as a custom tap:

brew tap simota/noa https://github.com/simota/Noa.git
brew install --cask simota/noa/noa

Installation requires a GitHub Release for the version declared in Casks/noa.rb, containing Noa-<version>-macos-arm64.zip. Maintainers create it by pushing a v<workspace-version> tag; the release workflow verifies that the Cargo, Cask, tag, and app-bundle versions match before publishing the archive and its SHA-256 checksum.

The cask temporarily uses sha256 :no_check because no release archive exists yet. Replace it with the published checksum after the first release. Release artifacts are Developer ID signed and notarized for a prompt-free Gatekeeper experience after download when the signing secrets are configured; without them the workflow falls back to ad-hoc signing. See docs/release-signing.md for the required secrets and local testing steps.

Linux

Noa also builds and runs on Linux (X11 and Wayland); see docs/LINUX.md for the full guide. Ghostty's Linux (GTK) keybindings are the defaults — ctrl+shift+c/ctrl+shift+v copy and paste, ctrl+shift+t opens a tab, ctrl+shift+p opens the command palette.

Build dependencies (Debian/Ubuntu names):

sudo apt install build-essential pkg-config libfontconfig1-dev libfreetype-dev \
  libxkbcommon-dev libwayland-dev

At runtime Noa needs a Vulkan driver (Mesa or a vendor driver) or OpenGL ES as a fallback, and loads X11/Wayland and libxkbcommon dynamically. Fonts come from fontconfig: the default is the first installed of JetBrains Mono, DejaVu Sans Mono, Noto Sans Mono, Ubuntu Mono, and Liberation Mono (then the generic monospace alias), with fontconfig fallback for CJK, emoji, and symbols.

To build a tarball with the desktop entry, AppStream metadata, and icons, and install it into ~/.local (or any prefix):

scripts/package-linux.sh
tar -xzf target/release/Noa-*-linux-*.tar.gz -C /tmp
/tmp/Noa-*-linux-*/install.sh                  # or: --prefix /usr/local
/tmp/Noa-*-linux-*/install.sh --uninstall      # remove again

Tagged releases also publish Noa-<version>-linux-x86_64.tar.gz with the same layout. The window's Wayland app id / X11 WM_CLASS is com.simota.noa.

Desktop integration uses standard tools: clipboard and the PRIMARY selection (copy-on-select, middle-click paste), xdg-open for links and files, notify-send for desktop notifications, and canberra-gtk-play (when installed) for the audible bell. Linux limitations compared to macOS:

  • quick-terminal-hotkey is not registered system-wide (Wayland offers no global-shortcut API to applications); a toggle_quick_terminal keybinding works while a Noa window is focused.
  • macOS-only integrations are absent: the menu bar and Ember, AppleScript, Dock badges, background blur, and the native AppKit overlay cards (the command palette and dialogs are drawn by the GPU renderer instead).
  • File previews open in your editor instead of a native text panel.
  • Encrypted scrollback persistence needs the macOS Keychain, so restored sessions come back without their scrollback.

Releasing

Maintainers can validate and publish the version declared in Cargo.toml and Casks/noa.rb with the release script:

scripts/release.sh --dry-run
scripts/release.sh

The script requires a clean main branch that exactly matches origin/main, runs formatting, locked workspace build, and locked workspace tests, then asks for confirmation before creating and pushing the matching v<version> tag. Use scripts/release.sh --yes only for trusted non-interactive automation.

If an invalid release must be withdrawn before users depend on it, delete the GitHub Release first, then its remote and local tags:

gh release delete v0.1.0 --repo simota/Noa --yes
git push origin :refs/tags/v0.1.0
git tag -d v0.1.0

Performance

Noa's defining trait is sustained output throughput: render throughput of 220–233 MB/s across plain, ANSI, and CJK workloads, with CJK as the fastest variant — wide-character handling carries no cost. Command overhead (1336 µs, zsh), idle input latency (1.2–1.3 ms), and settled idle memory (52 MB) round out the profile.

Every number is reproducible with the bundled benchmark harness (bench/run_all.sh), and performance changes are gated on it. See Positioning for the full claim and Methodology for how the numbers are measured.

Key features

  • GPU-rendered terminal grid with Kitty graphics support
  • Tabs, splits, multiple windows, session restore, and a quick terminal
  • DEC/ANSI VT handling, Kitty keyboard protocol, shell integration, and search
  • Font fallback, ligatures, background images, opacity, and blur
  • Ghostty-compatible configuration, live reload, and 574 bundled themes
  • macOS menus, command palette, notifications, and secure keyboard entry

See Features for the complete feature inventory.

Configuration

Noa reads its configuration from $XDG_CONFIG_HOME/noa/config, or ~/.config/noa/config when XDG_CONFIG_HOME is unset. CLI flags override file values.

window-width = 100
window-height = 30
font-size = 15.0
theme = "Catppuccin Mocha"

Useful one-shot queries include +version, +list-themes, +list-keybinds, +list-fonts, +show-config, +list-actions, and +help.

Importing a Ghostty configuration

From a source checkout, run:

cargo run -p noa -- --import-ghostty-config

For a Homebrew installation in /Applications, run the executable inside the app bundle:

/Applications/Noa.app/Contents/MacOS/Noa --import-ghostty-config

Noa imports every existing Ghostty configuration candidate in this order:

  1. $XDG_CONFIG_HOME/ghostty/config.ghostty
  2. $XDG_CONFIG_HOME/ghostty/config
  3. ~/Library/Application Support/com.mitchellh.ghostty/config.ghostty
  4. ~/Library/Application Support/com.mitchellh.ghostty/config

When XDG_CONFIG_HOME is unset or empty, the first two paths use ~/.config instead. The generated Noa configuration is $XDG_CONFIG_HOME/noa/config, or ~/.config/noa/config when the variable is unset or empty.

Lines whose keys are supported scalar settings, plus keybind lines, are copied unchanged. Non-comment lines that cannot be parsed as directives, and directives whose keys are unsupported, are retained as comments; existing comments and blank lines are preserved. In particular, config-file directives are commented out and their referenced files are not followed. When multiple candidates exist, their contents are appended in the order above, so later scalar values take precedence and keybind lines retain that order. The import refuses to overwrite an existing Noa configuration. Back up or rename the existing file before retrying if replacement is intended.

See the Configuration reference for supported keys and defaults, and Keybindings for shortcuts and actions.

Compatibility and limitations

Noa is an independent reimplementation and does not include or link Ghostty source code. Compatibility work focuses on observable terminal behavior rather than source-level equivalence.

  • The application is macOS-first; Linux is supported with the limitations listed under Linux.
  • Current parity protection is fixture-based; the automated Ghostty oracle is not implemented yet.
  • Some advanced terminal behavior may still differ from Ghostty.
  • Installation is available from source; the custom Homebrew tap becomes usable after a matching release is published.

See the parity harness and parity roadmap for current coverage and planned work.

Development

cargo build --workspace
cargo test --workspace
cargo fmt --all

Noa is a Cargo workspace. noa-vt and noa-grid implement the terminal parser and state model without windowing dependencies. noa-render owns GPU rendering, while noa-app owns the winit event loop and macOS integration. The binary in bin/noa is a thin entry point.

Dependency boundaries are intentional: only noa-app and noa-render use wgpu, and only noa-app uses winit.

License

MIT. See LICENSE.

About

GPU-accelerated terminal emulator for macOS, independently implemented in Rust with winit and wgpu, aiming for observable Ghostty compatibility.

Topics

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages