<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>NeuroSquad blog</title>
    <link>https://neurosquad.ai/en/blog/</link>
    <description>Notes from building NeuroSquad, the desktop app that runs AI agent CLIs as cards on one canvas: design decisions, measurements, bugs we found and what each release changed.</description>
    <language>en</language>
    <lastBuildDate>Sat, 26 Sep 2026 14:31:27 GMT</lastBuildDate>
    <atom:link href="https://neurosquad.ai/en/blog.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>Nineteen agent CLIs, one depth of integration</title>
      <link>https://neurosquad.ai/en/blog/nineteen-agent-clis/</link>
      <guid isPermaLink="true">https://neurosquad.ai/en/blog/nineteen-agent-clis/</guid>
      <pubDate>Sat, 26 Sep 2026 14:31:27 GMT</pubDate>
      <category>Release</category>
      <category>Integrations</category>
      <category>Engineering</category>
      <description>How NeuroSquad brought 19 agent CLIs to the level of Claude Code: a checklist of about forty capabilities, a different mechanism for each tool, and proof where one is impossible.</description>
      <content:encoded>&lt;p&gt;&lt;img src=&quot;https://neurosquad.ai/blog/nineteen-agent-clis/add-menu-en.webp&quot; alt=&quot;The add-card menu in NeuroSquad listing agent CLIs with their icons, installed ones marked&quot;/&gt;&lt;/p&gt;&lt;p&gt;NeuroSquad 0.1.137 adds nine agent CLIs — Gemini CLI, GitHub Copilot CLI, Amp, Factory Droid, aider, Goose, Kimi Code, Cline and Auggie — and brings Cursor CLI and Crush up to the same level as everyone else. That makes nineteen, and for the first time “supported” means the same thing for all of them.&lt;/p&gt;
&lt;p&gt;Three days ago it did not. The first release ran ten CLIs in cards, but only Claude Code was integrated deeply: its statuses came from its own hooks, its session resumed after a restart, it got tools over arrows. The others ran in a terminal and were mostly watched by a heuristic. This post is about closing that gap, in three releases within a day.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Which CLIs had the full integration, release by release. Move through the steps.&lt;/em&gt; &lt;a href=&quot;https://neurosquad.ai/en/blog/nineteen-agent-clis/&quot;&gt;Live replica — try it&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;What “the same depth” means&lt;/h2&gt;
&lt;p&gt;We wrote down everything the app does for Claude Code as a checklist of about forty capabilities, and every CLI gets its own document that goes through that list row by row. Each row is one of three things: &lt;strong&gt;native&lt;/strong&gt; (the CLI has it and the app uses it), &lt;strong&gt;emulated&lt;/strong&gt; (built from another mechanism of that CLI, and how), or &lt;strong&gt;impossible&lt;/strong&gt; — with the proof, usually a line of the CLI’s own source.&lt;/p&gt;
&lt;p&gt;The rows that matter most to someone using the canvas:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Session resume&lt;/strong&gt;: restart the app or the card, and the agent continues the same conversation.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Precise statuses&lt;/strong&gt;: working, needs you, finished — from the CLI’s own events, with the text of what it is asking.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Tools over arrows&lt;/strong&gt;: the app’s MCP tools, plus connected MCP servers and skills.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Canvas mode&lt;/strong&gt;: the agent works through cards (a terminal for commands, a browser for the web) instead of its own built-in tools, and that holds even in dangerous mode.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Safe interruption&lt;/strong&gt; by the budget brake, without losing the session.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Usage and model&lt;/strong&gt; per card, the &lt;strong&gt;context meter&lt;/strong&gt; and compaction, &lt;strong&gt;auto-continue&lt;/strong&gt; after a rate limit.&lt;/li&gt;&lt;/ul&gt;
&lt;h2&gt;Every CLI needs a different way in&lt;/h2&gt;
&lt;p&gt;The checklist is the same; the mechanism almost never is. For Claude Code, the app passes a settings file on top of yours, and its hooks report every state change with one &lt;code&gt;curl&lt;/code&gt; line. Here is how some of the others got there.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OpenCode&lt;/strong&gt; gets a plugin — one file for all cards — that reports its session status and permission requests. Its config goes through one environment variable, chosen by elimination: the variable for inline JSON was already carrying OpenRouter attribution headers, and two writers of one variable overwrite each other; the variable for a config &lt;em&gt;directory&lt;/em&gt; would have hidden your global instructions file. Interrupting it needed care too: Ctrl+C in OpenCode with an empty input &lt;strong&gt;closes the app&lt;/strong&gt;, and the budget brake used to send exactly that. It now presses Escape twice.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hermes Agent&lt;/strong&gt; reads an administrator-level config layer, which the app points at a file of its own per card, merged over yours leaf by leaf. A live test found that its interactive mode connects MCP servers only if they are in your raw config — so the card types &lt;code&gt;/reload-mcp&lt;/code&gt; itself once the prompt is ready, and the first prompt waits for “Agent updated” before it is inserted. Another finding: when the model provider fails, Hermes never sends its end-of-session event, and the card sat on “working” forever; while a turn is open, the app now also watches the terminal for the provider errors Hermes prints.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Gemini CLI&lt;/strong&gt; has a system settings path, like its fork Qwen Code, but it only loads that file if it is owned by the administrators and not writable by users. A file in the app’s folder is skipped with a security warning. What Gemini does honour is a home folder override, so every Gemini card runs with a home of its own, holding its settings layer — and everything else from your real &lt;code&gt;~/.gemini&lt;/code&gt;, sessions and login included, linked in with junctions. A card’s session is your session: &lt;code&gt;gemini --resume&lt;/code&gt; works from a plain terminal and back.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;aider&lt;/strong&gt; has no MCP client, no hooks and no plugin API. It is a Python program, though, and Python imports a &lt;code&gt;sitecustomize&lt;/code&gt; module from the path before anything else. An aider card starts with one folder first on &lt;code&gt;PYTHONPATH&lt;/code&gt; whose module patches six aider modules as they load — each patch guarded, so if a later aider renames a method only that one feature switches off — and then removes its own variables, so nothing aider starts inherits them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Kilo Code&lt;/strong&gt; by default attaches to a running Kilo daemon instead of starting its own worker, and the daemon has its own environment — so a card would silently lose its config, its tools and its MCP token. Every Kilo card now starts with the switch that turns attaching off. &lt;strong&gt;Codex CLI&lt;/strong&gt; used to survive stopping its card: the npm shim died and &lt;code&gt;codex.exe&lt;/code&gt; lived on. The card now starts the real executable directly.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://neurosquad.ai/blog/nineteen-agent-clis/new-agent-en.webp&quot; alt=&quot;The New agent dialog with the list of agent CLIs open&quot;/&gt;&lt;figcaption&gt;Pick the CLI, the provider and the model when you create an agent. Installed CLIs are found on this computer’s current PATH.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;“Impossible” is an answer too&lt;/h2&gt;
&lt;p&gt;Some rows cannot be filled, and saying so is part of the work. Several CLIs — Auggie, Droid, Goose, Kimi — do not let the caller choose a session id; the app captures the id they mint and resumes by it instead. Auggie has no compact command, because it summarizes history on its own when the window fills; its card simply has no Compact button. Cline reads a server’s tool list once, when its session starts, and nothing refreshes it — so an arrow drawn mid-session takes effect at the next start, and the docs say so.&lt;/p&gt;
&lt;p&gt;Kimi Code has the same limitation, and there it is emulated: a Kimi card is offered every built-in tool group from the start, and the arrows decide at call time whether a call is allowed. A note card spawned in the middle of a session was written to in that same session.&lt;/p&gt;
&lt;p&gt;Amp is the most honest case. Its agent loop — model calls included — runs on Amp’s servers; the local CLI only executes tools. So OpenRouter and its attribution are impossible for Amp, and everything the app does around it was verified against a local fake of Amp’s server.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Found live: a line broken by the terminal&lt;/strong&gt; When a Goose session is deleted, Goose prints “no such session exists”, and the app is supposed to recover with a fresh one. The first version missed it: the Windows console had wrapped the line as “no suc / h session exists”. Recovery markers are now matched with all whitespace removed.&lt;/p&gt;
&lt;h2&gt;How it was tested&lt;/h2&gt;
&lt;p&gt;Every CLI was installed into a scratch folder, never globally, and run by a separate build of the app with its own profile and a scratch home folder, so no real config of anyone’s was read or written. Most were pointed at a small scripted model server on the loopback interface — one that answers “PING”, calls tools, stalls for fifteen seconds, returns 429 — so rate limits, stalls and permission prompts could be produced on demand instead of waited for.&lt;/p&gt;
&lt;p&gt;The same server recorded request headers, which is how OpenRouter attribution was checked: every CLI that talks to OpenRouter now sends NeuroSquad’s headers, including cards on the CLI’s own OpenRouter login, and each one was &lt;strong&gt;measured on an intercepting server&lt;/strong&gt;, not taken from documentation.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://neurosquad.ai/blog/nineteen-agent-clis/add-menu-en.webp&quot; alt=&quot;The add-card menu: agent CLIs first, with a search box and installed ones marked&quot;/&gt;&lt;figcaption&gt;The add-card menu lists agents first; the ones installed on this computer are marked.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Two smaller fixes rode along the way: Kilo Code cards no longer lose their settings to a shared daemon, and Qwen Code’s token for the app’s MCP server is no longer written to disk. The full lists are in the changelog for &lt;a href=&quot;https://neurosquad.ai/en/changelog/#v0.1.128&quot;&gt;0.1.128&lt;/a&gt;, &lt;a href=&quot;https://neurosquad.ai/en/changelog/#v0.1.133&quot;&gt;0.1.133&lt;/a&gt; and &lt;a href=&quot;https://neurosquad.ai/en/changelog/#v0.1.137&quot;&gt;0.1.137&lt;/a&gt;.&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>Community cards, MCP servers and skills — all connected by an arrow</title>
      <link>https://neurosquad.ai/en/blog/cards-mcp-skills-by-arrow/</link>
      <guid isPermaLink="true">https://neurosquad.ai/en/blog/cards-mcp-skills-by-arrow/</guid>
      <pubDate>Fri, 25 Sep 2026 10:25:35 GMT</pubDate>
      <category>Release</category>
      <category>Extensions</category>
      <category>Security</category>
      <description>NeuroSquad opens up: cards anyone can build, MCP servers and skills from public catalogs, verified cards. How each is isolated, and why the arrow stays the permission.</description>
      <content:encoded>&lt;p&gt;&lt;img src=&quot;https://neurosquad.ai/blog/cards-mcp-skills-by-arrow/catalog-en.webp&quot; alt=&quot;The MCP and skills catalog in NeuroSquad, with search results from the official MCP Registry&quot;/&gt;&lt;/p&gt;&lt;p&gt;Until this week every card on a NeuroSquad canvas was ours. 0.1.123 changed that in three ways at once: &lt;strong&gt;community cards&lt;/strong&gt; that anyone can build and publish on GitHub, &lt;strong&gt;MCP servers&lt;/strong&gt; from the official MCP Registry, and &lt;strong&gt;skills&lt;/strong&gt; from skills.sh — each one given to a specific agent by drawing an arrow. An hour and a half later 0.1.125 added &lt;strong&gt;verified cards&lt;/strong&gt;: a reviewed list with a badge that means something precise.&lt;/p&gt;
&lt;p&gt;The canvas has one rule that makes it readable: an agent can use exactly what its arrows point to. Opening it to other people’s code was only worth doing if that rule survived. Most of the work in these releases is about making sure it does.&lt;/p&gt;
&lt;h2&gt;First, make a card cheap to add&lt;/h2&gt;
&lt;p&gt;The first cards were wired into the app by hand: a card type in a union, a branch in the canvas, labels, icons, an entry in the MCP server’s tables, a step in the removal cascade — about a dozen places per card. Tolerable one at a time, and a guaranteed conflict when several are built in parallel.&lt;/p&gt;
&lt;p&gt;So built-in cards became plugins first: one folder in the page, one module in the main process, IPC channels under a common prefix, MCP tools registered by the card itself, strings in their own file. The canvas, the sidebar, the arrows and removal handle every plugin card the same way. Once a card is a plugin, letting someone else write one is a question of isolation, not of wiring.&lt;/p&gt;
&lt;h2&gt;Community cards: a sandbox that cannot leave the card&lt;/h2&gt;
&lt;p&gt;A community card is a small web app. It could run in a separate native web view, but that is an OS-level overlay: it would sit on top of the canvas instead of inside it, and would not zoom or clip with it. It runs instead in a sandboxed iframe with an opaque origin, served through the app’s own protocol. Before building on that, we checked what such a frame can and cannot do in this exact version of Electron:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;It runs in &lt;strong&gt;a separate OS process&lt;/strong&gt;. A card spinning in a busy loop for four seconds did not freeze the canvas: the host’s timer kept ticking, with a largest gap of 63 ms.&lt;/li&gt;&lt;li&gt;&lt;code&gt;window.api&lt;/code&gt;, Node and &lt;code&gt;require&lt;/code&gt; are simply not there, and touching the parent page throws a security error.&lt;/li&gt;&lt;li&gt;&lt;code&gt;localStorage&lt;/code&gt; and IndexedDB are unavailable (hence a storage API of its own), and outside requests are blocked by the frame’s content security policy.&lt;/li&gt;&lt;li&gt;It cannot open windows, go fullscreen, read the clipboard or turn on the microphone.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Two checks failed, and those are the valuable ones. WebRTC ignores content security policy entirely: a peer connection reached a TCP listener on the local machine. The fix is blunt — the card’s boot script removes the WebRTC constructor before any card code runs. The second was in the app, not the frame: its permission handler granted the microphone to whoever asked. It now grants it only to the app’s own top-level page; that is the “Microphone access is granted only to the app itself” line in the changelog.&lt;/p&gt;
&lt;p&gt;A card never talks to the page it is drawn on. It gets a message port to the main process, bound to that one card instance, and every request is checked there against the permissions the package declared and you granted at install. Anything that reaches another card or an agent — sending data through a port, prompting an agent, typing into a terminal — needs &lt;strong&gt;both&lt;/strong&gt; the permission &lt;strong&gt;and&lt;/strong&gt; an arrow between the two cards. The arrow is the consent for that particular flow of data.&lt;/p&gt;
&lt;p&gt;Installing is by GitHub address, pinned to a commit and checked against the hash of the package’s file tree. Updates happen only when you click, and show you what changed in the permissions first. More on building one on the &lt;a href=&quot;https://neurosquad.ai/en/card-sdk/&quot;&gt;Card SDK page&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Verified cards: a badge that means one thing&lt;/h2&gt;
&lt;p&gt;An install-by-address model has an obvious gap: how do you find a card worth installing? 0.1.125 adds a catalog of cards reviewed by the NeuroSquad team, kept in a public repository and updated by pull request. You can search it in the “Custom card…” picker or in Settings.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://neurosquad.ai/blog/cards-mcp-skills-by-arrow/verified-en.webp&quot; alt=&quot;The Verified tab of the custom card picker, with a reviewed card and its green shield badge&quot;/&gt;&lt;figcaption&gt;Verified cards in the picker. The shield says this exact code was reviewed — not that it can never do harm.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The badge is decided by the main process and means exactly this: the installed card comes from the reviewed repository, at the reviewed commit, &lt;strong&gt;and&lt;/strong&gt; the hash of its files computed at install time equals the hash in the catalog. A local development folder, another commit or different files — no badge.&lt;/p&gt;
&lt;p&gt;Installing from the catalog goes one step further: if the name, version or hash does not match the catalog entry, the install is &lt;strong&gt;refused&lt;/strong&gt;. The choice here was between “install it without the badge” and “do not install it”, and a substituted package is not something to install quietly. A newer reviewed version is offered as an update with the usual permission diff, never applied by itself; a card that leaves the list loses its badge, and nothing is removed from your canvas.&lt;/p&gt;
&lt;h2&gt;MCP servers and skills, by arrow&lt;/h2&gt;
&lt;p&gt;The catalog in the app searches the official MCP Registry (about 35 thousand servers) and skills.sh (the 20 thousand most-installed skills). Search is local, in the app, over snapshots that ship with it and update incrementally — so it works offline and is instant.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://neurosquad.ai/blog/cards-mcp-skills-by-arrow/catalog-en.webp&quot; alt=&quot;The MCP servers tab of the catalog, with search results&quot;/&gt;&lt;figcaption&gt;Search the MCP Registry right in the app. Installing shows what will run, and asks once.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The obvious way to give an agent an MCP server is to write it into the agent CLI’s config. We deliberately did not. NeuroSquad is itself the MCP client of every server you install, and re-exposes that server’s tools through its own MCP server, as &lt;code&gt;&amp;lt;alias&amp;gt;__&amp;lt;tool&amp;gt;&lt;/code&gt;, only to agents with an arrow to the server’s card, only while the arrow exists. Nothing is written to your CLI’s config folders, and a server’s secrets never leave the main process. Claude Code picks up a new arrow without a restart; other CLIs see it at their next start.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A replica: an installed MCP server, two agents, and the arrow that gives the server to exactly one of them.&lt;/em&gt; &lt;a href=&quot;https://neurosquad.ai/en/blog/cards-mcp-skills-by-arrow/&quot;&gt;Live replica — try it&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Skills work the same way, through one tool, &lt;code&gt;skill_load&lt;/code&gt;, whose description lists the skills connected to that agent and when to use each. One flag made the difference between a feature and a demo: agents hide MCP tools behind a tool search, and in a live test a fresh agent never once loaded a matching skill. Marked “always load”, it loaded the right one on its own.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The same for a skill: connected by an arrow, loaded when the task calls for it.&lt;/em&gt; &lt;a href=&quot;https://neurosquad.ai/en/blog/cards-mcp-skills-by-arrow/&quot;&gt;Live replica — try it&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;What a security review changed&lt;/h2&gt;
&lt;p&gt;Both releases went through a security review before shipping, and three results are worth describing:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Every agent has its own token&lt;/strong&gt; for the app’s MCP server, derived from a per-launch secret and the agent’s id. Before, one agent could in principle act as another; now another agent’s path answers 401.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Third-party tools live on a second MCP server&lt;/strong&gt;, which is not in the CLI’s list of pre-approved tools. So the CLI asks you before every call to a tool from someone else’s server — and the tool list is fingerprinted at install, so a server that changes its tools later waits for you to accept the changes.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;A skill is taken whole, from one commit.&lt;/strong&gt; skills.sh’s own content hash could not be reproduced from the files it serves, so the app pins its own SHA-256 of the exact files you previewed, and installs exactly those.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Not everything fits. Figma’s official remote server answers 403 to dynamic client registration — it accepts only approved clients — so the catalog points to a community server that works with a personal token instead. Packages that need a local HTTP server are not supported yet. Both are written down rather than worked around.&lt;/p&gt;
&lt;p&gt;More on the &lt;a href=&quot;https://neurosquad.ai/en/mcp/&quot;&gt;MCP servers&lt;/a&gt; and &lt;a href=&quot;https://neurosquad.ai/en/skills/&quot;&gt;skills&lt;/a&gt; pages, and the full list in the changelog for &lt;a href=&quot;https://neurosquad.ai/en/changelog/#v0.1.123&quot;&gt;0.1.123&lt;/a&gt; and &lt;a href=&quot;https://neurosquad.ai/en/changelog/#v0.1.125&quot;&gt;0.1.125&lt;/a&gt;.&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>Fifty cards, one canvas: where the CPU was going, and the Squad card</title>
      <link>https://neurosquad.ai/en/blog/fifty-cards-one-canvas/</link>
      <guid isPermaLink="true">https://neurosquad.ai/en/blog/fifty-cards-one-canvas/</guid>
      <pubDate>Thu, 24 Sep 2026 19:07:33 GMT</pubDate>
      <category>Release</category>
      <category>Performance</category>
      <category>Engineering</category>
      <description>How NeuroSquad cut an idle canvas from ~100% to ~15% renderer CPU: measured causes, the WebGL context pool, semantic zoom, and the new Squad status card.</description>
      <content:encoded>&lt;p&gt;&lt;img src=&quot;https://neurosquad.ai/blog/fifty-cards-one-canvas/overview-en.webp&quot; alt=&quot;The “Launch day” workspace zoomed out: every card shows a large summary tile instead of its contents&quot;/&gt;&lt;/p&gt;&lt;p&gt;NeuroSquad 0.1.117 is a release you mostly notice by what stopped happening: the fan spinning up while nothing is going on, a stutter when you drag a frame full of cards, a hitch every time you zoom out past the point where cards turn into tiles. It also adds the Squad card — the one board that tells you what every agent in the workspace is doing.&lt;/p&gt;
&lt;p&gt;The goal for the canvas has been the same since the first weeks: up to fifty live cards — terminals, browsers, agents — with smooth pan, zoom, drag and resize. The rule for getting there has been the same too: measure first. Every number in this post comes from a separate instance of the app on a fresh profile, driven by real input events over the DevTools protocol.&lt;/p&gt;
&lt;h2&gt;Round one: fifty terminals&lt;/h2&gt;
&lt;p&gt;The first pass happened before the public release, on a workspace of fifty cards with twelve terminals printing as fast as they could. Zooming was slow for a reason that is easy to miss: the header of every card keeps a constant size on screen, and it did that with &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;margin&lt;/code&gt;. Those are layout properties. Every frame of a zoom resized every header, which resized every card body, which fired every terminal’s resize observer — fifty terminal refits, fifty messages to the main process, fifty console resizes. Per frame.&lt;/p&gt;
&lt;p&gt;The fix was to commit the zoom value once per gesture instead of every frame, resize terminals only when their grid of columns and rows actually changes, and swap live terminal grids for a static placeholder while the zoom is moving. Then the terminals moved from the DOM renderer to xterm’s WebGL renderer, which is where most of the time went: zoom median from 18.2 to 6.1 ms, p95 from 133 to 12 ms.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Chromium keeps exactly 16 WebGL contexts per process&lt;/strong&gt; We measured it rather than assumed it. With WebGL on all fifty terminals, the result was “live: 16, lost: 34” within a second — and the sixteen survivors were the first to mount, not the ones you were looking at. So terminals get contexts from a pool of fifteen, handed to the ones on screen and taken back from the ones that leave it.&lt;/p&gt;
&lt;p&gt;One measurement from that round decided a rule that is still in the code. Hiding terminals behind placeholders made zooming twice as fast (6.1 against 12.0 ms median) and panning slower (19.8 against 16.3 ms average): a pan just moves layers that are already painted, and swapping fifty grids out and back costs more than it saves. So placeholders appear only when a gesture actually changes the zoom.&lt;/p&gt;
&lt;h2&gt;Round two: the idle canvas&lt;/h2&gt;
&lt;p&gt;The second round started from a stranger complaint: the canvas was heavy while &lt;em&gt;nothing&lt;/em&gt; was happening. Four parallel reviews of the code and one live profiling session on the “Launch day” workspace found not one cause but a pile of small constant costs. The largest one was a cartoon.&lt;/p&gt;
&lt;p&gt;AI agent cards have a small mascot that shows the agent’s state. Its idle animations were infinite CSS animations on SVG children — and on those, the browser repaints on the main thread, every frame, forever. With three Claude Code cards on a canvas at 60% zoom, the renderer process used 98–104% of a core and the GPU 32–36%, doing nothing. Now only the “working” state loops, and it moves the HTML wrapper, which the compositor handles alone; every other state plays a few times and stops in a pose that already says what it means.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;~100% → 15%&lt;/strong&gt; — renderer CPU, idle canvas with three agent cards&lt;/li&gt;&lt;li&gt;&lt;strong&gt;~34% → 3%&lt;/strong&gt; — GPU on the same canvas&lt;/li&gt;&lt;li&gt;&lt;strong&gt;180 → 66&lt;/strong&gt; — compositor layers after one CSS rule&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;The rest was a list of things that each cost a little and all ran constantly:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;**Selectors with &lt;code&gt;&lt;em&gt;&lt;/code&gt; and &lt;code&gt;:has()&lt;/code&gt; under the canvas.&lt;/em&gt;* Toggling a class on the canvas pane cost 25–34 ms of style recalculation each time, because rules like “every descendant of a gesture” had to be re-matched against every node of every card. Listing the elements that actually animate brought it to about 1.5 ms.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;A CSS variable on the pane.&lt;/strong&gt; The zoom level lived in a custom property on the element that contains every card, and changing it invalidated the style of the whole subtree, terminals included — 22–34 ms per commit. It is now one rule in a &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tag that targets only the elements that read it.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Buttons with their own layers.&lt;/strong&gt; The component library gives buttons a GPU layer. Inside a canvas that meant dozens of extra layers; one override outside the pressed state took the count from 180 to 66.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Timers in cards.&lt;/strong&gt; Cards that poll — ports, budget, stand-up, the page watch — now tick only while their workspace is open and the window is visible, and they share one clock per period instead of one interval each.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;A browser card nobody was looking at&lt;/strong&gt; kept streaming frames. Now frames flow only while some window shows the card: 0 in the overview and in hidden workspaces, back on return.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Long tasks during gestures disappeared from dragging a frame, marquee selection, zooming across the overview threshold and panning in the overview. Panning and dragging need about half the renderer CPU they did; style and layout time in a pan trace fell from 311 to 53 ms and from 378 to 28 ms.&lt;/p&gt;
&lt;h2&gt;When cards are too small to read&lt;/h2&gt;
&lt;p&gt;Zoom far enough out and a terminal is a grey rectangle. Below 55% (you can change the threshold in Settings), every card shows a tile instead: its icon, its name and one fact that matters for its kind — an agent’s status, &lt;code&gt;3/11&lt;/code&gt; on a to-do list, the columns of a board, the first line of a note.&lt;/p&gt;
&lt;p&gt;The card body stays mounted underneath, in its own size — the terminal is not killed, not even refitted. The tile is drawn in screen pixels, so it stays legible at any zoom. Crossing the threshold re-renders zero card bodies and each tile once; panning renders nothing at all.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://neurosquad.ai/blog/fifty-cards-one-canvas/overview-en.webp&quot; alt=&quot;The Launch day workspace zoomed out below 55%: each card is a legible tile with its status&quot;/&gt;&lt;figcaption&gt;“Launch day”, zoomed out: every card turns into a tile with its main fact, while the terminals keep running underneath.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;There is one subtle part. A terminal behind a tile is invisible but not paused — the terminal library’s own visibility check does not see CSS visibility — so it would keep rendering output nobody sees. Instead, the card collects the output and writes it in one go when you zoom back in. Except for one kind of chunk: a question the program asks the terminal (“what are you?”, “where is the cursor?”) is part of a conversation and must be answered now. A delayed answer showed up in a bash prompt as literal &lt;code&gt;1;2c&lt;/code&gt; — found live, and fixed.&lt;/p&gt;
&lt;h2&gt;The Squad card&lt;/h2&gt;
&lt;p&gt;With many agents on a canvas, “who needs me?” should not require a tour of the canvas. The Squad card answers it on one board: every AI agent in the workspace, grouped into &lt;em&gt;needs you&lt;/em&gt;, &lt;em&gt;working&lt;/em&gt;, &lt;em&gt;finished&lt;/em&gt; and &lt;em&gt;idle&lt;/em&gt;, with its CLI, its model and how long the current turn has been running. Click a tile to filter; click a row and the camera flies to that card.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A replica of the Squad card with the app’s own strings. The clocks run; click a tile, then a row.&lt;/em&gt; &lt;a href=&quot;https://neurosquad.ai/en/blog/fifty-cards-one-canvas/&quot;&gt;Live replica — try it&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The model column is more careful than it looks. It shows the model of the agent’s last request as recorded in its own session log; failing that, the model set on the card; failing that, the default from the CLI’s own config file. When none of those exist it says “Default model” — not a guess.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://neurosquad.ai/blog/fifty-cards-one-canvas/squad-en.webp&quot; alt=&quot;The Squad card in the Launch day workspace, listing three Claude Code agents with their status&quot;/&gt;&lt;figcaption&gt;The real card. Its row turns amber once when an agent stops to ask you something.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Squad is added to every workspace once, to the left of the leftmost card. If you delete it, it stays deleted — you can add it back from the menu. Getting “once” right took one more fix: the first version placed the card before the workspace’s saved layout had loaded, and the canvas then laid out every card from scratch. Opening an existing workspace for the first time could pile all its cards up in one corner. That is the bug listed under “Fixed” in this release.&lt;/p&gt;
&lt;p&gt;The add-card menu changed too: agents come first, the ones installed on this computer are marked, there is a search box, and an empty canvas opens with big agent tiles. Full list in the &lt;a href=&quot;https://neurosquad.ai/en/changelog/#v0.1.117&quot;&gt;changelog for 0.1.117&lt;/a&gt;.&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>We wrote our own installer, and NeuroSquad now updates itself</title>
      <link>https://neurosquad.ai/en/blog/own-installer-and-auto-updates/</link>
      <guid isPermaLink="true">https://neurosquad.ai/en/blog/own-installer-and-auto-updates/</guid>
      <pubDate>Thu, 24 Sep 2026 06:17:11 GMT</pubDate>
      <category>Release</category>
      <category>Installer</category>
      <category>Engineering</category>
      <description>Why NeuroSquad replaced its generated installer with its own: a 550 MB download cut to 96 MB, processes named by PID, updates that never leave a half-installed app.</description>
      <content:encoded>&lt;p&gt;&lt;img src=&quot;https://neurosquad.ai/blog/own-installer-and-auto-updates/installer-welcome-en.webp&quot; alt=&quot;The NeuroSquad installer window: choosing the install folder, with the desktop shortcut option&quot;/&gt;&lt;/p&gt;&lt;p&gt;NeuroSquad 0.1.100 is the first version that keeps itself up to date. Getting here took three releases in less than a day, and the most useful lesson of the week: an installer is part of the product. It is the first window people see, and when it fails it fails in the worst place — between an old version that is gone and a new one that is not there yet.&lt;/p&gt;
&lt;h2&gt;From 550 MB to 96 MB&lt;/h2&gt;
&lt;p&gt;The first public installer weighed 550 MB. Most of it was the dictation model: about 640 MB unpacked, bundled so that voice input would work the moment the app opened. But dictation is optional, and making everyone download it to try a canvas of agents was the wrong trade.&lt;/p&gt;
&lt;p&gt;0.1.92 stopped bundling it. The model is now downloaded when you ask for it — at the Dictation step of the setup wizard or later in Settings — and dictation turns itself on as soon as the download completes, without a restart. Until then the status bar says “Dictation: download the model” instead of showing an error. The installer dropped to about 110 MB.&lt;/p&gt;
&lt;p&gt;The rest came from a less glamorous place: what gets packed. The packager copies every production dependency of the app in full, and the desktop app listed the whole UI stack there — component libraries, icon sets, the accessibility toolkit — even though the bundler already compiles all of that into the page. Moving everything only the page needs out of the runtime dependencies saved about 70 MB of files that nothing ever loaded. 0.1.94 shipped at 96 MB.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;550 MB&lt;/strong&gt; — first public installer, 0.1.91&lt;/li&gt;&lt;li&gt;&lt;strong&gt;110 MB&lt;/strong&gt; — without the dictation model, 0.1.92&lt;/li&gt;&lt;li&gt;&lt;strong&gt;96 MB&lt;/strong&gt; — only what the app loads at runtime, 0.1.94&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;The 1.7 GB detour&lt;/strong&gt; One experiment made the installer 1.7 GB. A file list declared for Windows only does not add to the general list — it replaces it — so the build packed everything in the folder. It is now a written rule of the build.&lt;/p&gt;
&lt;h2&gt;Why the generated installer had to go&lt;/h2&gt;
&lt;p&gt;The first installers were generated by the packaging tool, and two bugs in them were bad enough to justify writing our own.&lt;/p&gt;
&lt;p&gt;The first: it refused to install with “NeuroSquad cannot be closed” while NeuroSquad was already closed. Its check was “is any process running from the install folder”, with no names. What was running was the console host of the terminals from agent cards, left behind after the app exited. You could not see them, the message did not name them, and there was nothing to click.&lt;/p&gt;
&lt;p&gt;The second was worse: an interrupted install could leave a half-written app behind. One report was an &lt;code&gt;neurosquad.exe&lt;/code&gt; of 8 MB instead of 200, and no entry in Windows’ list of apps to uninstall it with.&lt;/p&gt;
&lt;h2&gt;The new installer&lt;/h2&gt;
&lt;p&gt;It is a small WPF program for the .NET Framework 4.8 that is already part of Windows 10 and 11, so it needs nothing installed first. The executable itself is about 240 KB; the app is appended to it as an LZMA payload, cut into 32 MB blocks that are packed and unpacked in parallel, with a CRC-32 for every file. The build downloads its C# compiler once and checks it against a pinned SHA-256; no SDK is required on the build machine either.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://neurosquad.ai/blog/own-installer-and-auto-updates/installer-welcome-en.webp&quot; alt=&quot;The installer’s first page: install folder and desktop shortcut&quot;/&gt;&lt;figcaption&gt;Pick the folder — the default one needs no administrator rights — and whether you want a desktop shortcut. The installer speaks English, Russian and Chinese.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;What it does differently is mostly about telling you the truth:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;A live log of every step&lt;/strong&gt;, in the window and in a file in &lt;code&gt;%TEMP%&lt;/code&gt;, so a failure has a line you can point at.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Processes in the way are listed by name and PID&lt;/strong&gt;, and ended only when you press the button. No guessing, no silent kills.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Updates never overwrite in place.&lt;/strong&gt; The new version is unpacked next to the old one, verified, and the two folders are swapped only when everything is there. A failure or a cancel leaves the old version exactly as it was.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Uninstall removes what was installed&lt;/strong&gt; — the files listed at install time, the shortcuts and the Apps entry. Your data is removed only if you tick the box.&lt;/li&gt;&lt;/ul&gt;
&lt;figure&gt;&lt;img src=&quot;https://neurosquad.ai/blog/own-installer-and-auto-updates/installer-processes-en.webp&quot; alt=&quot;The installer listing what holds the install folder: neurosquad.exe and OpenConsole.exe with their PIDs&quot;/&gt;&lt;figcaption&gt;What holds the folder, by name and PID — the app and the terminals of its cards — ended only when you press the button.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://neurosquad.ai/blog/own-installer-and-auto-updates/installer-failed-en.webp&quot; alt=&quot;An installation that could not replace a file: the error, the log, and a note that the previous version is still in place&quot;/&gt;&lt;figcaption&gt;When a file still cannot be replaced, the install stops with its log open, and the version you had stays as it was.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;One detail is invisible and essential: the Start menu shortcut must carry the app’s AppUserModelID. Without it, Windows does not deliver the app’s toast notifications — and “your agent needs you” is the notification the whole product is built around.&lt;/p&gt;
&lt;p&gt;Testing an installer on the machine you develop on is risky, so it has two switches for that. &lt;code&gt;--snapshot&lt;/code&gt; renders every page to a PNG, in any of the three languages. &lt;code&gt;--sandbox&lt;/code&gt; puts the shortcuts and the Apps entry into a folder instead of the Start menu and the registry, so install, update and uninstall can be run end to end without touching the system.&lt;/p&gt;
&lt;h2&gt;Updates that install themselves&lt;/h2&gt;
&lt;p&gt;With an installer that can replace a running copy safely, automatic updates became possible. NeuroSquad checks for a new release at every start and once an hour, downloads it in the background, and verifies its SHA-256 against the checksum the release itself publishes. No checksum, no install.&lt;/p&gt;
&lt;p&gt;Updates are not optional; what you choose is when. A ring in the title bar shows the download; then an icon with a dot lets you update at any moment, and a dialog asks once per version: now, or on the next start. “Now” closes the app, hands over to the installer, which waits for the app to exit, installs over it and starts the new version. The next start installs a known newer version before the app opens at all — and if you are offline, the app gives up after three attempts and opens the version you have.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A replica of the title bar and the update dialog, with the app’s own strings. Pick “Update now” or “On next start”.&lt;/em&gt; &lt;a href=&quot;https://neurosquad.ai/en/blog/own-installer-and-auto-updates/&quot;&gt;Live replica — try it&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;The bug the update test found&lt;/h2&gt;
&lt;p&gt;The update path was tested for real: two builds, a local release feed, an update at start, an update while the app was working, and an offline start with an update already downloaded. With “Update now”, the new version was on screen about ten seconds later.&lt;/p&gt;
&lt;p&gt;Before that, the first run failed — at the folder swap. Something still held the install folder, and it was not the app. It was the same orphaned console host that had confused the old installer: a child process of a card’s terminal, whose &lt;em&gt;working directory&lt;/em&gt; was the install folder, because that is where the app itself was started from. A process holding a folder as its current directory is enough to stop Windows from renaming it.&lt;/p&gt;
&lt;p&gt;The fix is one line at the very top of the app’s startup: change the working directory to the home folder. Children inherit it, and the install folder is no longer anybody’s current directory. 0.1.108 closed the other half: when updating from an older version whose leftover terminals still hold the folder, the installer now lists them with the other processes, and if something it cannot identify still holds a file — an Explorer window, say — it replaces the files one by one instead of giving up, and puts everything back if any step fails.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;An installer is the one part of an app that cannot be fixed by the next update. It has to be right while nothing else is running.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;If you are on 0.1.94 or older, run the new installer once over it; from then on updates arrive by themselves. Everything that changed is in the &lt;a href=&quot;https://neurosquad.ai/en/changelog/#v0.1.100&quot;&gt;changelog for 0.1.100&lt;/a&gt;.&lt;/p&gt;</content:encoded>
    </item>
    <item>
      <title>Why NeuroSquad: agents on a canvas, not in a row of tabs</title>
      <link>https://neurosquad.ai/en/blog/why-neurosquad/</link>
      <guid isPermaLink="true">https://neurosquad.ai/en/blog/why-neurosquad/</guid>
      <pubDate>Wed, 23 Sep 2026 15:33:19 GMT</pubDate>
      <category>Release</category>
      <category>Design</category>
      <description>The first public release of NeuroSquad: why agent CLIs get a card each on one canvas, how the app knows an agent is done or waiting for you, and why arrows are tools.</description>
      <content:encoded>&lt;p&gt;&lt;img src=&quot;https://neurosquad.ai/blog/why-neurosquad/canvas-en.webp&quot; alt=&quot;The NeuroSquad window: a canvas with an agent card, a terminal, a note, a to-do list and a kanban board connected by arrows&quot;/&gt;&lt;/p&gt;&lt;p&gt;Today NeuroSquad 0.1.91 went public — a Windows installer, ten agent CLIs, and a canvas. The first commit was on September 3rd, and along the way agents running in NeuroSquad’s own cards have helped build it. This post is about why it looks the way it does.&lt;/p&gt;
&lt;h2&gt;The problem: a row of tabs you have to babysit&lt;/h2&gt;
&lt;p&gt;Agent CLIs got good enough that one of them is no longer the bottleneck. You start a second one on the tests, a third on the docs, maybe a fourth on another repository. And then the work turns into watching: which tab has finished, which one has been sitting for ten minutes on a question like “may I run this command?”, which one is still going.&lt;/p&gt;
&lt;p&gt;Tabs are the wrong shape for this. They hide everything except the one in front of you, they say nothing about state, and they know nothing about each other. An agent in tab three cannot look at the browser in tab five, even when that is exactly what it needs.&lt;/p&gt;
&lt;p&gt;So NeuroSquad makes three bets. Every agent is a &lt;strong&gt;card with its real terminal&lt;/strong&gt; on a canvas you can see all at once. The app &lt;strong&gt;tells you&lt;/strong&gt; when an agent finishes a turn or needs you, so you stop polling. And an &lt;strong&gt;arrow&lt;/strong&gt; between two cards lets the agent use what the arrow points to.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://neurosquad.ai/blog/why-neurosquad/canvas-en.webp&quot; alt=&quot;The demo workspace in NeuroSquad: an agent card in the middle, with arrows to a terminal, a note and a to-do list&quot;/&gt;&lt;figcaption&gt;The workspace every new install opens with: a real Claude Code card, a real shell, a note, a to-do list and a board. The arrows are the agent’s tools.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;A card is a real terminal, and it must never die&lt;/h2&gt;
&lt;p&gt;A card is not a chat window pretending to be an agent. It is the CLI you already use — Claude Code, Codex CLI, OpenCode, Qwen Code and six more — running in a real pseudo-terminal, with its own interface, its own keys and its own quirks. If the CLI updates tomorrow, the card has the update tomorrow.&lt;/p&gt;
&lt;p&gt;That choice set the first invariant of the whole codebase: &lt;strong&gt;the terminal component may never unmount while its agent is alive&lt;/strong&gt;, because unmounting it kills the process. It sounds obvious. It turned out to shape almost every canvas feature:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Switching workspaces does not replace the canvas. Every workspace opened in a session keeps its own canvas mounted, and the inactive ones are only hidden.&lt;/li&gt;&lt;li&gt;Zooming into a group of cards is a camera move to the group’s frame, not a filter — filtering would unmount the cards outside it.&lt;/li&gt;&lt;li&gt;Expanding a card to full screen is a 1:1 viewport plus a saved geometry, not a different component.&lt;/li&gt;&lt;li&gt;The canvas library deletes a selected node on the Delete key. Here that would mean killing a session with one keystroke, so nodes are not deletable by the library at all: our own listener collects the selection and asks once, in a dialog.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;A lot of Windows plumbing sits under the same bet. The CLI is resolved to an absolute path through the system’s own lookup, because a desktop app does not see the same PATH as your terminal. Paths are passed with forward slashes, because the pseudo-terminal library mangles backslashes — except for &lt;code&gt;cmd.exe&lt;/code&gt;, which reads &lt;code&gt;C:/…&lt;/code&gt; as a list of switches. Variables a parent agent leaves in the environment are stripped before a child agent starts, or the child quietly stops saving its transcript. None of this is visible, and all of it had to be found by running the real thing.&lt;/p&gt;
&lt;h2&gt;“Finished” and “needs you” are different events&lt;/h2&gt;
&lt;p&gt;The whole point of the canvas is that you look away. So the app has to know when to call you back — and there are two very different reasons. &lt;em&gt;Finished&lt;/em&gt; means the agent completed its turn and you can read the answer whenever you like. &lt;em&gt;Needs you&lt;/em&gt; means the agent is blocked, right now, until you approve something.&lt;/p&gt;
&lt;p&gt;The first version could not tell them apart. It watched the terminal: when the window title stopped changing for 1.2 seconds and the output went quiet for 2.5 seconds, the turn was over. That is a fair guess for “finished”, and it is exactly the same silence as an agent waiting on a permission prompt.&lt;/p&gt;
&lt;p&gt;The answer was to ask the agent itself. Claude Code has lifecycle hooks, so each card starts it with a small settings file on top of your own: when you submit a prompt it reports &lt;em&gt;working&lt;/em&gt;, when it raises a notification it reports &lt;em&gt;needs you&lt;/em&gt;, when it stops it reports &lt;em&gt;finished&lt;/em&gt;. Each hook is a single &lt;code&gt;curl&lt;/code&gt; line to a server the app runs on the loopback interface, with the card’s token inside the URL rather than in a header — so the command survives whatever shell it runs in.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Two small rules that matter&lt;/strong&gt; A “needs you” notification carries the agent’s own words — “Claude needs your permission to use Bash” — because a toast that cannot tell a question about &lt;code&gt;rm -rf&lt;/code&gt; from a question about reading a file is noise. And it never times out: a blocked agent does not unblock itself after five seconds.&lt;/p&gt;
&lt;p&gt;Agents that report through hooks switch the old guessing detector off for themselves, or you would get two alerts and the guessed “finished” would overwrite the real “needs you”. CLIs without hooks still get the heuristic. Clicking a notification flies the canvas camera to the card, which flashes green long enough to still be flashing when the camera arrives.&lt;/p&gt;
&lt;h2&gt;Arrows are tools&lt;/h2&gt;
&lt;p&gt;The third bet is the one people ask about most. NeuroSquad runs its own MCP server on &lt;code&gt;127.0.0.1&lt;/code&gt;, and every agent that speaks MCP gets a session on it. What that session contains is decided by the arrows on the canvas.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;An arrow to a browser card gives the agent &lt;code&gt;browser_*&lt;/code&gt; tools: a real Chrome, visible in the card, that the agent clicks and types into while you watch.&lt;/li&gt;&lt;li&gt;An arrow to a terminal card gives it &lt;code&gt;terminal_&lt;em&gt;&lt;/code&gt;: run a command in &lt;/em&gt;that* shell and read its screen.&lt;/li&gt;&lt;li&gt;An arrow to a note gives it &lt;code&gt;note_&lt;em&gt;&lt;/code&gt;, to a to-do list &lt;code&gt;todo_&lt;/em&gt;&lt;/code&gt;.&lt;/li&gt;&lt;li&gt;An arrow to another agent gives it &lt;code&gt;agent_*&lt;/code&gt; — and that arrow has a direction. It points from the lead to the helper; the helper cannot send work back up.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;The arrow is the permission. No arrow, no tool — which makes the canvas an honest picture of what every agent is allowed to reach. And every call is drawn on its arrow as it happens, so you can see the lead handing a task to a helper instead of reading about it in a log.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A replica of the canvas, running on this page: a lead agent sends tasks to three helpers along its arrows, and each helper moves its own card on the board.&lt;/em&gt; &lt;a href=&quot;https://neurosquad.ai/en/blog/why-neurosquad/&quot;&gt;Live replica — try it&lt;/a&gt;&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://neurosquad.ai/blog/why-neurosquad/arrows-en.webp&quot; alt=&quot;Close-up of an agent card with arrows to a terminal, a note and a to-do list&quot;/&gt;&lt;figcaption&gt;The same wiring in the real app. Each arrow is a set of tools the agent has; the rest of the canvas is out of its reach.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;Local by default&lt;/h2&gt;
&lt;p&gt;There is no account and no server of ours in the loop. Workspaces, cards and arrows are JSON files in the app’s data folder. Dictation is recognized on your computer, with Parakeet or Whisper. The Usage section reads tokens and cost from the agents’ own logs rather than from a proxy in front of them. Deleting a card never touches your project folder.&lt;/p&gt;
&lt;p&gt;The release has more than this post can cover: &lt;a href=&quot;https://neurosquad.ai/en/remote/&quot;&gt;remote access&lt;/a&gt; that runs the whole app in a phone’s browser, isolated git worktrees per agent, and a budget brake that interrupts every agent in a workspace when a spending limit is reached — with Ctrl+C, not a kill, so no session is lost.&lt;/p&gt;
&lt;h2&gt;What is next&lt;/h2&gt;
&lt;p&gt;The first build ships as a 550 MB installer, and most of it is a speech model that only people who dictate will ever load. That is the first thing to fix. After that: an installer that tells you exactly what is in its way, and updates that install themselves.&lt;/p&gt;
&lt;p&gt;The full list of what is in 0.1.91 is in the &lt;a href=&quot;https://neurosquad.ai/en/changelog/#v0.1.91&quot;&gt;changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded>
    </item>
  </channel>
</rss>
