Skip to content
overterm
Documentation

Troubleshooting

The first-open warning, gh, the Metal toolchain, the Xcode versions that build it, and where the logs are.

The problems people actually hit, in the order they hit them.

“Overterm cannot be opened” on the first open

The release build is signed ad hoc and is not notarised — notarisation needs a paid Apple Developer membership the project does not have. macOS therefore refuses a plain double-click the first time.

Right-click Overterm in Applications, choose Open, and confirm. On macOS 15 and newer the dialog may not offer Open at all; go to System Settings → Privacy & Security, scroll to the bottom, and choose Open Anyway.

Or clear the quarantine attribute, which does the same thing:

xattr -dr com.apple.quarantine /Applications/Overterm.app

The keychain asks about Overterm after every update

An ad-hoc signature changes on every build, so macOS treats each build as a different application and asks again — about the keychain, about the microphone, about anything it has granted.

The cure is a stable signing identity. If you build from source, set SIGN_IDENTITY and make install re-signs the installed copy with it:

security find-identity -v -p codesigning     # list what you have
make install SIGN_IDENTITY="Apple Development: you@example.com (XXXXXXXXXX)"

See Build from source.

The pull request pane is empty, or there is no update chip

Both go through your own gh, and both need it logged in:

gh auth status
gh auth login

Overterm holds no token of its own and has no GitHub app. Without gh the pull request pane stays empty, no update chip appears, and nothing else changes.

Note also that gh is looked for in Homebrew’s paths as well as the usual ones — a GUI application’s PATH has none of them — so an unusual install location may not be found.

The microphone, and other privacy prompts

macOS charges whatever a program in the terminal asks for to Overterm, the app it runs in. Overterm therefore declares the microphone, speech recognition and audio capture, so that Claude Code’s /voice prompts you rather than getting silence. The first request asks; System Settings ▸ Privacy & Security is where you change your mind.

The simulator pane asks for nothing at all: it reads the device’s own framebuffer, not the Mac’s screen, so no Screen Recording grant is involved.

Building: metal not found

The terminal is rendered with Metal, so the Metal compiler has to be present. The Command Line Tools alone are not enough, and Xcode 26 downloads it separately:

xcodebuild -downloadComponent MetalToolchain

Building: which Xcode works

Xcode 16 or 26.2. Newer SDKs do not work yet, for two separate reasons:

  • the pinned Zig 0.15.2 cannot link against the macOS 26.5 and 27 SDKs — their libSystem lists only arm64e;
  • Xcode 27’s SwiftPM builds an app macOS then runs in a macOS 13 compatibility mode.

If you have a newer Xcode selected system-wide, point the build at a supported one for the shell only. The system’s choice is untouched:

export DEVELOPER_DIR=/Applications/Xcode-26.2.app/Contents/Developer

It crashes at launch, or has no shell integration

Run it from the bundle, not from a build directory:

./Overterm.app/Contents/MacOS/Overterm     # right
.build/debug/Overterm                      # wrong

A bare binary crashes in the notification centre (“bundleProxy ForCurrentProcess is nil”) and, because libghostty finds its resources by climbing from the executable to Contents/Resources, it has no terminfo and no shell integration either — you get xterm-256color instead of xterm-ghostty, and the prompt marks, command blocks and directory tracking all stop working.

make run and make install both produce a proper bundle.

A key does nothing

Almost always a Ghostty binding holding the key before the menu sees it. Both your own ~/.config/ghostty/config and Ghostty’s defaults count. Open Settings ▸ Keyboard Shortcuts: it reads the live menus, so it shows the key that is actually in force, and binding the command to something free fixes it. See keybindings.json.

If Settings shows a different key than you expect — Settings… as ⌘Ö on a Turkish keyboard, say — that is AppKit localising the key equivalent to your layout while keeping the physical key. The file still says cmd+,.

A divider will not drag

The grab band is over the gap between two cards. If a column seems stuck, check for a stale saved layout from a window with a different number of columns:

defaults delete io.github.overcraft-hq.overterm \
  "NSSplitView Subview Frames OvertermColumns.v5"

A shell looks idle when it is running, or vice versa

Shell integration reports the prompt, and in the first seconds after launch it has not done so yet. Give it a moment.

Diagnostic mode

Overterm has a built-in diagnostic mode that acts only on its own window — useful for reporting a layout problem without describing it. It is only in a build you run yourself from the bundle:

OVERTERM_DUMP_LAYOUT=$PWD/README.md \
OVERTERM_DUMP_PNG=/tmp/overterm.png \
  ./Overterm.app/Contents/MacOS/Overterm

It starts a fresh window — no session restore, no autosave, divider positions neither restored nor saved — opens the file in the editor, prints the view tree with frames and each column’s width to standard error, writes a capture of the composited window (no Screen Recording permission needed), drags both dividers and prints the widths before and after, then exits.

The switches combine:

Variable Does
OVERTERM_DUMP_LAYOUT=<file> the dump itself; an empty value opens no file
OVERTERM_DUMP_PNG=<file> also write a capture of the window
OVERTERM_DUMP_CWD=<dir> start the tab there, for instance in a scratch git repository
OVERTERM_DUMP_DIFF=1 open the changes pane
OVERTERM_DUMP_RENAME=1 start renaming the tab, then report whether it is still renaming
OVERTERM_DUMP_CLOSE=<s> run Close Tab after s seconds and report the confirmation sheet
OVERTERM_DUMP_PEEK=1 open Tab Peek first, and print where each card lands
OVERTERM_DUMP_GROUPS=1 make an island of two tabs first, and print the strip’s islands
OVERTERM_SUPPORT_DIR=<dir> keep all state in that directory instead of the real one

The repository’s own CLAUDE.md still calls these TERMINUS_DUMP_LAYOUT and TERMINUS_E2E. They were renamed with the app; the OVERTERM_ spellings above are the ones the code reads.

Logs

log stream --level debug --predicate \
  'subsystem == "io.github.overcraft-hq.overterm" OR subsystem == "com.mitchellh.ghostty"'

libghostty logs its configuration diagnostics, the resources directory it found — “ghostty terminfo not found” means you are not running from a bundle — shell integration and the renderer.

Crash reports

macOS writes its own to ~/Library/Logs/DiagnosticReports. libghostty also has an embedded crash reporter of its own, which writes to

~/.local/state/ghostty/crash/*.ghosttycrash

Those are local only, and about 800 KB each — worth clearing after a crash-hunting session.

Resetting state

Deleting the right file is often faster than working out what went wrong. Files on disk has the table, including resetting tabs, snippets, history, settings, key bindings and the window layout.