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
libSystemlists onlyarm64e; - 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.