ai-workbench: From Claude Cockpit to Backend Switcher
Three months of development on a terminal multiplexer – interchangeable AI backends, multi-line input, and a security release that took a feature with it.
At the end of July, we closed a security vulnerability in ai-workbench and in the process disabled pulling. Not with an error message – the feature was simply no longer accessible. It was noticed only during a review a week later. This is representative of the last three months on the terminal multiplexer: more choices, less friction, and the realization that securing things is rarely free.
TL;DR: ai-workbench replaces the predecessor project claude-workbench in July and has since supported six AI backends instead of one. In between: multi-line input in the AI area, signed release archives, a startup screen without waiting time – and a security release that flipped two default settings.
June: What the original still learned
Until the end of June, the tool was called claude-workbench and could precisely one AI backend. The month went almost entirely to fine-tuning – 47 commits that you barely notice individually and feel daily in sum.
The preliminary project remains open on GitHub and still receives security fixes, but no new features.
A security audit brought eight findings, which were closed on June 1. Among them predictable temp file paths during PDF export, a browser call without checking the passed program name, and an update selection that simply took the first entry of GitHub releases – a subsequently published patch release on an old branch could thus hide a real update. Since then, a version comparison according to semver decides.
The fix with the greatest everyday effect came on June 12. Claude Code has been drawing on the Alternate Screen since version 2.1.89 – that second screen buffer that vim or less also occupy – and reports mouse events itself. The local history buffer of the area thus remained empty, and the mouse wheel did nothing. The solution matches tmux's behavior: If an application with mouse tracking is running in the pane, the wheel event is passed through as a mouse sequence to the application. Only if nobody is listening does it scroll its own buffer.
Mid-June, standard shortcuts replaced the old block operations in the editor:Ctrl+C, Ctrl+X, Ctrl+V, Ctrl+Z instead of the F-key combinations in the style of Midnight Commander, which conflicted with global F-keys anyway. Plus a real hardware cursor, because the custom-drawn one remained invisible in Terminus and iTerm2.
On June 30, there was also Prefix Passthrough: With Ctrl+B in the shell area, all keys are passed raw to the application underneath – nano, mc, and vim get
their F keys back. You can access the Workbench commands via Ctrl+B
plus key.
July: The Cut
On July 10, ai-workbench appeared as its own project – with a change that carries the new name: The AI area is no longer fixed to Claude Code.
It started with a positional argument at startup
(ai-workbench opencode), two days later came the switch at runtime via
F8. It initially rotated silently through the backends, which in practice
was unusable – after three key presses you didn't know where you
had landed. Since v1.5.0, F8 opens a selection menu.
Today, six backends are available:
| Backend | Start | Note |
|---|---|---|
| Claude Code | ai-workbench claude |
Standard, with permission dialog |
| OpenCode | ai-workbench opencode |
Start command customizable in settings |
| Pi | ai-workbench pi |
ditto |
| Codex | ai-workbench codex |
OpenAI, since v1.8.0 |
| Ollama + OpenCode | ai-workbench ollama-opencode |
local, since v1.9.4 |
| Ollama + Pi | ai-workbench ollama-pi |
local, since v1.9.4 |
The choice is saved in the session. Claude-specific dialogs – such as the permission mode selection – only appear when the backend understands them.
Multi-line input, third attempt
Shift+Enter in the AI area sounds like a small thing and was the most stubborn issue of the month. Terminals report this key only when the Kitty keyboard protocol is active; the workbench therefore enables it and translates for the application underneath.
Then it turned out: Have you /terminal-setup run from Claude Code, this creates a global key binding in iTerm2 that Shift+Enter intercepts and sends a bare newline character – bypassing the protocol. Since v1.7.1, the AI area also treats this character as a line break. What your terminal actually sends is shown by ai-workbench --key-diag.
Alt+Enter and Ctrl+J work without protocol, and \ plus Enter remains the way that works everywhere.
Two things nobody missed
The startup showed a black screen for three to five seconds because the dependency check started twelve to twenty processes one after another before anything appeared. Since v1.9.0, the screen appears immediately, with the check running in the background.
Since v1.6.0, every release archive carries a cryptographic signature, generated with zipsign. The verification on download is not yet enabled – for that, a few signed releases are needed first in the history, otherwise I would lock out the own user base. All archives are openly on GitHub.
The theme behind many of these changes: SSH
Look at what work went into these three months – clipboard across five methods, file transfer through the terminal connection, XRDP specifics, an assistant for inserting images over SSH. Notably a lot of this does not concern the local terminal.
This is not a coincidence, but the reason why the whole thing is a terminal interface and not an application with windows: You start it via SSH on any server, and the complete cockpit runs there, where your code is. No local client, no counterpart that installs itself, no file synchronization between two machines.
Exactly why every little thing that is taken for granted locally costs remote work. Copying, for example: On your own machine, native integration is sufficient. Over SSH without a display, what remains is an escape sequence that sends the text through the terminal connection itself – and that cannot read back. Such limits need to be named, not hidden.
End of July: Security, and what it costs
v1.10.0 closed two holes of the same type: A directory that you only open should not determine which code runs.
A config.yamlin the working directory had highest priority until then and
among other things determines which commands start in the three areas. A
cloned repository with such a file was therefore enough to execute foreign
programs at startup. Since then, it only applies after explicit approval:
ai-workbench --trust-local-config
The approval is tied to the content, not just the path – a SHA-256 goes into a
list under ~/.config/ai-workbench/. If the file is edited or overwritten by a
git pull the approval becomes invalid.
Secondly, every Git call now carries a number of configuration values
on the command line so that the repository cannot overwrite them:
core.fsmonitor, core.sshCommand, core.gitProxy, credential.helper and
protocol.ext.allow. And git fetch no longer runs automatically when
entering a repository.
This exact disabled automatic mechanism was the only way to the pull dialog. With the new default value, pulling from the interface was no longer possible – without message, without hint. The comment in the source code even claimed that a keyboard shortcut for it was unaffected. This shortcut never existed.
v1.10.1 fixed this: The file menu has with F9 → p a real
entry for Git Pull that works regardless of the setting
and asks first. On this occasion, three other
things were noticed – filenames with umlauts lost their Git color, because git
by default treats them as "\303\234bung.txt" outputs, a German-language git caused
the detection "no remote configured" to run into nothing, and git pull
continued to execute the repository's hooks.
What remains: A git status can still start a command via .gitattributes and a suitable
filter. No command-line switch helps against this. That's why automatic fetch remains disabled – hardening is the
second line of defense, not the first.
What this means in practice
If you installed the Workbench via Homebrew, you get v1.10.1 with
brew upgrade ai-workbench. Two things are worth checking after the update:
- If there's a
config.yamlin your project directory, it will now be ignored. Read it once, thenai-workbench --trust-local-config. - If you miss the automatic remote sync, set
git.auto_fetch: truein the configuration – or pressF9→pif a pull is enough for you.
The three areas – AI, LazyGit, Shell – continue to show the same working directory as the file browser. This was the core of the tool from the beginning and has proven over three months to be the only thing that didn't need changing.