Shell Pilot 1.16.0
August 28, 2026
If you are on 1.15.1, please install this manually
In-app updating was broken in 1.15.1 and cannot fix itself. Releases through 1.15.1 were built in the Debug configuration, which embeds Apple's XCTest frameworks inside the shipped app. Those frameworks fail codesign --verify --deep --strict, which is exactly the check the updater runs on a downloaded build before installing it — so every update attempt aborted. The failure was written to a log that nothing displayed, so the app simply quit, reopened unchanged, and said nothing.
1.16.0 is built in Release, signed, and verified before packaging, so updating works again from this version onward. Getting here needs one manual download. As a side benefit the app is now 6.1 MB instead of 15.1 MB — the test frameworks were roughly 60% of the download.
Five features were switched off in every install
Command tracking had been gated behind an environment variable that nothing ever set, disabled in 1.14.3 to remove a base64 subprocess that ran on every command. That variable is what tells the app which command you are typing, so with it unset the app's headline features never ran at all:
- Autocomplete suggestions — the history-based overlay never appeared
- Semantic
# search — never appeared
- Inline command help — never appeared
- Man page auto-show, and the ⌘⇧M menu item, which was also a no-op
- Smart session auto-rename — the analyzer never received a single command
Tracking is now on by default and the subprocess is gone for good: commands are percent-encoded inside zsh itself, so the shell forks nothing per command. If you want it off, set SHELL_PILOT_DISABLE_COMMAND_TRACKING=1.
Crashes and hangs
- Fixed a hang that would have frozen the app on your first command containing a space. The auto-rename analyzer collapsed whitespace by replacing one regex match at a time with a single space — but a lone space is itself a match, so it rewrote its own replacement forever and pinned the main thread. It was unreachable while auto-rename was dead; turning tracking back on would have made it reachable immediately.
- Fixed a crash when closing the window after the app had been in the background. The metrics sampler cancelled its timer without resuming it first, which traps in GCD.
Shell integration
- Nested shells work again. The bootstrap's "already loaded" guard was exported, so any child zsh —
zsh, sudo -s, a tmux pane — re-entered the startup file, saw the guard, and bailed out. Inside that shell there was no directory tracking, no SSH detection and no key bindings, so cd silently stopped updating the sidebar and file tree until you exited.
- The app no longer writes its own install path into your shell startup file. It baked an absolute path into
~/Library/Application Support/Shell Pilot/zsh-startup/.zshrc, which meant whichever copy of the app launched last owned the configuration for every copy — and if the app was moved or deleted, integration silently vanished with no error. The path is now resolved at launch, and a missing script prints a real warning.
- Shell Pilot's own terminal control sequences now carry a per-launch token, so ordinary output —
cat of a file, text from a remote host — can no longer forge command-tracking events.
Autocomplete
- The model now actually learns from what you type. The incremental training and working-directory hooks existed but were never called, so the model only refreshed from your history file on a five-minute timer and directory-aware ranking never ran at all.
- Full retraining used to stamp every historical command with your current directory, which would have poisoned ranking the moment directory awareness started working.
- Directory-aware ranking now works for single-token commands, which were looking up a key that training never wrote.
- Suggestions no longer reshuffle between identical queries. Query expansion returned an unordered set, and Swift seeds hash tables per instance, so the same query could return different results and even different match types within one session.
- Weak suggestions are no longer presented alongside strong ones, and duplicates are actually removed.
- You can now turn suggestions off in Settings.
Interaction
- Find in scrollback (⌘F) — search your terminal history with match counts, next/previous, and case sensitivity. Matches are highlighted and scrolled into view.
- Session keyboard shortcuts — ⌘T for a new session, ⌘W to close (with confirmation if something is running), ⌘1–⌘9 to jump directly, ⌘⇧[ and ⌘⇧] to cycle. Closing the window moves to ⌘⇧W, matching Terminal.app.
- The suggestion overlay no longer takes keyboard focus from the terminal. It grabbed first-responder status to handle arrow keys, and with two lists on screen both grabbed it at once — a strong suspect for the intermittent input loss that caused a feature to be pulled in 1.13.4.
- ⌘+ and ⌘⇧+ resolved to the same physical key on a US layout, so one of the two font-size commands was unreachable. They are now ⌘= / ⌘- and ⌘⇧= / ⌘⇧-.
- Opening a second copy of the app no longer silently overwrites the first copy's session list.
Interface
- The current-directory label in the toolbar was being crushed to a two-pixel sliver that read as a rendering glitch. It now holds a minimum width, truncates in the middle, and shows the full path on hover.
- The file tree now uses the whole sidebar. It was a 240-point scroll view nested inside the sidebar's own scroll view, so the two fought over every gesture while hundreds of points sat empty below it.
- The file tree can drive the terminal — right-click or double-click a folder for "Open in Terminal", or right-click a file for "Insert Path".
- The metrics footer now names what it is measuring (the selected session's process tree), reads as idle rather than broken when nothing is happening, and explains what "Energy Impact" estimates.
- A failed update now tells you it failed instead of saying nothing.
Session auto-rename
- Ticket IDs are preserved exactly — a session is named "Committing PROJ-1234", not "Committing Proj 1234".
- Subcommands are no longer mistaken for subjects. Sessions were being named "Syncing Status" and "Cluster Ops Describe" from
git status and kubectl describe svc api; the command's own grammar is now skipped so the name reflects what you are working on.
Under the hood
- Build warnings went from 20 to 1, including every Swift 6 concurrency error in the autocomplete stack. Model training genuinely runs off the main thread now instead of merely appearing to.
- Running the test suite used to overwrite your real toolbar shortcuts — the store read and wrote live app preferences even when tests injected their own storage. Three tests also touched the real Keychain and could clear a valid license.
- The test suite went from 183 runnable tests with 2 failures to 204 passing. 21 tests could not run at all because of the hang above.
- The release process now refuses to ship a build that contains test frameworks, fails signature verification, or has the wrong bundle identifier.
Known limitations
- The app is signed but not notarized, so a first install still shows a Gatekeeper prompt.
- Remote directory listings over SSH are not covered by the new control-sequence token, because the remote host has no way to learn it. Terminal output can still spoof "this session is on SSH" and fake a remote file listing; it cannot forge command tracking.
- License activation still has no interface in the app. That work is scheduled separately.