danneu/danterm

a fast macOS terminal in pure swift

5

stars

2,880

commits

Swift

primary language

Sep 4, 2026

updated

macos
swift
terminal-emulator

README

DanTerm icon danterm

danterm is a fast macOS terminal built in Swift with no third-party dependencies.

DanTerm screenshot

Why?

I like vertical tabs, which for years meant using iTerm2 on macOS.

In the LLM era the terminal is becoming more and more central to my workflow, not less. So, I decided to build my own to satisfy my own preferences.

It runs on its own Swift terminal engine -- grid, parser, renderer, and pty, with no third-party dependencies. It started as an AppKit wrapper around libghostty, but LLMs made writing the engine itself tractable, and the project doubles as a testbed for automating high-quality software with AI.

Ideals

  • Everything should be both keyboard- and mouse-driven
  • The terminal engine should be reusable outside of danterm, embeddable by other projects
  • Cross-platform

Features

  • Vertical tabs
  • Split panes that inherit the current working directory
  • Persistent pane alerts and macOS notifications (click a notification to focus its pane)
  • Local and remote color themes
  • Save, restore, and crash-recover tabs, panes, and the commands running in them
  • Semantic pane states ("idle", "running command (make test)", "running agent claude (busy)") reported by shell and agent integrations
  • Full control via danterm command-line interface for scripts and coding agents
  • Remote IPC over a Tailscale tailnet (docs)
  • Config file
  • Drive danterm running on macOS machine over Tailnet via iPhone app (Experimental)
  • Linux GTK4 app (WIP)
  • And much more

Performance

Measured on a MacBookPro18,1 running macOS 26.5.2. Every terminal ran at 170x60 in Menlo 13.

Throughput

kitten __benchmark__ --render, 3 reps, median MB/s as the kitten reported it.

Testdantermghostty 1.3.1iterm2 3.6.6kitty 0.48.2
Only ASCII chars127.287.912.7105.5
Unicode chars135.3113.56.6103.5
Unique multi-codepoint Unicode cells53.347.11.123.0
CSI codes with few chars47.541.41.359.3

The kitten times parsing, not rendering: terminals render asynchronously, and --render only stops them from being asked not to.

Memory

10 tabs, each running an inert sleep. Activity Monitor phys_footprint, sampled every second for 10 seconds after a 5 second settle, median reported. One rep, so read these as a rough ranking rather than a precise number.

Terminal10 empty tabs10 tabs with scrollback
danterm57 MB248 MB
iterm2 3.6.6167 MB564 MB
kitty 0.48.2239 MB788 MB
ghostty 1.3.1793 MB1424 MB

The scrollback case writes 10000 full-width lines per tab. iTerm2 and kitty were capped at 10000 lines. danterm and Ghostty bound scrollback by bytes instead of lines: danterm at 16 MB per pane (it kept all 10004 rows), Ghostty at 10 MB per surface (retention not readable).

Install

Requires macOS 26 on Apple Silicon.

Download the latest .dmg from GitHub Releases, then move DanTerm to /Applications. Releases are Developer ID signed and notarized, and the whole app is an 8 MB download.

If your shell tools need them, grant DanTerm Full Disk Access and Developer Tools in System Settings under Privacy & Security.

Nix

DanTerm ships a flake and a Home Manager module: docs/integrations/nix.md.

Configure

Press Cmd+, to edit ~/.config/danterm/config.json, Cmd+Shift+, to reload it. Every setting has a default, so a new config file holds only {"schemaVersion": 1}.

KeyDefaultMeaning
font.familysystem monospaceTerminal font family. Omit the key to keep the system font.
font.size13Terminal font size, in points. Bounded to 8 through 72.
keyboard.optionAsAltnativeUse "left", "right", or "both" to send that physical Option key as terminal Alt. Omit the key for native macOS text input.
theme.default"Monokai Remastered"Theme for local panes.
theme.remote"Purplepeter"Theme for panes in an SSH or other remote session.
shell.localeFallbacktrueGive a local pane a UTF-8 LANG when it inherits none.
tailnet.listenabsentTailnet endpoint for remote IPC. See docs/tailnet.md.
tailnet.admittedNodeIdsabsentTailscale node ids allowed to use remote IPC. See docs/tailnet.md.
tailnet.enabletrueSet to false to keep the tailnet settings on disk with the listener closed.
ui.alertClearMode"focus""focus" clears pane alerts on focus, "manual" keeps them until you dismiss them.
ui.copyOnSelecttrueCopy a mouse selection to the clipboard when it finishes.
ui.unfocusedPaneOpacity1Opacity of every pane except its tab's focused one. Bounded to 0.1 through 1; 1 dims nothing.

Nix users can point this file at a dotfiles repository so app edits survive a rebuild: docs/integrations/nix.md.

Integrations

DanTerm is a plain terminal to everything you run in it. These are the tools it does something extra with, or that need a setting to work well with it.

ToolWhat DanTerm does with itSetup
zsh, bash, fishTracks cwd, running command, and prompt marks per paneshells.md
SSH, moshRemote theme and a user@host label on remote panesssh.md
tmuxNeeds two settings, or it eats notifications and invents otherstmux.md
Claude CodePane-control skill, plus notifications that name their paneclaude-code.md
CodexPane-control skill, plus notifications that name their panecodex.md
Nix, Home ManagerFlake and programs.danterm modulenix.md
DanTerm for iOSDrives a pane over a Tailscale tailnettailnet.md

A tool earns a page here when DanTerm ships code for it, or when DanTerm's behavior with it differs from a plain terminal's. Everything else just works and needs no page.

danterm doctor  # Check permissions, CLI, hooks, skills, jq, and configured font.

Shortcuts

ActionShortcut
New tabCmd+T
Close paneCmd+W
Close tabCmd+Shift+W
Split rightCmd+D
Split downCmd+Shift+D
Focus panesCmd+Shift+H/J/K/L
Zoom paneCmd+Enter
Theme browserCmd+Shift+B
Next alertCmd+Shift+A
Clear pane alertsCmd+Shift+.
PreferencesCmd+,
Reload configCmd+Shift+,

The app menus list all shortcuts. Rebind them in Settings > Key Bindings or the config file: docs/keybindings.md.

Command-line interface

danterm ls
danterm tab new --cmd 'just test'
danterm pane split -h
danterm pane read --pane "$DANTERM_PANE" --lines 50

See integrations/danterm/SKILL.md for all commands and examples, and the terminal capability contract for terminal behavior.

Develop

bash ./dev-build.sh --no-install  # Build without replacing an installed app.
just provision-worktree           # Run once in a new Git worktree.
just launch-slot                  # Run an isolated development copy.
just test                         # Run the test suite.

License

MIT

Contributors

danneu

2,771 commits

danneu/danterm

a fast macOS terminal in pure swift

5

stars

2,880

commits

Swift

primary language

Sep 4, 2026

updated

macos
swift
terminal-emulator

README

DanTerm icon danterm

danterm is a fast macOS terminal built in Swift with no third-party dependencies.

DanTerm screenshot

Why?

I like vertical tabs, which for years meant using iTerm2 on macOS.

In the LLM era the terminal is becoming more and more central to my workflow, not less. So, I decided to build my own to satisfy my own preferences.

It runs on its own Swift terminal engine -- grid, parser, renderer, and pty, with no third-party dependencies. It started as an AppKit wrapper around libghostty, but LLMs made writing the engine itself tractable, and the project doubles as a testbed for automating high-quality software with AI.

Ideals

  • Everything should be both keyboard- and mouse-driven
  • The terminal engine should be reusable outside of danterm, embeddable by other projects
  • Cross-platform

Features

  • Vertical tabs
  • Split panes that inherit the current working directory
  • Persistent pane alerts and macOS notifications (click a notification to focus its pane)
  • Local and remote color themes
  • Save, restore, and crash-recover tabs, panes, and the commands running in them
  • Semantic pane states ("idle", "running command (make test)", "running agent claude (busy)") reported by shell and agent integrations
  • Full control via danterm command-line interface for scripts and coding agents
  • Remote IPC over a Tailscale tailnet (docs)
  • Config file
  • Drive danterm running on macOS machine over Tailnet via iPhone app (Experimental)
  • Linux GTK4 app (WIP)
  • And much more

Performance

Measured on a MacBookPro18,1 running macOS 26.5.2. Every terminal ran at 170x60 in Menlo 13.

Throughput

kitten __benchmark__ --render, 3 reps, median MB/s as the kitten reported it.

Testdantermghostty 1.3.1iterm2 3.6.6kitty 0.48.2
Only ASCII chars127.287.912.7105.5
Unicode chars135.3113.56.6103.5
Unique multi-codepoint Unicode cells53.347.11.123.0
CSI codes with few chars47.541.41.359.3

The kitten times parsing, not rendering: terminals render asynchronously, and --render only stops them from being asked not to.

Memory

10 tabs, each running an inert sleep. Activity Monitor phys_footprint, sampled every second for 10 seconds after a 5 second settle, median reported. One rep, so read these as a rough ranking rather than a precise number.

Terminal10 empty tabs10 tabs with scrollback
danterm57 MB248 MB
iterm2 3.6.6167 MB564 MB
kitty 0.48.2239 MB788 MB
ghostty 1.3.1793 MB1424 MB

The scrollback case writes 10000 full-width lines per tab. iTerm2 and kitty were capped at 10000 lines. danterm and Ghostty bound scrollback by bytes instead of lines: danterm at 16 MB per pane (it kept all 10004 rows), Ghostty at 10 MB per surface (retention not readable).

Install

Requires macOS 26 on Apple Silicon.

Download the latest .dmg from GitHub Releases, then move DanTerm to /Applications. Releases are Developer ID signed and notarized, and the whole app is an 8 MB download.

If your shell tools need them, grant DanTerm Full Disk Access and Developer Tools in System Settings under Privacy & Security.

Nix

DanTerm ships a flake and a Home Manager module: docs/integrations/nix.md.

Configure

Press Cmd+, to edit ~/.config/danterm/config.json, Cmd+Shift+, to reload it. Every setting has a default, so a new config file holds only {"schemaVersion": 1}.

KeyDefaultMeaning
font.familysystem monospaceTerminal font family. Omit the key to keep the system font.
font.size13Terminal font size, in points. Bounded to 8 through 72.
keyboard.optionAsAltnativeUse "left", "right", or "both" to send that physical Option key as terminal Alt. Omit the key for native macOS text input.
theme.default"Monokai Remastered"Theme for local panes.
theme.remote"Purplepeter"Theme for panes in an SSH or other remote session.
shell.localeFallbacktrueGive a local pane a UTF-8 LANG when it inherits none.
tailnet.listenabsentTailnet endpoint for remote IPC. See docs/tailnet.md.
tailnet.admittedNodeIdsabsentTailscale node ids allowed to use remote IPC. See docs/tailnet.md.
tailnet.enabletrueSet to false to keep the tailnet settings on disk with the listener closed.
ui.alertClearMode"focus""focus" clears pane alerts on focus, "manual" keeps them until you dismiss them.
ui.copyOnSelecttrueCopy a mouse selection to the clipboard when it finishes.
ui.unfocusedPaneOpacity1Opacity of every pane except its tab's focused one. Bounded to 0.1 through 1; 1 dims nothing.

Nix users can point this file at a dotfiles repository so app edits survive a rebuild: docs/integrations/nix.md.

Integrations

DanTerm is a plain terminal to everything you run in it. These are the tools it does something extra with, or that need a setting to work well with it.

ToolWhat DanTerm does with itSetup
zsh, bash, fishTracks cwd, running command, and prompt marks per paneshells.md
SSH, moshRemote theme and a user@host label on remote panesssh.md
tmuxNeeds two settings, or it eats notifications and invents otherstmux.md
Claude CodePane-control skill, plus notifications that name their paneclaude-code.md
CodexPane-control skill, plus notifications that name their panecodex.md
Nix, Home ManagerFlake and programs.danterm modulenix.md
DanTerm for iOSDrives a pane over a Tailscale tailnettailnet.md

A tool earns a page here when DanTerm ships code for it, or when DanTerm's behavior with it differs from a plain terminal's. Everything else just works and needs no page.

danterm doctor  # Check permissions, CLI, hooks, skills, jq, and configured font.

Shortcuts

ActionShortcut
New tabCmd+T
Close paneCmd+W
Close tabCmd+Shift+W
Split rightCmd+D
Split downCmd+Shift+D
Focus panesCmd+Shift+H/J/K/L
Zoom paneCmd+Enter
Theme browserCmd+Shift+B
Next alertCmd+Shift+A
Clear pane alertsCmd+Shift+.
PreferencesCmd+,
Reload configCmd+Shift+,

The app menus list all shortcuts. Rebind them in Settings > Key Bindings or the config file: docs/keybindings.md.

Command-line interface

danterm ls
danterm tab new --cmd 'just test'
danterm pane split -h
danterm pane read --pane "$DANTERM_PANE" --lines 50

See integrations/danterm/SKILL.md for all commands and examples, and the terminal capability contract for terminal behavior.

Develop

bash ./dev-build.sh --no-install  # Build without replacing an installed app.
just provision-worktree           # Run once in a new Git worktree.
just launch-slot                  # Run an isolated development copy.
just test                         # Run the test suite.

License

MIT

See what people are saying

Contributors

danneu

2,771 commits

Languages

Swift

82.2%

Python

12.2%

Shell

5.0%