TransIT AI

Blog · August 4, 2026 · Knox Hutchinson

We added a local terminal and SFTP. The AI still can't touch either.

Transit started as an SSH client with an investigation-only AI built in. The rule from day one was that a human can do anything and the AI can only look. In v5 the product grew a lot of new surface, and every bit of that new surface belongs to the human. The AI got nothing.

That sounds like a slogan, so this post is the mechanism behind it.

The question we ask about every feature

Before we build anything new, the first question is not “is this useful” or “will people pay for it.” It is “can the AI reach it, and if so, what can it now do that it couldn’t before.” If a feature grows the AI’s blast radius, it needs its own safety story and its own review. If it doesn’t, we can ship it like any other piece of software.

For the three things we shipped in v5, the answer to that question was no. Not because we told the model to stay away. Because the code that implements them is not reachable from the code that runs the agent.

What shipped in v5

Three things people kept asking for.

A local terminal. A real local OS shell (zsh, bash, fish, PowerShell, cmd, a WSL distro, or a Python or Node REPL) as a tab next to your SSH sessions. It renders through the GPU like the rest of the terminal, resizes for real, and logs to a file if you want. The launcher enumerates the shells actually installed on your machine and shows their versions, so you pick one instead of typing a path.

SFTP file transfer. A dual-pane browser, local on the left and remote on the right, over the devices already in your inventory. Same credentials, same host-key trust as the SSH session you’d open to that box. Drag a file across the panes, or drag one in from Finder or Explorer, and it lands in a transfer queue with per-file progress and a cancel button. Directories copy recursively and modification times come along.

Split-screen tiling. Split any tab into a resizable grid, panes side by side or stacked, nested as deep as you want. Drag a tab into a pane to tile it. SSH, serial console, and local shells all live in the same layout.

All three are in the free download. None of them touched the AI.

Two actors, still

The model we shipped on is two actors sharing one workspace. You are one actor and you can do anything a terminal or a file client lets you do. The agent is the other actor and it has five abilities: list open sessions, read redacted scrollback, propose a command, propose a read-only API call, and ask you a question. Every command it proposes passes a per-vendor allowlist and then your explicit click. It cannot execute, configure, or write on its own.

Adding a local shell, a file browser, and a tiling layout is all on the human’s side of that line. The agent’s side did not move. It still has those same five abilities, and none of them is “open a local shell” or “read a file off the disk” or “put a file on a switch.”

How “the AI can’t touch it” is actually enforced

Here is the part worth pulling apart, because “the AI can’t do X” is easy to say and hard to trust.

The agent reaches live sessions through exactly two seams, both rebuilt on every chat turn. One is the source it reads sessions and scrollback from. The other is the executor that runs an approved command. The local terminal and the SFTP surface are wired into neither of them. So when the agent lists sessions, a local shell is not in the list. When it tries to read one, it gets the same “no such session” it would get for a session that was never opened. There is no separate error, no hint that another surface exists. The absence is the whole point.

That omission could be a comment that a future refactor quietly deletes, so it isn’t a comment. The file-transfer engine lives in its own crate, and so does the local-PTY code, and both are on a deny list that forbids the agent’s crate from importing them. It is the same cargo deny mechanism that keeps the agent’s code away from the credential store. If someone adds the dependency, the build fails in CI before it merges. A prompt can’t add a dependency. A jailbreak can’t add a dependency. Only a pull request can, and that pull request goes red.

The tool count didn’t change either. It’s still five, asserted at compile time, and a pinned test opens a real local shell and checks that the agent’s session list does not contain it. Giving the agent a file tool or a shell tool would be a deliberate release with its own write-up, not something the model can talk its way into at runtime.

The honest part: upload is a new human write path

One thing did genuinely change, and it’s worth stating plainly rather than burying.

Uploading a file over SFTP is the first structured way a human can write to a device through Transit that is not the policy gate. Until v5, a write to a device was either a command the agent proposed (gated, then clicked) or keystrokes you typed into a live session. An SFTP put is neither.

That is fine, and here is why. The policy gate exists to constrain the agent, not the human. A human with credentials to a box could always scp a file to it from any terminal on their machine, including the local terminal we just shipped. What the gate protects is that the AI can never be the one making the change, and that hasn’t moved an inch. The agent has no path to the file-transfer surface, so it can’t upload anything, propose an upload, or even tell that the surface is there. The new write path is the human’s, exercised with their own hands, file by file.

The off switch

Both surfaces have a config flag that removes them entirely. [terminal] enabled = false takes the local terminal out, and [files] enabled = false takes file transfer out: the rail entry disappears and the backend refuses the calls, including for a session that’s already open. For a locked-down or DLP-conscious deployment that is a one-line answer, and it isn’t a paywall.

Why this let us ship fast

The reason all of this shipped in one release instead of three careful ones is that none of it required a new safety argument. We didn’t have to reason about what an AI could do with a file browser, because the AI can’t see the file browser. The blast-radius question got a boring answer, and a boring answer is exactly what you want when the thing you’re adding sits next to production gear.

That’s the pattern we try to hold to. Grow what a human can do as fast as the work allows. Keep what the AI can do fixed, small, and enforced by the compiler instead of by good intentions.

The whole thing is a free download at transitai.app. If you want the deeper version of the read-only architecture, the original write-up covers the agent surface and the permit list in detail.

FAQ

Can the AI move files for me if I ask it to? No. It has no file tool and no path to the transfer engine. It can’t upload, download, or browse, and it can’t see that the SFTP surface exists.

Can it run something in my local terminal? No. The local shell is not one of the sessions the agent can list or read, and there is no tool to type into it.

Is the file transfer SFTP or SCP? SFTP today. SCP for gear without an SFTP subsystem is planned.

Does turning the surfaces off cost anything? No. The [terminal] and [files] config flags are a deployment control, not a tier. Everything here is in the free download.