blog · Artikel auf Englisch

Snotra 1.23 to 1.27.1: nine releases that work off the architecture review

Nine releases in five days, and most of them answer a finding of the architecture review. Snotra Agent now says when something goes wrong in the background, saves a running turn after every step, flags tool results that read like instructions and passes images to every provider. Underneath, the chat moved out of the window into a core that runs without Electron.

Between October 15 and 19, Snotra went from 1.23.0 to 1.27.1. In the middle of that, on October 16, I agreed the architecture review: 29 quality scenarios checked against the code, 38 findings, each one an issue of its own. When the article about it went out a day later, 13 were closed. Today 35 are.

So most of what changed in these nine releases has a reason that is written down, and that reason is more useful to you than a version number. This round-up is ordered by the quality goal behind each change. The release it came with is in brackets, and the finding as AR-nn where there is one. The cost estimate per chat came with 1.23.0 and has an article of its own.

Nothing goes wrong without a word

The review rated robust operation at risk, and that was the finding that hurt. In the interview I had named silent misbehaviour the worst failure Snotra can have, and there was no safety net against it. An error outside a chat run vanished. A chat that could not be saved was gone on quit. A settings file Snotra could not read was moved aside without telling anyone.

  • Errors in the background have somewhere to go (1.24.1, AR-03). Snotra now writes a local log file, main.log in its data folder, rotated at 1 MB and never sent anywhere. An error no run catches shows one notice, Something went wrong in the background., with a count, and offers to copy a diagnostics report or show the log file. Both are also in the Help menu. If the window itself crashes, you get a box with Reload Window and Quit instead of a blank window. The manual describes it under The log file.
  • A running turn is saved after every step (1.24.1, AR-04). Until now a turn was written when the question went out and when the run ended. The tool steps in between lived in memory only, so a crash or a reload lost them. Now every finished step is saved, and a turn that never got to its end comes back with the note Interrupted. under what it did finish.
  • The chat says when it is not being saved (1.23.1, AR-02), and Snotra tells you when it had to set a settings file or the history aside as unreadable (1.24.0, AR-26).
  • A failed update rolls back (1.24.2 and 1.25.0, AR-28). The helpers that swap the app on macOS and Linux now keep a status file and put the old version back when the swap fails. On Windows, Snotra keeps the backup until the new version has actually started, and starts the previous one if it does not.

None of this makes Snotra fail less often. It makes failures visible, which is what the review asked for, and I would rather explain a notice than have someone lose a chat and never know why.

Protection is only loosened when you say so

Agent security is the goal ranked first, and the review called the design mature, with two paths that fail open. Both are closed.

The first was a check that keeps your own provider keys out of tool results and out of the prompt. If reading the list of keys threw an error, the check compared against an empty list, and every result went through. Since 1.23.1 the output is held back instead, and the card in the chat says it could not be checked (AR-01). Since 1.24.2 the check also finds a key that a command printed base64-, hex- or URL-encoded (AR-18).

The second is the one you will notice. Switching on Allow shell commands or Allow Python execution now shows a confirmation that says what the tool may then do, and adding a local MCP server, or changing its command, arguments, working folder or environment, shows you the command line before it is stored (1.27.1, AR-05). Switching something off never asks, and renaming a server never asks either. The reason goes beyond the dialog. These confirmations used to exist only as Electron dialogs inside the handlers that talk to the window. They now sit behind a port in the core, and the core falls back to no when nobody answers. A second front end, a phone or a command line, cannot loosen a protection by simply not having the dialog.

A hint when a tool result reads like instructions (1.27.1, AR-36)

When a web page, a file or a command output tries to tell the agent what to do, the chat shows a box under the tool log with the passage in question. It is a hint, and Snotra says so in the box. The model gets the result unchanged, and the policy, the approval cards and the sandbox never look at the flag. The review wrote that down as a rule: injection detection is an extra layer, never the protection. Isolation and approvals protect. A detector may only warn.

A warning that shows up on every other web page teaches you to skip it, so the patterns were tuned for silence. A strong signal flags on its own, for example ignore your previous instructions in English or German, a fake SYSTEM: line or hidden Unicode tag characters. Weak signals only count in pairs, and a phrase in quotation marks does not count at all, because that is how a text talks about injections. Against about 30,800 real Markdown, JSON and text files, some 40 web pages read through Snotra’s own fetch_url and real git log output, it raised no flag except on pages that carry an actual injection example. The manual has the details under When a tool result looks like instructions.

Privacy, tested instead of assumed

Snotra promises that nothing leaves your machine except to the services you set up. The review found that the promise had never been tested, and that the update check at start-up could not be switched off.

The switch is in Settings › General since 1.24.0, Check for updates at start-up, on by default (AR-12). Help › Check for Updates… still works when it is off.

The test came with 1.24.2 (AR-13). It starts the app, lets it sit idle with a misspelled sentence in the message field, and checks the network log that nothing went out. On macOS and Windows nothing did. On Linux, the first CI run caught Chromium downloading a spell-checking dictionary, en-us-10-1.bdic, from a Google server the moment the window opened, before anyone typed a word. That is a request to a service nobody set up, so the spell checker is now off on Linux. The test runs in CI on all three platforms.

Two smaller things in 1.25.0 follow the same rule: the microphone’s tooltip now says that recordings go to OpenAI, and Update prices names the server it loads the price table from.

Faster, and measured first

Performance has budgets in the quality model, and the review found that not one of them was measured. So the measuring came before the optimising (1.24.1, AR-09). A script starts the real app against a fixture with 200 chats, one of them 200 messages long, and a workspace with 2,000 folders. On my M3 Pro the first run gave 1.3 seconds until the app is ready, 155 milliseconds to switch to the long chat, 101 milliseconds for the longest frame while the big folder opens, and 845 MB after use. All four were within budget. The report now runs on every push to main on macOS, Windows and Linux.

Then two findings that would have shown up there sooner or later were fixed in 1.25.0. Streaming used to redraw the whole answer with every chunk; now only the block still being written is drawn, and finished answers are cached (AR-23). And the chat history was one encrypted file that every list, save and delete read, decrypted and wrote back in full (AR-10). It is now one encrypted file per chat with an index kept in memory, so saving a chat writes that chat and nothing else.

That second change has a cost you should know about. The first start of 1.25.0 or later moves your history to the new format on its own. If you go back to 1.24 afterwards, that version shows an empty history. Your chats are not lost, they are back once you update again.

The same features with every provider and platform

The review rated parity at risk: features that worked with OpenAI only, and Windows behaving differently from what the manual said (AR-19, AR-16).

  • Reasoning levels for Claude, Gemini and Ollama (1.26.0). The model menu below the message field offers them for every provider whose model can think, not only for OpenAI.
  • Images reach Claude, Gemini and Ollama (1.27.0). A screenshot you paste into the chat goes to the model with Anthropic, Google and Ollama as well. With Ollama it depends on the model whether it can see it. Gemini takes PNG, JPEG and WebP, and a GIF is now refused in the composer instead of being dropped without a word.
  • Nothing keeps running on Windows after a command (1.26.0). A program that a command or a Python script started in the background now ends with the run, through a Windows Job Object. The manual had promised that for a while; on Windows it was not true.
  • Git over SSH inside the sandbox on Linux (1.27.1). git fetch, pull and push sign in through your ssh-agent, as they already did on macOS since 1.21.1. Your private key files stay unreadable for the run.
  • Accessibility is checked automatically (1.26.0, AR-24). It used to be checked by hand, on macOS only. Now axe-core checks the welcome page, the help window, a file preview, a chat turn and all six settings sections against WCAG 2.1 AA, each in light and dark mode. On the way, Snotra learned to follow your system’s appearance (Settings › General › Appearance › System), grey text in dark mode got more contrast, and a screen reader reads the chat as a list of messages.

Also new, without a finding behind it

  • Edit text files in the preview (1.24.0). An Edit toggle in the file header turns the preview into an editor. There is no save button: the file is saved a second after you stop typing, and Cmd+S saves at once. If the file changed on disk in the meantime, you choose which version to keep. While the agent is running, editing pauses.
  • Send feedback from inside Snotra (1.25.0). Help › Send Feedback… or the speech bubble at the bottom of the sidebar opens a short form for a bug, an idea or praise, no GitHub account needed. The message becomes a public issue on GitHub; an e-mail address you add does not. The gear next to it opens the settings, which used to be reachable only through the menu.
  • MCP servers over the network (1.25.0). In the MCP settings, Add server now offers Connection: Remote (HTTP) with a URL and, if needed, a header for your access token, stored encrypted. Servers that want a browser sign-in (OAuth) are not supported yet.
  • The sandbox has a page of its own (1.26.0). Settings › Tools › Security shows per workspace whether the sandbox is on, which programs get more room and which hosts stay open, and an allowance can now apply to one workspace or to all of them. The former Tools & security is now Settings › Tools › Autonomy.
  • The update dialog speaks your language (1.25.0) and shows a short summary instead of a list of pull requests.

The chat moved out of the window

Most of the work in 1.26.0 and 1.27.1 changes nothing you can see, and it is the part I care most about. The review rated the separable core at risk. The core really knew nothing of Electron, but it was small, and the conversation itself lived in the window: the renderer ran the turns, saved the chat, added up the cost and asked for the title. A command line or a phone app built on that would have had to take most of the desktop app along.

Since 1.27.1 the window sends a question and a chat id, and the core keeps the chat (AR-06). The composition is split in two: createCore() builds every service from ports and plain values, and a test runs it under plain Node without a keyring and without loading Electron, through a whole chat turn with a list_directory call (AR-08). Business logic moved out of the IPC handlers (AR-31), each tool got one descriptor that the window reads instead of knowing about tools on its own (AR-33), and the capabilities of providers and platforms sit in one register each (AR-21). In numbers, src/application grew from 5,315 lines at 1.23.0 to 14,020 at 1.27.1.

The code is still plain JavaScript without a build step, and that decision stands. What changed is that tsc --checkJs now type-checks all of the main process, the core and the shared contracts, with strictNullChecks and noImplicitAny switched on in 1.27.1 (AR-29). Contracts that drifted apart had shown up in five blocks of the earlier code review.

The reason for all this has a name: a remote control from the phone. Its pairing and its channel are specified, with test vectors, and the desktop half of the pairing is in the code since 1.26.0. There is nothing you can switch on yet; the settings page for it is still an open issue.

What is still open

Three findings are open, and they belong together. Windows has no sandbox for shell commands and Python (AR-15), and MCP servers run without a sandbox on every platform (AR-17). The third is a decision I still owe (AR-11). Where the platform has no sandbox, which means Windows and Ubuntu 24.04 with restricted user namespaces, Auto mode still runs shell and Python commands without a card and without isolation, shown only as an amber pill. The review says a missing protection should fall back to the stricter state, the code does not, and one of them has to change. Until it does, I would not use Auto with shell commands switched on under Windows.

Getting it

Snotra checks for a newer version at start-up, unless you switched that off, and walks you through the update one confirmed step at a time. Otherwise, download it for macOS, Windows or Linux. Every release has its notes on GitHub, and the review with all 38 findings is in docs/architecture-review.md.

If you run Snotra on Windows, what do you use the shell tool for? That answer decides how AR-11 goes, and the Discussions are the place for it.