# NeuroSquad Docs > NeuroSquad is a free desktop app for Windows and macOS that runs AI coding agent CLIs — Claude Code, Codex CLI, Gemini CLI, OpenCode and 15 more — side by side as live terminal cards on one canvas or in a grid. An arrow from an agent to another card gives the agent that card’s tools: a browser, a terminal, a note, an MCP server or another agent. It tells you when an agent finishes or needs your input, can be driven from a phone, and shows exactly what each agent costs. This is its user guide. - Download for Windows or macOS: https://neurosquad.ai/en/download/ - Product site (facts, FAQ, agent CLIs, plugins, changelog): https://neurosquad.ai/llms.txt The short index: https://docs.neurosquad.ai/llms.txt --- ## What is NeuroSquad > A two-minute tour of what NeuroSquad does and the few ideas behind it. Source: https://docs.neurosquad.ai/en/getting-started NeuroSquad is a free desktop app for Windows and macOS for working with AI coding agents — Claude Code, Codex, Gemini CLI, Qwen Code and [15 more agent CLIs](https://docs.neurosquad.ai/en/agents). Instead of juggling terminal windows, you get **one big canvas** where every agent lives in its own card, next to the tools it works with. Press play and watch one turn: ### Four ideas, and you know the whole app - **Workspace**: One project folder. Every agent you add to a workspace works inside that folder. The sidebar lists your workspaces. - **Card**: Anything on the canvas: an agent, a terminal, a browser, a note, a task board and [many more](https://docs.neurosquad.ai/en/cards). You drag them, resize them and group them however you like. - **Arrow**: A line from one card to another. An arrow from an agent **gives it the ability** to use the other card — browse in that browser, run commands in that terminal, write in that note, or hand work to that agent. [More about arrows](https://docs.neurosquad.ai/en/canvas/arrows). - **Attention**: When an agent finishes, or stops to ask you something, NeuroSquad tells you: a sound, a glowing card, a desktop notification. You can look away and still not miss it. ### What it is not - **Not a new AI.** NeuroSquad runs the agents you already have, with your own accounts. It doesn't replace them. - **Not a cloud service for your code.** Your agents, projects and files stay on your computer. You sign in with a free NeuroSquad account, and the app sends usage statistics — counts, never code, files or prompts. See [Account & sign-in](https://docs.neurosquad.ai/en/getting-started/account). ### Next - **[Install](https://docs.neurosquad.ai/en/getting-started/installation)**: Download the installer, run the setup wizard, done. - **[Your first workspace](https://docs.neurosquad.ai/en/getting-started/first-workspace)**: Point NeuroSquad at a project. --- ## Install > Download the NeuroSquad installer for Windows, choose where to install it, and let the setup wizard get everything else ready. Source: https://docs.neurosquad.ai/en/getting-started/installation NeuroSquad comes as a ready-made installer for **Windows 10 and 11 (64-bit)**. The download is a small web installer (160 KB): it fetches the latest version (about 100 MB), checks its SHA-256 checksum and starts setup. There is nothing to build and no terminal involved. On a Mac, see [Install on macOS](https://docs.neurosquad.ai/en/getting-started/macos); a Linux version is coming later. [Go to the download page](https://neurosquad.ai/en/download/) **1. Download NeuroSquad-Installer.exe** Open the [download page](https://neurosquad.ai/en/download/) on our site and press **Download for Windows**. When you run it, it downloads the latest NeuroSquad, checks it and opens setup. **2. Run it — and get past SmartScreen** The installer isn't code-signed yet, so Windows may show a blue **Windows protected your PC** window. Click **More info**, check that the app is `NeuroSquad-Installer.exe`, then press **Run anyway**. **3. Choose where to install** The **Install location** is filled in for you: `%LOCALAPPDATA%\Programs\NeuroSquad`. Keep it, or pick another folder with **Browse…** — the line below shows how much space NeuroSquad needs (369 MB) and how much the disk has free. Leave **Desktop shortcut** on if you want a NeuroSquad icon on your desktop. The default folder installs NeuroSquad for your Windows account only, and the note at the bottom says **no administrator rights needed**. A folder such as Program Files says **needs administrator rights · Windows will ask** instead — Windows then asks for permission when you press Install. **4. Press Install** The window shows each step, how many files are unpacked and a progress bar. **Show log** opens the setup log: every file with its size and checksum, with timestamps. **Cancel** works while the files are being unpacked, and removes whatever was copied so far. **5. Launch NeuroSquad** When you see **NeuroSquad is installed**, press **Launch NeuroSquad**. From now on it's in the Start menu (and on the desktop, if you kept the shortcut). > SmartScreen shows that warning for any new app that isn't signed with a certificate yet. Only ever > download the installer from our [download page](https://neurosquad.ai/en/download/). ### Install from a terminal The same installer, unattended: for your Windows account, without administrator rights. Every way checks the download against its SHA-256 checksum before running it, and NeuroSquad keeps itself up to date afterwards whichever way you installed it. **winget** — Windows Package Manager, built into Windows 10 and 11: ```powershell winget install NeuroSquad.NeuroSquad ``` **Scoop** — adds the NeuroSquad bucket, then installs into Scoop's apps folder: ```powershell scoop bucket add neurosquad https://github.com/glmn-ai/scoop-neurosquad scoop install neurosquad ``` **PowerShell** — downloads the latest version, installs it into `%LOCALAPPDATA%\Programs\NeuroSquad` and starts NeuroSquad (Windows PowerShell 5.1 or PowerShell 7): ```powershell irm https://neurosquad.ai/install.ps1 | iex ``` ### Sign in On first launch NeuroSquad asks you to sign in to your NeuroSquad account — it's free. Your browser opens app.neurosquad.ai: sign in with a code sent to your email or with Google, press **Connect**, and the app picks it up. Until then the app shows only its sign-in screen. Step by step, and what the app sends while you're signed in: [Account & sign-in](https://docs.neurosquad.ai/en/getting-started/account). ### The setup wizard Once you're signed in, NeuroSquad checks what your computer already has and offers to install what is missing. Nothing changes until you press a button, and every step can be skipped — the one exception is Node.js (below). **1. Agent CLI** The AI agent your cards will run. If you already have one, the wizard says so. If not, pick Claude Code, Codex CLI, OpenCode or Kilo Code and press **Install it for me** — the wizard installs it with npm and shows exactly which command runs. No npm yet? The agent CLIs need it, so the wizard installs Node.js LTS by itself: the official archive from nodejs.org, checked against its published SHA-256, for your account only — no administrator rights. On Windows the installer already does this at install time when Node.js is missing; a Node.js you already have is never touched. **2. Terminal & Git** Git for Windows brings Git Bash, which terminal cards and isolated worktrees use. The wizard installs it with `winget` — and always asks first. **3. Dictation** The speech model for voice input isn't part of the installer — it's a separate download. Pick a model and press **Download**, or skip the step: dictation is optional and nothing else depends on it. You can download it later in **Settings → Dictation**; until then the status bar says **Dictation: download the model**. See [Speech models](https://docs.neurosquad.ai/en/dictation/models). **4. Ready** Press **Start working**. You can reopen the same steps any time in **Settings → Setup**. > You still sign in to each agent the usual way — run it once in its card and follow its own login > prompt. NeuroSquad never asks for your keys. ### Updating NeuroSquad updates itself. To update by hand, run `NeuroSquad-Installer.exe` from the [download page](https://neurosquad.ai/en/download/) again — it always fetches the newest version. Setup finds the installed version on its own: the location points at the existing install folder, the button reads **Update**, and a note says your workspaces, agents and settings are kept — they live in `%APPDATA%\NeuroSquad`, not in the app's own folder. If NeuroSquad is still running, the installer shows **NeuroSquad is still running** with every process that keeps its files busy — the app itself and the terminals of its cards — by name and PID. Close NeuroSquad yourself and press **Check again**, or press **End them and continue** (terminals open in NeuroSquad cards will stop). The new version is unpacked next to the old one and swapped in only once it is complete. If the update fails or you cancel it, the version you had stays untouched. ### Uninstalling Open **Windows Settings → Apps**, find **NeuroSquad** and choose **Uninstall** (or run `Uninstall NeuroSquad.exe` in the install folder). It removes exactly the files it installed, the shortcuts and the Apps entry. Files you put into the install folder yourself stay. Your data stays too, unless you turn on **Also delete my NeuroSquad data** (off by default). That deletes `%APPDATA%\NeuroSquad`: the workspace list, agents, settings, dictation models and the agents' isolated worktrees — uncommitted work in those worktrees is lost. Your project folders are never touched. See [Where your data lives](https://docs.neurosquad.ai/en/help/data). ### Unattended install For IT admins and scripts, the installer runs without a window. The full installer of the newest release is at `https://neurosquad.ai/downloads/NeuroSquad-Setup.exe`; the web installer passes the same options on to it. ```text NeuroSquad-Setup.exe --silent [--dir ] [--no-desktop] [--launch] [--close-app] ``` - `--dir` — install location (default: `%LOCALAPPDATA%\Programs\NeuroSquad`, or the existing install) - `--no-desktop` — no desktop shortcut - `--launch` — start NeuroSquad when done - `--close-app` — end running NeuroSquad processes instead of failing Exit codes: `0` installed, `1` failed, `2` files in use (NeuroSquad is running and `--close-app` wasn't given). To uninstall silently: ```text "Uninstall NeuroSquad.exe" --silent [--delete-data] ``` ### If something goes wrong The failure page says what happened in plain words, shows the details and the log, and offers **Try again**. If the installer fails before replacing anything, your previous version still works. The installer keeps a full log of every run in `%TEMP%\NeuroSquad-Setup-.log`, and a copy of it as `install.log` in the install folder. Press **Copy log** or **Open log file** in the log panel, and attach the log when you report a problem. ### Next - **[Your first workspace](https://docs.neurosquad.ai/en/getting-started/first-workspace)**: Point NeuroSquad at a project folder — or explore the demo. --- ## Install on macOS > Install NeuroSquad on a Mac with Apple silicon or Intel — from Terminal in one line or from a .dmg — and what macOS asks on the first launch. Source: https://docs.neurosquad.ai/en/getting-started/macos NeuroSquad runs on **macOS 12 Monterey or newer**, with separate builds for **Apple silicon** (M1, M2, M3, M4 and newer) and **Intel** Macs. Not sure which one you have? Open the Apple menu → **About This Mac**: "Chip: Apple M…" means Apple silicon, "Processor: Intel" means Intel. [Go to the download page](https://neurosquad.ai/en/download/#macos) ### From Terminal (recommended) One line picks the right build for your Mac, checks it against its published SHA-256 checksum, puts **NeuroSquad.app** into **Applications** and opens it: ```bash curl -fsSL https://neurosquad.ai/install.sh | bash ``` If your macOS account can't write to `/Applications`, the script installs into `~/Applications` instead — no administrator password either way. A copy installed this way opens straight away, without even the first-launch question described below. Running the line again updates an existing install. ### With Homebrew If you use [Homebrew](https://brew.sh), install NeuroSquad from our own tap: ```bash brew install --cask glmn-ai/neurosquad/neurosquad ``` It installs the build for your chip, checked against its SHA-256 checksum, and removes the download mark so the app opens without the first-launch question. NeuroSquad then updates itself, so `brew upgrade` leaves it alone (`brew upgrade --greedy` updates it too). `brew uninstall --cask neurosquad` removes the app; add `--zap` to delete your NeuroSquad data as well. ### From a .dmg **1. Download the .dmg for your Mac** On the [download page](https://neurosquad.ai/en/download/#macos) press **Download .dmg** under **Apple silicon** or **Intel** (the page highlights the one your browser reports). Direct links: [Apple silicon](https://neurosquad.ai/downloads/NeuroSquad-arm64.dmg), [Intel](https://neurosquad.ai/downloads/NeuroSquad-x64.dmg); checksums — [SHA256SUMS-mac.txt](https://neurosquad.ai/downloads/SHA256SUMS-mac.txt). **2. Drag NeuroSquad into Applications** Open the .dmg and drag **NeuroSquad** onto the **Applications** folder next to it. **3. First launch: press Open** NeuroSquad is signed with an Apple Developer ID and notarized by Apple. The first time you open a copy downloaded in a browser, macOS asks the question it asks for every app from the internet: **“NeuroSquad” is an app downloaded from the Internet. Are you sure you want to open it?** — and adds that Apple checked it for malicious software and none was detected. Press **Open**. macOS doesn't ask again. > The question is about how the file was downloaded, not about the app: a browser marks every > download as "from the internet". The Terminal install, Homebrew and NeuroSquad's own updates > download without that mark, so they skip even this question. #### If macOS still refuses to open it Versions before 0.1.218 were not notarized. If macOS says **“NeuroSquad” Not Opened**, that Apple could not verify it, or that it is damaged, you most likely have such an older copy: move it to the Trash and download the .dmg again from the [download page](https://neurosquad.ai/en/download/#macos), or install with the Terminal line or Homebrew above. Your data stays where it is. ### Permissions for dictation Voice dictation asks macOS for two things. **Settings → Dictation** shows what is still missing, with an **Allow** button and a shortcut to the right page of System Settings: - **Microphone** — to record your voice. macOS asks the first time you dictate. - **Accessibility** — for the global dictation hotkey, which works in any app. Turn **NeuroSquad** on in **System Settings → Privacy & Security → Accessibility**; the hotkey starts working as soon as it's allowed. These permissions stay granted after updates. One exception: if you installed version 0.1.214, the first Mac build, macOS asks for Microphone and Accessibility once more after the update to 0.1.218, because that is when the app's signature changed to the Apple Developer ID. ### Sign in and the setup wizard The rest is the same as on Windows — see [Sign in](https://docs.neurosquad.ai/en/getting-started/installation#sign-in) and [The setup wizard](https://docs.neurosquad.ai/en/getting-started/installation#the-setup-wizard). On a Mac the wizard installs agent CLIs with npm and, when there is no npm, Node.js LTS into `~/.neurosquad/node` (no shell profile is edited); Git it can't install unattended, so it points you to its download page (with Homebrew: `brew install git`). Terminal cards use your login shell (`$SHELL`, zsh by default), and NeuroSquad finds CLIs installed with Homebrew, npm, bun, cargo and the like even though apps started from the Dock get a minimal `PATH`. ### Updating NeuroSquad updates itself, as on Windows: a newer version downloads in the background, is checked against its SHA-256 checksum, and installs when you restart — the app is replaced in its folder and opens again. **NeuroSquad → Check for Updates…** in the menu bar checks right away. If NeuroSquad can't write to its own folder (for example, it's in `/Applications` and your account isn't an administrator), it unpacks the update into **Downloads** and shows it in Finder instead: quit NeuroSquad and drag the new copy into Applications, replacing the old one. ### Closing and quitting The red close button hides the window; NeuroSquad and its agents keep running, and clicking its Dock icon brings the window back. Quit with **Cmd+Q** (or **NeuroSquad → Quit NeuroSquad**) — that stops the agents' terminals. ### Uninstalling Quit NeuroSquad and move **NeuroSquad.app** from Applications to the Trash. Your data — workspaces, agents, settings, dictation models — stays in `~/Library/Application Support/NeuroSquad`; delete that folder too if you want everything gone. Your project folders are never touched. See [Where your data lives](https://docs.neurosquad.ai/en/help/data). --- ## Account & sign-in > Why NeuroSquad asks you to sign in, how signing in from the app works, your plan and devices, working offline, and exactly which usage statistics the app sends. Source: https://docs.neurosquad.ai/en/getting-started/account NeuroSquad works with a **NeuroSquad account**. It's free: every account is on the **Free** plan, with no limits. You sign in once on each computer, in your browser, with a code sent to your email or with Google. Your code, files, prompts and terminals stay on your computer — the account doesn't change that. It changes two things: the app asks you to sign in, and while you're signed in it sends **usage statistics** — counts, never content. The full list is [below](#what-the-app-sends). ### Why an account - **Your plan belongs to you**, not to one computer. - **You see every computer** that uses your account, and can sign any of them out. - **We learn how NeuroSquad is used** — which agents, cards and features — so we know what to build next. ### Sign in from the app Until you sign in, NeuroSquad shows only the sign-in screen: no canvas, and no agents start. **1. Your browser opens** The app opens **app.neurosquad.ai** in your default browser and shows a short code, like `ABCD-EFGH`. **2. Sign in on the page** Enter your email and type the 6-digit code we send you (it's valid for 10 minutes), or press **Google**. A new email simply creates a new account — there's no separate sign-up. **3. Connect this computer** The page asks whether to connect NeuroSquad on your computer — by its name — and shows the same code. Check that it matches the code in the app and press **Connect**. The page then says **Done — return to NeuroSquad**. **4. Back in the app** The app notices by itself within a few seconds — or press **I've signed in** to check right away. Closed the tab by mistake? **Open the browser again** brings it back. The code works for 10 minutes; after that, start over. > Press **Connect** only for a code you see in your own NeuroSquad window. Connecting someone else's > code signs *their* computer in to *your* account. ### Your plan The app shows the account you're signed in with and its plan. Today every account is on **Free — unlimited**. ### Switch account or sign out Signing out returns the app to the sign-in screen. Nothing on your computer is deleted: workspaces, agents, notes and settings stay where they are, and they're there again after you sign back in — with the same account or another one. ### Manage your account on the web Open [app.neurosquad.ai/account](https://app.neurosquad.ai/account) in any browser and sign in the same way. There you can: - **Change your name and picture.** Pictures can be PNG, JPEG or WebP up to 2 MB; they're re-encoded to 256×256 and their metadata is removed. Without a picture, you get a circle with your initials — the same one in the app and on the web. - **See your devices** — each computer's name, system, app version and when it was last seen — and **sign out** any of them. That computer goes back to its sign-in screen. - **Delete your account.** You confirm it with a code sent to your email. The account and its usage statistics are deleted; nothing on your computers is touched. ### Working offline You need the internet to sign in. After that, NeuroSquad keeps working when NeuroSquad Cloud can't be reached: the app works as usual and shows a quiet **offline** note. This lasts **7 days** from the last time the app reached the cloud; after that it asks you to sign in again. If this computer's session ends — for example, you signed it out on the web — the app goes back to the sign-in screen. Your data on the computer is untouched. ### What the app sends While you're signed in, the app sends these usage statistics to NeuroSquad Cloud (`api.neurosquad.ai`) — and nothing else. Your computer is identified by a random install ID, and each workspace by a random ID made for it, never by its folder or name. The statistics are linked to your account, and the NeuroSquad team can see them account by account. | When | What | | --- | --- | | Every minute while the app runs | App version, operating system, whether the window is in focus, how many workspaces are open, how many agents of each agent CLI are running | | When the app starts | App version, operating system and its version, the app's language; the first start of a new install is marked | | When a workspace opens, then every 30 minutes | How many cards of each type, agents of each agent CLI, arrows and groups it has | | When an agent starts | Which agent CLI, its own login or OpenRouter, whether dangerous mode and canvas mode are on | | When you use certain features | The feature's name, from a fixed list built into the app | | Each time you dictate | How long the recording was, which speech model and engine (CPU or GPU), whether text came out — never the text | | When you sign in, and with each of the above | Your country, worked out on the server from your IP address — the IP itself is not stored | Individual events are kept for 90 days; daily totals made from them (such as how many people were active that day) are kept after that. #### Never sent - Code, file contents, file names, folder paths, repository addresses - Names of workspaces, cards and agents - Prompts, agent answers, terminal output - Environment variables, passwords, tokens and API keys The server rejects any field that isn't on its list, so even a bug in the app can't slip content in. The agents themselves still talk to their own AI services directly, the way they always do — not through NeuroSquad. The complete privacy notice is on [neurosquad.ai/en/privacy](https://neurosquad.ai/en/privacy/). ### Next - **[Your first workspace](https://docs.neurosquad.ai/en/getting-started/first-workspace)**: Point NeuroSquad at a project folder — or explore the demo. - **[Where your data lives](https://docs.neurosquad.ai/en/help/data)**: What stays on your computer, and how to back it up. --- ## Your first workspace > Create a workspace for a project folder, or open the ready-made demo and Launch day workspaces to look around first. Source: https://docs.neurosquad.ai/en/getting-started/first-workspace A **workspace** is a project folder. Every agent in it starts in that folder, so it already knows what "the code" means. ### Look around the demo first On a brand-new installation NeuroSquad creates a small **NeuroSquad demo** workspace: a **Lead** Claude Code agent already wired to a terminal, a **Start here** note and a **Try these** todo list, plus a task board and a note that explains how arrows work. A first prompt is typed into the agent, waiting for you to press Enter. It lives in a scratch folder — nothing of yours is touched. If you delete it and want it back, the empty canvas has a button to open it again. ### See everything at once: "Launch day" Want to see a full setup? Open **What's new** at the bottom of the sidebar and press **Open Launch day**. You get a small online shop getting ready for a launch, laid out in five framed chapters: - **Start here** — a sticky, a guide note and a todo-list tour. - **Build squad** — three Claude Code agents (**Lead**, **Frontend**, **Backend**) and a task board whose tasks are already assigned to them. Press **Start** to begin. - **Dev tools** — a dev server terminal, a browser and a dev servers card. - **Business desk** — notes, a Telegram bot card and a reference card with mockups. - **Mission control** — standup, budget, a web watch and a flow timer. Like the demo, it lives in a scratch folder. Deleting it costs nothing. ### Create a workspace **1. Press + next to Workspaces in the sidebar** The **Create workspace** dialog opens. **2. Give it a name** Something meaningful to you — "Online shop", "Blog", "Client X". **3. Choose the project folder** Press **Browse…** and pick the folder with your project. Agents will work there. **4. Pick an accent colour (optional)** Handy once you have several workspaces — it marks the workspace in the sidebar. > Deleting a workspace only removes it from NeuroSquad. The folder and your files stay exactly where > they are. ### Optional extras If your agents will work in [isolated worktrees](https://docs.neurosquad.ai/en/agents/worktrees), the workspace's edit dialog also lets you add a **setup command** (for example, installing dependencies), **files to copy** into each new worktree (like `.env`), and a **run command** that starts your project and opens it in a browser card. The same dialog holds the [instructions file](https://docs.neurosquad.ai/en/agents/instructions) mirror. ### Next - **[Your first agent](https://docs.neurosquad.ai/en/getting-started/first-agent)**: Add an agent and send it a prompt. --- ## Your first agent > Add an agent card, send your first prompt, and get notified when it's done. Source: https://docs.neurosquad.ai/en/getting-started/first-agent Every card starts in the same menu. The main button adds the agent you used last; the arrow next to it opens everything else. Point at anything in it: **1. Open the add menu** With a workspace open, press **Add Claude Code** (or the arrow next to it) at the top right of the canvas, the add row under the workspace in the sidebar, or the button on an empty canvas. It is the same menu everywhere. **2. Pick an agent** Choose one of the AI agents you have installed — say, **Claude Code**. A card appears with a live terminal, and the agent starts in your project folder. Want to pick a model or a role first? Choose **New agent… (provider, model, role)** — see [OpenRouter](https://docs.neurosquad.ai/en/providers/openrouter) and [Roles](https://docs.neurosquad.ai/en/agents/roles). **3. Type your prompt** Click into the card and type, just like in a normal terminal. Try: *"Look around this project and tell me what it does."* **4. Look away** Switch to something else. When the agent finishes — or needs your answer — you'll hear a chime, the card will glow, and a desktop notification will name the agent. See [Finished / needs your input](https://docs.neurosquad.ai/en/agents/notifications). The card's title fills itself in from what the agent is working on. Click the title to give it your own name. > If the agent asks whether it can trust the folder, NeuroSquad answers for you — you already chose > this folder when you created the workspace. ### Where to go next - **[Give it abilities](https://docs.neurosquad.ai/en/canvas/arrows)**: Connect a browser or a terminal with an arrow. - **[Notifications](https://docs.neurosquad.ai/en/agents/notifications)**: "Finished" versus "needs your input". - **[Everything in an agent card](https://docs.neurosquad.ai/en/agents/card-menu)**: The header and the ⋯ menu, row by row. - **[Add a second agent](https://docs.neurosquad.ai/en/squads)**: And let the first one lead. --- ## Finding your way around > The sidebar and its five sections, the canvas, the top bar and the status bar — what's where. Source: https://docs.neurosquad.ai/en/getting-started/the-window Point at the blue dots to see what each part of the window is for: ### The sidebar A row of five buttons at the top of the sidebar switches between its sections. Badges on them count the agents that are working, the ones waiting for you and the open tasks. Click through them: - **Workspaces**: Your projects and, inside each, its agents and groups. A spinning ring around an agent's icon means it's working right now. - **Agents**: Every AI agent across all workspaces, grouped by what it's doing: **Needs input**, **Working**, **Finished**, **Idle**, **Not running**. Filter by name, workspace or agent type. - **Inbox**: Everything waiting on you — agents that finished or stopped to ask something. **Mark all seen** when you've caught up. - **Tasks**: The tasks from every [task board](https://docs.neurosquad.ai/en/cards/kanban) and [todo list](https://docs.neurosquad.ai/en/cards/todo), across workspaces. - **Integrations**: Your [Telegram cards](https://docs.neurosquad.ai/en/integrations/telegram) and your [model providers](https://docs.neurosquad.ai/en/providers). At the bottom: **Features** (the attention inbox, templates, the crash log, activity and command history), **Usage**, **What's new** and **Settings**. Drag the sidebar's edge to make it wider or narrower. ### The rest of the window - **Canvas (centre)**: Where your cards live. Pan, zoom, move cards, draw arrows. See [Canvas basics](https://docs.neurosquad.ai/en/canvas). - **Top bar**: Shows where you are (workspace › group), then the remote access button, the notifications bell, the [Squad board](https://docs.neurosquad.ai/en/squads) button, the dictation history button and the window buttons. - **Status bar (bottom)**: How many agents are running or waiting, the app version (click it to see what's new) and the dictation status. - **Dictation history (right)**: Everything you dictated recently, ready to copy again. See [Dictation history](https://docs.neurosquad.ai/en/dictation/history). ### Handy shortcuts | Shortcut | What it does | | --- | --- | | `Ctrl Shift P` | Jump to any agent by name | | `Ctrl Shift J` | Fly to the agent that has been waiting for you the longest | | `Ctrl Shift F` | Search the output of all agents | | `Ctrl Shift Space` | Start or stop dictation | | `F5` | Present the canvas card by card | The full list is in [Keyboard shortcuts](https://docs.neurosquad.ai/en/help/shortcuts). --- ## Canvas basics > The canvas is an endless board where your agents and their tools live as cards. Source: https://docs.neurosquad.ai/en/canvas Every workspace has its own **canvas** — an endless board you can pan and zoom. Everything you add to a workspace appears on it as a **card**. Switching to another workspace doesn't stop anything: agents in other workspaces keep working in the background, and the sidebar shows which ones are busy. - **[Adding and arranging cards](https://docs.neurosquad.ai/en/canvas/cards)**: Add, move, resize, rename and delete cards. - **[Arrows give abilities](https://docs.neurosquad.ai/en/canvas/arrows)**: Connect cards so agents can use them. - **[Groups](https://docs.neurosquad.ai/en/canvas/groups)**: Put related cards in a named frame. - **[Zoom, pan and undo](https://docs.neurosquad.ai/en/canvas/moving-around)**: Get around a big canvas; overview tiles when zoomed out. - **[Canvas tools](https://docs.neurosquad.ai/en/canvas/tools)**: Guides, minimap, colour tags, presentation mode, arrow log, templates. --- ## Adding and arranging cards > How to add, move, resize, rename, select and delete cards on the canvas. Source: https://docs.neurosquad.ai/en/canvas/cards ### Add a card Press **Add Claude Code** at the top right of the canvas (the name is whichever agent you added last), or the arrow next to it for everything else. The sidebar's add row and the empty canvas open the same menu: - **AI agents** — Claude Code, OpenCode, Hermes Agent, Kilo Code, Codex CLI, Pi, omp, Cursor CLI, Qwen Code and Crush, plus **New agent…** to pick a provider, model and role first. - **Terminals** — your system shell, Windows PowerShell, PowerShell 7, Command Prompt and Bash (only the ones found on your computer). - **Cards** — browser, note, todo list, budget, task board, Telegram bot, reference, dev servers, web watch, flow timer, sticky and standup. See [All cards](https://docs.neurosquad.ai/en/cards). A new card lands to the right of the last one. Cards that an agent creates for itself appear around that agent. ### Move, resize, rename - **Move:** drag the card by its header. - **Resize:** drag a card's edge or corner. - **Rename:** click the title in the header and type. - **Expand:** the expand button in the header makes a card fill the canvas; press it again to go back. ### Select several cards Hold `Shift` and drag across empty canvas to draw a selection box, or hold `Shift` or `Ctrl` and click cards one by one. Then drag them together. ### Delete Select one or more cards and press `Delete`. An agent's **Delete agent** is the last row of its ⋯ menu; other cards have a delete button in the header. NeuroSquad always asks first, because deleting an agent ends its running session. > Deleting a card never deletes files in your project. ### Pop out An agent card can be popped out into its own window (**Pop out to new window** in its ⋯ menu) — handy on a second monitor. It is the same agent, just shown in two places. --- ## Arrows give abilities > Draw an arrow from an agent to another card, and the agent can use that card. Source: https://docs.neurosquad.ai/en/canvas/arrows This is the most important idea in NeuroSquad. **An arrow from an agent to a card gives that agent the ability to use the card.** Watch it from the first arrow to the arrow log: ### Draw an arrow Hover a card — small dots appear on its edges. Drag from a dot onto another card and let go. To remove an arrow, select it and press `Delete`, or double-click it. ### What each arrow gives | Arrow from an agent to… | Its label | The agent can… | | --- | --- | --- | | a [browser](https://docs.neurosquad.ai/en/cards/browser) | browser tools | open pages, click, type, read what's on screen and in the console | | a [terminal](https://docs.neurosquad.ai/en/cards/terminal) | terminal tools | run commands and read their output | | a [note](https://docs.neurosquad.ai/en/cards/note) | shared note | read and write the note | | a [todo list](https://docs.neurosquad.ai/en/cards/todo) | todo list | write its plan and tick tasks off | | a [task board](https://docs.neurosquad.ai/en/cards/kanban) | task board | add tasks and move its own tasks along | | another agent | squad link | hand it tasks and read its answers — see [Squads](https://docs.neurosquad.ai/en/squads) | Other cards work with arrows too: a [dev servers](https://docs.neurosquad.ai/en/cards/dev-servers) card tells a connected agent which servers are running, a [reference](https://docs.neurosquad.ai/en/cards/reference) card lets it read your mockups and specs, a [web watch](https://docs.neurosquad.ai/en/cards/web-watch) tells it when a page changes, and a [Telegram](https://docs.neurosquad.ai/en/integrations/telegram) card passes your messages on and lets it answer. ### Watch it happen While an agent is using a card, the arrow comes alive and shows what it's doing — "Opening", "Clicking", "Running", "Adding to the note". You always see which agent is touching what. ### Arrow log Click an arrow to open its **Arrow log**: every command, page visit, note or delegated task that went over it, with times — kept across restarts. **Clear log** empties it. > Every supported agent can use connected cards — **aider** and **Pi** through a NeuroSquad > extension, since they have no MCP client of their own. See [Supported agents](https://docs.neurosquad.ai/en/agents) for what > else each one gets. --- ## Grid mode > See your agents side by side in a tidy, resizable grid — and switch back to the canvas any time. Source: https://docs.neurosquad.ai/en/canvas/grid-mode The canvas is great for building a squad: place cards anywhere, draw arrows, group them. When the squad is just *working*, you often want the opposite — every agent's terminal on screen at once, neatly lined up. That's **Grid mode**. Switch with the **Canvas / Grid** toggle in the title bar, or press `Ctrl` `Shift` `G` (`⌘` `Shift` `G` on a Mac). Each workspace remembers its own mode. > Switching never restarts anything. The same terminals move between the canvas and the grid — > sessions keep running, and what's on screen stays exactly where it was. ### Layouts The bar above the grid picks a layout: | Layout | What you get | | --- | --- | | All tiles | Every agent, in a tidy grid that fits your window | | One tile | One agent fills the area | | Two side by side | Two agents, left and right | | 2 × 2 | Four agents | | 3 × 2 | Six agents | | Focus and stack | One large agent on the left, up to three stacked on the right | When a layout has fewer places than you have agents, the rest wait in the **Not in view** strip under the grid. Click one to bring it in — it takes the place of the tile you were using. Tiles never get too small to read: with many agents in a small window, the grid scrolls instead of shrinking them. The **add** button in the bar adds an agent or card without leaving the grid (in a group, the new card joins that group). ### Arrange the tiles - **Resize:** drag the thin line between two tiles. Double-click the line to even them out again. - **Tidy:** makes every tile in the current layout the same size. - **Swap:** drag a tile by its header (its name works too) onto another tile. - **Maximize:** the expand button in a tile's header (or `Ctrl` `Alt` `Enter`) lets one agent fill the grid; press it again to go back. - **Move between tiles:** `Ctrl` `Alt` and the arrow keys — the terminal you land on is ready to type in. - **Undo:** `Ctrl` `Z` steps back through layout changes in the grid (outside a terminal). ### What's connected to what Under each tile, a row of chips shows the tile's [arrows](https://docs.neurosquad.ai/en/canvas/arrows): the agents it leads or reports to, and the cards it uses — a note, a browser, an MCP server, a skill, a plugin. The small arrow on each chip shows the direction. - Hover a tile and the tiles it's wired to light up. - Click a chip of another agent to jump to that agent's tile. - Click a chip of any other card to see what it is and what it's connected to, with a **Show on canvas** button. Arrows are drawn and removed on the canvas; the grid shows them. ### Filters - **Only agents** hides terminals, notes, browsers and every other card, leaving just the AI agents. - **Cards** shows or hides the side strip with everything that isn't a tile — notes, to-dos, the browser, MCP and skill cards. Hover a card there to see which tiles it's wired to; collapse the strip to a thin rail of icons. - The **Squad** button opens or closes the Squad panel on the right. The grid follows the sidebar: pick a group and you see only that group's agents. --- ## Groups > Put related cards inside a named, coloured frame and zoom to it in one click. Source: https://docs.neurosquad.ai/en/canvas/groups A **group** is a named, coloured frame on the canvas. Use it to keep a squad, a feature or an experiment together. - **Create:** press **New group** at the top of the canvas (or the folder button next to the workspace in the sidebar), give it a name and a frame colour. - **Add cards:** drag a card into the frame. Drag it out to take it out of the group. - **Move together:** drag the frame and everything inside moves with it. - **Focus:** click the group in the sidebar — the canvas zooms to that frame. - **Rename or delete:** from the group's edit dialog. Deleting a group keeps its cards; they simply become ungrouped. --- ## Zoom, pan and undo > Getting around a big canvas, overview tiles when zoomed out, and undoing a layout change. Source: https://docs.neurosquad.ai/en/canvas/moving-around | Do this | To | | --- | --- | | drag empty canvas | pan | | scroll over empty canvas | zoom | | scroll over a card | scroll that card's contents | | `Ctrl` + scroll over a terminal | make its text bigger or smaller | | `Ctrl Z` / `Ctrl Shift Z` | undo / redo moving, resizing or arranging cards | The buttons in the bottom-left corner of the canvas zoom in and out, fit everything on screen, and **arrange everything** into a tidy grid. ### Overview tiles when you zoom out Zoom far out and each card turns into a large, readable **tile**: its name and the one thing that matters for it — an agent's state and mascot, a todo list's progress, a board's column counts, a budget's share of its limit, a timer's time left. Nothing stops meanwhile: agents keep working and their tiles update live. Zoom back in and the full cards are exactly where they were. **Settings → Canvas** has **Card overview when zoomed out** (on or off) and **Switch to the overview below** — the zoom level at which cards become tiles. ### Jump straight to something - `Ctrl Shift P` — find any agent by name, in any workspace. - `Ctrl Shift J` — fly to the agent that has been waiting for you the longest. - Click a notification — the canvas flies to that card and it flashes green. - Click a group in the sidebar — the canvas zooms to that group. For guides, snapping, the minimap and presentation mode, see [Canvas tools](https://docs.neurosquad.ai/en/canvas/tools). --- ## Canvas tools > Guides and snapping, the minimap, colour tags, presentation mode, mascots, the arrow log and workspace templates. Source: https://docs.neurosquad.ai/en/canvas/tools Most of these live in the **canvas tools** menu — the sliders button at the top right of the canvas. Switch its **View** options on and off here: The same switches are also in **Settings → Canvas**. ### Line cards up neatly - **Alignment guides** — while you drag a card, it snaps to the edges and centres of nearby cards, and a guide line shows the match. - **Snap to grid** — cards move in steps of the dot grid, so rows and columns line up by themselves. ### Minimap A small overview of the whole canvas in the corner. Drag or scroll it to move around. It's off by default; switch on **Minimap** in the tools menu. ### Colour tags Right-click any card's header and pick a **Colour tag** — the card gets a coloured edge (for an agent, also **Color tag** in its ⋯ menu). **Remove tag** takes it off. ### Jump to whoever's waiting `Ctrl Shift J` flies the camera to the agent that has been waiting for you the longest. Press it again for the next one. ### Present your canvas Press `F5` (or **Present cards** in the tools menu) to step through the cards one by one, like slides — great for showing a colleague what your squad did. Use the arrow buttons or keys to move, and **End presentation** to leave. [Sticky cards](https://docs.neurosquad.ai/en/cards/sticky) make good title slides. ### Agent mascots A tiny robot on each AI agent card shows at a glance whether it is **Working**, **Waiting for you**, **Finished**, **Idle** or **Stopped**. Turn **Agent mascots** off in the tools menu if you prefer a calmer canvas. ### Arrow log Click an arrow to open its **Arrow log**: every command, page visit, note or delegated task that went over it, with times — kept across restarts. **Clear log** empties it. (Double-clicking an arrow still removes it.) See it in action on [Arrows give abilities](https://docs.neurosquad.ai/en/canvas/arrows). ### Workspace templates Built a setup you like? **Save as template…** keeps its cards, layout, arrows and frames — plus card names, colour tags and the workspace's setup commands. Conversations, terminal history, notes and lists stay behind. To reuse it: **New workspace from template…**, give it a name and a project folder, and you get the same setup, ready to go. #### Add a template to a workspace you already have A template doesn't need a workspace of its own. **Insert template…** (in the canvas tools menu, and as **Template…** at the bottom of the add-card menu) opens the templates on that workspace; any also starts on **Add to existing**, and **New workspace** is one press away. - The workspace keeps its folder and where it runs (this computer, WSL or SSH), so the dialog only lists what can run there; agents that can't are named before you confirm. - The new cards land together beside what's already on the canvas, in the template's own arrangement — in a frame named after the template when it brings no frame of its own. Nothing that was there moves, and no running agent is restarted. - Cards a workspace needs only once — squad, budget, Code Graph, RTK, and a Memory, caveman, Context7, MCP or skill card set up the same way — are reused: the template's arrows go to your card instead of a second copy. - An agent that asks for its own worktree gets one only if the folder is a git repository; otherwise it works in the folder itself, and the dialog says so. - **Undo** in the toast that follows removes exactly the added cards and frames. Anything installed for the template stays installed. --- ## Supported agents > The AI coding agents NeuroSquad can run, and what each one supports. Source: https://docs.neurosquad.ai/en/agents An **agent card** runs a real AI coding agent — the same program you'd run in a terminal, with your own account. NeuroSquad supports nineteen of them, plus ordinary terminals. - **Claude Code**: The deepest support: exact “finished” vs “needs your input”, context meter, journal. - **Codex CLI**: Exact “finished” vs “needs your input” with what it asks, arrows, canvas mode, picks up where it left off, context meter, journal, OpenRouter models. - **Qwen Code**: Exact “finished” vs “needs your input” with what it asks, arrows, canvas mode, picks up where it left off, context meter, journal, OpenRouter models. - **Gemini CLI**: Exact “finished” vs “needs your input” with what it asks, arrows (new ones work without a restart), canvas mode, skills, picks up where it left off, context meter, Compact, journal, per-card tokens, OpenRouter models through NeuroSquad. - **Kimi Code**: Exact “finished” vs “needs your input” with what it asks, arrows, canvas mode, skills, picks up where it left off, context meter, Compact, journal, per-card cost, OpenRouter models. - **GitHub Copilot CLI**: Exact “finished” vs “needs your input” with what it asks, arrows, canvas mode, skills, picks up where it left off, context meter, Compact, journal, OpenRouter models without a Copilot subscription. - **Hermes Agent**: Exact “finished” vs “needs your input”, arrows, canvas mode, skills, picks up where it left off, context meter, journal, OpenRouter models. - **OpenCode**: Exact “finished” vs “needs your input”, arrows, canvas mode, picks up where it left off; free models need no key. - **Kilo Code**: Exact “finished” vs “needs your input”, arrows, canvas mode, skills, picks up where it left off, context meter, journal, OpenRouter models. - **omp**: Exact “finished” vs “needs your input” with what it asks, arrows, canvas mode, skills, picks up where it left off, context meter, journal, OpenRouter models. - **Pi**: Exact “finished” vs “needs your input”, arrows, canvas mode, skills, picks up where it left off, context meter, journal, OpenRouter models. - **aider**: Exact “finished” vs “needs your input” with what it asks, arrows and canvas mode through a NeuroSquad extension, skills, picks up where it left off, context meter, Compact, journal, OpenRouter models. - **Factory Droid**: Exact “finished” vs “needs your input” with what it asks, arrows, canvas mode, skills, picks up where it left off, context meter, Compact, journal, OpenRouter models without a Factory account. - **Amp**: Exact “finished” vs “needs your input” through a NeuroSquad plugin, arrows, canvas mode, skills, picks up where it left off, context meter, journal. Runs on your own Amp account — its models are served by Amp, so no OpenRouter and no per-card cost here. - **Auggie**: Exact “finished” vs “needs your input” with the command it asks about, arrows, canvas mode, skills, picks up where it left off, context meter, journal, per-card tokens. Runs on your own Augment account — its models are served by Augment, so no OpenRouter. - **Cursor CLI**: “Finished” vs “needs your input” with the command it asks about, arrows (the app's tools pre-approved), canvas mode, skills, picks up where it left off, context meter, Compact, journal, hand-off. Runs on your own Cursor account — its models are served by Cursor, so no OpenRouter and no per-card cost here. - **Goose**: Exact “finished” vs “needs your input” with what it asks, arrows, canvas mode, skills, picks up where it left off, context meter, Compact, journal, per-card cost, OpenRouter models. - **Cline CLI**: Exact “finished” vs “needs your input” with what it asks, through a NeuroSquad plugin, arrows, canvas mode, skills, picks up where it left off, context meter, Compact, journal, per-card cost, OpenRouter models. - **Crush**: Exact “finished” vs “needs your input” with what it asks, through its own status channel, arrows, canvas mode, skills, picks up where it left off, context meter, Compact, journal, per-card cost, OpenRouter models. | Agent | Arrows give abilities | Picks up where it left off | Dangerous mode | | --- | --- | --- | --- | | **Claude Code** | Yes | Yes | Yes | | **Codex CLI** | Yes | Yes | Yes | | **Qwen Code** | Yes | Yes | Yes | | **Gemini CLI** | Yes | Yes | Yes | | **Kimi Code** | Yes | Yes | Yes | | **GitHub Copilot CLI** | Yes | Yes | Yes | | **Cursor CLI** | Yes | Yes | Yes | | **OpenCode** | Yes | Yes | Yes | | **Hermes Agent** | Yes | Yes | Yes | | **Kilo Code** | Yes | Yes | Yes | | **Pi** | Yes | Yes | No | | **omp** | Yes | Yes | Yes | | **Crush** | Yes | Yes | Yes | | **aider** | Yes | Yes | Yes | | **Factory Droid** | Yes | Yes | Yes | | **Amp** | Yes | Yes | Yes | | **Auggie** | Yes | Yes | Yes | | **Goose** | Yes | Yes | Yes | | **Cline CLI** | Yes | Yes | Yes | - **Arrows give abilities**: The agent can use connected browsers, terminals, notes and other agents, and work in [canvas mode](https://docs.neurosquad.ai/en/squads/canvas-mode). See [Arrows](https://docs.neurosquad.ai/en/canvas/arrows). - **Picks up where it left off**: After you restart NeuroSquad, the agent continues the same conversation. Agents without this start a fresh conversation each time. - **Dangerous mode**: The agent can skip asking for permission. See [Dangerous mode](https://docs.neurosquad.ai/en/agents/dangerous-mode). **Claude Code**, **Codex CLI**, **Hermes Agent**, **OpenCode**, **Kilo Code** and **Qwen Code** have the deepest support: they tell NeuroSquad exactly when they are [waiting for your answer](https://docs.neurosquad.ai/en/agents/notifications), and they have the context meter, Compact and the journal. Token usage of Claude Code, Codex CLI, OpenCode, Kilo Code, Hermes Agent, Qwen Code, Pi and omp shows up in [Usage & costs](https://docs.neurosquad.ai/en/usage). Claude Code, Codex CLI, OpenCode, Kilo Code, Qwen Code and Hermes Agent can also run on models from [OpenRouter](https://docs.neurosquad.ai/en/providers/openrouter) instead of your own login. **GitHub Copilot CLI** gets the same depth: its own hooks tell NeuroSquad when it is working, finished or waiting for your answer — with the command it wants to run or the question it asks. New arrows reach it without a restart, canvas mode stays on in dangerous mode, it continues the same conversation after a restart, and it has the context meter, Compact, the journal and usage per card. It runs on your Copilot subscription — or, with no subscription at all, on OpenRouter models. **Pi** gets the same depth through a small NeuroSquad extension it loads at start: it reports when it is working, finished or waiting for your answer, uses arrows and canvas mode, and has the context meter, Compact, the journal and OpenRouter models. Pi never asks for permission before running a tool, so there is no dangerous mode to switch on — it already works that way. **omp** gets the same depth: it has its own MCP client, and a small NeuroSquad extension it loads at start reports when it is working, finished or waiting for your answer — including which tool it wants to run or what it is asking. It uses arrows and canvas mode (which stays on even in dangerous mode), continues the same conversation after a restart, and has the context meter, Compact, the journal and OpenRouter models. ### Terminals You can also add plain terminals — your system shell, Windows PowerShell, PowerShell 7, Command Prompt or Bash (Git Bash). See [Terminal card](https://docs.neurosquad.ai/en/cards/terminal). > Not sure which agents you have? **Settings → Harnesses** lists what NeuroSquad found on your > computer, and **Settings → Setup** can install one for you. --- ## Finished / needs your input > How NeuroSquad tells you an agent is done, or is waiting for you to answer. Source: https://docs.neurosquad.ai/en/agents/notifications You don't have to watch your agents. NeuroSquad lets you know when one of them needs you — and it tells the two cases apart: ### Two kinds of signal - **Done**: The agent has completed its turn and is waiting for your next prompt. The status chip turns green. - **Needs input**: The agent has stopped halfway and is asking you something — usually for permission, like "may I run this command?". The chip turns amber and the card pulses. The notification shows what it's asking, and it stays on screen until you answer, because a blocked agent won't unblock itself. Once you answer, it goes away by itself. > Claude Code, OpenCode, Kilo Code and Hermes Agent tell NeuroSquad exactly which of the two it is. For other agents, NeuroSquad notices > when the agent has gone quiet and treats it as finished. ### How you're told - a short **sound** (Chime, Ping or Marimba), - the card **glows**, and a dot appears next to the agent in the sidebar, - a **desktop notification** — click it and the canvas flies straight to that card, - the **notifications bell** in the top bar keeps a list of what happened, - optionally, a message to **Slack or Discord** through a webhook, - optionally, a message in [Telegram](https://docs.neurosquad.ai/en/integrations/telegram) — for when you're away from your desk. Each of these can be switched on or off in **Settings → Notifications**. ### Catching up quickly - `Ctrl Shift J` — fly to the agent that has been waiting the longest. - `Ctrl Shift A` — the "needs attention" inbox: every waiting agent in one list. - The **Inbox** section of the sidebar shows the same list. Need quiet for a while? A [flow timer](https://docs.neurosquad.ai/en/cards/flow-timer) holds the "finished" pings until your focus block ends. ### What you're notified about In **Settings → Notifications** each kind has its own switch: an agent **waiting for you** (with what it asks), an agent that **finished**, one that hit its **usage limit**, and an agent CLI **update that NeuroSquad skipped** so your agents keep working (you decide when to update). **Send a test notification** shows one right away. If your system doesn't show notifications — for example, Windows has them switched off for all apps (Settings → System → Notifications) — NeuroSquad says so there and shows them in the bottom-right corner of its own window instead; **System notification settings** opens the right place to turn them on. Windows' Focus assist / Do not disturb can also hold them back. ### Agent CLI updates don't interrupt your agents Several agent CLIs update themselves at startup, and some stop to ask first ("Update now / Skip") — which would leave a card where neither you nor a lead agent can type. Inside NeuroSquad cards this is switched off (only for NeuroSquad's own cards — the CLI in your own terminal keeps its settings), and a prompt that appears anyway is answered **Skip**. When a newer version is out, NeuroSquad tells you once per version, with the command to update from a terminal — you decide when. --- ## Giving agents tasks > Assign board tasks to specific agents, and let them pick up the next task on their own. Source: https://docs.neurosquad.ai/en/agents/tasks You can always just type a prompt into an agent. For a bigger job with several agents, use a [task board](https://docs.neurosquad.ai/en/cards/kanban) instead — every task has one owner, and **Start** sends it to that agent only: **1. Put the tasks on a board** Add a task board and add one task per line — or ask a lead agent to break the job down onto it. **2. Assign each task** Press **Assign** on a task and pick the agent. Only that agent receives the task, and other agents can't take it or move it. **New agent for this task** creates a fresh agent for it in one click. **3. Press Start** The task goes to its agent as a prompt and moves to **Doing**. When the agent finishes, move it to **Review** or **Done**. ### Let it run by itself - **Depends on** — a task waits, **Blocked**, until the tasks it depends on are **Done**. - **Auto-dispatch** (the lightning button in the board's header) — when an agent finishes its turn, its task moves to **Review** and its next ready task is sent automatically. - **Give unassigned tasks to any idle connected agent** — free tasks go to whichever agent is free. Put a [budget card](https://docs.neurosquad.ai/en/cards/budget) next to a self-running board, so it can't overspend while you're away. ### See every task in one place The **Tasks** section of the sidebar gathers the tasks from every task board and todo list across your workspaces. --- ## Prompt queue & daily prompts > Line up the next prompts for a busy agent, or send the same prompt every day. Source: https://docs.neurosquad.ai/en/agents/queue ### Prompt queue Got the next task in mind while the agent is still busy? Put it in the queue. **1. Open Queue in the agent card's ⋯ menu** Type the message and press **Add to queue**. Add as many as you like, reorder them with the arrows, click one to edit it. **2. Carry on with your day** As soon as the agent finishes its turn, the next message is sent automatically — one per turn. The queue survives closing the workspace or the app. If the agent isn't running, messages just wait. ### Daily prompts **Schedule** in the agent card's ⋯ menu sends a prompt to that agent every day at a set time — "every morning at 9, check for new issues". Each scheduled prompt has its own on/off switch. --- ## Roles > Give an agent a job description — reviewer, tester, researcher and more — in one click. Source: https://docs.neurosquad.ai/en/agents/roles A **role** tells an agent what kind of work it's there for. NeuroSquad has ready-made roles — **Reviewer**, **Tester**, **Researcher**, **Architect**, **Writer** — or **Custom**, where you describe the role in your own words. ### Give a role - **When creating an agent** — pick a role in the **New agent** dialog. It's typed into the new agent as its first prompt; press Enter in its terminal to send it. - **To an agent that's already running** — choose **Role** in its ⋯ menu, pick one and press **Send role**. The role is sent once, as a normal prompt you can see. NeuroSquad never changes or re-sends it behind your back. The card shows the role next to the agent's name. **Good for:** a squad where each agent has a clear job — one writes the code, one tests it, one reviews it. --- ## Long sessions > Keep an eye on the context, compact it, resume after a usage limit, hand off to a fresh agent, and keep a journal. Source: https://docs.neurosquad.ai/en/agents/long-sessions Agents that work for hours run into limits: their memory (the **context**) fills up, and your plan's **usage limit** runs out. NeuroSquad helps with both. ### Context meter and Compact The small ring in the agent card's header shows how full the context is. Past 80% it turns amber. Click it for the token breakdown and: - **Compact** — asks the agent to summarise the conversation so far and carry on from the summary. - Or **hand off** to a fresh agent (below). ### Auto-resume after a usage limit When an agent stops with a "usage limit reached" message, its header shows a countdown to the reset. Switch on **Auto-resume after a usage limit** (in that chip's popover, or in the card's ⋯ menu), and NeuroSquad sends "continue" to the agent at that time — so an overnight job carries on by itself. **Resume now** and **Dismiss** are right there too. ### Hand off to a new agent **Hand off to a new agent…** in the ⋯ menu starts a fresh agent beside this one, in the same folder, on any agent program you like. It comes with a summary of the work so far — press **Ask the agent to write it**, or write and edit it yourself. The summary is typed into the new agent, not sent, so you can check it before pressing Enter. ### Journal Turn on **Journal to linked note** in the ⋯ menu, and each finished answer is added to a connected [note card](https://docs.neurosquad.ai/en/cards/note) — a running log of what the agent did. > The context meter, Compact and the journal work with Claude Code, OpenCode, Kilo Code and Hermes Agent. --- ## One instructions file > Write your project instructions once in AGENTS.md, and every agent reads them. Source: https://docs.neurosquad.ai/en/agents/instructions Agent programs read project instructions from different files: Codex and many others read `AGENTS.md`, Claude Code reads `CLAUDE.md`, Qwen Code reads `QWEN.md`, Gemini reads `GEMINI.md`. Keeping them all in sync by hand is tedious. NeuroSquad lets you keep **one** file — `AGENTS.md` — and mirrors it to `CLAUDE.md`, `GEMINI.md` and `QWEN.md`. **1. Open the workspace's edit dialog** The **Instructions file** section lists each file with its state: **Missing**, **In sync** or **Differs**. **2. Tick the files to mirror** Choose **Copy** (a full copy) or **@import** (a short file that points at `AGENTS.md`), then press **Write**. If a file already has different content, NeuroSquad never overwrites it silently: **Review…** shows you exactly what would change, and only **Overwrite** replaces it. No `AGENTS.md` yet? **Create AGENTS.md from** an existing file, such as your `CLAUDE.md`. --- ## Isolated worktrees > Give an agent its own copy of the project so several agents never step on each other's changes — and add a reviewer on a different AI. Source: https://docs.neurosquad.ai/en/agents/worktrees When several agents work in the same folder, they can overwrite each other's changes. An **isolated** agent gets its own copy of the project (a git worktree) on its own branch, so it can change anything without disturbing you or other agents. ### Turn it on In the sidebar's add row under the workspace, switch on **Isolate in git worktree** (the button with stacked squares) before adding the agent. The card says **Preparing** while its copy is set up, then the agent starts. > Your project needs to be a git repository. The setup wizard can install Git if you don't have it. ### Get the copy ready automatically A fresh copy has no installed dependencies and none of your private files. In the workspace's edit dialog you can set: - **Setup command for isolated agents** — runs once in every new copy before the agent starts, e.g. `npm install`. Its output shows in the card while it runs. - **Files to copy into a new worktree** — files git doesn't track but the agent needs, like `.env`. - **Run command** — starts your project from an agent's card (**Run this project** in its ⋯ menu); a browser card opens on your app as soon as it prints its local address. ### Add a reviewer When the work looks done, choose **Add a reviewer** in the agent's ⋯ menu. A second agent starts — on a **different AI** when you have one installed — in the same worktree, with an arrow from the author, and is told to read the changes and **not edit anything**. ### Bring the work back The agent's changes live on its own branch. When you're happy with them, merge that branch from a [terminal card](https://docs.neurosquad.ai/en/cards/terminal) — or simply ask the agent to commit and merge its work. --- ## Dangerous mode > Let an agent work without stopping to ask for permission — and when not to. Source: https://docs.neurosquad.ai/en/agents/dangerous-mode Normally an agent asks before doing something risky — running a command, editing a file. **Dangerous mode** switches those questions off, so the agent works without stopping. ### Turn it on Open the agent card's ⋯ menu and choose **Enable dangerous mode**. An amber triangle appears in the card's header. The setting is per card — it never applies to all agents at once. **Disable dangerous mode** in the same place turns it off. - **Claude Code** switches instantly, both ways: the very next approval follows the toggle — no restart, same conversation. - **Every other agent** reads the mode when it starts. NeuroSquad offers **Restart now**: the agent restarts and continues the same conversation. Choose **Later** to apply it at its next start. > In dangerous mode the agent can delete files and run any command without asking. Use it on a > project you have backed up, ideally together with an [isolated worktree](https://docs.neurosquad.ai/en/agents/worktrees) and a > [budget](https://docs.neurosquad.ai/en/cards/budget). Pi doesn't offer this mode — it never asks before running a tool in the first place. Plain terminals don't need it either. --- ## Everything in an agent card > The agent card's header and its ⋯ menu, row by row. Source: https://docs.neurosquad.ai/en/agents/card-menu The header shows what you need from across the canvas: who this is, what it's doing, and any standing fact that changes how it behaves. Everything you *do* to an agent lives in the **⋯** menu. Point at the dots, then open the menu: ### The header - **Icon**: The agent's own icon, with a spinning ring while it works. - **Name**: Filled in from what the agent is working on. Click it and type your own — your name always wins. - **Role or session title**: Small text after the name: the agent's [role](https://docs.neurosquad.ai/en/agents/roles), or what it's busy with. - **Status**: **Working**, **Needs input**, **Done**, **Exited**, **Crashed**… Nothing at all while it's idle. See [Finished / needs your input](https://docs.neurosquad.ai/en/agents/notifications). - **Usage limit and context**: A countdown when a usage limit stopped the agent, and the context meter. See [Long sessions](https://docs.neurosquad.ai/en/agents/long-sessions). - **Model**: A chip with the model, when the agent runs on one you picked. See [OpenRouter](https://docs.neurosquad.ai/en/providers/openrouter). - **Flags**: An amber triangle for [dangerous mode](https://docs.neurosquad.ai/en/agents/dangerous-mode), a green frame for [canvas mode](https://docs.neurosquad.ai/en/squads/canvas-mode). - **Expand and ⋯**: Fill the canvas with the card; open the menu. On AI agents a small [mascot](https://docs.neurosquad.ai/en/canvas/tools#agent-mascots) sits on top of the card and mirrors its state. ### The ⋯ menu - **Session**: **Restart session** (a brand-new conversation; the card keeps its place), **Pop out to new window**, **Minimize**, and **Run this project** when the workspace has a run command (see [Isolated worktrees](https://docs.neurosquad.ai/en/agents/worktrees)). - **Agent**: **Provider and model**, **Enable dangerous mode**, **Enable canvas mode**, **Role**, **Journal to linked note**, **Auto-resume after a usage limit**, **Hand off to a new agent…**, **Clone agent** and **Add a reviewer**. - **Prompts**: **Queue** and **Schedule** — see [Prompt queue & daily prompts](https://docs.neurosquad.ai/en/agents/queue). - **Organize**: **Color tag**, private **Notes** (you can dictate them), an **Issue/PR link**, and **Annotations** pinned to spots in the output. - **Transcript**: **Copy transcript**, **Export transcript**, **Export as HTML**, **Open last mentioned file**, **Save snapshot** and your **Snapshots**. - **Delete agent**: The last row, on its own. It asks first — and never touches your files. ### In the terminal - Right-click for **Copy**, **Paste** and **Select all**. - `Ctrl F` searches the output. - `Ctrl` + scroll changes the text size. - Drop files from Explorer (Finder on a Mac) onto the card to type their paths into the prompt. ### If an agent crashes NeuroSquad restarts it automatically a few times (**Auto-reconnect** in Settings → General). If it still won't come back, the card shows a **Reconnect** button, and the **Crash log** under **Features** in the sidebar records what happened. ### Templates Set up an agent you use often — agent type, colour, starting prompt — and save it as a **template** (**Features → Templates** in the sidebar). Your templates then appear at the bottom of the add menu. --- ## All cards > Every kind of card you can put on the canvas, and what each one is for. Source: https://docs.neurosquad.ai/en/cards Besides agents, the canvas can hold many other cards. Add any of them from the add menu. Most become even more useful when you connect an agent to them with an [arrow](https://docs.neurosquad.ai/en/canvas/arrows). Here is each one the way it looks when you zoom out: ### Work - **[Terminal](https://docs.neurosquad.ai/en/cards/terminal)**: A real shell — for you, or for an agent to run commands in. - **[Browser](https://docs.neurosquad.ai/en/cards/browser)**: A real browser an agent can see and click through. - **[Note](https://docs.neurosquad.ai/en/cards/note)**: Shared notes in Markdown — for you and your agents. - **[Todo list](https://docs.neurosquad.ai/en/cards/todo)**: A checklist you and your agents tick off together. - **[Task board](https://docs.neurosquad.ai/en/cards/kanban)**: Assign tasks to agents and let them pick up the next one. - **[Sticky](https://docs.neurosquad.ai/en/cards/sticky)**: Big headings to organise the canvas. - **[Flow timer](https://docs.neurosquad.ai/en/cards/flow-timer)**: Focus blocks that hold non-urgent pings. - **[Reference](https://docs.neurosquad.ai/en/cards/reference)**: Links, images, PDFs and folders for your agents. - **[Dev servers](https://docs.neurosquad.ai/en/cards/dev-servers)**: Running dev servers, one click from a browser card. ### Keeping watch - **[Budget](https://docs.neurosquad.ai/en/cards/budget)**: A token limit for the whole workspace. - **[Web watch](https://docs.neurosquad.ai/en/cards/web-watch)**: Tells your agents when a web page changes. - **[Standup](https://docs.neurosquad.ai/en/cards/standup)**: What each agent did today. ### Integrations - **[Telegram bot](https://docs.neurosquad.ai/en/integrations/telegram)**: Talk to your agents from Telegram. --- ## Terminal card > A real shell on the canvas — for you, or for an agent to run commands in. Source: https://docs.neurosquad.ai/en/cards/terminal A **terminal card** is an ordinary shell in your project folder: Windows PowerShell, PowerShell 7, Command Prompt, Bash (Git Bash) or your system's default shell. Pick one under **Terminals** in the add menu. ### Use it yourself Type commands as in any terminal. Right-click for Copy / Paste / Select all, `Ctrl F` to search, `Ctrl` + scroll to change the text size. ### Let an agent use it Draw an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) from an agent to the terminal. The agent will run its commands **here**, where you can see them, instead of hidden inside its own window. Long-running things — a dev server, a test watcher — are best given a terminal card each. **Good for:** starting your app, running tests, watching logs while the agent works. --- ## Browser card > A real browser on the canvas that an agent can see and use. Source: https://docs.neurosquad.ai/en/cards/browser A **browser card** is a real browser inside a card, with back, forward, reload and an address bar. You can browse in it yourself — and an agent connected by an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) can open pages, click, type and read what's on screen. > The first time, NeuroSquad downloads its own browser (Chrome by default, about 200 MB). It's kept > separate from your everyday browser. The card starts by itself when the download is done. You can > switch to Firefox in **Settings → Browser**. Logins you make inside a browser card are remembered, so you can sign in to a site once and let the agent work there afterwards. **Good for:** checking the app the agent just changed, reproducing a bug, filling in a web form, research. --- ## Note card > A shared note in Markdown — for you and your agents. Source: https://docs.neurosquad.ai/en/cards/note A **note card** holds text in Markdown: headings, lists, tables, code. An empty note opens for editing; a filled one shows the formatted text — click to edit, `Esc` to finish. Connect an agent with an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) and it can read and write the note too. The card shows who wrote the latest version. **Good for:** a findings log the agent keeps as it works, instructions you want several agents to share, a scratchpad for the task at hand. --- ## Todo list card > A checklist that you and your agents keep up to date together. Source: https://docs.neurosquad.ai/en/cards/todo A **todo list** you and your agents share. Each task has a status dot: | Dot | Means | | --- | --- | | grey ring | not started | | spinning ring | in progress | | green dot | done | | red dot | failed | - **Add** a task in the line at the bottom. - **Click the dot** to move a task to the next status. - **Click the text** to edit it. Connect an agent with an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) and it will put its plan here and tick tasks off as it goes — so you see progress at a glance. You can have as many lists as you like. --- ## Task board card > A kanban board for your squad — assign each task to an agent and let the next one start by itself. Source: https://docs.neurosquad.ai/en/cards/kanban A **task board** has four columns: **To do**, **Doing**, **Review** and **Done**. Add tasks and move them between columns yourself, or let agents do it. ### Give a task to a specific agent - **Assign** — pick the agent that should do the task. Only that agent ever receives it; other agents can't move or remove it. - **Start** — sends the task to its agent and moves it to **Doing**. - **New agent for this task** (in the same list) — creates a fresh agent for it in one click. ### Tasks that depend on others **Depends on** lets you tick the tasks that must be **Done** first. Until then the task is marked **Blocked** and shows what it's waiting for. ### Auto-dispatch Turn on **Auto-dispatch** (the lightning button in the board's header) and the board runs itself: when an agent finishes its turn, its task moves to **Review** and its next ready task is sent to it automatically. With **Give unassigned tasks to any idle connected agent**, free tasks go to whichever connected agent is free. Agents connected by an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) can also add tasks and move their own along. See [Giving agents tasks](https://docs.neurosquad.ai/en/agents/tasks) for the whole picture. **Good for:** a squad working through a backlog, where you want to see at a glance who is doing what. --- ## Sticky card > Big headings and labels to organise and explain your canvas. Source: https://docs.neurosquad.ai/en/cards/sticky A **sticky** is a big, bold label: a heading and an optional subtitle, in one of six colours. Double-click it to write. Use stickies to divide a large canvas into chapters — "Build", "Marketing", "Watching" — or to leave a note for whoever opens the workspace next. They look especially good in [presentation mode](https://docs.neurosquad.ai/en/canvas/tools#present-your-canvas). --- ## Flow timer card > A focus timer that holds your agents' "finished" pings until your focus block ends. Source: https://docs.neurosquad.ai/en/cards/flow-timer Agents finishing one after another can make it hard to concentrate. The **flow timer** gives you a focus block — **25 / 5**, **50 / 10**, or your own minutes — and keeps the noise down while it runs. - Press **Start focus**. The card shows the time left and when the block ends. - With **Hold agent pings while focusing** on, "finished" notifications wait until the block ends. "Needs your input" always comes through — a blocked agent shouldn't wait for you by accident. - When the block ends, **While you focused** shows what happened in one list. The card also counts how many focus blocks you did today. --- ## Reference card > Links, images, PDFs and folders you want your agents to keep in mind. Source: https://docs.neurosquad.ai/en/cards/reference A **reference card** is a pinboard of material for your agents: web links, images, PDFs, documents or a whole folder. - **Add a link** — paste it and press Enter. - **Add files** or drop them onto the card; **Reference a folder** to point at a folder instead of copying it. - Click an item to **Open** it. Every agent connected by an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) can see what's on the card and read it when it needs to — so you don't have to paste the same mockups or specs into every prompt. **Good for:** design mockups, a product spec, brand guidelines, the documentation of an API. --- ## Dev servers card > Every dev server running on your computer — open one in a browser card with one click. Source: https://docs.neurosquad.ai/en/cards/dev-servers Agents love to start dev servers — and then you have to guess which port it was. The **dev servers card** lists every one running on your computer, updated every few seconds. - **Open in a browser card** — one click, and a [browser card](https://docs.neurosquad.ai/en/cards/browser) opens on that address. - **Copy URL**, or **Stop process** when you're done with it. (System processes and NeuroSquad itself can't be stopped from here.) - **Show every listening port** if you want to see more than dev servers. Connected agents can ask the card which servers are running, too. **Good for:** keeping track of what's running while several agents work on a web project. --- ## Budget card > A token limit for a whole workspace that pauses its agents when crossed. Source: https://docs.neurosquad.ai/en/cards/budget A **budget card** shows how many tokens all the agents in this workspace have used, broken down by agent, against a limit you set. - **Set limit** — pick a token limit (250K, 1M, 5M, 20M or your own). The ring turns amber — **Near limit** — as you get close. - **When the limit is crossed**, the workspace is paused: every agent is interrupted (not closed — its conversation is kept), and automatic prompts — the queue, daily prompts, tasks from a board, messages from other agents — stop. - **Typing yourself still works** — the budget only stops the automatic stuff. - **To continue**, press **Resume**, or **Raise limit** above what's already spent. Token counts come from the same place as [Usage & costs](https://docs.neurosquad.ai/en/usage), so every agent whose usage NeuroSquad can read is counted. **Good for:** leaving a squad running overnight without a surprise bill. --- ## Web watch card > Watches a web page and tells your agents when it changes. Source: https://docs.neurosquad.ai/en/cards/web-watch A **web watch card** checks a page on a schedule and notices when it changes — a changelog, a price, a status page, a competitor's pricing. **1. Enter the page** Paste the address and choose how often to check. **2. Choose what to compare** The **Whole page**, only the part **Between** two phrases (e.g. between "Latest release" and "Older releases"), or matches of a pattern. **3. Start watching** The first check is the starting point. After that, every change is recorded with what was added and removed. With **Tell connected agents when it changes** on, every agent connected by an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) gets a message about the change — so an agent can react on its own: update the docs for a new library version, say, or write you a summary. **Check now**, **Pause** and **Resume** are always at hand. The card reads the page as it's served, so text drawn later by scripts on the page isn't seen. --- ## Standup card > A daily digest of what each agent in the workspace did today. Source: https://docs.neurosquad.ai/en/cards/standup The **standup card** answers "what did everyone do today?" For each agent in the workspace it shows: - how many turns it took and how long it was working, - the files it touched and the tokens it used, - what it was last asked, and what it last answered. **Copy as Markdown** to paste the digest into a chat, or **Send to note** to drop it into a connected [note card](https://docs.neurosquad.ai/en/cards/note). Claude Code, OpenCode, Kilo Code and Hermes Agent agents are covered in full. For other agents the card shows what happened since NeuroSquad started. --- ## What is a squad > Several agents working together on one canvas, connected by arrows. Source: https://docs.neurosquad.ai/en/squads A **squad** is a group of agents working together. One agent can lead and hand out work; others do the pieces; browsers, terminals and notes connect them all. You build a squad simply by adding cards and drawing [arrows](https://docs.neurosquad.ai/en/canvas/arrows). The helpers don't have to be the same AI as the lead: There are two ways to split the work — let a lead agent delegate over arrows, or put the tasks on a [task board](https://docs.neurosquad.ai/en/cards/kanban) and give each one to a specific agent: - **[A lead agent that delegates](https://docs.neurosquad.ai/en/squads/lead-agent)**: One agent hands tasks to others and collects the results. - **[Tasks for specific agents](https://docs.neurosquad.ai/en/agents/tasks)**: Assign, Start, dependencies and auto-dispatch on a task board. - **[Canvas mode](https://docs.neurosquad.ai/en/squads/canvas-mode)**: The agent creates the cards it needs by itself. - **[Squad recipes](https://docs.neurosquad.ai/en/squads/recipes)**: Ready-made setups to copy. ### The Squad board Every workspace has a **Squad** card: all its AI agents on one board — who is waiting for you, who is working and for how long, who has finished — with the agent type and model of each. Click a row to fly to that agent. The **Squad** button in the top bar opens the same board as a **right sidebar**, for the workspace you have open — it stays there while you switch workspaces, even if you deleted the card. Drag its edge to resize it. While the board is in the sidebar, the card on the canvas just says so (the board is never shown twice); **Move back to canvas** puts it back — and brings the card back if you had deleted it. --- ## A lead agent that delegates > Let one agent hand tasks to other agents and collect their answers. Source: https://docs.neurosquad.ai/en/squads/lead-agent Draw an arrow **from** one agent **to** another. The first becomes the **lead**, the second its **helper**. The lead can now send the helper a task, wait for it to finish, and read the answer. **1. Add two agents** For example, Claude Code as the lead and Codex as a helper. They can be different AIs. **2. Draw the arrow from the lead to the helper** Direction matters: the arrow points from whoever gives the work to whoever does it. **3. Tell the lead what you want** *"Fix the checkout bug. Ask the helper to write tests for it while you work on the fix."* The arrow lights up whenever the lead talks to the helper, and you can watch the helper work in its own card. A lead can have several helpers, and a helper can lead helpers of its own. > The lead must be Claude Code, OpenCode, Kilo Code, Hermes Agent, Codex CLI or Qwen Code — the agents that [arrows give > abilities](https://docs.neurosquad.ai/en/canvas/arrows) to. The helper can be any agent. ### Let the lead build the team A lead can also create its helpers itself — and choose what each one runs on. Ask it something like *"Plan this project for a team of four developers: pick a harness and a model for each and create them."* The lead then: - sees which agents are **installed on this computer** — it cannot create one you don't have; - sees each agent's **own models** (for example `opus` or `sonnet` for Claude Code) and, if you connected [OpenRouter](https://docs.neurosquad.ai/en/providers/openrouter), that it may use OpenRouter models, with their prices and context size — it never sees your key; - creates each helper with its harness, model, a role and a first task, already connected to it by an arrow. A helper's model shows on its card and on the Squad board. The lead can change the model of a helper it created while that helper isn't running. ### Give helpers the cards they need A helper only sees the cards connected to **its own** card — not the lead's. So when the lead hands out work that needs a card (a note with the brief, a terminal, a browser, a task board), it wires the helper to that card itself: it can create a helper already connected to your note, or draw an arrow from an existing helper to it in the middle of the work. The new arrow appears on the canvas, shows who drew it for a moment, and stays in the [arrow log](https://docs.neurosquad.ai/en/canvas/arrows#arrow-log). A helper that is already running gets the new abilities straight away. What a lead may wire is limited on purpose, because an arrow hands out abilities: - only cards of the **same workspace**; - without [canvas mode](https://docs.neurosquad.ai/en/squads/canvas-mode), one end of the arrow must be the lead itself or a card it created; with canvas mode, any two cards; - a **terminal**, **browser**, MCP server, Telegram or custom card that **you** set up is passed on only if you connected it to the lead first — the lead cannot reach your own terminal on its own; - a helper cannot take over its own lead, and cannot cut the arrow its lead reaches it by; - no wiring while the workspace [budget](https://docs.neurosquad.ai/en/cards/budget) is paused, and at most 30 arrow changes a minute per agent. Leads never delete cards this way — removing an arrow leaves both cards where they are. --- ## Canvas mode > The agent works through cards — it opens its own terminals, browsers, notes and helpers. Source: https://docs.neurosquad.ai/en/squads/canvas-mode Normally you set up the cards and arrows. In **canvas mode** the agent does it itself: it works through cards on the canvas instead of hidden inside its own window. The whole story, step by step, and what working this way gives you: [neurosquad.ai/en/canvas-mode](https://neurosquad.ai/en/canvas-mode/). - It opens a **terminal card** for commands — one per long-running process. - It opens a **browser card** when it needs the web. - It keeps its log in a **note card**. - It creates **helper agents** for work that can run in parallel. - It **wires its helpers** to the cards their task needs — your note, a terminal, a browser, a task board — since a helper only sees cards connected to its own card. In canvas mode it may connect any two cards of the workspace ([what it may wire](https://docs.neurosquad.ai/en/squads/lead-agent#give-helpers-cards)). Everything it does is right there on the canvas for you to see. A card in canvas mode has a faint green glow. ### Turn it on Agent card menu → **Enable canvas mode**. It is there for every AI CLI that gets NeuroSquad's card tools — all 19: Claude Code, Codex CLI, OpenCode, Kilo Code, Hermes Agent, Qwen Code, Gemini CLI, GitHub Copilot CLI, Factory Droid, Amp, Auggie, Cursor CLI, Cline CLI, Goose, Kimi Code, Crush, aider, Pi and omp. The card tools and the instructions switch at once, while the agent is running. On top of that, NeuroSquad takes away the CLI's **own** shell and web tools, so the agent really does use the cards. Each CLI has its own way to do it: | CLI | How its own shell and web are cut off | Holds in dangerous mode | From | | --- | --- | --- | --- | | Claude Code | `Bash`, `WebSearch`, `WebFetch` disabled at launch; dangerous mode never approves them | yes | next launch | | Codex CLI | shell tool and web search switched off — not offered to the model | yes | next launch | | OpenCode, Kilo Code | `bash`, `webfetch`, `websearch` denied in the card's config | yes | next launch | | Hermes Agent | the `terminal`, `code_execution`, `web`, `search` and `browser` toolsets disabled | yes | next launch | | Qwen Code | `run_shell_command`, `monitor`, `web_fetch`, `web_search` disabled and denied | yes | next launch | | Gemini CLI | `run_shell_command`, its background-process tools, `web_fetch`, `google_web_search` excluded | yes | next launch | | GitHub Copilot CLI | the bash/PowerShell tools, `web_fetch` and `web_search` excluded, the shell denied | yes | next launch | | Factory Droid | a hook denies `Execute`, `Script`, `WebSearch`, `FetchUrl` | yes | next launch | | Amp | NeuroSquad's plugin refuses its shell tools, `web_search` and `read_web_page` on every call | yes | next launch | | Auggie | the process tools, `web-fetch` and `web-search` removed | yes | next launch | | Cursor CLI | a hook denies `Shell`, `WebFetch`, `WebSearch` — read from the card on every call | yes | immediately | | Cline CLI | NeuroSquad's plugin removes `run_commands`, `fetch_web_content`, `web_search` and refuses them | yes | next launch | | Goose | the `developer` extension keeps only its file tools (no `shell`); `code_execution` and `computercontroller` get no tools | yes¹ | next launch | | Kimi Code | `Bash`, `WebSearch`, `FetchURL` disabled, plus a hook that blocks them | yes | next launch | | Crush | `bash`, its job tools, `download`, `fetch`, `agentic_fetch`, `sourcegraph` disabled | yes | next launch | | aider | it stops suggesting shell commands and stops fetching URLs from the chat² | yes | next launch | | Pi | `bash` and `powershell` excluded; Pi has no web tools of its own | yes | next launch | | omp | `bash`, `eval`, `web_search` and URL reads blocked and hidden from the model | yes | next launch | ¹ Goose's extension manager stays, so a model that goes out of its way could turn another extension on. ² `/run` and `/web` remain yours to type. "Next launch" means the CLI picks it up when the card starts again; the running session keeps its tools until then. Dangerous mode skips approval prompts — it doesn't give back what canvas mode took away. > Canvas mode is not a sandbox. The agent still reads and edits your project's files with its own > tools, and what it runs in a terminal card are real commands on your computer. --- ## Squad recipes > Ready-made squad setups you can copy onto your canvas. Source: https://docs.neurosquad.ai/en/squads/recipes ### Builder and tester **Cards:** an agent, a terminal running your dev server, a browser. **Arrows:** agent → terminal, agent → browser. Ask: *"Add a newsletter sign-up form, then open the page in the browser and check that it works."* The agent edits the code, sees the result in the browser and fixes what's broken. ### Lead and helpers **Cards:** one lead agent, two helper agents, a [task board](https://docs.neurosquad.ai/en/cards/kanban). **Arrows:** lead → each helper, all three → task board. Ask the lead to split the job into tasks on the board and hand them out. You watch tasks move from **To do** to **Done**. ### Author and reviewer **Cards:** an [isolated](https://docs.neurosquad.ai/en/agents/worktrees) agent. Then choose **Add a reviewer** in the agent's menu — a second agent on a different AI reads the changes without editing anything. You read both, pass notes back to the author, and merge its branch. ### Night shift **Cards:** an [isolated](https://docs.neurosquad.ai/en/agents/worktrees) agent, a [budget](https://docs.neurosquad.ai/en/cards/budget) card. **Schedule** in the agent's menu starts the work at night, the budget makes sure it can't overspend, and because the agent works on its own branch, in the morning you merge what you like and throw away what you don't. --- ## Your agents on your phone > Watch and drive NeuroSquad from your phone — at home or away. Source: https://docs.neurosquad.ai/en/remote Started a long task and stepped away? **Remote access** lets you open NeuroSquad on your phone: see which agents are working or waiting, read their screens, send prompts, and get a chime when one needs you. Your computer does all the work — the phone is just a window onto it. No app store, nothing to sign in to on the phone: you scan a QR code and add the page to your home screen. - **[Pair a phone](https://docs.neurosquad.ai/en/remote/pairing)**: Turn it on and scan the code — on the same Wi-Fi. - **[Away from home](https://docs.neurosquad.ai/en/remote/internet)**: Reach your computer over the internet through Cloudflare. - **[What you can do from the phone](https://docs.neurosquad.ai/en/remote/on-the-phone)**: Workspaces, cards, prompts and alerts. ### You always know when someone is connected While any phone is connected, a **green bar** runs across the top of the NeuroSquad window: "iPhone is connected remotely on your network". It can't be dismissed — remote access can do everything the window can, so you should never have to go looking. The **Remote access** button in the top bar lists the connected devices and switches remote access off. > Anyone who has your pairing link can read your terminals and send prompts to your agents. Don't > share the link or a screenshot of the QR code. If you ever did, press **Regenerate** — every paired > phone is disconnected at once. --- ## Pair a phone > Turn on remote access and scan the QR code with your phone. Source: https://docs.neurosquad.ai/en/remote/pairing **1. Open Remote access** Click the **Remote access** button in the top bar (or go to **Settings → Remote access**) and switch it on. **2. Choose Local network** Your phone must be on the same Wi-Fi as your computer. If your computer is on several networks, pick the one your phone uses. **3. Scan the QR code** Point your phone's camera at the code and open the link. You're in. **4. Add it to your home screen** In your phone's browser, use **Share → Add to Home Screen**. It opens like an app from then on. > Keep the port the same in **Settings → Remote access** so the home-screen shortcut keeps working. ### Unpair a phone In **Settings → Remote access**, press **Regenerate** next to **Pairing link**. Every phone paired with the old link stops working straight away and would need to scan the new code. --- ## Away from home > Reach NeuroSquad from mobile data or another network through a free Cloudflare tunnel. Source: https://docs.neurosquad.ai/en/remote/internet On the same Wi-Fi, your phone talks to your computer directly. To reach it from mobile data or another network, switch **Share access over** to **Internet**. NeuroSquad connects through a **Cloudflare tunnel** — nothing to set up on your router. ### Two kinds of tunnel - **Quick (no account)**: Free, no sign-up. You get a random https address. It changes every time NeuroSquad starts, so scan the code again after a restart. The first time, NeuroSquad downloads Cloudflare's small helper program (about 55 MB). - **My Cloudflare tunnel**: A permanent address on your own domain. Create a tunnel in your Cloudflare dashboard, then paste its public hostname and tunnel token into **Settings → Remote access**. > This puts NeuroSquad on the open internet. The pairing link is the only thing between a stranger > and your agents — never share it. Traffic is encrypted, and it passes through Cloudflare. ### Local network or internet? | | Local network | Internet | | --- | --- | --- | | Works | on the same Wi-Fi | anywhere | | Setup | none | none (quick) or a Cloudflare account (own tunnel) | | Address | stays the same | quick: changes on restart | --- ## What you can do from the phone > Workspaces, live agent screens, prompts, new cards and alerts — from your phone. Source: https://docs.neurosquad.ai/en/remote/on-the-phone - **See every workspace** — how many cards it has, how many are working and how many are waiting on you. - **Open a workspace** — a map of its canvas, with every card and its status. - **Read an agent's screen** — live, with zoom. - **Send a prompt** — type it on the phone, or use the phone's own voice keyboard. - **Add a card** or **create a workspace** — pick a folder on your computer right from the phone. - **Get alerts** — while the page is open, it chimes and lists every agent that finishes or needs you. > A card only runs while its workspace is open on the computer. If you open a card whose workspace > isn't open there, the phone will tell you to open it on the desktop first. > Push notifications to a locked phone aren't available yet — they need a permanent https address. > Keep the page open to hear the chime. --- ## Talk instead of typing > Press a hotkey, speak, and your words appear as text — processed entirely on your computer. Source: https://docs.neurosquad.ai/en/dictation Explaining a task out loud is often faster than typing it. NeuroSquad has built-in dictation that works anywhere on your computer — not just in NeuroSquad. **1. Press the hotkey** `Ctrl Shift Space`. A small black capsule shows that it's listening. **2. Speak** Say what you want, as long as you like. **3. Press the hotkey again** The text is copied to your clipboard. If NeuroSquad is in front, it's also typed straight into the agent you're working with. **Tap** the hotkey to start and stop, or **hold** it while you speak and let go when you're done. > Speech never leaves your computer. The speech model runs locally, and audio is kept only for as > long as it takes to turn it into text. ### Change the hotkey **Settings → Dictation → Dictation shortcut → Change**, then press the new combination. You can also choose where the capsule appears on screen (**Overlay position**). - **[Speech models](https://docs.neurosquad.ai/en/dictation/models)**: Faster, or more accurate — your choice. - **[Dictation history](https://docs.neurosquad.ai/en/dictation/history)**: Everything you said, ready to copy again. --- ## Speech models > Choose between the default speech model and larger, more accurate ones. Source: https://docs.neurosquad.ai/en/dictation/models Pick a model in **Settings → Dictation**. All of them run on your computer. None of them is part of the installer: each is a one-time download, offered by the first-run wizard or right there in Settings. Until a model is on disk, the status bar says **Dictation: download the model**. - **Parakeet (default)**: A one-time download, used by default. Fast on any computer and accurate enough for everyday dictation. Supports English and major European languages, including Russian. - **Whisper large-v3-turbo**: A one-time download. Noticeably better with accents, background noise and punctuation, but slower on an ordinary processor. - **Whisper with GPU (faster-whisper)**: The same Whisper model, made fast by an NVIDIA graphics card: ten minutes of speech in a few seconds. Needs a one-time extra install, offered right there in Settings. Windows only. Don't have an NVIDIA card? Stay with Parakeet — it's the right choice for most people. --- ## Dictation history > Everything you dictated, in a side panel, ready to copy again. Source: https://docs.neurosquad.ai/en/dictation/history Everything you dictate is kept as text in the **dictation history** panel on the right side of the window. Open it to copy an earlier dictation again — handy when the text went to the wrong window. - **Copy** an entry with one click. - **Delete** a single entry, or **Clear** the whole history. Only the text is kept, never the audio, and it stays on your computer. --- ## Usage & costs > See exactly how many tokens your agents use and what they cost — by agent, workspace, agent type, model and provider. Source: https://docs.neurosquad.ai/en/usage AI agents are paid by the token. The **Usage** section in the sidebar shows where your tokens — and your money — go. ### Pick a period Choose **Today**, **7 days**, **30 days**, **This month**, **Last month** or **All time**, or any **Date range** you like. Every number is compared with the previous period of the same length. Narrow it down to one workspace or one agent with the filters. **Include usage outside cards** also counts sessions you ran in your own terminal, outside NeuroSquad. ### What you see - **Tokens and cost** for the period, at the top. - **Tokens over time**, stacked by agent, and **What the tokens were** — new input, context re-read from cache, context written to cache, output. - **When the tokens go out** — a weekday × hour map of when your agents are busiest. - **Every agent** — a sortable table with the exact numbers: requests, input, cache, output, total, peak context, cost and share. Breakdown tabs split the same numbers **By agent**, **By workspace**, **By harness**, **By model** and **By provider**. Click an agent or workspace to jump to it. ### Compare models **Compare models** puts several models side by side: cost, tokens, cost per request, cost per 1,000 output tokens, share of the period, and each model's list price. ### Exact numbers, and where they come from Costs are counted exactly and only rounded on screen. The rows always add up to the total. Each cost is either what the agent program itself recorded, or the model's list price — and requests sent through [OpenRouter](https://docs.neurosquad.ai/en/providers/openrouter) are priced from OpenRouter's own catalogue. > Usage is read from the agents' own logs: **Claude Code**, **Codex CLI**, **OpenCode**, **Kilo Code**, **Hermes Agent**, **Pi** and > **omp**. The section tells you which of your agents aren't counted. If you're on a subscription > rather than paying per token, the cost shown is what the same work would cost at list price. ### Export **Export CSV** saves the table, to open in Excel or Google Sheets. ### OpenRouter If you use [OpenRouter](https://docs.neurosquad.ai/en/providers/openrouter), the **By provider** tab shows what OpenRouter reports for your key: spent today, this week, this month and all time, and your limit. That's for the key as a whole — every agent and every other app that uses it. ### Keep costs under control - The agent card shows how full a Claude Code, OpenCode, Kilo Code or Hermes Agent agent's context is. - A [Budget card](https://docs.neurosquad.ai/en/cards/budget) sets a token limit for a whole workspace and pauses its agents when it's crossed. --- ## Model providers > Choose which AI model each agent runs on — with your own login, or through a provider like OpenRouter. Source: https://docs.neurosquad.ai/en/providers By default every agent runs on the account you signed in with — your Claude subscription for Claude Code, your OpenAI account for Codex, and so on. In NeuroSquad this is called **Default (harness login)**. A **model provider** lets you choose the model yourself instead: connect a provider once in **Settings → Providers**, then pick a provider and model for each agent. Handy for trying a different model on a task, or running a cheaper one on routine work. - **[OpenRouter](https://docs.neurosquad.ai/en/providers/openrouter)**: Hundreds of models from many AI labs with one key — for Claude Code, Codex CLI, OpenCode, Kilo Code, Qwen Code, Hermes Agent, Pi and omp. - **[CLI accounts and plan limits](https://docs.neurosquad.ai/en/providers/accounts)**: Several Claude Code or Codex sign-ins side by side, a meter for each plan, and one-click hand-off to another account. You can see which provider and model an agent uses on a small chip in its card, and what each one costs in [Usage & costs](https://docs.neurosquad.ai/en/usage). ### A model of the agent's own login Without any provider you can still pick which of its **own** models an agent runs on: open the card's ⋯ menu → **Provider and model**, keep **Default (harness login)** and choose or type a model — for example `opus` for Claude Code or `anthropic/claude-sonnet-4-5` for OpenCode. It is passed to the agent the next time it starts. Crush and Amp choose their model themselves, so they don't offer this. --- ## OpenRouter > Run Claude Code, Codex CLI, OpenCode, Kilo Code, Qwen Code, Gemini CLI, GitHub Copilot CLI, Hermes Agent, Pi, omp, Factory Droid or Crush on hundreds of models with one OpenRouter key. Source: https://docs.neurosquad.ai/en/providers/openrouter [OpenRouter](https://openrouter.ai) gives you models from many AI labs with a single key, billed to your OpenRouter credits. NeuroSquad can run **Claude Code**, **Codex CLI**, **OpenCode**, **Kilo Code**, **Qwen Code**, **Gemini CLI**, **Hermes Agent**, **Pi**, **omp**, **Factory Droid** and **Crush** agents through it (Factory Droid needs no Factory account for this; Gemini CLI goes through a small translator NeuroSquad runs on your machine, since OpenRouter does not speak its Gemini API). ### 1. Connect your key **1. Open Settings → Providers** Press **Get a key** if you don't have one yet — it opens OpenRouter's site. **2. Paste the key and press Save and test** You'll see **Key works**. The key is encrypted by your operating system and only ever handed to the agents you point at it. Once connected, the same page shows what you've **Spent** today, this week and this month, your limit if you set one on OpenRouter, and the list of available **Models**. ### 2. Create an agent on a model In the add menu, choose **New agent… (provider, model, role)**. The dialog asks for: - **Harness** — which agent program to run (Claude Code, Codex CLI, OpenCode, Kilo Code, Qwen Code, Gemini CLI, GitHub Copilot CLI, Hermes Agent, Pi, omp, Factory Droid or Crush). - **Provider** — **OpenRouter**, or **Default (harness login)**. - **Model** — search the catalogue; each model shows its context size and price per million tokens. Leave it on **Harness default** to let the agent choose. - **Role** (optional) — see [Roles](https://docs.neurosquad.ai/en/agents/roles). - **Name** (optional). The agent's card shows a chip with its provider and model. ### Change it later Open **Provider and model** in the agent card's menu, pick new values and press **Apply**. The change takes effect the next time the agent starts. ### Without a key If no key is saved, nothing is sent to OpenRouter: the agent simply runs on its **default login**, and its chip turns amber to tell you so. The **New agent** dialog also warns you and offers **Open settings**. > Claude Code is only guaranteed to work with Anthropic's own models. On other models, its tools may > not work properly — the model picker warns you. --- ## CLI accounts and plan limits > Keep several Claude Code or Codex sign-ins side by side, see how much of each plan's limit is used, and continue work on another account with one click. Source: https://docs.neurosquad.ai/en/providers/accounts If you have more than one Claude or ChatGPT subscription, say a personal one and one from work, NeuroSquad keeps each sign-in separate and shows how much of each plan is used. ### Plan meters A **Claude Code** or **Codex CLI** card shows a small ring in its header. It shows how full the plan's busiest window is, for example `7d 80%`. Click it to see every window with its reset time: - **Claude Code** (Pro and Max): the 5-hour window and the weekly window. - **Codex CLI** (ChatGPT plans): the windows your plan has, for example 5 hours and a week. The ring turns amber at 80% and red at 95%. At those two points you also get a notification, which you can switch off in **Settings → Notifications → An agent hit its usage limit**. All the meters are in one place too: - **Usage → Plan limits** lists every account. - The **Squad** board has a line for each account its agents use. The numbers come from the CLIs themselves: - **Claude Code** reports them to its status line after every answer. - **Codex** writes them into its own session log. NeuroSquad never reads your sign-in and never asks a service for your usage on its own. As a result: - A Claude Code meter appears after the first answer in a card. - It stays at its last value while no Claude Code card runs, and shows the age of those numbers. - A window whose reset time has passed shows as started over. #### Your Claude Code status line keeps working To receive the numbers, a Claude Code card routes its status line through NeuroSquad. If you have your own status line, NeuroSquad still runs your command and shows its output. If you don't, the line shows the meter, for example `5h 6% · 7d 80%`. To leave Claude Code's status line completely untouched, switch off **Settings → CLI accounts → Claude Code plan meter**. Claude Code cards then have no meter. Other CLIs don't hand plan numbers to local tools, so they have no meter. You can still see what they cost in [Usage & costs](https://docs.neurosquad.ai/en/usage). ### Several accounts of one CLI Open **Settings → CLI accounts** and press **Add account** under Claude Code or Codex CLI. Give it a name such as *Work*. - Each account gets a folder of its own for that CLI's sign-in, settings and history. - **Your account**, your usual sign-in, stays exactly where it was. - A new account starts empty: it doesn't copy your settings. To use an account, choose it for a card in one of these places: - The card's ⋯ menu → **Provider and model** → **Account**. - The **New agent…** dialog. It applies the next time the card starts. The first time, sign in **inside the card** with the CLI's own sign-in: - In Claude Code, run `/login`. - Codex shows its sign-in screen by itself. > NeuroSquad never reads, copies or sends what a CLI stores in an account's folder. Sign-in always > happens in the CLI itself. Deleting an account deletes its folder: that sign-in and the conversations on it. Cards that used it go back to your account the next time they start. ### Continue on another account When a card's plan is nearly used up, or a limit has been hit, open the meter or the limit chip and press **Continue on another account…**. The [hand-off](https://docs.neurosquad.ai/en/agents/long-sessions) dialog opens. Pick the account, check the summary and create the new card. It starts beside the old one, in the same folder, with the summary typed in. Nothing switches accounts on its own. Each account is used the way its plan allows, and moving the work is always your decision. If the account has never been signed in from NeuroSquad, the new card opens the CLI's sign-in first. The summary is copied to the clipboard so you can paste it once you're in. ### Usage by account **Usage → By account** splits tokens and cost by the sign-in that paid for them. Each CLI's own sign-in is listed as *Your account*, and every added account gets a row of its own. --- ## Integrations > Connect your agents to Telegram, and how saved tokens and keys are kept. Source: https://docs.neurosquad.ai/en/integrations Integrations work just like every other card: add the card, connect your account once, and draw an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) from an agent to it. The agent can then use that service — and you see every call on the arrow. - **[Telegram bot](https://docs.neurosquad.ai/en/integrations/telegram)**: Talk to your agents from Telegram, and get told when they finish. ### Your passwords and tokens are safe Passwords, tokens and keys are encrypted by your operating system and stored on your computer. Once saved, they're never shown again — not in the app, not on your phone through [remote access](https://docs.neurosquad.ai/en/remote). Deleting a card deletes its saved secrets too. > The **Integrations** section of the sidebar lists your Telegram cards across all workspaces, plus > your [model providers](https://docs.neurosquad.ai/en/providers). --- ## Telegram bot > Message your agents from Telegram and get their answers — and a ping when they finish. Source: https://docs.neurosquad.ai/en/integrations/telegram The **Telegram card** connects your own Telegram bot to your agents. Write to the bot from your phone, and the message reaches the agents connected to the card by an [arrow](https://docs.neurosquad.ai/en/canvas/arrows). They can answer you back in the same chat. It runs from your computer — no server to set up. ### Set it up **1. Create a bot** In Telegram, open **@BotFather** (the card has a button for it), send `/newbot` and pick a name. BotFather replies with a token. **2. Paste the token** Add a Telegram card, paste the token and press **Connect**. **3. Write to your bot, then press Allow** Send `/start` to your bot. The card shows the chat under "Wants to talk to your agents" — press **Allow**. > Only chats you **Allow** ever reach your agents. Anyone else who finds your bot is ignored. ### Get told in Telegram **Tell me in Telegram when a connected agent finishes or needs input** sends a message to every allowed chat — so you can leave your desk and still know when to come back. You can also type messages as the bot right in the card, and choose which connected agent receives them. --- ## Skills & MCP > Give agents skills from skills.sh and tools from any MCP server — installed once, handed to specific agents with an arrow. Source: https://docs.neurosquad.ai/en/skills-mcp Two kinds of add-ons make an agent better at a job, and NeuroSquad installs both for you: - **MCP server**: A small program or web service that gives an agent **new tools**: read a Figma file, open GitHub issues, query a database, fetch current library docs. It speaks the Model Context Protocol, the standard every major coding agent understands. - **Skill**: A folder of **expert instructions** (a `SKILL.md`, sometimes with scripts and reference files) that tells an agent how to do a kind of task well: brainstorm before building, design a distinctive interface, write a proper test plan. ### How it works **1. Find it in the catalog** **Skills & MCP** searches the official **MCP Registry** (about 35,000 servers) and **skills.sh** (the 20,000 most popular skills, with install counts and security scans) — as you type. See [Catalog and installing](https://docs.neurosquad.ai/en/skills-mcp/catalog). **2. Install it once** You see exactly what will run before anything is downloaded, and confirm. Everything goes into NeuroSquad's own folder — nothing is installed globally, and your own agent settings are never touched. **3. Put a card on the canvas and draw an arrow** An **MCP server** card or a **Skill** card stands for one installed item. Draw an arrow from it to an agent, and that agent has it. See [Giving them to agents](https://docs.neurosquad.ai/en/skills-mcp/cards). > **Only the agents you connect see them.** An agent without an arrow to an MCP or skill card sees > none of what you installed — not even that it exists. Five agents can share one server, or each > get a different one. ### Which agents can use them | Agent | Skills and MCP servers | After you draw an arrow | | --- | --- | --- | | **Claude Code** | Yes | Right away, no restart | | **Hermes Agent** | Yes | Right away, no restart | | **Kilo Code** | Yes | Right away, no restart | | **GitHub Copilot CLI** | Yes | Right away, no restart | | **Pi** | Yes | Right away, no restart | | **omp** | Yes | Right away, no restart | | **aider** | Yes | Right away, no restart | | **Factory Droid** | Yes | Right away, no restart | | **Amp** | Yes | Right away, no restart | | **Auggie** | Yes | Right away, no restart | | **Goose** | Yes | Right away, no restart | | **Codex CLI** | Yes | On the agent's next start | | **Qwen Code** | Yes | On the agent's next start | | **Gemini CLI** | Yes | Right away | | **Kimi Code** | Yes | On the agent's next start | | **Cline CLI** | Yes | On the agent's next start | | Other agents | No | — | The card says the same thing next to each connected agent: **Live**, **Next start** or **Can't use**. The last one means NeuroSquad doesn't give tools to that agent at all — the same agents that [arrows](https://docs.neurosquad.ai/en/canvas/arrows) don't give abilities to. ### How the agent knows what it has You don't have to tell the agent anything. - **Skills:** the agent's `skill_load` tool lists every connected skill with its "when to use it" line, so the agent loads the matching skill on its own before it starts a task — the same way Claude Code's own skills work. - **MCP servers:** each server's tools appear under the server's name, like `framelink__get_figma_data`, with the server named in every description, plus the server's own usage notes. - **`neurosquad_connections`** — the tool an agent calls to see what is on the other end of its arrows — lists the connected servers and skills too. ### Things to know - **You approve each call to an installed server.** Its tools come from a separate server entry (`ns-connected`) that NeuroSquad does not pre-approve, so Claude Code, Codex and Qwen ask before each call — unless you switched your agent to a mode that approves everything itself. Hermes Agent never asks on its own, so for it NeuroSquad asks: **Allow once**, **Allow for this session** or **Deny** (no answer in five minutes counts as Deny). A server that later changes its tools shows "This server changed its tools" on its card; new and changed tools stay hidden from agents until you press **Accept changes**. - **It's third-party code.** A server you install runs on your computer (or is a service on the internet); a skill's text goes straight into the agent's instructions. Install what you trust — the catalog shows the source, the exact commands and, for skills, security scans. - **Not every server can be installed yet.** Servers published only as MCPB bundles, NuGet or Cargo packages, and packages that start a local web server, are shown but not installable. - **Some sign-ins only allow approved apps.** Figma's official remote server, for example, refuses sign-in from apps it hasn't approved. Use a server that takes a personal token instead — **Framelink Figma MCP** (`FIGMA_API_KEY`) works with your own Figma token. --- ## Catalog and installing > Search the MCP Registry and skills.sh, see exactly what will run, and install servers and skills into NeuroSquad's own folder. Source: https://docs.neurosquad.ai/en/skills-mcp/catalog **Skills, MCP & plugins** is one window with four tabs: **MCP servers**, **Skills**, **Plugins** and **Installed**. Open it from the sidebar (**Integrations → Skills, MCP & plugins**), or from an empty MCP or skill card with **Browse** — then whatever you install lands on that card. The add-card menu's **Plugin…** entry opens it on the Plugins tab. ### Search Results appear as you type. The whole catalog is kept on your computer and refreshed in the background, so search is instant and works offline. - **MCP servers** come from the official **MCP Registry** — every server published there. Filter by how it runs: **Local** (a package that runs on your computer), **Remote** (a service on the internet), and **No setup** (nothing to fill in). - **Skills** come from **skills.sh**, the most popular directory of agent skills. The most installed come first; while you are online, its own search is merged in with install counts. - **Installed** is your library: everything on this computer, with settings, updates and uninstall. ### Install an MCP server **1. Choose how it runs** Many servers can run several ways — an **npm** package (needs Node.js), a **PyPI** package (needs uv or Python), a **Docker** image (needs Docker), or a **remote** service over HTTPS. Ways NeuroSquad can't run yet are shown greyed out, with the reason. **2. Fill in its settings** Keys and tokens (a Figma token, an API key) go into password fields. They are encrypted with your system's keychain and **never shown to agents** — the agent only gets the tools. **3. Read “What will run”** The exact commands, the package and its pinned version, and the names of the settings it receives. If a Docker image asks for access to your files, network or devices, you get a warning. **4. Confirm and install** Tick the box and press **Install**. The output streams below the button. NeuroSquad then starts the server once to list its tools, and it is ready. > Everything goes into NeuroSquad's own data folder — its own copy of each package, its own > Python environment. Nothing is installed globally, and your `~/.claude`, `~/.codex` and other > agent settings stay untouched. Docker images are the exception: they live in Docker, as always. After installing, open it in **Installed** to: - **Test** — start it again and re-read its tools. - **Show its log** — what the server printed, when it won't start. - **Sign in / Sign out** — for remote servers that use your account (OAuth). The login page opens in your browser; the tokens are stored encrypted. - Change its **settings** — a saved key stays saved unless you type a new one. - **Uninstall** — removes its files, settings and saved keys. Cards that used it stay on the canvas and ask for another one. A server starts only when an agent first needs it, is shared by every agent connected to it, and stops after ten minutes without use. ### Install a skill **5. Open it** You get its `SKILL.md` rendered in full, its files and size, its license, and the security scans skills.sh publishes (Snyk, Socket and others). **6. Mind the scripts** If the skill ships scripts, you're told: an agent following the skill may run them. **7. Confirm and install** Tick "I read this skill" and press **Install**. What gets installed is exactly what you just read — if the skill changed upstream meanwhile, you're asked to look again. In **Installed** you can **Update** a skill when a newer version appears, **Open folder** to see its files, or **Uninstall** it. ### Add a plugin Plugins are built into NeuroSquad — nothing is downloaded to list them. Each one is a card that changes how the agents connected to it work; the first is the [RTK-AI Token Saver](https://docs.neurosquad.ai/en/plugins/rtk-ai-token-saver), which compresses the output of their shell commands. 1. Choose **Plugin…** in the add-card menu (typing `token` or `rtk` in the menu's search finds it too), or open the **Plugins** tab of the catalog. 2. Pick a plugin: you see what it does, how to use it and which agents it works with. 3. Press **Add to canvas**. The card appears on the canvas of the workspace you opened the menu in (from the sidebar: the workspace on screen). Draw an arrow from an agent to it. ### Safety - **Everything from a catalog is third-party.** An MCP server is a program with the rights of your user account, or a web service your agents talk to. Install what you'd install anyway. - **Skill text becomes agent instructions.** A skill can tell an agent to do anything — read it before you install it; the catalog shows it in full for that reason. - Remote servers are **HTTPS only**. Keys never appear on a command line or in a log. --- ## Giving them to agents > The MCP server card and the Skill card — connect them to agents with arrows; only connected agents get them. Source: https://docs.neurosquad.ai/en/skills-mcp/cards An installed server or skill reaches an agent through a card on the canvas. Add one from the [add menu](https://docs.neurosquad.ai/en/canvas/cards) — **MCP server** or **Skill** — and choose what it stands for: **Browse** opens the catalog, or pick one you already installed right on the card. ### Connect with an arrow Draw an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) between the card and an agent. That's all: - The agent gets the server's tools, or the skill — and **no other agent does**. - One card can connect to several agents; one agent can have several cards. - Delete the arrow and the agent loses it again. Each card lists the agents it is given to, and what that means for each: - **Live**: The agent has it right away, mid-conversation. Claude Code, Kilo Code and Hermes Agent work this way. - **Next start**: The agent reads its tools when it starts: restart it to pick up a new arrow. Codex CLI and Qwen Code work this way. - **Can't use**: NeuroSquad doesn't give tools to this kind of agent. Click an agent's name on the card to fly to it. ### The MCP server card - **Header:** the server's name, how many tools it has, and a dot — running, idle (it starts on the first call), starting, failed, or waiting for sign-in. - **Tools:** every tool the server offers. The one an agent called last is highlighted, and the card says "by Designer" for a moment. - **Problems in place:** "The server did not start" with the last line of its log and **Try again**; "needs you to sign in" with a **Sign in** button. - **Settings** opens it in the catalog; **Change server** points the card at another one. ### The Skill card - The skill's name, where it comes from, its files and whether it has scripts, and its description — the "when to use it" line the agent sees. - Who loaded it last and how many times. - Expand the card to read the whole `SKILL.md`. - **Details** opens it in the catalog (update, open folder, uninstall); **Change skill** points the card at another one. Zoomed out, the cards become tiles that show the server's tool count and agents, or the skill's name. > An agent loads a matching skill **before** starting the task, on its own — its `skill_load` tool > lists every connected skill with when to use it. If you want a particular skill used anyway, just > say so: "use the brainstorming skill". --- ## Plugins > Built-in add-ons you connect to an agent with an arrow — no restart, no changes to your CLI's own settings. Source: https://docs.neurosquad.ai/en/plugins A plugin changes how a connected agent works. You add it from the add-card menu — **Plugin…** opens the **Plugins** tab of the catalog, where you search and pick one — and connect it to an agent with an [arrow](https://docs.neurosquad.ai/en/canvas/arrows). The agent picks it up on its next action; remove the arrow and it stops. Plugins ship with NeuroSquad and are checked before they get into the list. Your CLI's own settings are never changed: a plugin is a layer NeuroSquad adds to that one agent card. - **[RTK-AI Token Saver](https://docs.neurosquad.ai/en/plugins/rtk-ai-token-saver)**: Compresses the output of an agent's shell commands — fewer tokens, same facts. - **[Caveman](https://docs.neurosquad.ai/en/plugins/caveman)**: Makes the agent's answers short — no filler, code and errors kept exact. - **[Memory (mem0)](https://docs.neurosquad.ai/en/plugins/mem0-memory)**: Long-term memory your agents share across sessions — kept on your computer. - **[Context7 — up-to-date docs](https://docs.neurosquad.ai/en/plugins/context7-docs)**: Current, version-specific library docs for your agents instead of stale training data. - **[Code Graph](https://docs.neurosquad.ai/en/plugins/code-graph)**: A knowledge graph of your code — agents find callers, callees and definitions instead of grepping. - **[Graphify](https://docs.neurosquad.ai/en/plugins/graphify)**: A live map of your code — agents ask it structural questions, and every query lights up on the map. More plugins are on the way. Skills and MCP servers work the same way through their own tabs of the catalog — see [Skills & MCP](https://docs.neurosquad.ai/en/skills-mcp). --- ## RTK-AI Token Saver > Connect an agent to it and the output of its git, ls, grep and test commands comes back compressed — fewer tokens, same facts. Source: https://docs.neurosquad.ai/en/plugins/rtk-ai-token-saver Agents read a lot of command output: every `git status`, `git log`, directory listing and test run lands in their context. The **RTK-AI Token Saver** plugin routes an agent's shell commands through [RTK](https://github.com/rtk-ai/rtk), an open-source tool that keeps the facts and drops the noise — `git status` becomes a compact list of changed files, a passing test suite becomes one line. ### How to use it 1. In the add-card menu choose **Plugin…**, open **RTK-AI Token Saver** in the **Plugins** tab and press **Add to canvas**. 2. If RTK isn't installed, press **Download RTK**. NeuroSquad downloads the official build from GitHub (about 4.5 MB) and checks it against the checksum GitHub publishes — without a checksum it refuses to download. Already have RTK (`winget install rtk-ai.rtk`, `brew install rtk`)? It's found automatically. 3. Draw an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) from an agent to the card. That's it — the agent's **next** command already goes through RTK. No restart. Remove the arrow and the next command runs as usual again. ### What the card shows - **How much less output** the connected agents read, in percent, and roughly how many tokens that saved. - Each connected agent with its own savings and the last command RTK compressed, for example `git status → rtk git status`. - Which RTK version is in use, and whether it's your own install or the downloaded one. Each compressed command also flashes on the arrow and is listed in the arrow's log. > RTK estimates tokens as bytes ÷ 4, so the percentage is accurate and the token count is > approximate. RTK compresses the output of shell commands only — your prompts, the agent's own > file reads and its answers are unchanged. ### Which agents it works with It works live with **Claude Code**, **Cursor CLI**, **OpenCode** and **Kilo Code**. Other agents can be connected, but the card marks them **Not supported** — their CLIs don't offer a way to rewrite a command before it runs yet. - **Dangerous mode** — every supported command is compressed. - **Normal mode (Claude Code)** — read-only commands such as `git status`, `git log`, `ls`, `cat` and `grep` are compressed with no prompt, exactly as they ran before. Commands that would have asked you anyway (`git push`, `cargo test`…) still ask once — you approve the `rtk` version. Anything else runs unchanged. RTK never adds a prompt and never approves something that would have asked. - **Normal mode (Cursor, OpenCode, Kilo)** — their permission prompts can't be predicted from outside, so RTK works for them in dangerous mode only. - **Canvas mode** — the agent has no shell of its own, so there is nothing to compress. If RTK is missing, fails or doesn't know a command, the original command runs unchanged. An agent that needs the full output of one command can run it with `RTK_DISABLED=1` in front. ### Privacy RTK runs on your computer. NeuroSquad turns RTK's own (opt-in) telemetry off for every agent it starts and keeps RTK's history per agent inside NeuroSquad's data folder. Your RTK settings stay as they are. RTK is made by rtk-ai and published under the Apache 2.0 license. --- ## Caveman > Connect an agent to it and its answers get short — no filler, with code, commands and error messages kept exact. Source: https://docs.neurosquad.ai/en/plugins/caveman Agents like to explain: a friendly opening, a recap, "I'd recommend…". The **Caveman** plugin gives a connected agent the reply rules of [caveman](https://github.com/JuliusBrussee/caveman), an open-source project by Julius Brussee: drop the filler, keep every technical fact. In the author's words, "Caveman no make brain smaller. Caveman make *mouth* smaller." The same question, from caveman's own README: - **Without caveman:** "The reason your React component is re-rendering is likely because you're creating a new object reference on each render cycle. When you pass an inline object as a prop, React's shallow comparison sees it as a different object every time, which triggers a re-render. I'd recommend using useMemo to memoize the object." - **With caveman (Full):** "New object ref each render. Inline object prop = new ref = re-render. Wrap in `useMemo`." ### How to use it 1. In the add-card menu choose **Plugin…**, open **Caveman** in the **Plugins** tab and press **Add to canvas**. 2. Pick a level on the card: - **Lite** — no filler or hedging, full sentences stay. - **Full** — the classic caveman style and the author's default. - **Ultra** — the tersest: conjunctions go too, each fact is said once. - **文言文** — the same three levels in classical Chinese. 3. Draw an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) from an agent to the card. That's it — the agent's **next** answer already follows the rules. No restart, nothing is installed into your CLI. Change the level and the next turn gets the new one. Remove the arrow and the next turn gets a short note to answer normally again. ### What stays exact Code, commands, file paths and error messages are never shortened — only the prose around them. Security warnings and confirmations of irreversible actions come back in full sentences. Code, commit messages, documentation and pull-request text the agent writes stay in normal prose. The agent keeps answering in your language. ### What the card shows - The level, with caveman's own example answer for it (and the same answer without caveman). - Each connected agent: whether it works live, what it got last (the rules, a reminder, or the note to switch back) and how many turns carried the rules. - What the rules cost: they are input for the model — the full set once per session (about 1,400 tokens), then a short reminder on every turn (about 60 tokens). Both are estimates at 4 characters per token. > Shorter answers mean fewer **output** tokens, but the rules themselves are extra **input** tokens, > and the model's thinking is not shortened. On very short questions the rules can cost more than > they save — caveman's author says the same. Try it on your own work and keep it where it pays off. ### Which agents it works with It works live with **Claude Code**, **Codex** and **Qwen Code** — the rules go out through a hook that runs before each turn and can add text for the model. Other agents can be connected, but the card marks them **Not supported**: their CLIs don't offer a way to add text to a turn from outside yet. Dangerous mode and canvas mode don't matter here: the plugin changes how the agent writes, not what it may do. ### Where it comes from The rules are caveman's own — its `caveman` skill text and its per-turn reminder — copied into NeuroSquad unchanged from a pinned version and used under the MIT license. NeuroSquad doesn't download anything, doesn't send anything anywhere and doesn't change your CLI's settings. caveman's separate proxy and engine are not part of this plugin. --- ## Memory (mem0) > Long-term memory your agents share across sessions — they save facts and decisions and recall them later. Kept on your computer. Source: https://docs.neurosquad.ai/en/plugins/mem0-memory An agent forgets everything when its session ends. The **Memory** plugin gives connected agents a long-term memory: they save what is worth keeping — a decision, a convention, your preference, a fact about the project — and find it again in later sessions, in other agents, after a restart. It runs on [mem0](https://github.com/mem0ai/mem0), an open-source memory engine (Apache-2.0), built into NeuroSquad. The memory is stored on your computer, in NeuroSquad's data folder. There is no account to create and no server to run. ### How to use it 1. In the add-card menu choose **Plugin…**, open **Memory (mem0)** in the **Plugins** tab and press **Add to canvas**. 2. Draw an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) from an agent to the card. The agent now has memory tools. Ask it to remember something ("remember that we deploy only through GitHub Actions") or just work — agents are told to search memory before work that may depend on earlier decisions and to save lasting facts. Remove the arrow and the tools are gone; the memories stay on the card. Most agents get the tools right away, without a restart. Codex, Kimi Code, Cursor and Crush read their tool list once at start, so they see the memory tools from the start and the arrow decides whether a call goes through. Qwen Code and Cline pick them up on their next start. ### What the agent can do | Tool | What it does | | --- | --- | | `memory_search` | Finds the memories relevant to a question, best first | | `memory_add` | Saves a fact (or a piece of conversation to extract facts from) | | `memory_list` | Lists the memories, newest first | | `memory_get` | Reads one memory | | `memory_update` | Corrects a memory that became wrong | | `memory_delete` | Forgets a memory | An agent can change or delete only the memories **it** saved. To let agents edit any memory — yours and other agents' — turn on **Agents may edit any memory** in the card's settings. ### The card The card shows how many memories there are, the newest first, who saved each and when. A memory an agent has just written glows for a moment. You can search, add a memory yourself with **+**, edit or delete any memory, export everything to a JSON file and clear the memory. ### Whose memory: the scope Open the settings (the sliders icon on the card) and pick a **scope**: - **This workspace** (default) — every agent connected to a Memory card in this workspace shares one memory. - **All workspaces** — one memory for every workspace: good for what holds everywhere, like your preferences and conventions. - **Per agent** — each connected agent has its own private memory; the card shows them all. Memories belong to the scope, not to the card: delete the card and add a new one with the same scope, and the memories are still there. **Clear** in the settings deletes them. ### Search: by words or by meaning Out of the box the card searches by **keywords** — shared words and word parts, so "postgres" finds "PostgreSQL". It works offline with nothing set up, but it won't connect synonyms ("car" and "automobile"). For search **by meaning**, press **Download 150 MB** under **Smart search** on the card (or pick it in Settings → Search). It downloads a small multilingual model once — it runs on your computer, works offline and understands English, Russian, Chinese and dozens of other languages, so a question in Russian finds a memory written in English. Every file is checked against its checksum. You can also use an embedding model from [OpenRouter](https://docs.neurosquad.ai/en/providers/openrouter) or from a [model server](https://docs.neurosquad.ai/en/providers) you added in Settings → Providers that speaks the OpenAI API — for example Ollama with `nomic-embed-text`, or LM Studio. The choice applies to every Memory card. When you switch, every memory is re-indexed; the card shows the progress, and agents wait until it finishes. ### Fact extraction By default a memory is stored exactly as written. Choose a model under **Fact extraction** and mem0 turns what agents save into short facts and skips what it already knows. This costs one request to that model per save. ### Automatic memory Two switches in the settings, both off by default: - **Automatic recall** — before each of your prompts, the most relevant memories are added to the agent's turn as notes. Works with **Claude Code**, **Codex**, **Qwen Code**, **OpenCode**, **Kilo Code**, **Gemini CLI**, **pi** and **omp**. Other agents use `memory_search` themselves. - **Automatic saving** — when a connected agent finishes a turn, your prompt and the agent's final answer go to the fact-extraction model, which keeps only lasting facts (often none). Needs a fact-extraction model. ### History, export and import - The clock button on a memory shows its history: when it was added and each edit, with the text before. - **Export** in the settings saves the card's memories to a JSON file. **Import** reads such a file, shows how many are new and how many are already there (they are skipped), lets you choose the scope, and adds the new ones. **Undo** on the card removes exactly what the last import added. ### WSL and SSH workspaces Agents in a workspace inside WSL or on an SSH host use the card the same way: their arrow gives them the `memory_*` tools, and automatic recall reaches Claude Code there through its prompt hook. The memories themselves stay in NeuroSquad's data folder on this computer — nothing is stored on the other side — and the workspace scope keeps each workspace's memories apart as usual. ### Deleting a workspace or an agent Deleting a workspace also deletes the memories saved for it; deleting an agent deletes its private memories (per-agent scope). The confirmation says how many. Memories shared by all workspaces stay. > Your keys stay in NeuroSquad: they are only sent to the provider you chose, with each request. > Nothing is sent to mem0 — the engine's own usage reporting is switched off. > Memories are notes from the past, not instructions: they can be outdated. Don't ask an agent to > remember passwords or keys. --- ## Context7 — up-to-date docs > Connect an agent to it and the agent looks up current, version-specific documentation for the libraries it works with, instead of relying on what it remembers from training. Source: https://docs.neurosquad.ai/en/plugins/context7-docs A model knows a library as it was when the model was trained. APIs change: a hook gets a new signature, a config option is renamed, a framework moves to a new router. The **Context7** plugin gives a connected agent two tools from [Context7](https://github.com/upstash/context7), an open-source project by Upstash: look up a library, then read its current documentation and code examples — for the version the project uses. ### How to use it 1. In the add-card menu choose **Plugin…**, open **Context7 — up-to-date docs** in the **Plugins** tab and press **Add to canvas**. 2. Draw an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) from an agent to the card. The agent now has two tools: - `context7_resolve_library_id` — finds the library by name ("React", "Next.js", "Django") and lists the matches with their Context7 id (`/reactjs/react.dev`), how many code examples there are, how trusted the source is and which versions are indexed. - `context7_query_docs` — returns the documentation and examples of one library for one focused question ("useEffect cleanup function"). Most agents use them on their own when a task touches a library API. You can also ask: "check the Next.js docs first", or add **use context7** to your prompt. Remove the arrow and the tools are gone. No restart for most CLIs, and nothing is installed into your CLI. ### It works without an account Context7's documentation index is a hosted service, free to use. Without a key it has a lower rate limit; a free API key from the [Context7 dashboard](https://context7.com/dashboard) raises it. Paste the key in the card's **Key & cache** panel — it is stored encrypted on your computer, never shown again and never written into a file or a command line. One key serves every Context7 card. The card shows how many requests are left and when the limit resets. When the limit is used up the card says **Rate-limited**, agents get a clear message instead of an error, and no further requests are sent until the limit resets — answers already in the cache still work. ### The cache Every answer is kept on your computer for 24 hours. When two agents ask the same question, or the same agent asks again, the answer comes from the cache and costs no request. The **Key & cache** panel shows how many answers are cached and how many lookups they served, and clears the cache. ### Auto-docs Turn on **Auto-docs** on the card and the agent gets help before each of your prompts: - When the prompt names one of the project's dependencies (from `package.json`, `requirements.txt`, `pyproject.toml`, `Cargo.toml` or `go.mod`), the agent gets a one-line note that current docs for it are available — with the version your project declares. No request is sent for this, so the turn starts just as fast. The note comes once per library every half hour. - When the prompt says **context7** ("use context7") and names a dependency or a library id (`/vercel/next.js`), the documentation itself is added to the turn. NeuroSquad waits for it for about a second and a half; if Context7 is slower, the agent gets the note instead, and the answer is cached for the next time. Auto-docs works with **Claude Code**, **Codex**, **Qwen Code**, **OpenCode**, **Kilo Code**, **pi**, **omp** and **Gemini CLI**. Every other agent connected by an arrow still gets the two tools. ### WSL and SSH workspaces Agents in a workspace inside WSL or on an SSH host get the two tools by arrow as usual — the lookups are made by NeuroSquad on this computer. Auto-docs reads the project's `package.json` and other manifests from WSL or over the SSH connection. ### What the card shows - The service state — **Ready**, **Rate-limited**, **Offline** or **Error** — with requests left and the reset date. - **Try a lookup**: type a library and a question to see what an agent would get. - **Recent lookups**: which library and question, which agent asked, when, and whether it came from the cache. > Library names and questions are sent to Context7's servers (run by Upstash). Never put secrets, > passwords or proprietary code into a question — the tool descriptions tell agents the same. The > rest of your project stays on your computer: auto-docs reads the dependency list locally and sends > only a library name and the question. ### Where it comes from The two tools are those of Context7's official MCP server (`@upstash/context7-mcp`, MIT license), with its descriptions; NeuroSquad calls the same Context7 API directly, so nothing extra is installed or started. The documentation index itself is Context7's hosted service. If you want documentation lookups that never leave your computer, a self-hosted documentation MCP server can be added from the **MCP** tab of the catalog instead. --- ## Code Graph > Connect an agent to it and the agent finds code by structure — who calls a function, what it calls, where a symbol lives — instead of grepping and reading file after file. Source: https://docs.neurosquad.ai/en/plugins/code-graph To answer "what calls `processOrder`?" an agent usually greps, opens a file, greps again, opens the next one — and spends thousands of tokens on code it didn't need. The **Code Graph** plugin indexes your workspace's code into a knowledge graph — functions, classes, methods, calls, imports, routes — with [codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp), an open-source engine by DeusData. A connected agent asks the graph instead and gets the answer in one call. ### How to use it 1. In the add-card menu choose **Plugin…**, open **Code Graph** in the **Plugins** tab and press **Add to canvas**. 2. Press **Download** on the card. NeuroSquad downloads the official codebase-memory-mcp build from GitHub (about 40 MB; about 300 MB once unpacked) and checks it against the checksum pinned in the app — a file that doesn't match is deleted. This happens once. 3. Press **Build graph**. Most projects take seconds, a very large one a few minutes. 4. Draw an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) from an agent to the card. The agent now has the graph tools. Most CLIs pick them up without a restart; remove the arrow and they are gone. ### What the agent can do | Tool | What it answers | | --- | --- | | `codegraph_search_graph` | Find functions, classes and other symbols by name, pattern or meaning | | `codegraph_trace_path` | Who calls a function and what it calls, several hops deep | | `codegraph_get_code_snippet` | The source of one symbol, without opening the whole file | | `codegraph_query_graph` | Read-only Cypher queries for multi-step questions | | `codegraph_get_architecture` | Languages, packages, entry points, routes, hotspots | | `codegraph_search_code` | Text search ranked by the graph | | `codegraph_get_file_outline` | Everything declared in one file | | `codegraph_detect_changes` | Which symbols your uncommitted changes affect | | `codegraph_get_graph_schema`, `codegraph_index_status`, `codegraph_check_index_coverage` | What's in the graph and how complete it is | | `codegraph_reindex` | Re-index now, after edits made a moment ago | You can simply ask: "use the code graph to find everything that calls `validateOrder`". ### The card - **The main fact** — how many symbols the graph holds, with files, calls and links, and whether it's up to date. - **A search box** — try a name and see where it's defined. - **What's in it** — functions, interfaces, classes, types and the languages of the project. - **Agents using it** and the last graph call each of them made. ### Always up to date With **Auto-update** on (the default), the card notices when files change and re-indexes a few seconds later — only what changed, so it's quick. It also refreshes after a connected agent finishes a turn. Turn it off to update by hand with **Update now**. > The graph is built from the workspace's folder. An agent working in an isolated worktree still > queries the graph of the main folder. ### WSL and SSH workspaces For a workspace inside WSL or on an SSH host, the engine runs **there**, next to the code. The card shows where — **WSL · Ubuntu** or **SSH · your host**: - **Download** fetches the engine's Linux build (x86-64 or ARM64, picked by the host's CPU) and checks it here; the first **Build graph** copies it into NeuroSquad's own folder on that side (`~/.neurosquad`), checks it again and unpacks it there — once per distro or host. - The graph lives in that folder too. Nothing is written into your project or the rest of your home there, and your code doesn't come to this computer: agents get the answers to their queries. - Freshness: for a WSL project on a Windows drive (`/mnt/c/…`) the card watches the files as usual; elsewhere it updates after a connected agent's turn and on **Update now**. - Deleting the card (or the workspace) deletes the graph on that side; quitting NeuroSquad stops the engine there. The engine runs on Linux only: an SSH host running macOS shows "No engine build for this host". ### Privacy and storage Everything runs on your computer. codebase-memory-mcp sends nothing anywhere — no account, no telemetry, your code never leaves the machine. The engine and the graph live in NeuroSquad's data folder: nothing is written into your project or your home folder, and if you have your own codebase-memory-mcp installed, it keeps working separately. Delete the card and its graph is deleted too. codebase-memory-mcp is made by DeusData and published under the MIT license. --- ## Graphify > A live map of your code's structure. Connected agents ask it structural questions instead of grepping, and every query lights up on the map as it happens. Source: https://docs.neurosquad.ai/en/plugins/graphify Questions like "how does a request reach the database?" or "what breaks if I change `parseConfig`?" usually cost an agent a long chain of greps and file reads. The **Graphify** plugin maps your workspace into a knowledge graph with [graphify](https://github.com/Graphify-Labs/graphify), an open-source tool by Graphify-Labs: files, functions, classes, calls, imports, Markdown sections and `NOTE:` / `WHY:` comments, grouped into subsystems. A connected agent asks the graph in plain words or by symbol name and gets the relevant part of it in one call, with file and line for every hit. The card draws the graph as a map, and every query an agent makes plays on it live: you see what the agent asked, which nodes it started from, how the search spread and what it found. ### How to use it 1. In the add-card menu choose **Plugin…**, open **Graphify** in the **Plugins** tab and press **Add to canvas**. 2. Press **Install** on the card (once per computer). NeuroSquad downloads [uv](https://github.com/astral-sh/uv) 0.12.22 from GitHub and checks it against the checksum pinned in the app, uv sets up a private Python 3.12, and then installs graphify 0.9.74 from PyPI with every package pinned by hash (`--require-hashes`, binary wheels only). About 250 MB, all in the app's data folder. Your own Python, uv or pip settings are not used and not changed. 3. The card then builds the graph of the **whole workspace** by itself. It shows the files read so far, the total and an estimate of the time left. 4. Draw an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) from an agent to the card. The agent now has the graph tools. Most CLIs pick them up without a restart; remove the arrow and they are gone. ### What the agent can do | Tool | What it answers | | --- | --- | | `graphify_query` | A question in words or symbol names → the relevant subgraph (symbols, files with lines, calls/imports edges) | | `graphify_neighbors` | Everything one symbol calls, is called by, imports or is imported by, with the file:line of each use | | `graphify_path` | The shortest chain of calls/imports between two things | | `graphify_affected` | The blast radius of a change: everything that depends on a symbol or file, transitively | | `graphify_node` | Where one symbol is, its type and its subsystem | | `graphify_community` | Every member of one subsystem | | `graphify_god_nodes` | The most connected symbols: the core of the codebase | | `graphify_stats` | Size of the graph and how many links were read directly from the code | | `graphify_reindex` | Update the graph now, after edits made a moment ago | While the first build is still running, the tools answer with how far it is ("still building: 37%, 170 of 461 files…"), so the agent can carry on with its usual search and ask again later. ### How agents are guided to the graph An agent that has a graph tool does not always use it: models are used to grep. Graphify adds three light layers, none of which blocks anything: - **Tool descriptions** say when the graph is the better choice ("use this before grep when the question is about structure") and when text search is still right (string literals, log messages, config values). In Claude Code, `graphify_query`, `graphify_neighbors` and `graphify_affected` are always loaded instead of waiting behind a tool search. - **A note on the first turn.** The first turn of a session that has the arrow carries one short, factual note: what the graph is, which tool answers which question, and when grep is still the right tool. Later turns carry a one-line reminder when the prompt is about code structure (and every fifth turn regardless). When you remove the arrow, the next turn gets one note that the tools are gone. Claude Code, Codex and Qwen Code receive it through their prompt hook; OpenCode, Kilo Code, pi, omp and Gemini CLI through NeuroSquad's plugin, extension or hook bridge. Other CLIs get the tools only. - **A hint before a text search (Claude Code).** When the agent is about to run `Grep`, `Glob`, or a `grep` / `rg` / `find` command for something that looks like a symbol name, it gets one line of context pointing at `graphify_neighbors` and `graphify_query`. The search still runs exactly as requested: no permission decision is made, your allow and deny rules and prompts work as before. The hint stays quiet for two minutes after the agent used the graph, and comes at most every 45 seconds and every fourth search. Turn **Guide agents to the graph** off in the card's settings to keep only the tools. ### The map - **Files** are drawn as dots sized by how much they contain and coloured by subsystem. Zoom in (or press **Show symbols**) to see the functions and classes around each file. - **Live queries.** When an agent asks the graph, its starting nodes ripple, the search spreads hop by hop along the links it followed, and the results panel lists what was found with file and line. Press a result to centre the map on it, or open the file in your editor. - **Timeline** at the bottom: recent queries with who asked them. Press one to replay it. - **Search** the graph yourself from the box in the corner; the matches light up the same way. - **Click a node** for its details and links; **Fit the map** brings everything back into view. - **Expand** the card for a large view of the map. Pan with the mouse, zoom with the wheel; the map pauses its animations while you zoom the canvas or when the card is off screen. ### Always up to date With **Auto-update** on (the default), the card notices changed files and updates the graph about 4 seconds after the last change. It also updates after a connected agent finishes a turn, and once when you open the app. graphify keeps a cache of every file it has read, so an update re-reads only what changed. Turn it off to update by hand with **Update now**. ### Settings The settings button on the card's header: - **Auto-update** and **Guide agents to the graph** (see above). - **Languages**: leave whole languages out of the graph. - **Also ignore**: extra patterns, one per line, in `.gitignore` syntax. `.gitignore` and `.graphifyignore` in the project are always respected. - **Include git-ignored files**: for generated code that belongs in the graph. Changing what is indexed rebuilds the graph. ### WSL and SSH workspaces - **WSL**: graphify runs on Windows and reads the distro's files through their Windows path. For a project on a Windows drive (`/mnt/c/…`) the card watches the files as usual; for one on the distro's own disk it updates after a connected agent's turn and on **Update now**. - **SSH**: not supported; the card says so. Use the [Code Graph](https://docs.neurosquad.ai/en/plugins/code-graph) plugin, which runs its engine on the SSH host. ### Graphify or Code Graph? Both index your code; they answer different questions well, and you can use both at once. | | Code Graph | Graphify | | --- | --- | --- | | Best at | Exact navigation: callers and callees, code snippets, read-only Cypher, semantic search | Questions in words → the relevant subgraph, how things connect, what a change affects | | Also maps | Routes, packages | Subsystems, Markdown sections, `NOTE:` / `WHY:` comments | | On the card | Index stats and a search box | The live map with every query animated | | WSL / SSH | Runs inside WSL and on SSH hosts | WSL through Windows paths; no SSH | > The graph is built from the workspace's folder. An agent working in an isolated worktree still > queries the graph of the main folder. ### Privacy and storage Everything runs on your computer. Graphify reads code only (no documents, images or other content that would need a language model), no language model backend is ever used and no API key reaches it. graphify has no telemetry, and its optional query log is switched off. The engine lives in the app's data folder, and each graph in `graphify/projects/-/` there. Nothing is written into your project or your home folder. Deleting the last card of a folder deletes its graph. graphify is made by Graphify-Labs and published under the Apache License 2.0. ### Troubleshooting - **Install fails behind a proxy.** uv uses `HTTPS_PROXY` / `HTTP_PROXY` from the app's environment; set it before starting NeuroSquad and press **Install** again. - **Install fails with "no matching distribution".** One of the packages has no binary wheel for your system; graphify is not built from source. The card shows uv's message. - **"Still building".** The first build of a very large workspace takes a while; the card shows the progress. Agents get the same progress when they ask. - **The agent keeps grepping.** Check that the arrow is there, that **Guide agents to the graph** is on, and that the agent's CLI is one of those that get the guidance (the card marks the others as tools only). Asking it once ("use graphify to find…") also works. - **The map is empty or misses files.** Check **Languages** and **Also ignore** in the settings, and the project's `.gitignore`. - **The card says SSH is not supported.** Use the Code Graph plugin for SSH workspaces. --- ## Settings > What you can change in NeuroSquad's settings, section by section. Source: https://docs.neurosquad.ai/en/settings Open **Settings** at the bottom of the sidebar. Changes apply immediately. - **Language**: English, Русский or 中文 — the language of the whole app. It switches instantly; until you pick one, NeuroSquad follows your system's language. - **General**: **Auto-reconnect** — restart an agent automatically if it exits unexpectedly. On by default. - **System**: **Keep agents running when the window is closed** — closing the window hides NeuroSquad in the system tray instead of quitting, so agents keep working and still notify you. Off by default. - **Notifications**: **Sound** (Chime, Ping or Marimba), **Highlight** (and its colour), **System notifications**, and an optional **Webhook** for Slack or Discord. See [Finished / needs your input](https://docs.neurosquad.ai/en/agents/notifications). - **Dictation**: Speech-to-text model, CPU or GPU, the **Dictation shortcut**, and the **Overlay position** of the recording capsule. See [Dictation](https://docs.neurosquad.ai/en/dictation). - **Canvas**: **Card overview when zoomed out** and the zoom it switches at, **Alignment guides**, **Snap to grid**, **Minimap** and **Agent mascots**. See [Canvas tools](https://docs.neurosquad.ai/en/canvas/tools). - **Browser**: Which browser browser cards use — Chrome (default) or Firefox — and download or remove it. - **Harnesses**: Which AI agents NeuroSquad found on your computer. Installed a new one? Press **Check again**. - **Setup**: The same steps as the first-launch wizard: install an agent, Git, or a speech model. - **Providers**: Your OpenRouter key, what you've spent, and the model catalogue. See [Model providers](https://docs.neurosquad.ai/en/providers). - **Remote access**: Remote access from your phone — pairing link, port, network address, internet tunnel. See [Remote access](https://docs.neurosquad.ai/en/remote). - **Shortcuts**: The list of keyboard shortcuts (`Ctrl Shift /`). See [Keyboard shortcuts](https://docs.neurosquad.ai/en/help/shortcuts). ### Set elsewhere - **Dangerous mode** and **canvas mode** — per agent, in the agent card's ⋯ menu. - **Terminal text size** — `Ctrl` + scroll over any terminal. - **Setup command, files to copy, run command, instructions file** — in each workspace's edit dialog. --- ## Card SDK > Build your own cards for the NeuroSquad canvas — small web apps that watch and prompt agents, exchange data over arrows and give agents new tools — and share them on GitHub. Source: https://docs.neurosquad.ai/en/card-sdk A **custom card** is a small web app that lives on the canvas next to your agents, terminals and notes. Anyone can build one with the Card SDK (`@neurosquad/card-sdk`), push it to GitHub, and anyone else can install it by pasting `owner/repo` into NeuroSquad. This section is for two readers: - **Everyone** who wants to use a card someone else made — start with [Installing community cards](https://docs.neurosquad.ai/en/card-sdk/community-cards). It explains what a card can and cannot do, what the install dialog tells you, and how to take access back. - **Developers** who want to build one — start with the [Quick start](https://docs.neurosquad.ai/en/card-sdk/quick-start): a working card on your canvas in a few minutes. ### What a card can do A custom card is a first-class citizen of the canvas: it has the same header, resizes, joins [groups](https://docs.neurosquad.ai/en/canvas/groups), takes [arrows](https://docs.neurosquad.ai/en/canvas/arrows), shows a tile when you zoom out and sits in the sidebar like every other card. Inside its box it draws whatever it wants. Through the SDK it can: - **Watch your agents**: Who is working, who waits for you, when a turn starts and ends — and, when you connect it, what an agent prints. - **Prompt agents**: Send an instruction to an agent you connected it to. Prompts queue while the agent works and respect the workspace budget. - **Talk to other cards**: Typed ports over arrows: a card can append to a note, add tasks to a checklist, or feed another custom card. - **Give agents tools**: Declare a tool, implement it in the card; connected agents call it over the app's MCP server. - **Reach the web**: Fetch from the hosts it declared — through the app's proxy, with secrets the card never sees. - **Work with project files**: Read and write files in the workspace folder, when you allow it. - **Run commands**: Run a command in a terminal card you connected it to, and get the exit code and output. - **Settings and storage**: A settings form drawn by the app, per-card storage that survives restarts, the app's theme and language. ### Cards never leave the canvas Community code is not trusted, so a card runs **sealed inside its own box**: - It runs in a separate, sandboxed process. A card that hangs or crashes cannot freeze the canvas or take anything else with it. - It cannot reach the app itself, your other cards, Node.js, your files, cookies or the internet on its own. Everything goes through the SDK, and the app checks every single request against what you allowed. - It cannot open windows or pop-ups, go fullscreen, show system dialogs, send OS notifications, download files or navigate the app away. It draws only inside its card. - When a card needs your decision — a confirmation, a link to open, a permission, a prompt to an agent in dangerous mode, a secret such as an API key — the **app** asks you in its own dialog, which **dims the whole window**, sidebar and title bar included. A card cannot paint outside its box, so it can never fake that. Anything inside the card body is the card's own: NeuroSquad never asks for a key there. ### The security model in plain words - **You decide what it may do**: A card lists the [permissions](https://docs.neurosquad.ai/en/card-sdk/permissions) it needs. You see them, high-risk first, before anything is installed. A card without permissions can only draw inside its box. - **Arrows are consent**: Anything that reaches another card or an agent — data over a port, a prompt, a command, reading a screen — needs an arrow between the two cards **and** the matching permission. No arrow, no data. - **Pinned to a commit**: An install is this repository at this exact commit — a commit of the repository itself, not of a fork. Nothing changes behind your back: updates are never automatic, and one that asks for more access, or changes what the card offers to agents, asks you again. - **Secrets stay in the app**: API keys are typed only into the app's own dialog, stored encrypted, and added by the app to requests to the internet hosts you granted. The card itself never sees them. - **Some files are off limits**: Even with file access, a card can never change `.git`, your agents' settings and instructions (`.claude/`, `.mcp.json`, `CLAUDE.md`, `AGENTS.md`…) or CI workflows — and it gets no file access at all if the workspace is your home folder or a whole drive. - **Everything shows**: A prompt or a tool call made through a card lights up the arrow it went over and lands in the [arrow log](https://docs.neurosquad.ai/en/canvas/arrows#arrow-log) with the card's name. > Community cards are not made or checked by the NeuroSquad team. Install cards from people you > trust, and read the permission list — a card that may prompt agents or run commands can do > anything those agents and terminals can. ### In this section - **[Installing community cards](https://docs.neurosquad.ai/en/card-sdk/community-cards)**: For users: install, review, revoke, update and remove. - **[Quick start](https://docs.neurosquad.ai/en/card-sdk/quick-start)**: From an empty folder to a card on your canvas, and on GitHub. - **[Manifest reference](https://docs.neurosquad.ai/en/card-sdk/manifest)**: Every field of `neurosquad-card.json`. - **[Permissions](https://docs.neurosquad.ai/en/card-sdk/permissions)**: Each one: what the user sees, what it unlocks. - **[API reference](https://docs.neurosquad.ai/en/card-sdk/api)**: Every method and event, with types and examples. - **[React bindings](https://docs.neurosquad.ai/en/card-sdk/react)**: `CardProvider` and hooks. - **[UI kit & styling](https://docs.neurosquad.ai/en/card-sdk/styling)**: Look native, or style it your way. - **[Testing](https://docs.neurosquad.ai/en/card-sdk/testing)**: An in-memory host for tests and browser previews. - **[CLI reference](https://docs.neurosquad.ai/en/card-sdk/cli)**: `create`, `dev`, `validate`, `pack`. - **[Publishing & updates](https://docs.neurosquad.ai/en/card-sdk/publishing)**: GitHub, versions, what users see on update. - **[Security checklist](https://docs.neurosquad.ai/en/card-sdk/security)**: What to check before you share a card. - **[FAQ & troubleshooting](https://docs.neurosquad.ai/en/card-sdk/faq)**: Common errors and how to fix them. > The Card SDK is new. Everything here describes version 1 of the card protocol; a few things are > deliberately left for later — a card gallery, automatic updates, cards that run with no frame at > all, a file picker, and running card code on the phone. Each is called out where it matters. --- ## Installing community cards > What a community card is, how to install one from GitHub, how to read the permission dialog, and how to update, turn off, revoke or remove it. Source: https://docs.neurosquad.ai/en/card-sdk/community-cards Community cards are cards other people built with the [Card SDK](https://docs.neurosquad.ai/en/card-sdk) and shared on GitHub. They live in **Settings → Custom cards**, and once installed you add them from the canvas like any other card. ### Install a card **1. Open Settings → Custom cards** Under **Install a card**, paste the GitHub address you were given. Any of these work: `owner/repo`, `owner/repo@v1.2.0` (a tag, branch or commit), `owner/repo/cards/pomodoro` (a card in a subfolder), or a full `https://github.com/…` link — including a `/tree//` or `/releases/tag/` link. **2. Press Install and read the dialog** NeuroSquad downloads that exact commit, checks it, and shows you what the card is and what it asks to do. Nothing is installed yet. **3. Press Install in the dialog** Or **Cancel** — the download is thrown away. **4. Add it to a canvas** In the add menu (the **+** on the canvas or in the sidebar) choose **Custom card…** and pick it. You can add as many copies as you like; each has its own settings and data. > Looking for cards someone has already checked? The [verified cards](https://docs.neurosquad.ai/en/card-sdk/verified-cards) list > has community cards the NeuroSquad team reviewed, installable from the **Verified** tab of the > **Custom card…** picker. ### Reading the install dialog - **Name, author, version**: The author is **self-declared** — the card says who made it, nobody checked. Trust the repository address, not the name. Only official cards may call themselves "NeuroSquad", "official" or "verified"; the app refuses any other card that tries. - **Source and commit**: The GitHub repository and the exact commit that will be installed, with **View source** to read that code. The install is pinned to that commit, and the commit must belong to the repository itself (be on its default branch): a commit that exists only in a fork is refused. A repository that was renamed or moved must be installed under its new name. - **Community or Official**: Every card is marked **Community code, not made or checked by NeuroSquad** — except cards published by the NeuroSquad team from the `glmn-ai` organization on GitHub (checked against GitHub's own account id, not just the name), which carry an **Official** badge. - **This card will be able to**: The [permissions](https://docs.neurosquad.ai/en/card-sdk/permissions) it needs, **high risk first** and shown before the card's own description, each with a plain explanation and, often, the author's reason. They are all-or-nothing: to install the card you grant all of them. - **It may ask later for**: Optional permissions. They are **not** granted at install; the card asks on screen when it needs one, and you can say no. - **Tools and ports**: The tools it offers to agents you connect it to, and how many data ports it has for arrows. > Pay most attention to the **High risk** lines. A card that may **give instructions to agents** or > **run commands in terminals** can do anything those agents and terminals can — edit your code, > delete files, push to git. A card with **read files** plus **any network address** could send your > project files there. ### What a card can never do Whatever it asks for, a card runs sealed inside its box. It cannot open windows, reach the app or other cards directly, read your files or go online outside what you granted, show system notifications, or draw outside its card. The app checks every request a card makes, on every call. See [Cards never leave the canvas](https://docs.neurosquad.ai/en/card-sdk#cards-never-leave-the-canvas). **A real NeuroSquad prompt dims the whole window.** Whenever a card needs your decision — a confirmation, a link, a permission, a prompt to an agent in dangerous mode, a secret key — the app asks in its own dialog headed **NeuroSquad is asking**, over a backdrop that darkens the sidebar and the title bar too. A card can only draw inside its own box, so it cannot imitate that. The card's own words appear in such a dialog only as a quote, and **Cancel** is always the app's. **Anything inside the card body belongs to the card.** NeuroSquad never asks for passwords or API keys inside a card. When a card needs a key, you enter it through the card's **Settings…** (the secret field opens the app's dialog) — the key is stored encrypted, sent only to the internet addresses you granted, and the card never sees it. **Your agents' settings and the repository are protected.** Even a card allowed to change files cannot touch `.git`, agent settings and instructions (`.claude/`, `.codex/`, `.cursor/`, `.mcp.json`, `CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, `QWEN.md`…), editor and CI configuration (`.vscode/`, `.idea/`, `.github/workflows/`, `.husky/`…) or package-manager settings (`.npmrc`, `.yarnrc`…). And no card gets any file access when the workspace folder is your home folder, the root of a drive, or contains NeuroSquad's own data. ### Using a card - **Arrows.** Most cards do more when you connect them. An arrow between a card and an agent lets it watch that agent's screen or send it prompts (if it has those permissions) and lets the agent call the card's tools. An arrow between two cards lets data flow over their ports, from the arrow's tail to its head. - **Settings…** in the card's **⋯** menu opens the card's settings, if it has any. Some are shared by every copy of that card (marked so in the form). - **Prompts to an agent in dangerous mode** always need your OK: the app shows what the card wants to send, and you press **Send prompt** or **Cancel**. Prompts a card queued for an agent are dropped if you remove the arrow, revoke the permission or switch the agent to dangerous mode; the queue shows which card each one came from. - **Links** a card wants to open are shown in full first; only `https://` links, and only after you press **Open link**. - **Limits.** A card can send at most 6 prompts and 30 terminal commands a minute, however it sends them. - **Attention.** A card can pulse and appear in the Inbox when it needs you — like an agent that is waiting. It cannot make sounds or OS notifications. - **Paused cards.** A card you have not looked at for a while (its workspace hidden for a minute, or too many cards open) is paused to save memory and resumes where it left off. Cards with the **Keep running when you are not looking** permission are not paused. ### Updates NeuroSquad checks for new versions a minute after it starts and then once a day (or when you press **Check for updates**). A card that follows a branch updates to its newest commit; one installed from a release follows the latest release; one pinned to a tag or a commit never updates. **Nothing updates on its own.** An available update shows as **Update** in **Settings → Custom cards** and as a dot on the card. Pressing it shows what changes — **new permissions**, **new addresses it will connect to**, permissions it **no longer needs**, and changes to what it offers: new or reworded **tools** for agents, new or retyped **ports**, new **secret settings**, a changed **name, author or homepage** — with a link to see the code changes on GitHub. If the update asks for anything of that kind, it waits for your OK; until then the old version keeps running. ### Turning off, revoking, removing In **Settings → Custom cards**, each installed card has: - **Turned on** switch — off stops every copy of it (its cards show "This card is turned off"), its tools disappear from agents, and nothing is deleted. - **Permissions** — press **Revoke** next to any permission to take it back. Cards of that package reload without it. - **Uninstall** — removes the package. You choose whether to **also delete its cards from every canvas** (on by default; otherwise they stay as "package missing" placeholders) and whether to **also delete its saved data and secrets** (off by default). ### Private repositories and GitHub limits GitHub limits how often anyone can download without an account. If installing or checking for updates says GitHub is limiting requests — or you want to install from a private repository — add a **GitHub token** in **Settings → Custom cards**. It is stored encrypted and never shown to cards. ### Custom cards on your phone With [remote access](https://docs.neurosquad.ai/en/remote), a custom card shows on your phone as its header and its summary tile, with "Open on the computer to use this card". Its code runs only on the computer — its tools, ports and prompts keep working there while you watch from the phone. --- ## Verified cards > The list of community cards the NeuroSquad team has reviewed — where to find it, what the Verified badge means and doesn't, how verified updates work, and how authors submit a card for review. Source: https://docs.neurosquad.ai/en/card-sdk/verified-cards Anyone can publish a [community card](https://docs.neurosquad.ai/en/card-sdk/community-cards) on GitHub, and nobody checks it before you install it. **Verified cards** are the exception: community cards the NeuroSquad team has read and tested, one exact version at a time. They are listed in a public catalog, and the app can install them straight from it. The catalog is the file `verified.json` in the public repository [glmn-ai/neurosquad-cards](https://github.com/glmn-ai/neurosquad-cards). Each entry records what was reviewed: - the card's name and description (in English, Russian and Chinese), its author and licence; - where it lives — the GitHub repository `owner/repo` and, optionally, a folder inside it; - the reviewed **version**, the exact reviewed **commit**, and the **tree hash** of the card's folder at that commit; - the permissions and network addresses the card uses; - tags and a category — agents, productivity, dev tools, data, integrations, fun or other; - who reviewed it, when, and any notes from the review. The app downloads the list when it starts, every 6 hours, and when you press **Refresh**. Offline, it shows the last copy it downloaded — or, on a fresh install, the copy that ships with the app. ### Find and install a verified card The list is in two places: the **Verified** tab of the **Custom card…** picker in the add menu (the **+** on the canvas or in the sidebar), and the **Verified cards** section of **Settings → Custom cards**. Search looks at names in all three languages, descriptions and tags, right on your computer. You can also filter by category. Each row shows the card's icon, name, description, author, category and a summary of its permissions, with a button: **Install**, **Installed**, or **Verified update**. **1. Find the card** Open the **Verified** tab or the **Verified cards** section, search or pick a category. **2. Press Install** NeuroSquad downloads **exactly the reviewed commit** — not the newest code in the repository — and compares the files' tree hash with the reviewed one. If they differ, the install is refused: "the files differ from what was reviewed". **3. Read the permission dialog and confirm** You see the same [install dialog](https://docs.neurosquad.ai/en/card-sdk/community-cards#reading-the-install-dialog) as for any other card. Verified does not skip your consent: you still decide whether the card gets what it asks for. You can still install any card by its GitHub address, as before. The catalog only adds a list of cards somebody has looked at. ### The Verified badge A verified card carries a **Verified** badge — a shield with a check mark — on its catalog row, in the install dialog, on the installed card in **Settings → Custom cards**, and in the card's **About** panel. It is a different badge from **Official**. Official means the card is published by the NeuroSquad team from its `glmn-ai` organization on GitHub; Verified means the team reviewed this version. A card can carry both. The badge is shown only when all three match a current entry of the list: - the card's source — the same repository and folder; - the commit it was installed from; - the tree hash of its files, equal to the reviewed one. So a card linked from a local folder, installed from another commit (for example, the newest commit of a branch), or whose files differ carries no badge — even if another version of it is verified. > **Verified** means: reviewed by the NeuroSquad team at version X on date Y. It is not a guarantee > that the card has no bugs or will stay safe forever, and it says nothing about any other version. > Read the permission dialog as carefully as for any other card. ### Verified updates When the list points a card at a newer reviewed version, **Settings → Custom cards** shows **Verified update available** for it. Pressing it installs exactly that reviewed commit through the usual [update dialog](https://docs.neurosquad.ai/en/card-sdk/community-cards#updates), which shows what changes in the card's permissions. Nothing is updated automatically. If a card is removed from the list, its badge disappears and a neutral note says it is no longer in the verified list. The card stays installed and keeps working; whether to keep it is your call. ### On the phone With [remote access](https://docs.neurosquad.ai/en/remote), you can browse the verified list on your phone, but not install from it: installing is only possible on the computer. ### For card authors: get your card verified Verification is a pull request to [glmn-ai/neurosquad-cards](https://github.com/glmn-ai/neurosquad-cards) that adds your card's entry to `verified.json`. The exact rules and the entry format are in its [CONTRIBUTING.md](https://github.com/glmn-ai/neurosquad-cards/blob/HEAD/CONTRIBUTING.md) — read it before you open the pull request. **4. Publish the card** It must be in a **public** GitHub repository, on the **default branch**. See [Publishing & updates](https://docs.neurosquad.ai/en/card-sdk/publishing). **5. Get the commit and the tree hash** Take the exact commit you want reviewed. For the tree hash, run [`neurosquad-card pack`](https://docs.neurosquad.ai/en/card-sdk/cli#pack) on the card's folder at that commit — it prints the tree hash the app records at install. **6. Open a pull request** Add your entry to `verified.json` — names and descriptions, repository and folder, version, commit, tree hash, permissions, network addresses, tags, category, licence — as CONTRIBUTING.md describes. **Updating a verified card** is another pull request that bumps the version, commit and tree hash. Each version is reviewed again; until the new one is accepted, users keep the badge on the version that was reviewed, and code you push in the meantime is not offered as a verified update. #### What reviewers check - The full source at that commit. No obfuscated code, and no minified-only code without its source. - Permissions and network addresses are the minimum the card needs, and match the entry. - The descriptions of its tools and ports are honest. - The manifest matches the entry — name and version. - The tree hash reproduces. - The card has a licence. - It installs and works on the current version of the app. - It does not impersonate NeuroSquad or any other brand. - It does no tracking beyond what it declares. The [security checklist](https://docs.neurosquad.ai/en/card-sdk/security) covers most of this — go through it before you submit. --- ## Quick start > Create a card from a template, run it live in NeuroSquad with hot reload, publish it on GitHub and install it from there. Source: https://docs.neurosquad.ai/en/card-sdk/quick-start You need NeuroSquad and Node.js 18.17 or newer. No developer account, and no build tools for the plain template. ### 1. Create a card ```bash npx @neurosquad/card-sdk create my-card # plain HTML + JS, no build step npx @neurosquad/card-sdk create my-card --template react # React + Vite + TypeScript ``` Both templates give you the same working card: the agents on the canvas with live statuses, a scratchpad saved in the card's storage, an input and an output [port](https://docs.neurosquad.ai/en/card-sdk/api/ports), and a [tool](https://docs.neurosquad.ai/en/card-sdk/api/tools) connected agents can call. Read it, then change it. **Plain template** (`vanilla`): ```text my-card/ neurosquad-card.json the manifest: name, size, permissions, settings, ports, tools index.html the page loaded into the card main.js the card's code style.css icon.png square PNG or WebP, 128 KB at most vendor/ the SDK (card-sdk.js), the UI kit (ui.css), the mock host, the manifest schema ``` **React template**: the same manifest and icon, `src/` with `main.tsx`, `App.tsx` and `i18n.ts`, and a Vite config already set up for cards (relative URLs, no inline scripts). Run `npm install` first; `npm run build` writes `dist/`, which is what the app loads. ### 2. See it without the app Open the page on its own and it runs against a **mock host** with sample agents and a connected note, so you can work on the look in any browser: ```bash npx serve . # plain template, then open http://localhost:3000 npm run dev # React template ``` In the browser console, `mockHost` drives it: `mockHost.setAgentStatus('a2', 'working')`, `mockHost.setLanguage('ru')`, `mockHost.sendPortMessage('text', 'hello')`. See [Testing with the mock host](https://docs.neurosquad.ai/en/card-sdk/testing). ### 3. Run it live in NeuroSquad **1. Turn on developer mode** In NeuroSquad: **Settings → Custom cards → Developer mode**. It lets the CLI on this computer ask to link a folder; it listens only on `127.0.0.1`. **2. Link the folder** In your card folder run `npx @neurosquad/card-sdk dev`. The app asks you to confirm the link, then shows the same permission dialog a user would see. Accept it. **3. Add the card** On the canvas: **+ → Custom card…** and pick your card (it has a **Dev** badge). **4. Edit and save** Every save reloads the card. The terminal running `dev` prints the card's log — `card.log.*`, uncaught errors and rejected promises. Press **r** to reload by hand, **q** to quit. With the React template, `dev` also runs `npm run watch` for you, so `dist/` is rebuilt on every save. Pass `--no-build` to run your own watcher. > Developer mode is not a way around consent: a linked folder gets exactly the permissions its > manifest declares, after the same dialog. Change the permissions in the manifest and the card > asks again. **Without the CLI.** **Settings → Custom cards → Link a folder…** links a folder too — handy if you only want to try a card someone sent you as a folder. ### 4. Check it like the installer will ```bash npx @neurosquad/card-sdk validate ``` `validate` runs the app's own manifest checks and the installer's file rules, warns about things the sandbox will block (inline scripts, external files), and prints the install dialog your users will see. `pack` goes one step further and lists exactly which files would be installed, with the **tree hash** the app records. See the [CLI reference](https://docs.neurosquad.ai/en/card-sdk/cli). ### 5. Publish it on GitHub Push the card folder to a GitHub repository — its own repository, or a folder inside a bigger one. That's all publishing is. A few things to get right: - `neurosquad-card.json` must be at the root of the card folder. - **Commit your build output.** The app installs straight from the repository and never runs a build. The React template's `.gitignore` deliberately does not ignore `dist/`. - Tag releases (`v1.0.0`) and people can install a fixed version, or follow your latest release. More in [Publishing & updates](https://docs.neurosquad.ai/en/card-sdk/publishing). ### 6. Install it from GitHub In **Settings → Custom cards → Install a card**, paste `your-name/my-card` (or `your-name/my-cards/pomodoro` for a card in the `pomodoro` folder of a repository, `your-name/my-card@v1.0.0` for a tag) and press **Install**. That's what your users do; see [Installing community cards](https://docs.neurosquad.ai/en/card-sdk/community-cards). ### The smallest possible card No template needed. Three files: ```json filename="neurosquad-card.json" { "manifestVersion": 1, "name": "hello-card", "displayName": "Hello", "version": "0.1.0", "protocol": 1 } ``` ```html filename="index.html"

…

``` ```js filename="main.js" // card-sdk.js is dist/card-sdk.js from the @neurosquad/card-sdk package, copied next to this file. import { connect } from './card-sdk.js' const card = await connect() document.getElementById('title').textContent = `Hello from ${card.workspace.name}` card.setStatus('Ready', { tone: 'success' }) ``` It asks for no permissions, so it can only draw in its box, keep storage and settings, and set its header — which is already a useful card. ### Next - **[Manifest reference](https://docs.neurosquad.ai/en/card-sdk/manifest)**: Size, permissions, settings, ports, tools. - **[API reference](https://docs.neurosquad.ai/en/card-sdk/api)**: What `card.*` can do. - **[Security checklist](https://docs.neurosquad.ai/en/card-sdk/security)**: Before you share it. --- ## Manifest reference > Every field of neurosquad-card.json — identity, size, permissions, the settings form, ports and tools — with the rules the app checks. Source: https://docs.neurosquad.ai/en/card-sdk/manifest Every card has a `neurosquad-card.json` at the root of its folder. The app reads it at install and refuses a card whose manifest does not pass; `npx @neurosquad/card-sdk validate` runs the very same checks on your machine. For editor completion, point `$schema` at the schema that ships with the SDK: `./node_modules/@neurosquad/card-sdk/schema/neurosquad-card.v1.json` (React template) or `./vendor/neurosquad-card.schema.json` (plain template). It is also exported as `@neurosquad/card-sdk/schema.json`. ### A complete example ```json { "$schema": "./node_modules/@neurosquad/card-sdk/schema/neurosquad-card.v1.json", "manifestVersion": 1, "name": "test-radar", "displayName": { "en": "Test radar", "ru": "Радар тестов", "zh": "测试雷达" }, "version": "1.0.0", "protocol": 1, "description": "Runs the test suite in a connected terminal and shows what broke.", "author": { "name": "Acme", "url": "https://acme.dev" }, "license": "MIT", "homepage": "https://acme.dev/test-radar", "keywords": ["tests", "ci"], "icon": "icon.png", "minAppVersion": "0.1.100", "entry": "dist/index.html", "card": { "defaultSize": { "w": 460, "h": 340 }, "minSize": { "w": 320, "h": 220 } }, "permissions": [ "agents.read", "terminals.write", { "id": "fs.read", "reason": "Reads the JUnit report" }, { "id": "network", "hosts": ["api.github.com"], "reason": "Links failures to GitHub issues" }, { "id": "clipboard.write", "optional": true } ], "settings": [ { "key": "command", "type": "string", "label": "Test command", "default": "npm test" }, { "key": "githubToken", "type": "secret", "label": "GitHub token", "scope": "package" } ], "ports": { "inputs": [{ "id": "run", "label": "Run", "type": "ns:trigger", "default": true }], "outputs": [ { "id": "failures", "label": "Failures", "type": "ns:tasks", "retain": true }, { "id": "summary", "label": "Summary", "type": "ns:markdown" } ] }, "tools": [ { "name": "run_tests", "title": "Run the tests", "description": "Runs the project's tests and returns failing test names with messages.", "inputSchema": { "type": "object", "properties": { "filter": { "type": "string", "maxLength": 200 } } }, "timeoutMs": 120000 } ] } ``` ### Identity | Field | Required | Rule | Meaning | | --- | --- | --- | --- | | `$schema` | | string | For your editor. Ignored by the app. | | `manifestVersion` | yes | `1` | The manifest format. | | `name` | yes | `a-z`, digits and `-`, starts with a letter, 2–48 chars | The package slug. It prefixes the card's [tool names](https://docs.neurosquad.ai/en/card-sdk/api/tools) and namespaces its custom port types. Reserved (built-in cards and tool families): `neurosquad`, `neurosquad-card`, `custom`, `canvas`, `browser`, `terminal`, `agent`, `note`, `todo`, `kanban`, `host`, `system`, `telegram`, `image`, `reference`, `ports`, `web-watch`, `watch`, `timer`, `sticky`, `standup`, `squad`, `mcp`, `skill`, `official`. | | `displayName` | yes | localized text, ≤ 80 | The card's name in menus, the header and the install dialog. | | `version` | yes | SemVer (`1.2.0`, `1.2.0-beta.1`) | Informational — installs are pinned to a commit, not a version. Bump it anyway: users see it on update. | | `protocol` | yes | integer | The card protocol you built against — `1` today. A card built for a newer protocol than the app speaks is refused with "needs a newer NeuroSquad". | | `description` | | localized text, ≤ 300 | Shown in the install dialog and the card picker. | | `author` | | `{ "name", "url"? }` | `url` must be `https://`. Shown as **self-declared**. | | `license` | | string ≤ 100 | An SPDX id such as `MIT`. | | `homepage` | | `https://` URL | | | `keywords` | | ≤ 20 unique strings, ≤ 40 chars each | | | `icon` | | path to a `.png` or `.webp` in the package | Square, ≤ 128 KB (128×128 or larger looks sharp). Checked by its bytes at install. Without one the card shows a puzzle piece. | | `minAppVersion` | | SemVer | The lowest NeuroSquad version that can run the card. | | `entry` | | path to an `.html` file, default `index.html` | The page loaded into the card. | **Localized text** is either a plain string or an object with English required: `{ "en": "Test radar", "ru": "Радар тестов", "zh": "测试雷达" }`. The app shows the user's language and falls back to English. **Text rules.** Names, descriptions, labels, reasons and tool descriptions may not contain control characters (tab and newline are allowed in descriptions), bidi overrides or isolates, line separators, zero-width or other invisible characters. Only official cards (published from the `glmn-ai` organization) may call themselves "NeuroSquad", "official" or "verified" in `displayName` or `author` — `validate` warns, the app refuses. **Paths** (`entry`, `icon`) are relative to the manifest, with `/` separators — no `..`, no leading `/`, no backslashes, no Windows device names (`con`, `nul`…), nothing under `__ns/` (the app reserves it), at most 20 levels and 240 characters. ### Size — `card` ```json "card": { "defaultSize": { "w": 460, "h": 340 }, "minSize": { "w": 320, "h": 220 }, "maxSize": { "w": 1200, "h": 900 } } ``` Sizes are in canvas units (CSS pixels at 100 % zoom), whole numbers, width 200–2400 and height 120–1800, with `minSize ≤ defaultSize ≤ maxSize`. Defaults: 420×320, min 200×120, max 2400×1800. The user resizes within min/max; [`card.requestResize()`](https://docs.neurosquad.ai/en/card-sdk/api/card-ui#resize) is clamped to them too. ### Permissions — `permissions` A list (≤ 32) of permission ids, or objects that add details: ```json "permissions": [ "agents.read", { "id": "network", "hosts": ["api.github.com", "*.example.com", "status.example.org:8443"] }, { "id": "fs.read", "reason": { "en": "Reads the JUnit report", "ru": "Читает отчёт JUnit" } }, { "id": "clipboard.write", "optional": true } ] ``` | Key | Meaning | | --- | --- | | `id` | One of the ids on [Permissions](https://docs.neurosquad.ai/en/card-sdk/permissions). | | `hosts` | `network` only, and required there: ≤ 32 host patterns. | | `reason` | Localized text ≤ 300, shown under the permission in the install dialog. Say why. | | `optional` | `true` = not asked at install; the card asks at runtime with [`card.permissions.request()`](https://docs.neurosquad.ai/en/card-sdk/api/environment#permissions). | Required permissions are all-or-nothing at install. Listing the same id twice merges it (and a required entry wins over an optional one). **Host patterns** for `network`: lowercase host names only — `api.example.com`, `api.example.com:8443` (a port other than 443), or `*.example.com` (any subdomain, not `example.com` itself). No scheme, path, IP address, bare `*` or `localhost` — this computer is the separate `network.local` permission. ### Settings form — `settings` Up to 40 fields. The app draws the form (open it from the card's **⋯ → Settings…** or with [`card.settings.open()`](https://docs.neurosquad.ai/en/card-sdk/api/storage-settings#settings)); the card reads the values. ```json "settings": [ { "key": "command", "type": "string", "label": "Test command", "default": "npm test", "maxLength": 200 }, { "key": "notes", "type": "text", "label": "Notes", "placeholder": "Anything the agents should know" }, { "key": "interval", "type": "number", "label": "Check every (min)", "default": 5, "min": 1, "max": 60, "step": 1 }, { "key": "compact", "type": "boolean", "label": "Compact view", "default": false }, { "key": "branch", "type": "select", "label": "Branch", "default": "main", "options": [{ "value": "main", "label": "main" }, { "value": "dev", "label": "dev" }] }, { "key": "accent", "type": "color", "label": "Accent", "default": "#22c55e" }, { "key": "apiKey", "type": "secret", "label": "API key", "required": true, "scope": "package" } ] ``` | Key | Meaning | | --- | --- | | `key` | Starts with a letter; letters, digits, `_`, `-`; ≤ 64. Unique. | | `type` | `string` (one line), `text` (several lines), `number`, `boolean`, `select`, `color` (`#rrggbb`), `secret`. | | `label`, `description`, `placeholder` | Localized text (≤ 80, ≤ 300, ≤ 80). | | `default` | Of the field's type. Must be one of the options for `select`, `#rrggbb` for `color`, within `min`/`max` for `number`. **Not allowed for `secret`.** | | `required` | The form will not save without it. | | `scope` | `instance` (default): per card on the canvas. `package`: shared by every card of this package. | | `maxLength` | `string`, `text`, `secret`. Defaults: 2 000 for `string`, 20 000 for `text`. | | `min`, `max`, `step` | `number`. | | `options` | `select` only, 1–50 `{ "value", "label" }`. | **Secrets** are entered only in the app's form, stored encrypted, and never reach the card: the card only learns whether one is set, and uses it through a `{{secret:}}` placeholder in [network request headers](https://docs.neurosquad.ai/en/card-sdk/api/network#secrets). ### Ports — `ports` Typed data connections over arrows: up to 16 `inputs` and 16 `outputs`. Full guide: [Ports](https://docs.neurosquad.ai/en/card-sdk/api/ports). ```json "ports": { "inputs": [ { "id": "run", "label": "Run", "type": "ns:trigger", "default": true }, { "id": "lookup", "label": "Look up", "type": "ns:text", "mode": "request", "response": { "type": "ns:json" } } ], "outputs": [ { "id": "failures", "label": "Failures", "type": "ns:tasks", "retain": true }, { "id": "coverage", "label": "Coverage", "type": "test-radar/coverage", "description": "Line coverage per file, 0..1", "schema": { "type": "object", "additionalProperties": { "type": "number", "minimum": 0, "maximum": 1 } } } ] } ``` | Key | Applies to | Meaning | | --- | --- | --- | | `id` | both | `a-z`, digits, `-`, starts with a letter, ≤ 32. Unique per direction. | | `label`, `description` | both | Localized text (≤ 80, ≤ 500). Shown to users, peer cards and agents discovering the port. | | `type` | both | A well-known `ns:*` type or a custom `/`. | | `schema` | both | Extra JSON Schema the value must also match. **Required for custom types.** | | `mode` | inputs | `stream` (default): fire-and-forget messages. `request`: the sender waits for a reply. | | `response` | request inputs | `{ "type", "schema"? }` — the reply's type. Required for `mode: "request"`. | | `default` | inputs | The preferred input when a peer's output fits several. At most one. | | `retain` | outputs | The app keeps the last value: peers can read it at any time, and a newly connected peer gets it once. | A custom type from another package's namespace is allowed (with a warning) — that is how two cards agree on a shared format. ### Tools — `tools` Up to 32 tools that agents connected to the card can call. Guide: [Tools for agents](https://docs.neurosquad.ai/en/card-sdk/api/tools). | Key | Meaning | | --- | --- | | `name` | `a-z`, digits, `_`, starts with a letter, ≤ 40. The agent sees `_`, e.g. `test_radar_run_tests`. That exposed name may not equal a built-in NeuroSquad tool (`canvas_spawn_card`, `terminal_send_keys`…) and may not contain `__`. | | `title` | ≤ 80, a human title. | | `description` | ≤ 2 000, **for the model**, in English: what it does and what it returns. | | `inputSchema` | JSON Schema with `"type": "object"`. The property `card` is reserved (the app adds it). | | `readOnly` | `true` when the tool changes nothing — a hint shown to the agent. | | `timeoutMs` | 1 000–120 000, default 30 000. | ### JSON Schemas you write Port schemas, response schemas and tool `inputSchema` use a safe subset of JSON Schema 2020-12, checked at install (≤ 500 nodes, ≤ 16 levels deep): - **Supported:** `type`, `enum`, `const`, `properties`, `required`, `additionalProperties`, `minProperties`, `maxProperties`, `items`, `minItems`, `maxItems`, `uniqueItems`, `minLength`, `maxLength`, `format`, `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`, `multipleOf`, `anyOf`, `oneOf`, `$ref` (`#` or `#/$defs/`), `$defs`. - **Formats:** `uri`, `date-time`, `date`, `email`, `color`, `uuid`. - **Ignored annotations:** `$id`, `$schema`, `$comment`, `title`, `description`, `default`, `examples`, `deprecated`, `readOnly`, `writeOnly`. - **Caps:** `enum` ≤ 256 options and ≤ 16 KB in total; `const` ≤ 4 KB. - **Not allowed:** `pattern` (regular expressions from a card would run in the app — a denial of service risk), and any keyword not listed above. > The schema's `$id`, `https://neurosquad.ai/schemas/neurosquad-card.v1.json`, is an identifier, not > a download: point `$schema` at the copy in the SDK. --- ## Permissions > The thirteen card permissions — the risk of each, the exact words users see at install, what each one unlocks, and the scope rules the app enforces. Source: https://docs.neurosquad.ai/en/card-sdk/permissions A card without permissions can draw in its box, keep [storage](https://docs.neurosquad.ai/en/card-sdk/api/storage-settings), read its settings, set its header, exchange nothing with anybody. Everything else is a permission you declare in the [manifest](https://docs.neurosquad.ai/en/card-sdk/manifest#permissions) and the user grants. How grants work: - **Per package, checked on every request.** The user grants a permission to your card package (every copy of it on every canvas). The app checks the grant on every single call, in the app — not in the SDK, not in your card. - **Required ones are all-or-nothing at install.** The install dialog lists them high-risk first. Declining means not installing. - **Optional ones are asked at runtime** (`"optional": true`). Call [`card.permissions.request()`](https://docs.neurosquad.ai/en/card-sdk/api/environment#permissions) while the card is on screen; the app asks in its own window-wide dialog, and the user can say no. - **Some imply others.** `fs.write` includes `fs.read`; `agents.output`, `agents.prompt` and `terminals.write` include `agents.read`. - **Users can revoke** any permission in **Settings → Custom cards**. The card's frames reload with the smaller grant and get a `permissions.changed` event; code defensively. - **An update that adds permissions or network hosts** needs the user's consent before it applies. Permissions you drop are revoked. - **Arrows are consent for data.** Permissions that reach another card, agent or terminal work only with cards connected to yours by an [arrow](https://docs.neurosquad.ai/en/canvas/arrows) — either direction, unless said otherwise. A missing permission makes the call fail with `PERMISSION_DENIED` (`error.permission` names it). ### At a glance | Permission | Risk | Unlocks | | --- | --- | --- | | `agents.read` | Low | `agents.list/get`, status/turn/changed events, the agent `status` port | | `agents.output` | High | Reading screens and replies of **connected** agents and terminals | | `agents.prompt` | High | Sending prompts to **connected** AI agents | | `terminals.write` | High | Running commands in **connected** terminals | | `cards.connected` | Medium | Reading and changing **connected** notes, todo lists, task boards, stickies | | `network` + hosts | Medium | `net.fetch` to the listed hosts | | `network.local` | High | `net.fetch` to servers on this computer | | `fs.read` | High | Reading files in the workspace folder | | `fs.write` | High | Writing files in the workspace folder (implies `fs.read`) | | `clipboard.write` | Low | Copying text to the clipboard | | `canvas.spawn` | Low | Adding up to 4 cards next to itself | | `background` | Low | Staying alive while nobody looks | | `usage.read` | Low | Token usage and cost of the workspace | ### Each permission #### `agents.read` — low **Users see:** *See the agents on this canvas.* Their names, which tool they run, and whether they are working, waiting for you or finished. **Unlocks:** [`card.agents.list()` / `get()`](https://docs.neurosquad.ai/en/card-sdk/api/agents), the events `agents.status`, `agents.turn`, `agents.changed`, and the built-in agent `status` output port. **Scope:** AI agents and terminals of the card's own workspace. Other cards are not agents and are not listed. #### `agents.output` — high **Users see:** *Read what agents and terminals connected to it print.* Everything on the screens of agent and terminal cards you connect to it with an arrow, including anything secret shown there. **Unlocks:** `card.agents.readScreen()`, `card.agents.lastReply()`, live output with `card.agents.onOutput()`, the agent `reply` and terminal `exit` output ports. **Scope:** arrow-connected agents and terminals only. Implies `agents.read`. #### `agents.prompt` — high **Users see:** *Give instructions to agents connected to it.* Type and send prompts to AI agents you connect to it with an arrow. An agent can edit files and run commands, so this card can make it do anything the agent can do. **Unlocks:** [`card.agents.prompt()`](https://docs.neurosquad.ai/en/card-sdk/api/agents#prompting) and the agent `prompt` input port. **Scope:** arrow-connected **AI** agents (not terminals). Prompts go through the prompt queue and the workspace [budget](https://docs.neurosquad.ai/en/cards/budget), at most 6 a minute per card (counted together for the method and the agent's `prompt` port); each one shows on the arrow and in the arrow log. To an agent in [dangerous mode](https://docs.neurosquad.ai/en/agents/dangerous-mode) every prompt waits for the user's OK on the card. Implies `agents.read`. #### `terminals.write` — high **Users see:** *Run commands in terminals connected to it.* Type and run commands in terminal cards you connect to it with an arrow — anything you could run yourself. **Unlocks:** [`card.terminals.run()` and `write()`](https://docs.neurosquad.ai/en/card-sdk/api/agents#terminals), the terminal `command` input port. **Scope:** arrow-connected terminal cards (bash, PowerShell, cmd). At most 30 commands a minute per card, counted together for `run` and the terminal's `command` port; `write` at most 60 a minute. Each command shows on the arrow. Implies `agents.read`. #### `cards.connected` — medium **Users see:** *Read and change cards connected to it.* Notes, checklists, task boards and stickies you connect to it with an arrow. **Unlocks:** the [built-in card ports](https://docs.neurosquad.ai/en/card-sdk/api/ports#built-in-cards) of note, todo list, task board and sticky — append to a note, add tasks, read a checklist. **Scope:** arrow-connected cards of those four kinds. #### `network` — medium, needs `hosts` **Users see:** *Connect to `api.github.com`, `*.example.com`.* Send and receive data from these internet addresses only. Anything the card can see may be sent there. **Unlocks:** [`card.net.fetch()`](https://docs.neurosquad.ai/en/card-sdk/api/network) to those hosts over `https`. **Scope:** exactly the declared host patterns, public addresses only — a host that resolves to a private, loopback or cloud-metadata address is refused, on every redirect too. A card cannot ask for "any host" in version 1. #### `network.local` — high **Users see:** *Connect to servers on this computer.* Reach programs listening on localhost, such as dev servers and local databases. **Unlocks:** `card.net.fetch()` to `localhost`, `127.0.0.1` and `::1`, over `http` or `https`. **Scope:** any port except NeuroSquad's own servers: its MCP server, the remote access server, the developer link server, the debugging port of every browser card's Chrome, and the development server of the app itself. [Secret placeholders](https://docs.neurosquad.ai/en/card-sdk/api/network#secrets) are never filled in for requests to this computer. #### `fs.read` — high **Users see:** *Read files in the workspace folder.* Any file in this workspace's project folder, including secrets stored in files like `.env`. **Unlocks:** [`card.fs.stat/list/read*/watch()`](https://docs.neurosquad.ai/en/card-sdk/api/files) and the workspace's absolute `path` in `card.workspace`. **Scope:** the workspace folder. Paths are relative to it; `..` and absolute paths are refused, and a link that points outside the folder is refused too. If the workspace folder is the user's home folder, the root of a drive, or contains NeuroSquad's own data folder, every file call is refused. #### `fs.write` — high **Users see:** *Change files in the workspace folder.* Create, overwrite and move files to the trash in this workspace's project folder. Agents in this workspace read and run these files, so this card can make them run commands. Protected: `.git`, agent settings (`.claude`, `.mcp.json`, `CLAUDE.md`, `AGENTS.md` and similar) and NeuroSquad's own data. **Unlocks:** `card.fs.writeText/writeBytes/mkdir/trash()`. **Scope:** as `fs.read`, minus [protected paths](https://docs.neurosquad.ai/en/card-sdk/api/files#protected): any `.git`, agent and editor settings, CI workflows. There is no hard delete — `trash` moves to the OS trash. Implies `fs.read`. #### `clipboard.write` — low **Users see:** *Copy to your clipboard.* Replace what is on your clipboard with text from the card. **Unlocks:** [`card.copyText()`](https://docs.neurosquad.ai/en/card-sdk/api/files#clipboard), once a second. Reading the clipboard is not possible. #### `canvas.spawn` — low **Users see:** *Add cards next to itself.* Place up to 4 new cards beside it on the canvas. **Unlocks:** [`card.spawn()`](https://docs.neurosquad.ai/en/card-sdk/api/card-ui#spawn) — another copy of your card, or a note, todo list, task board or sticky, connected to it with an arrow. **Scope:** 4 cards per card, 4 a minute, within the workspace's card cap. #### `background` — low **Users see:** *Keep running when you are not looking.* Stay active while its workspace is hidden. Uses more memory and battery. **Unlocks:** the card is not [suspended](https://docs.neurosquad.ai/en/card-sdk/api/environment#lifecycle) when hidden. **Scope:** at most 8 such cards run in the background app-wide; beyond that, the least recently seen are suspended anyway. #### `usage.read` — low **Users see:** *See token usage and costs.* How many tokens the agents on this workspace used and what they cost. **Unlocks:** [`card.usage()`](https://docs.neurosquad.ai/en/card-sdk/api/files#usage). **Scope:** the card's own workspace. ### What the install dialog lists besides permissions Derived from the manifest, not permissions: the names of the [tools](https://docs.neurosquad.ai/en/card-sdk/api/tools) the card offers to connected agents, and how many input and output ports it has. Optional permissions appear under **It may ask later for**. > Ask for the least you need. Every high-risk line makes careful users think twice, and a missing > `reason` makes them guess. If a feature needs a strong permission only sometimes, make it > optional and ask when the user reaches for that feature. --- ## connect() and the card > Connecting a card to NeuroSquad, the typed Card object, its live context, calling any method and listening to any event. Source: https://docs.neurosquad.ai/en/card-sdk/api Everything a card does goes through one object, the **card**, which you get from `connect()`: ```ts import { connect } from '@neurosquad/card-sdk' const card = await connect() card.setStatus(`Hello, ${card.workspace.name}`, { tone: 'success' }) ``` `connect()` waits for the app to hand the card its private channel, introduces itself, and resolves with a [`Card`](#the-card-object). Calling it again returns the same card. > **Import the SDK from your entry script.** It starts listening for the app's handshake the moment > it loads. A card that loads the SDK late (a dynamic `import()` after a timer) can miss it and > fail with `UNAVAILABLE`. ### `connect(options?)` ```ts import { connect } from '@neurosquad/card-sdk' const card = await connect({ theme: true, // apply the app theme as --ns-* CSS variables on (default true) syncLang: true, // keep equal to the app language (default true) forwardErrors: true, // send uncaught errors and rejections to the card log (default true) timeoutMs: 10_000 // how long to wait for the app (default 10 000) }) ``` | Option | Default | Meaning | | --- | --- | --- | | `theme` | `true` | `false` to leave your CSS alone; an element to put the `--ns-*` variables on it instead of ``. See [Theme](https://docs.neurosquad.ai/en/card-sdk/api/environment#theme). | | `syncLang` | `true` | Keep `` equal to the app's language. | | `forwardErrors` | `true` | Forward `error` and `unhandledrejection` to the [card log](https://docs.neurosquad.ai/en/card-sdk/api/environment#log). | | `timeoutMs` | `10000` | Waiting for the app's channel, then for its answer. | | `port` | — | Use this channel instead of waiting for the app — for the [mock host](https://docs.neurosquad.ai/en/card-sdk/testing). | It rejects with a [`CardSdkError`](https://docs.neurosquad.ai/en/card-sdk/api/errors): - `UNAVAILABLE` — the page is not inside a NeuroSquad card (opened on its own in a browser). For a preview, use the [mock host](https://docs.neurosquad.ai/en/card-sdk/testing), as the templates do. - `PROTOCOL_MISMATCH` — the app is older than the card protocol your SDK speaks. The card shows "needs a newer NeuroSquad". ### The card object | Member | What | | --- | --- | | `card.context` | Everything the app told the card, [kept current](#context). | | `card.setTitle / setStatus / setBadge / setOverview / attention / requestResize / openLink / focusCard / spawn` | [Card chrome](https://docs.neurosquad.ai/en/card-sdk/api/card-ui) | | `card.ui` | [Toasts, confirm dialog, the card's menu](https://docs.neurosquad.ai/en/card-sdk/api/card-ui#ui) | | `card.storage` | [Per-card and per-package storage](https://docs.neurosquad.ai/en/card-sdk/api/storage-settings#storage) | | `card.settings` | [The settings form's values](https://docs.neurosquad.ai/en/card-sdk/api/storage-settings#settings) | | `card.agents` | [Agents, their statuses, output and prompts](https://docs.neurosquad.ai/en/card-sdk/api/agents) | | `card.terminals` | [Commands in connected terminals](https://docs.neurosquad.ai/en/card-sdk/api/agents#terminals) | | `card.ports` | [Typed data to and from connected cards](https://docs.neurosquad.ai/en/card-sdk/api/ports) | | `card.tools` | [Tools for connected agents](https://docs.neurosquad.ai/en/card-sdk/api/tools) | | `card.net` | [HTTP through the app's proxy](https://docs.neurosquad.ai/en/card-sdk/api/network) | | `card.fs` | [Files in the workspace folder](https://docs.neurosquad.ai/en/card-sdk/api/files) | | `card.permissions` | [Grant state, asking for optional ones](https://docs.neurosquad.ai/en/card-sdk/api/environment#permissions) | | `card.lifecycle` | [Visibility, suspend, expand, resize](https://docs.neurosquad.ai/en/card-sdk/api/environment#lifecycle) | | `card.log` | [Lines for the card log](https://docs.neurosquad.ai/en/card-sdk/api/environment#log) | | `card.copyText / usage / getWorkspace / getTheme / getI18n` | [Clipboard, usage](https://docs.neurosquad.ai/en/card-sdk/api/files), fresh snapshots | | `card.host` | [Feature detection](#feature-detection) | | `card.call / on / once / waitFor` | [Any method, any event](#any-method-any-event) | | `card.close() / closed` | Close the channel; later calls fail with `UNAVAILABLE`. | ### The context `card.context` is a `HostContext`: what the app sent when the card connected, **updated from every event** (visibility, size, theme, language, settings, permissions, peers). The object is replaced, never mutated, on each change — safe to use with React's `useSyncExternalStore`. ```ts import type { HostContext } from '@neurosquad/card-sdk' function describe(context: HostContext): string { const { instance, workspace, visibility, i18n, launch } = context return `${instance.displayName} ${instance.version} in "${workspace.name}", ${visibility}, ${i18n.language}, started: ${launch}` } card.onContextChange((context) => render(describe(context))) ``` | Field | Type | Meaning | | --- | --- | --- | | `instance` | `CardInstanceInfo` | `instanceId` (this card's id on the canvas), `packageId`, `name`, `displayName`, `version`, `commit` (`null` for a linked folder), `title`, `size`, `dev`. | | `workspace` | `WorkspaceInfo` | `id`, `name`, and `path` (absolute) only with `fs.read`. | | `visibility` | `'visible'`, `'offscreen'`, `'overview'` or `'hidden'` | See [Lifecycle](https://docs.neurosquad.ai/en/card-sdk/api/environment#lifecycle). | | `expanded` | `boolean` | The card is expanded to fill the canvas. | | `theme` | `ThemeSnapshot` | The app's colours, radii and fonts. | | `i18n` | `{ language, locale }` | `en`, `ru` or `zh`, and a locale for `Intl`. | | `settings` | `SettingsSnapshot` | `values`, and `secrets` (which secret keys are set). | | `permissions` | `PermissionState[]` | Every declared permission with `granted`, `optional`, `hosts`, `reason`. | | `ports` | `{ inputs, outputs }` | Your own ports, labels resolved. | | `peers` | `PeerInfo[]` | Cards connected by arrows. | | `launch` | `'created'`, `'opened'`, `'resumed'`, `'reloaded'` or `'updated'` | Why this frame started. | | `spawnInit` | JSON or absent | Data from the card that [spawned](https://docs.neurosquad.ai/en/card-sdk/api/card-ui#spawn) this one, on its first start. | | `chrome` | `CardChromeState` or absent | What the app is showing for this card right now — `title`, `status`, `badge`, `overview`, `attention` — kept across reloads. See [Card chrome](https://docs.neurosquad.ai/en/card-sdk/api/card-ui#attention). Absent on older app versions. | | `appVersion` | `string` | NeuroSquad's version. | | `limits` | `LIMITS` | Every limit of the protocol, see [Limits](https://docs.neurosquad.ai/en/card-sdk/api/errors#limits). | | `protocol` | `number` | The card protocol the app speaks. | Shortcuts on the card: `card.instanceId`, `card.instance`, `card.workspace`, `card.visibility`, `card.expanded`, `card.size`, `card.theme`, `card.i18n`, `card.language`, `card.launch`, `card.spawnInit`, `card.limits`, `card.appVersion`. **`launch`** tells you what happened: `created` (just added to the canvas), `opened` (the workspace was opened), `resumed` (back after being [suspended](https://docs.neurosquad.ai/en/card-sdk/api/environment#lifecycle)), `reloaded` (the user pressed Reload, a file changed in dev mode, or a permission was revoked), `updated` (a new version of your card was installed). ### Any method, any event The namespaces are sugar over two primitives, both fully typed from the protocol: ```ts // Any method: params and result are typed from the method name. const { keys } = await card.call('storage.keys', { scope: 'instance', prefix: 'draft:' }) const info = await card.call('card.getInfo') // Any event: the payload is typed from the event name. Returns a function that removes the listener. const off = card.on('agents.turn', (turn) => { if (turn.phase === 'end') render(`${turn.agentId} finished a turn`) }) off() // Once, or as a promise. card.once('lifecycle.expanded', ({ expanded }) => render(expanded)) const next = await card.waitFor('agents.status', (e) => e.status === 'needs-input', { timeoutMs: 60_000 }) render(next.agentId) ``` Subscribable topics (`agents.status`, `agents.turn`, `agents.changed`, `storage.changed`) are subscribed with the app automatically while at least one listener exists, and unsubscribed when the last goes. `agents.output` needs agent ids — use [`card.agents.onOutput()`](https://docs.neurosquad.ai/en/card-sdk/api/agents#output). If a topic needs a permission you do not have, the listener simply gets nothing, and a warning goes to the card log. Events that could arrive before you attach a listener — `ports.message`, `ui.menu`, `fs.changed` — are kept (up to 100) and delivered to the first listener, so nothing is lost between `connect()` and your `on()`. #### All events | Event | Payload | When | | --- | --- | --- | | `lifecycle.visibility` | `{ state }` | Visibility changed. | | `lifecycle.suspend` | `{ graceMs }` | The frame is about to be unloaded. Use `card.lifecycle.onSuspend`. | | `lifecycle.expanded` | `{ expanded }` | Expanded or restored. | | `lifecycle.resized` | `{ w, h }` | The card was resized. | | `settings.changed` | `SettingsSnapshot` | Settings changed (form or `settings.set`). | | `theme.changed` | `ThemeSnapshot` | The app's theme changed. | | `i18n.changed` | `{ language, locale }` | The app's language changed. | | `permissions.changed` | `PermissionState[]` | A grant changed. | | `ui.menu` | `{ id }` | A menu item you added was chosen. | | `ports.message` | see [Ports](https://docs.neurosquad.ai/en/card-sdk/api/ports#receiving) | A value arrived on an input. | | `ports.request` | see [Ports](https://docs.neurosquad.ai/en/card-sdk/api/ports#requests) | A peer asks a request input. Use `card.ports.onRequest`. | | `ports.peersChanged` | `PeerInfo[]` | Arrows or peers changed. | | `tools.call`, `tools.cancel` | see [Tools](https://docs.neurosquad.ai/en/card-sdk/api/tools) | An agent calls a tool. Use `card.tools.handle`. | | `net.chunk` | see [Network](https://docs.neurosquad.ai/en/card-sdk/api/network#streaming) | A streamed response chunk. Use `response.chunks()`. | | `fs.changed` | `{ watchId, path, type }` | A watched file changed. Use `card.fs.watch`. | | `storage.changed` | `{ scope, key, byInstance }` | Another copy of the card wrote a package key. Topic. | | `agents.status` | `{ agentId, status, at }` | An agent's status changed. Topic, `agents.read`. | | `agents.turn` | `{ agentId, phase, at }` | A turn started or ended. Topic, `agents.read`. | | `agents.changed` | `{ agents }` | Agents added, removed or renamed. Topic, `agents.read`. | | `agents.output` | `{ agentId, text, at }` | Output of a connected agent. `agents.output`. | | `host.ping` | `{ seq }` | Heartbeat — the SDK answers for you. | ### Feature detection New methods and events arrive within a protocol version. Check before you use one the user's app might not have yet: ```ts if (await card.host.supports('usage.summary')) { const usage = await card.usage('today') render(usage.totalCostMicroUsd) } const { protocol, methods, events } = await card.host.capabilities() render(protocol, methods.length, events.length) // A method newer than your SDK's types: const result = await card.callUnchecked('some.newMethod', { any: 'params' }) render(result) ``` ### Conventions - **Ids.** Card and agent ids are the canvas ids — the same `cardId` you get from `card.ports.peers`, `card.agents.list()` or `card.spawn()`. - **Connected** means an arrow between the two cards, in either direction. Ports additionally care about the direction (see [Ports](https://docs.neurosquad.ai/en/card-sdk/api/ports#direction)). - **Every call is checked twice.** The SDK validates params against the same schemas the app uses and fails fast with `INVALID_PARAMS` and the exact path; the app checks again, plus permissions, visibility, arrows and rate limits. - **Only JSON crosses.** No `Blob`, no `ArrayBuffer`: the helpers that take bytes (`fs.writeBytes`, `net.fetch` bodies) encode them as base64 for you. - **Replies can come out of order;** events arrive in the order the app sent them. - **Never trust `window` `message` events.** Any other card on the canvas can `postMessage` your frame. The only trusted channel is the one the SDK receives from the app at `connect()`; do not add your own `message` listeners that act on what arrives. --- ## Card chrome & dialogs > The card's header — title, status, badge — its overview tile, attention, resize, links, camera focus and spawning cards; toasts, confirm dialogs and the card's menu. Source: https://docs.neurosquad.ai/en/card-sdk/api/card-ui The card's header, overview tile and dialogs are drawn **by the app**, not by your page — so they look native, work while your card is suspended, and show on the phone. You set their content. **Call them as often as you like.** The app throttles these updates (title 30 a minute; status, badge and overview 120 a minute each; attention once every 10 seconds), and the SDK absorbs that for you: for `setTitle`, `setStatus`, `setBadge`, `setOverview` and `attention` it sends one call at a time per method, folds calls made meanwhile into one with the latest value, and retries the latest value when the app says `RATE_LIMITED`. They never throw for rate — updating on every render is fine. An update that changes nothing costs nothing. ### Title ```ts await card.setTitle('Checkout tests') // null clears it ``` The name shown in the header, the sidebar and the Squad card. If the user renamed the card, the user's name wins; without either, the manifest's `displayName` shows. ≤ 120 characters; control, bidi and invisible characters are stripped. ### Status ```ts await card.setStatus('Running tests…', { busy: true }) // spinner await card.setStatus('3 failed', { tone: 'danger' }) await card.setStatus(null) // clear ``` A chip in the header, ≤ 80 characters. Tones: `default`, `accent`, `success`, `warning`, `danger`. ### Badge ```ts await card.setBadge(3) // a count await card.setBadge('NEW', { tone: 'accent' }) // or a short text, ≤ 12 characters await card.setBadge(null) // clear ``` ### Overview tile When the user zooms out past the overview threshold, every card shows a tile with its main fact instead of its body. Yours shows what you set here — and keeps showing it while the card is suspended, and on the [phone](https://docs.neurosquad.ai/en/card-sdk/phone). The app remembers it. ```ts await card.setOverview({ primary: '3 failing', // big line, ≤ 160 secondary: 'checkout, auth', // small line, ≤ 160 progress: 0.8, // 0..1, a progress bar; null hides it tone: 'danger', icon: 'bug-ant' }) ``` Keep it current: it is the only thing of your card most people see on a busy canvas. **Icons** the app can draw (heroicons, outline): `academic-cap`, `arrow-path`, `beaker`, `bell`, `bolt`, `book-open`, `bug-ant`, `calendar`, `camera`, `chart-bar`, `chart-pie`, `chat-bubble-left-right`, `check-circle`, `clock`, `cloud`, `code-bracket`, `command-line`, `cpu-chip`, `cube`, `currency-dollar`, `document-text`, `exclamation-triangle`, `film`, `fire`, `flag`, `folder`, `globe-alt`, `heart`, `inbox`, `key`, `light-bulb`, `link`, `list-bullet`, `map`, `megaphone`, `moon`, `musical-note`, `newspaper`, `paper-airplane`, `pause`, `photo`, `play`, `puzzle-piece`, `rocket-launch`, `server`, `shield-check`, `signal`, `sparkles`, `star`, `stop`, `sun`, `table-cells`, `tag`, `trash`, `trophy`, `users`, `wrench-screwdriver` (the list is `HOST_ICON_NAMES` in the SDK). Inside your own page, draw any icon you like. ### Attention ```ts await card.attention('needs-input', 'Pick a branch to deploy') await card.attention('info') // a softer pulse await card.attention('none') // clear ``` `needs-input` makes the card pulse like an agent waiting for the user and lists it in the **Inbox**. At most once every 10 seconds. There is no sound and no OS notification in version 1. **What is showing now.** The app keeps a card's title, status, badge, overview and attention across reloads, suspension and updates. `card.context.chrome` tells your page what it currently holds, so a card that raised attention before a reload can clear a stale pulse: ```ts const attention = card.context.chrome?.attention if (attention && !stillNeedsTheUser()) await card.attention('none') declare function stillNeedsTheUser(): boolean ``` `chrome` is absent on older app versions — treat that as "unknown". ### Resize ```ts const applied = await card.requestResize({ w: 640, h: 480 }) render(applied.w, applied.h) ``` Clamped to the manifest's `minSize`/`maxSize`; resolves with the size actually applied. It goes into the canvas undo history like a resize by hand. At most every 500 ms. The user can always resize too — listen with [`card.lifecycle.onResized`](https://docs.neurosquad.ai/en/card-sdk/api/environment#lifecycle). ### Open a link ```ts const opened = await card.openLink('https://github.com/acme/app/issues/42') ``` The app shows the full address in its own window-wide dialog; the link opens in the user's browser only after **Open link**. `https://` only, and only while the card is visible (`NOT_VISIBLE` otherwise). Resolves `false` if the user declined. A card cannot navigate itself or open windows. ### Fly to another card ```ts await card.focusCard(cardId) ``` Moves the camera to another card of the same workspace — for "show me the failing agent" buttons. Only while your card is visible, at most every 5 seconds. ### Spawn a card Needs [`canvas.spawn`](https://docs.neurosquad.ai/en/card-sdk/permissions#canvas-spawn). ```ts // A note next to this card, connected with an arrow from this card. const noteId = await card.spawn('note', { title: 'Test report' }) await card.ports.send(noteId, 'summary', '# Report\n\nAll green.') // Another copy of this card, with data for its first start. await card.spawn('self', { init: { suite: 'e2e' }, connect: false }) ``` Kinds: `self` (another card of your package, which gets `init` as `card.spawnInit` on its first start), `note`, `todo`, `kanban`, `sticky`. The new card is placed next to yours and connected with an arrow from your card unless `connect: false`. At most 4 per card and 4 a minute. ### Card info ```ts const info = await card.getInfo() // CardInstanceInfo, fresh from the app render(info.instanceId, info.packageId, info.commit ?? 'dev folder', info.size) ``` ### Toasts ```ts await card.ui.toast('Copied', { tone: 'success', durationMs: 2000 }) ``` A small toast inside the card's box, ≤ 280 characters, 1–15 seconds, at most one every 2 seconds. ### Confirm dialog `alert`, `confirm` and `prompt` do nothing in a card's sandbox. Ask the app instead: ```ts const ok = await card.ui.confirm({ title: 'Delete all saved runs?', message: 'This removes 42 runs from this card. It cannot be undone.', confirmLabel: 'Delete', cancelLabel: 'Keep', tone: 'danger' }) if (ok) await card.storage.clear() ``` The app shows this as **its own dialog over the whole window**, not inside your card: a fixed heading saying your card asks for confirmation, your `title` and `message` as a quote, your `confirmLabel` (replaced with the app's "Confirm" if it reads like cancel/no/deny, names NeuroSquad or contains control characters) and the app's own Cancel. Only while the card is visible, at most 10 a minute. Dialogs from several cards queue. ### The card's menu Add up to 12 items to the card's **⋯** menu, after the app's own (Settings…, Reload, About…). ```ts await card.ui.setMenu([ { id: 'rerun', label: 'Run again', icon: 'arrow-path', onSelect: () => void rerun() }, { id: 'export', label: 'Copy report', icon: 'document-text', onSelect: () => void copyReport() }, { id: 'reset', label: 'Reset', tone: 'danger', disabled: true } ]) // Or handle every choice in one place: card.ui.onMenu((id) => card.log.info('menu', id)) declare function rerun(): Promise declare function copyReport(): Promise ``` Each call replaces the previous items (at most 30 calls a minute). `onSelect` stays in your card — it is not sent to the app. Labels ≤ 60 characters; `icon` is one of the [host icons](#overview). > Everything on this page except dialogs and links works while the card is not on screen. Dialogs, > links, camera focus and permission requests need the user to be looking: they fail with > `NOT_VISIBLE` otherwise. --- ## Storage & settings > Persistent key/value storage per card and per package, and reading and changing the settings form the app draws from your manifest. Source: https://docs.neurosquad.ai/en/card-sdk/api/storage-settings ### Storage A card's page has no `localStorage`, `indexedDB` or cookies — its sandbox has no origin to keep them in. `card.storage` is the replacement: JSON values the app keeps on disk, atomically, across reloads, suspension and restarts. No permission needed. ```ts // This card on the canvas (instance scope). const draft = await card.storage.get('draft', '') // string, '' when missing await card.storage.set('draft', `${draft}\nmore`) await card.storage.set('runs', [{ at: Date.now(), failed: 3 }]) const runs = await card.storage.get<{ at: number; failed: number }[]>('runs') // undefined when missing await card.storage.delete('draft') const keys = await card.storage.keys('run:') // keys starting with a prefix const { bytes, quota } = await card.storage.usage() render(runs?.length, keys, bytes, quota) // Shared by every copy of this card, on every canvas (package scope). await card.storage.package.set('lastSync', Date.now()) card.storage.onChange(({ key, byInstance }) => { if (key === 'lastSync') render(`updated by card ${byInstance}`) }) ``` | Method | Result | | --- | --- | | `get(key)` | The value, or `undefined`. | | `get(key, fallback)` | The value, or `fallback`. The result is typed like the fallback. | | `set(key, value)` | Stores any JSON value. | | `delete(key)` | | | `keys(prefix?)` | `string[]` | | `clear()` | Deletes every key of that scope. | | `usage()` | `{ bytes, quota, keys }` | | `onChange(handler)` | Another copy of this card wrote a **package** key: `{ scope, key, byInstance }`. | The same methods exist on `card.storage.package`. **Limits:** keys ≤ 256 characters, values ≤ 1 MB, ≤ 10 000 keys; 5 MB per card, 20 MB per package. Going over fails with `QUOTA_EXCEEDED`. Writes reach the disk within about a quarter of a second and are flushed when the app quits. **What happens to it:** instance storage is deleted with the card. Package storage survives uninstalling unless the user ticks **Also delete its saved data and secrets**. Storage survives updates — keep your stored shapes readable by newer versions (store a `version` field if you might change them). > Save before you are unloaded: a card that is hidden for a while is suspended, and its page is > thrown away. Use [`card.lifecycle.onSuspend`](https://docs.neurosquad.ai/en/card-sdk/api/environment#lifecycle) to write what is > still in memory. ### Settings Declare fields in the manifest's [`settings`](https://docs.neurosquad.ai/en/card-sdk/manifest#settings); the app draws the form (from the card's **⋯ → Settings…**, or when you call `card.settings.open()`), validates it and stores the values. Your card reads them: ```ts const command = card.settings.value('command') ?? 'npm test' const all = card.settings.values // defaults filled in, secrets never included const hasKey = card.settings.hasSecret('apiKey') // true when the user saved one card.settings.onChange((snapshot) => { render(snapshot.values['command'], snapshot.secrets['apiKey']) }) // Change your own non-secret settings (a toggle in your UI, say). Validated like the form. await card.settings.set({ compact: true }) // Open the form on the card (only while it is visible). if (!hasKey) await card.settings.open() render(command, all) ``` | Member | What | | --- | --- | | `values` | Current values, defaults filled in. Kept current. | | `secrets` | `Record`: which secret settings are set. | | `value(key)` | One value, typed by you. | | `hasSecret(key)` | Whether a secret setting is set. | | `get()` | A fresh `SettingsSnapshot` from the app. | | `set(values)` | Changes non-secret settings; every copy of the card gets `settings.changed`. Invalid values fail with `INVALID_PARAMS`. At most 60 a minute. | | `open()` | Opens the settings form on the card. `NOT_VISIBLE` if the card is off screen. | | `onChange(handler)` | The user saved the form, or `set` changed something. | **Scopes.** A field with `"scope": "package"` has one value for every copy of your card; the rest are per card. **Secrets.** A `secret` field is typed only into the app's own dialog — in the settings form its row shows just "set" or "not set" and opens that window-wide dialog — and stored encrypted by the app. The card can never read it — not through `values`, not through any method. To use one, put `{{secret:}}` into a [network request header](https://docs.neurosquad.ai/en/card-sdk/api/network#secrets); the app fills it in on its way out, only for internet hosts your card was granted (never for `localhost`). Do not build your own "paste your API key" field inside the card: the key would then be yours to leak, and users are told that NeuroSquad never asks for keys inside a card. --- ## Theme, language & lifecycle > Following the app's theme and language live, visibility and suspension, the workspace, optional permissions at runtime, and the card log. Source: https://docs.neurosquad.ai/en/card-sdk/api/environment ### Theme `connect()` writes the app's live theme onto your page's `` as CSS variables and keeps them current: - `--ns-` for each token: `background`, `background-secondary`, `background-tertiary`, `foreground`, `muted`, `surface`, `surface-foreground`, `surface-secondary`, `surface-secondary-foreground`, `surface-tertiary`, `surface-tertiary-foreground`, `overlay`, `overlay-foreground`, `default`, `default-foreground`, `accent`, `accent-foreground`, `accent-soft`, `accent-soft-foreground`, `success`, `success-foreground`, `success-soft`, `warning`, `warning-foreground`, `warning-soft`, `danger`, `danger-foreground`, `danger-soft`, `border`, `border-secondary`, `separator`, `focus`, `link`, `field-background`, `field-foreground`, `field-placeholder`, `field-border`, `radius`, `field-radius`; - `--ns-font-sans`, `--ns-font-mono` — the app's font stacks (the fonts themselves are not shared: ship your own or use system fonts); - `color-scheme` and `data-ns-scheme="dark"` on ``. ```css .panel { background: var(--ns-surface); color: var(--ns-surface-foreground); border: 1px solid var(--ns-border); border-radius: var(--ns-radius); font-family: var(--ns-font-sans); } .panel--alert { background: var(--ns-danger-soft); color: var(--ns-danger); } ``` In code, `card.theme` is the `ThemeSnapshot` (`scheme`, `tokens`, `fontSans`, `fontMono`), kept current; `card.on('theme.changed', …)` tells you when it changes, and `applyTheme(snapshot, element)` writes the variables anywhere you like (for example into a shadow root). > The app is dark today, so `scheme` is always `dark` — but do not hard-code it: use the variables > and a light theme will just work when it arrives. Styling guide: [UI kit & styling](https://docs.neurosquad.ai/en/card-sdk/styling). ### Language The app speaks English, Russian and Simplified Chinese and switches live. `card.i18n` is `{ language: 'en' | 'ru' | 'zh', locale }` (`locale` is `en-US`, `ru-RU` or `zh-CN`, for `Intl`), `` follows it, and texts in your manifest (`displayName`, labels, descriptions) are resolved by the app. For your own strings, `createTranslator` follows the app's language live: ```ts import { createTranslator } from '@neurosquad/card-sdk' const t = createTranslator( { en: { title: 'Tests', failed_one: '{{count}} test failed', failed_other: '{{count}} tests failed' }, ru: { title: 'Тесты', failed_one: '{{count}} тест упал', failed_few: '{{count}} теста упало', failed_many: '{{count}} тестов упало', failed_other: '{{count}} теста упало' }, zh: { title: '测试', failed_other: '{{count}} 个测试失败' } }, card ) render(t('title'), t('failed', { count: 3 })) t.onChange(() => render(t('title'))) // re-render on a language switch const when = new Intl.DateTimeFormat(card.i18n.locale, { timeStyle: 'short' }).format(Date.now()) render(when) ``` - Keys can be nested (`{ list: { empty: '…' } }` → `t('list.empty')`); `en` is required and is the fallback, then the key itself. - `{{name}}` placeholders are filled from the second argument; numbers are formatted for the locale. - With `count`, plural forms `key_one`, `key_few`, `key_many`, `key_other` are chosen by `Intl.PluralRules` — Russian uses all four, Chinese only `_other`. - `t.language`, `t.locale`, `t.onChange(fn)`, `t.setLanguage(lang)`, `t.dispose()`. ### Lifecycle and visibility A 50-card canvas cannot run 50 web apps at full speed, so the app tells your card where it is and pauses it when nobody can see it. | `card.visibility` | Meaning | What to do | | --- | --- | --- | | `visible` | On screen, body shown. | Run. | | `offscreen` | Its workspace is shown, the card is outside the view. | Stop animations and polling. | | `overview` | Zoomed out: the app shows your [overview tile](https://docs.neurosquad.ai/en/card-sdk/api/card-ui#overview) instead of the body. | Stop animations; keep the tile current. | | `hidden` | Its workspace is not shown, or the window is hidden. | Stop everything that is only for the eyes. | ```ts card.lifecycle.onVisibility((state) => { if (state === 'visible') startAnimation() else stopAnimation() }) card.lifecycle.onSuspend(async (graceMs) => { // The page is about to be unloaded. You have graceMs (about a second) to save. await card.storage.set('draft', currentDraft()) }) card.lifecycle.onExpanded((expanded) => render(expanded ? 'big layout' : 'compact layout')) card.lifecycle.onResized(({ w, h }) => render(w, h)) if (card.launch === 'resumed') render('back from a pause — state restored from storage') declare function startAnimation(): void declare function stopAnimation(): void declare function currentDraft(): string ``` **Suspension.** A card whose workspace has been hidden for a minute is suspended: it gets `lifecycle.suspend`, has about a second (`graceMs`) to save, then its page is unloaded. The app keeps showing its header and [overview tile](https://docs.neurosquad.ai/en/card-sdk/api/card-ui#overview). When the user looks again, the page starts fresh with `card.launch === 'resumed'`. At most 24 card pages run at once across the app; beyond that, the least recently seen offscreen or hidden cards are suspended too. Cards with the [`background`](https://docs.neurosquad.ai/en/card-sdk/permissions#background) permission are not suspended when hidden (up to 8 app-wide). **Lazy start.** A card's page is created the first time the card is actually visible in the shown workspace, not when the workspace opens. Until then the body shows a placeholder and the header shows what you set last time. **Other things to know** - Tools and request ports **wake** a suspended card: the app starts its page (waiting up to 10 seconds) before delivering the call. Stream messages to a suspended card are dropped — use `retain` on outputs so a card can catch up with `ports.read`. - While the canvas is being dragged or zoomed, your card does not get mouse events. - The mouse wheel inside your card scrolls your card, never the canvas. App keyboard shortcuts do not work while focus is inside a card. - A card that stops answering the app's heartbeat for 15 seconds is shown as **Not responding** with a Reload button. The SDK answers heartbeats for you; a long synchronous loop in your code is what triggers it. - Every distinct card package is one browser process (~30–60 MB); copies of the same card share it. **Events are not replayed.** While a card's page is not running — not yet mounted, suspended, or unloaded — it misses events such as `agents.turn`. On start, rebuild what you show from `card.agents.list()` (`status`, `turnStartedAt`, and `lastTurn` — when the last turn ended and how) and from retained port values rather than assuming you saw every event. ### Workspace ```ts const workspace = await card.getWorkspace() // { id, name, path? } render(workspace.name, workspace.path ?? 'no fs.read — no path') ``` `card.workspace` holds the same, kept current. `path` (absolute) is there only with `fs.read`. ### Permissions at runtime ```ts async function copyReport(text: string): Promise { if (!card.permissions.has('clipboard.write')) { // Declared with "optional": true in the manifest. Only while the card is visible. const granted = await card.permissions.request('clipboard.write') if (!granted.includes('clipboard.write')) return false } await card.copyText(text) return true } card.permissions.onChange((all) => render(all.filter((p) => p.granted).map((p) => p.id))) ``` | Member | What | | --- | --- | | `all` | Every declared permission: `{ id, granted, optional, hosts?, reason? }`. Kept current. | | `has(id)` | Granted, directly or implied (`fs.write` implies `fs.read`). | | `list()` | A fresh list from the app. | | `request(...ids)` | Asks the user for **optional** declared permissions (in the app's window-wide dialog). Resolves with the ids granted now. Only while the card is visible, once every 5 seconds; asking for anything not declared as optional fails with `PERMISSION_DENIED`. | | `onChange(handler)` | A grant changed — the user granted, or revoked in Settings. | ### The card log ```ts card.log.info('run started', { filter: 'checkout' }) card.log.warn('slow response', 1834, 'ms') card.log.error(new Error('parser failed')) ``` Lines go to the package's log in the app (`card-logs`, 256 KB, rotating) and, while you run `neurosquad-card dev`, to your terminal. Arguments are joined like `console.log` (objects as JSON, errors with their stack), ≤ 2 000 characters a line, at most 50 lines a second — beyond that lines are dropped and one "N lines dropped" warning is written. Uncaught errors and unhandled promise rejections are logged as `error` automatically (`forwardErrors: false` in `connect()` to turn that off). --- ## Agents & terminals > Listing agents and their live status, turn events, reading the screens of connected agents, sending prompts, and running commands in connected terminals. Source: https://docs.neurosquad.ai/en/card-sdk/api/agents ### Listing agents Needs [`agents.read`](https://docs.neurosquad.ai/en/card-sdk/permissions#agents-read). ```ts import type { AgentInfo } from '@neurosquad/card-sdk' const agents: AgentInfo[] = await card.agents.list() const waiting = agents.filter((a) => a.kind === 'ai' && a.status === 'needs-input') const one = await card.agents.get(agents[0].id) render(waiting.map((a) => a.name), one.model ?? 'default model') ``` Every AI agent and terminal in the card's workspace (other cards are not agents): | Field | Type | Meaning | | --- | --- | --- | | `id` | `string` | The card's id on the canvas. | | `name` | `string` | What the user sees. | | `harness` | `string` | `claude-code`, `codex-cli`, `opencode`, `qwen-code`, `shell-bash`, `shell-powershell`, `shell-cmd`… | | `kind` | `'ai'` or `'shell'` | An AI agent or a terminal. | | `status` | `AgentStatus` | `working`, `needs-input`, `finished`, `idle` or `exited`. | | `connected` | `boolean` | An arrow connects it with your card. | | `sessionTitle` | `string?` | The title the agent gave its session. | | `turnStartedAt` | `number?` | Epoch ms the current turn started, while `working`. | | `lastTurn` | `{ startedAt, endedAt, endedAs }?` | The last finished turn since the app started: epoch ms (`startedAt` may be `null`), and `endedAs` `finished` or `needs-input` — to catch up on turns your card missed while it was not running. | | `model` | `string?` | The model it runs on, when known. | Statuses come from the same tracker as the rest of the app — for Claude Code from its own hooks (for OpenCode and Kilo Code from their NeuroSquad plugin, for Hermes Agent from its lifecycle webhooks), so `needs-input` ("waiting for your permission") and `finished` are told apart exactly. ### Events ```ts card.agents.onStatus(({ agentId, status }) => render(agentId, status)) card.agents.onTurn(({ agentId, phase, at }) => render(agentId, phase, new Date(at))) card.agents.onChanged((agents) => render(agents.length)) // added, removed or renamed // Only one agent: card.agents.onStatus((e) => render(e.status), agentId) ``` - `agents.status` — `{ agentId, status, at }` whenever a status changes. - `agents.turn` — `{ agentId, phase: 'start' | 'end', at }`. A turn starts when a prompt is submitted and ends when the agent finishes or needs input. - `agents.changed` — `{ agents }`, the whole new list. The SDK subscribes while you have listeners. Each returns a function that removes it. ### Reading output Needs [`agents.output`](https://docs.neurosquad.ai/en/card-sdk/permissions#agents-output), and an **arrow** between your card and the agent or terminal. ```ts // The visible screen, as text (up to 500 lines). const screen = await card.agents.readScreen(agentId, 80) // The last reply, from the agent's own session log (Claude Code, OpenCode, Kilo Code, Hermes Agent). null for others. const { text, at } = await card.agents.lastReply(agentId) // Live output: ANSI colours stripped, delivered in chunks about every 100 ms. const stop = card.agents.onOutput([agentId, shellId], ({ agentId: from, text: chunk }) => { if (chunk.includes('FAIL')) render(`${from} printed a failure`) }) stop() // when you no longer need it render(screen, text, at) ``` Calling these for an agent without an arrow fails with `NOT_CONNECTED`. `readScreen` of an agent that is not running fails with `UNAVAILABLE`. ### Prompting agents Needs [`agents.prompt`](https://docs.neurosquad.ai/en/card-sdk/permissions#agents-prompt) and an arrow to an **AI** agent (terminals take [commands](#terminals) instead). ```ts import { isCardSdkError } from '@neurosquad/card-sdk' try { const delivered = await card.agents.prompt(agentId, 'Run the checkout tests and fix what fails.') // 'sent' — submitted now // 'queued' — the agent is working; it goes out when the turn ends // 'inserted'— typed in only (submit: false); the user presses Enter card.ui.toast(delivered === 'queued' ? 'Queued after the current turn' : 'Sent') } catch (error) { if (isCardSdkError(error, 'NOT_CONNECTED')) card.ui.toast('Draw an arrow from me to an agent') else if (isCardSdkError(error, 'BUDGET_PAUSED')) card.ui.toast('The workspace is over its budget') else if (isCardSdkError(error, 'USER_CANCELLED')) card.ui.toast('Not sent') else throw error } ``` Options — `card.agents.prompt(agentId, text, { submit, whenBusy })`: | Option | Default | Meaning | | --- | --- | --- | | `submit` | `true` | `false` types the text into the agent's input without pressing Enter — the user reviews and sends it. Result `inserted`. | | `whenBusy` | `'queue'` | While the agent is working: `queue` puts it in the agent's [prompt queue](https://docs.neurosquad.ai/en/agents/queue) (`queued`), `send` submits anyway (`sent`), `fail` refuses with `BUSY`. | What the app does with every prompt: - It goes through the same path as the prompt queue and the [budget](https://docs.neurosquad.ai/en/cards/budget): over the workspace's budget, it fails with `BUDGET_PAUSED` (a person typing is never limited — your card is). - It shows on the arrow and in its [arrow log](https://docs.neurosquad.ai/en/canvas/arrows#arrow-log) with your card's name. - To an agent in [dangerous mode](https://docs.neurosquad.ai/en/agents/dangerous-mode), the app first shows the prompt in its own window-wide dialog and waits for **Send prompt**; if the user declines — `USER_CANCELLED`; if your card is not on screen — `NOT_VISIBLE`. - At most 6 prompts a minute per card — counted together with prompts sent through the agent's `prompt` port — ≤ 20 000 characters each. - Queued prompts from cards are capped at 10 per agent, show which card they came from, and are dropped before they go out if the arrow, the permission, the card or its package is gone, or the agent was switched to dangerous mode. > A prompt is an instruction to something that can edit files and run commands. Never forward text > from the web, a file or another card into a prompt without showing it to the user first — that is > how prompt injection happens. Prefer `submit: false` when the text is not yours. ### Terminals Needs [`terminals.write`](https://docs.neurosquad.ai/en/card-sdk/permissions#terminals-write) and an arrow to a terminal card (bash, PowerShell or cmd). ```ts // Run a command and wait for it to finish. const result = await card.terminals.run(shellId, 'npm test -- --reporter=dot', { timeoutMs: 120_000 }) if (result.timedOut) render('still running after 2 minutes') else render(result.exitCode === 0 ? 'passed' : `failed with ${result.exitCode}`, result.output) // Or just type into it (and press Enter). await card.terminals.write(shellId, 'git status', { submit: true }) ``` | | `run(agentId, command, { timeoutMs? })` | `write(agentId, text, { submit? })` | | --- | --- | --- | | Does | Runs one command and waits for the prompt to come back | Types text; `submit: true` presses Enter after it | | Returns | `{ exitCode, output, truncated, timedOut }` | nothing | | Limits | timeout 1–120 s (default 120), output ≤ 64 KB; 30 commands a minute per card, shared with the terminal's `command` port | 60 a minute | `exitCode` is `null` in cmd, which does not report one. The user sees every command in the terminal itself and on the arrow. Commands are not limited by the agents' budget — a terminal is not an AI agent — but they run with the user's full rights: see the [security checklist](https://docs.neurosquad.ai/en/card-sdk/security). --- ## Ports: cards talking to cards > Typed inputs and outputs over arrows — well-known types and your own JSON Schema types, emit, send, request/response, retained values, discovering what a connected card accepts, and the built-in note, todo, task board, sticky, agent and terminal ports. Source: https://docs.neurosquad.ai/en/card-sdk/api/ports Ports let a card exchange **typed data** with the cards it is connected to by arrows: your test radar pushes failures into a todo list, a note feeds its text into your summariser, two custom cards agree on their own format. You declare ports in the [manifest](https://docs.neurosquad.ai/en/card-sdk/manifest#ports); the app routes, converts and validates every value. ### Direction An arrow **from card A to card B** carries A's **outputs** to B's **inputs**. For a pair connected both ways, data flows both ways. (Tools and agent permissions do not care about direction; ports do.) `card.ports.peers` lists every card connected to yours, with `direction`: - `downstream` — your card → peer: your outputs reach its inputs; - `upstream` — peer → your card: its outputs reach your inputs; - `both`. ### Types Every port has a type: a **well-known** `ns:*` type, or a **custom** `/` type with a JSON Schema. | Type | Value | | --- | --- | | `ns:any` | Any JSON. As an input it accepts every output type unchanged. | | `ns:text` | A string (≤ 1 000 000). | | `ns:markdown` | A Markdown string (≤ 1 000 000). | | `ns:number` | A number. | | `ns:boolean` | `true` or `false`. | | `ns:json` | An object or an array. | | `ns:url` | A URI string. | | `ns:image` | `{ mimeType, data, alt? }` — base64 PNG, JPEG, WebP or GIF, ~700 KB at most. | | `ns:file-ref` | `{ path, line? }` — a file in the workspace folder. Receiving one grants no file access. | | `ns:task` | `{ text, id?, status?, column?, assignee? }` — `status` is `pending`, `active`, `done` or `error`. | | `ns:tasks` | An array of up to 200 `ns:task`. | | `ns:task-patch` | `{ ref, text?, status?, column? }` — change one task; `ref` is its id or exact text. | | `ns:table` | `{ columns: string[], rows: (string, number, boolean or null)[][] }` | | `ns:event` | `{ type, data?, at? }` | | `ns:trigger` | An empty signal: `{}` or `null`. | A **custom type** is named after your package — `test-radar/coverage` — and must carry a `schema` (the [safe subset](https://docs.neurosquad.ai/en/card-sdk/manifest#json-schema), no `pattern`). Another card can declare the same type to interoperate with yours. Any port may also add a `schema` on top of its type; values must match both. ### Sending: `emit` ```ts const delivered = await card.ports.emit('failures', [ { text: 'checkout › pays with a saved card', status: 'error' }, { text: 'auth › logs in with SSO', status: 'error' } ]) if (delivered === 0) card.ui.toast('Connect me to a todo list to track these') ``` The value is checked against the output's schemas, then delivered to **every downstream peer** that has a compatible input. On each peer the app picks the input: the one marked `default`, else one of exactly the same type, else the first compatible one (request inputs are never picked by `emit`). The value is converted if the types differ (below) and checked against that input's schemas. You get the number of peers that received it. To aim at one peer, and optionally one input: ```ts await card.ports.send(noteId, 'summary', '## Nightly run\n\nAll green.', { input: 'replace' }) ``` ### Receiving ```ts card.ports.onMessage((text, message) => { render(`${message.fromKind} card ${message.from} sent ${message.type} on ${message.output}`, text) }, { input: 'notes' }) ``` `message` is `{ from, fromKind, output, input, type, sourceType, data, at }` — `type` is **your** input's type (after conversion), `sourceType` the sender's declared output type before conversion (absent on older app versions). Leave out `input` to receive on all inputs. Messages that arrive before you subscribe are kept (up to 100) and delivered to your first listener. ### Conversion between types An output reaches an input of a different type only where there is a conversion: | Input type | Accepts outputs of type | How | | --- | --- | --- | | same type | same type | unchanged | | `ns:any` | anything | unchanged | | `ns:text` | `markdown`, `url` | unchanged | | | `number`, `boolean` | `String(value)` | | | `json` | pretty JSON | | `ns:markdown` | `text`, `url` | unchanged | | | `number` | `String(value)` | | | `json` | a fenced `json` code block | | | `table` | a Markdown table | | | `tasks` | a checklist (`- [x] done`, `- [ ] open`) | | `ns:tasks` | `task` | wrapped in an array | | | `text`, `markdown` | one task per non-empty line (list markers and checkboxes stripped) | | `ns:json` | `table`, `tasks`, `task`, `event`, `file-ref`, `task-patch` | unchanged | | `ns:trigger` | `event`, `text`, `number`, `boolean`, `json` | becomes `{}` — "something happened" | Custom types only match the same custom type (or `ns:any`). The helpers `portsCompatible`, `portCoercion`, `coercePortValue` and `pickInputFor` are exported by the SDK if you want to reason about it yourself. ### Requests: ask and answer An input with `"mode": "request"` answers questions. Declare the reply's type in `response`: ```json { "id": "lookup", "label": "Look up", "type": "ns:text", "mode": "request", "response": { "type": "ns:json" } } ``` ```ts // The answering card: card.ports.onRequest('lookup', async (query, request) => { const hits = await search(query, request.signal) // request.signal aborts at the deadline return { query, hits } // checked against response.type }) // The asking card (connected to it by an arrow, either direction): const answer = await card.ports.request<{ hits: string[] }>(peerId, 'lookup', 'flaky tests', { timeoutMs: 10_000 }) render(answer.hits) declare function search(q: string, signal: AbortSignal): Promise declare const peerId: string ``` Throwing in the handler sends an error back; the asker's promise rejects. Requests that arrive before you register the handler wait until shortly before their deadline, then get "no handler". Default timeout 30 s, max 120 s (`TIMEOUT`). A request to a suspended card wakes it (up to 10 s), or fails with `UNAVAILABLE`. ### Retained values Mark an output `"retain": true` and the app keeps its last value (≤ 256 KB): - a peer connected **later** receives it once, right away; - any connected peer can read it at any time, whichever way the arrow points: ```ts const last = await card.ports.read<{ text: string }[]>(todoId, 'items') if (last) render(`${last.data.length} items, as of ${new Date(last.at).toLocaleTimeString()}`) declare const todoId: string ``` Retained values are how a card catches up after being suspended — stream messages sent while it was unloaded are not queued. ### Discovering peers A card can find out what the cards it is connected to output and accept — including the built-in ones — and adapt: ```ts import type { PeerInfo } from '@neurosquad/card-sdk' function describePeer(peer: PeerInfo): string { const ins = peer.inputs.map((p) => `${p.id}:${p.type}`).join(', ') || 'none' const outs = peer.outputs.map((p) => `${p.id}:${p.type}`).join(', ') || 'none' return `${peer.name} (${peer.kind}, ${peer.direction}) — in: ${ins}; out: ${outs}` } card.ports.peers.forEach((peer) => render(describePeer(peer))) card.ports.onPeersChanged((peers) => render(peers.map(describePeer))) // Is there a checklist downstream that takes tasks? const taskSink = card.ports.peers.find( (p) => p.direction !== 'upstream' && p.inputs.some((i) => i.type === 'ns:tasks') ) render(taskSink?.name ?? 'no task list connected') ``` `PeerInfo` is `{ cardId, kind, name, type?, direction, inputs, outputs }`. `kind` is `custom`, `note`, `todo`, `kanban`, `sticky`, `agent`, `terminal` or `other` (a card without ports, such as a browser). `type` is the harness for agents and terminals, the package name for custom cards. Each port is a `PortInfo`: `{ id, label, description?, type, schema?, mode, response?, retain, default, permission? }` — `permission` is set on built-in ports and names what **your** card needs to use it. Your own ports: `card.ports.inputs`, `card.ports.outputs`, or `card.ports.describe()`. Three helpers cover what most cards need before sending: ```ts import { hasDownstreamPeer, permissionForPeer, requestPermissions } from '@neurosquad/card-sdk' async function sendSummary(text: string): Promise { if (!hasDownstreamPeer(card.ports.peers)) { card.ui.toast('Draw an arrow from this card to a note') return } // Which permission does sending Markdown to each peer need? (cards.connected for a note) const needed = card.ports.peers .map((peer) => permissionForPeer(peer, { outputType: 'ns:markdown' })) .filter((id) => id !== null) // Asks only for what is missing; never throws — resolves with what is usable now. const usable = await requestPermissions(card, ...needed) if (usable.length === needed.length) await card.ports.emit('summary', text) } ``` ### Built-in cards The app's own cards take part through adapters. Using one needs the permission in the last column — on **your** card. | Card | Inputs | Outputs | Needs | | --- | --- | --- | --- | | Note | `append` (`ns:markdown`, default): adds a paragraph at the end · `replace` (`ns:markdown`): replaces the whole note | `text` (`ns:markdown`, retained): the note, on every change | `cards.connected` | | Todo list | `add` (`ns:tasks`, default): adds items · `update` (`ns:task-patch`): changes one item's text or status | `items` (`ns:tasks`, retained): all items, on every change | `cards.connected` | | Task board | `add` (`ns:tasks`, default): adds unassigned tasks · `update` (`ns:task-patch`): moves or edits one task | `tasks` (`ns:tasks`, retained): all tasks with their columns | `cards.connected` | | Sticky | `title` (`ns:text`, default): sets the title | `title` (`ns:text`, retained) | `cards.connected` | | AI agent | `prompt` (`ns:text`, default): sends a prompt — exactly like [`agents.prompt`](https://docs.neurosquad.ai/en/card-sdk/api/agents#prompting) with its defaults | `status` (`ns:event`, retained): `{ type: "status", data: { status } }` | `agents.prompt` / `agents.read` | | | | `reply` (`ns:markdown`, retained): the final message when a turn ends — Claude Code and Hermes Agent | `agents.output` | | Terminal | `command` (`ns:text`, default): runs one command | `exit` (`ns:event`): `{ type: "exit", data: { command, exitCode } }` after each command | `terminals.write` / `agents.output` | So with an arrow from your card to a note, `card.ports.emit('summary', '# Done')` appends a paragraph to it; with an arrow from a todo list to your card, your `ns:tasks` input gets every change of the list. ### Limits A value ≤ 1 MB (a retained value ≤ 256 KB); at most 20 messages a second per output. A value that fails a schema is refused with `INVALID_PARAMS` and the exact path — the app never delivers something that does not match what the receiver declared. > Ports need no permission between two custom cards: the user drawing the arrow is the consent. Data > flows only over arrows, only from declared outputs to declared inputs, and only in the arrow's > direction. --- ## Tools for agents (MCP) > Declare a tool in the manifest, implement it in the card, and let connected agents call it through NeuroSquad's MCP server — results, images, errors, progress, cancellation and timeouts. Source: https://docs.neurosquad.ai/en/card-sdk/api/tools A card can give agents new abilities. Declare a tool in the manifest, implement it in the card, and every agent connected to the card by an arrow sees it in its tool list — through the MCP server the app already runs for its agents (Claude Code, Codex, Qwen Code). No permission is needed: the arrow the user draws is the consent. ### Declare ```json "tools": [ { "name": "run_tests", "title": "Run the tests", "description": "Runs the project's tests in the connected terminal and returns the failing tests with their messages, or 'All tests passed'.", "inputSchema": { "type": "object", "properties": { "filter": { "type": "string", "maxLength": 200, "description": "Only tests whose name contains this" } } }, "timeoutMs": 120000 } ] ``` The agent sees it as **`_`** — `test_radar_run_tests` for a card named `test-radar` — with your `inputSchema` plus an optional `card` argument the app adds (an id or a name, to pick one card when several copies are connected). The description reaches the model prefixed with `[Custom card "" by , community code]`. If two packages would produce the same name, the one installed first keeps it and the later one gets `_2`, `_3`. Names the app refuses at install: an exposed name equal to one of NeuroSquad's own tools (`canvas_spawn_card`, `terminal_send_keys`, `browser_navigate`…), any name containing `__` (reserved for MCP servers the user installs), and a card `name` that is a built-in family such as `telegram`, `squad`, `ports` or `mcp` (see [reserved names](https://docs.neurosquad.ai/en/card-sdk/manifest#identity)). An update that adds a tool or rewords a tool's description asks the user again. Write the description for a model: what the tool does, when to use it, and what it returns. Keep arguments few and constrained (`enum`, `maxLength`, `minimum`…); the app validates them before your card sees them. ### Implement ```ts import { toolError } from '@neurosquad/card-sdk' card.tools.handle<{ filter?: string }>('run_tests', async ({ filter }, call) => { call.progress('running the tests…') // shown on the arrow const terminal = (await card.agents.list()).find((a) => a.kind === 'shell' && a.connected) if (!terminal) return toolError('Connect a terminal card to the Test radar card first.') const result = await card.terminals.run(terminal.id, `npm test -- ${filter ?? ''}`, { timeoutMs: 110_000 }) if (call.signal.aborted) return // the agent gave up; nothing is sent return result.exitCode === 0 ? 'All tests passed' : result.output }) ``` The handler gets the validated arguments and a `call`: | `call.` | What | | --- | --- | | `callId` | The call's id. | | `tool` | The tool name as in your manifest. | | `agent` | `{ id, name }` of the calling agent. | | `deadline` | Epoch ms after which the app has given up. | | `signal` | An `AbortSignal`, aborted on cancellation or at the deadline. | | `progress(message)` | A short line (≤ 200) shown on the arrow while you work; throttled to 4 a second. | **What you return** becomes the tool result: | Return | The agent gets | | --- | --- | | a string | that text | | `undefined` | `OK` | | any other JSON value | pretty-printed JSON text | | `toolText(text)` | text (same as a string) | | `toolImage(base64, 'image/png', caption?)` | an image, and the caption as text | | `toolError(message)` | a failed result (`isError: true`) the model can read and react to | | a `ToolResultPayload` | exactly that: `{ content: [{ type: 'text', text } or { type: 'image', data, mimeType }], isError? }`, 1–16 parts | **Throwing** also returns an error to the agent, with the error's message (and writes a warning to your card log). Results are ≤ 1 MB. ### Timing - Default timeout 30 s, or the tool's `timeoutMs` (up to 120 s). At the deadline, the app tells the agent the call timed out and sends your card `tools.cancel` — `call.signal` aborts, and whatever you return afterwards is dropped. - Calls that arrive before your handler is registered (say, while the card is still loading its data) wait for `handle()` until their deadline. - A call to a card whose page is suspended wakes it (up to 10 s); if its workspace is not open the agent is told to open the workspace that has the card. - Every call runs on the arrow: its label shows the tool and your progress lines, and it is kept in the [arrow log](https://docs.neurosquad.ai/en/canvas/arrows#arrow-log). ### Turning a tool on and off ```ts await card.tools.setEnabled('run_tests', false) // hidden from agents (e.g. until the user signs in) await card.tools.setEnabled('run_tests', true) ``` This applies to every copy of your card. ### With React ```tsx import { useTool } from '@neurosquad/card-sdk/react' export function Scratchpad({ text }: { text: string }) { useTool('read_scratchpad', () => text || '(empty)') // the latest `text` is always used return
{text}
} ``` > Tool results go straight into an agent's context. Treat anything you return that came from the > web, a file or a user as untrusted: say where it came from, keep it short, and never let a tool > that the agent can call silently do something destructive — ask the user with `card.ui.confirm` > first. --- ## Network > card.net.fetch — HTTP through NeuroSquad's proxy to the hosts a card declared, JSON, binary and streamed responses, secrets in headers, redirects and limits. Source: https://docs.neurosquad.ai/en/card-sdk/api/network A card's page cannot reach the network at all — its sandbox blocks every request, image and font from outside the package. `card.net.fetch` goes through a proxy in the app instead, which lets through only what the user granted: - [`network`](https://docs.neurosquad.ai/en/card-sdk/permissions#network) with `hosts`: `https` requests to those hosts; - [`network.local`](https://docs.neurosquad.ai/en/card-sdk/permissions#network-local): `http` or `https` to `localhost`, `127.0.0.1` and `::1` — except NeuroSquad's own local servers (its MCP server, remote access, developer link, the browser cards' Chrome debugging ports), which are unreachable. ### Fetch ```ts const res = await card.net.fetch('https://api.github.com/repos/acme/app/issues?state=open', { headers: { accept: 'application/vnd.github+json' }, responseType: 'json' }) if (!res.ok) throw new Error(`GitHub said ${res.status} ${res.statusText}`) const issues = await res.json<{ number: number; title: string }[]>() render(issues.map((i) => `#${i.number} ${i.title}`)) ``` It reads like `fetch`, with a few differences: | Option | Meaning | | --- | --- | | `method` | `GET` (default), `HEAD`, `POST`, `PUT`, `PATCH`, `DELETE`. A body without a method means `POST`. | | `headers` | An object or `[name, value]` pairs. May contain [`{{secret:}}`](#secrets). | | `body` | A string (sent as is), bytes (`Uint8Array`, `ArrayBuffer`), or any other JSON value (serialized, with `content-type: application/json` unless you set one). ≤ 5 MB. | | `responseType` | `text` (default), `json` (parsed by the app), `base64` (binary), or `stream`. | | `timeoutMs` | 1 000–120 000, default 30 000. | | `signal` | An `AbortSignal`; aborting cancels the request in the app. | The result is a `CardResponse`: `ok`, `status`, `statusText`, `url` (after redirects), `headers` (`get`, `has`, iterable; names lowercase), `truncated`, and the body methods `text()`, `json()`, `bytes()`, `arrayBuffer()`, `chunks()`, `lines()` — read the body once, like a `Response`. ```ts // POST JSON, read binary. const upload = await card.net.fetch('https://api.example.com/v1/render', { method: 'POST', body: { chart: 'coverage', width: 640 }, responseType: 'base64' }) const png = await upload.bytes() render(png.byteLength) ``` **Conditional requests and empty bodies.** Conditional headers such as `If-None-Match` and `If-Modified-Since` are forwarded, and every response header except `set-cookie` comes back (so `etag` and rate-limit headers are there). An empty body — a `304 Not Modified` or `204 No Content` — with `responseType: 'json'` gives `null` from `res.json()`. ### Secrets in headers Never put an API key in your card's code or storage. Declare a `secret` [setting](https://docs.neurosquad.ai/en/card-sdk/manifest#settings), let the user type it into the app's settings form, and reference it in a **header value**: ```ts if (!card.settings.hasSecret('apiKey')) { await card.settings.open() } else { const res = await card.net.fetch('https://api.example.com/v1/me', { headers: { authorization: 'Bearer {{secret:apiKey}}' }, responseType: 'json' }) render(await res.json()) } ``` The app replaces `{{secret:apiKey}}` with the stored secret (this card's, then the package-scope one) on its way out — only for requests to granted **internet** hosts, never to this computer (`network.local`). Your card never sees the value. Placeholders work only in header values — not in the URL or the body, which end up in server logs — and the secret headers are **dropped** if a redirect leads to another host. A placeholder for a secret the user has not set fails with `INVALID_PARAMS`. ### Streaming For server-sent events, NDJSON or long downloads, ask for a stream. The promise resolves as soon as the headers arrive; the body comes in chunks (≤ 64 KB each): ```ts const controller = new AbortController() const stream = await card.net.fetch('https://api.example.com/v1/events', { headers: { accept: 'text/event-stream' }, responseType: 'stream', signal: controller.signal }) for await (const line of stream.lines()) { if (line.startsWith('data: ')) render(JSON.parse(line.slice(6))) } // controller.abort() ends it early. ``` `chunks()` gives strings for text chunks and `Uint8Array` for binary ones; `lines()` splits on line breaks; `for await (const chunk of response)` works too. A failed stream throws `NETWORK_ERROR`. At most 4 streams open at once; a stream is closed after 5 minutes without data or after 256 MB. WebSockets are not supported in version 1. ### What the proxy enforces 1. **Scheme.** `https` only, except `http` to this computer with `network.local`. No user name or password in the URL; the `#fragment` is not sent. 2. **Host.** Exactly your declared patterns (`api.example.com`, `*.example.com`, `host.example.com:8443`). Anything else fails with `HOST_NOT_ALLOWED`. 3. **Address.** The app resolves the name itself; for a public host grant, every address must be public — private networks, loopback, link-local and cloud metadata addresses are refused, and the request goes to the address that was checked (no DNS rebinding). 4. **Headers.** You cannot set `host`, `cookie`, `origin`, `referer`, `user-agent`, `content-length`, `connection`, `proxy-*`, `sec-*`, `x-forwarded-*` and similar. The app sends `User-Agent: NeuroSquad-Card/ ()`. No cookies are ever stored or sent, and `set-cookie` is never returned to you. 5. **Redirects.** Followed by the app, at most 5, and every hop is checked again by rules 1–4. 6. **Limits.** Request body ≤ 5 MB; response ≤ 10 MB (a longer text or base64 body comes back cut, with `truncated: true`; a longer JSON body fails with `TOO_LARGE`); 6 requests at once; 120 a minute; timeout up to 120 s — and the timeout covers reading the whole body, not just the headers. Errors: `HOST_NOT_ALLOWED` (host or address not granted), `NETWORK_ERROR` (DNS, connection, TLS), `TIMEOUT`, `TOO_LARGE`, `RATE_LIMITED`, `PERMISSION_DENIED` (no network permission at all). An HTTP error status is **not** an exception — check `res.ok`. > The install dialog tells users that anything your card can see may be sent to the hosts you list. > Keep the list short and specific: a wildcard or a generic host (a paste bin, a URL shortener) > makes a careful user decline. --- ## Files, clipboard & usage > Reading, writing, listing and watching files in the workspace folder; copying to the clipboard; the workspace's token usage and costs. Source: https://docs.neurosquad.ai/en/card-sdk/api/files ### Files in the workspace folder Needs [`fs.read`](https://docs.neurosquad.ai/en/card-sdk/permissions#fs-read) to read and [`fs.write`](https://docs.neurosquad.ai/en/card-sdk/permissions#fs-write) to change. Every path is **relative to the workspace folder** — the project folder the user chose for the workspace — with `/` or `\` separators; `''` or `'.'` is the folder itself. ```ts // Read const pkg = JSON.parse(await card.fs.readText('package.json')) as { name: string } const logo = await card.fs.readBytes('public/logo.png') const info = await card.fs.stat('src/index.ts') // { path, type, size, mtimeMs } const { entries, truncated } = await card.fs.list('src', { recursive: true, maxEntries: 2000 }) render(pkg.name, logo.byteLength, info.size, entries.length, truncated) // Write (atomically: a temporary file, then a rename) await card.fs.writeText('reports/latest.md', '# Report\n', { createDirs: true }) await card.fs.mkdir('reports/archive') await card.fs.trash('reports/old.md') // to the OS trash; there is no hard delete // Write only if nobody changed it since you read it const before = await card.fs.stat('TODO.md') await card.fs.writeText('TODO.md', '- [ ] ship it\n', { ifMtimeMs: before.mtimeMs }) ``` | Method | Result | | --- | --- | | `stat(path)` | `{ path, type: 'file' or 'directory', size, mtimeMs }` | | `list(path?, { recursive?, maxEntries? })` | `{ entries: { path, type, size? }[], truncated }` — ≤ 5 000 entries; recursive listing skips `.git` and `node_modules` unless you list inside them | | `readText(path, { maxBytes? })` | UTF-8 text | | `readBytes(path, { maxBytes? })` | `Uint8Array` | | `read(path, { encoding?, maxBytes? })` | `{ data, encoding, size, truncated }` — the raw result | | `writeText(path, text, { createDirs?, ifMtimeMs? })` | the new `FsStat` | | `writeBytes(path, bytes, { createDirs?, ifMtimeMs? })` | the new `FsStat` | | `mkdir(path)` | `FsStat` | | `trash(path)` | moves a file or folder to the OS trash (60 a minute) | | `watch(path, handler, { recursive? })` | resolves with a function that stops watching | Reads and writes are up to 10 MB each. **Watching:** ```ts const stop = await card.fs.watch('reports', ({ path, type }) => { render(`${path} ${type === 'rename' ? 'was added or removed' : 'changed'}`) }, { recursive: true }) // later await stop() ``` Changes are debounced by 100 ms; at most 20 watchers per card; watchers stop when the card's page is unloaded (watch again after `launch === 'resumed'`). **The fence.** Absolute paths and any `..` are refused outright. After that, the app resolves the real path of the target (or, for a new file, of its nearest existing folder) and refuses it unless it is inside the workspace folder — so a symbolic link or junction that points outside does not help. All of these fail with `FS_DENIED`; other file system problems (not found, not a folder…) with `FS_ERROR`, and a failed `ifMtimeMs` check with `FS_ERROR` and `data.conflict`. **No file access at all** — every `fs.*` call fails with `FS_DENIED` — when the workspace folder is the user's home folder, the root of a drive, or contains NeuroSquad's own data folder. #### Protected paths Writes, `mkdir` and `trash` are refused (`FS_DENIED`) for these, at any depth, checked on the path you give and on the real path behind any link — they would let a card run code through git, the user's agents or their tools: - anything inside a folder named `.git` (including a submodule's or worktree's `.git` file), `.gitmodules`, `.gitattributes`; - the folders `.claude`, `.codex`, `.cursor`, `.gemini`, `.qwen`, `.opencode`, `.kilocode`, `.windsurf`, `.continue`, `.vscode`, `.idea`, `.husky`, `.devcontainer` and `.github/workflows`; - the files `.mcp.json`, `CLAUDE.md`, `CLAUDE.local.md`, `AGENTS.md`, `GEMINI.md`, `QWEN.md`, `.cursorrules`, `.windsurfrules`, `opencode.json`, `opencode.jsonc`, `.envrc`, `.npmrc`, `.yarnrc`, `.yarnrc.yml`, `.pnpmfile.cjs`. Reading them is allowed with `fs.read`. > There is no file picker in version 1: a card works with the workspace folder only. To point a card > at a file, let the user type the path in a setting, or receive an `ns:file-ref` over a port. ### Clipboard Needs [`clipboard.write`](https://docs.neurosquad.ai/en/card-sdk/permissions#clipboard-write) — a good candidate for an optional permission. ```ts await card.copyText('npm test -- --grep checkout') ``` At most once a second, ≤ 1 MB. The browser's own `navigator.clipboard` does not work in a card, and reading the clipboard is not possible at all. ### Token usage and costs Needs [`usage.read`](https://docs.neurosquad.ai/en/card-sdk/permissions#usage-read). ```ts const summary = await card.usage('7d') // 'today' (default), '7d' or '30d' const dollars = (summary.totalCostMicroUsd / 1_000_000).toFixed(2) render(`$${dollars}${summary.partial ? ' + unpriced models' : ''}`) for (const row of summary.rows) { render(row.name, row.harness, row.inputTokens, row.outputTokens, row.costMicroUsd ?? 'no price') } ``` The same numbers as the app's [Usage](https://docs.neurosquad.ai/en/usage) page, for the card's workspace: `period`, `from` and `to` (local days, end exclusive), and per agent `inputTokens`, `outputTokens`, `cacheReadTokens`, `cacheWriteTokens` and `costMicroUsd`. Money is in **whole micro-dollars** (1 000 000 = $1). A model without a known price has `costMicroUsd: null` — never `0` — is left out of `totalCostMicroUsd`, and sets `partial: true`. --- ## Errors & limits > CardSdkError and every error code, what causes each and what to do, plus every limit of the card protocol in one table. Source: https://docs.neurosquad.ai/en/card-sdk/api/errors ### `CardSdkError` Every refusal — from the app, or from the SDK's own checks before a request leaves your card — is a `CardSdkError`: ```ts import { CardSdkError, isCardSdkError } from '@neurosquad/card-sdk' async function saveReport(text: string): Promise { try { await card.fs.writeText('reports/latest.md', text, { createDirs: true }) } catch (error) { if (isCardSdkError(error, 'PERMISSION_DENIED')) { card.ui.toast(`This needs the ${error.permission} permission`) } else if (isCardSdkError(error, 'RATE_LIMITED')) { await new Promise((resolve) => setTimeout(resolve, error.retryAfterMs ?? 1000)) return saveReport(text) } else if (error instanceof CardSdkError) { card.log.error(error.code, error.method, error.hostMessage, error.data) } else { throw error } } } ``` | Property | What | | --- | --- | | `code` | One of the codes below. | | `message` | `method: host message [CODE] — hint`, ready for the log. | | `hostMessage` | The app's message alone (English, for developers — show your own text to users). | | `method` | The method that failed, when it came from a call. | | `data` | Details: schema issues, `{ permission }`, `{ retryAfterMs }`, `{ conflict }`… | | `hint` | A one-line suggestion, for the codes that have one. | | `permission` | For `PERMISSION_DENIED`: the missing permission. | | `retryAfterMs` | For `RATE_LIMITED`: how long to wait. | | `issues` | For `INVALID_PARAMS` / `BAD_REQUEST`: `{ path, keyword, message }[]` — where the params did not match. | `isCardSdkError(error, code?)` is a type guard, optionally for one code. ### Error codes | Code | Means | Usually | | --- | --- | --- | | `BAD_REQUEST` | The message was malformed or its params are not plain JSON. | A `Date`, `Map` or class instance in params — send plain data. | | `INVALID_PARAMS` | Params do not match the method's schema. | See `error.issues` for the exact path. Also a port value that fails a schema, or a `{{secret:…}}` that is not set. | | `METHOD_NOT_FOUND` | The app does not know this method. | An older app — check with `card.host.supports()`. | | `PERMISSION_DENIED` | The package lacks the permission. | Declare it in the manifest, or ask with `card.permissions.request()` if optional. | | `NOT_CONNECTED` | The target card or agent is not connected to yours by an arrow. | Ask the user to draw one. | | `NOT_FOUND` | No such card, agent, key, file or port. | | | `QUOTA_EXCEEDED` | A quota is used up: storage bytes or keys, spawned cards, file watchers, an agent's full prompt queue. | Delete old data, stop old watchers, wait. | | `RATE_LIMITED` | Too many calls. `data.retryAfterMs` says how long to wait. | Batch, debounce, or back off. (Title, status, badge, overview and attention never reject for this — the SDK folds and retries them.) | | `TOO_LARGE` | A message, value or response over its limit. | See [Limits](#limits). | | `TIMEOUT` | No answer in time (a port request, a command, a fetch). | | | `BUDGET_PAUSED` | The workspace is over its budget; programmatic prompts are refused. | The user raises the limit in the [Budget](https://docs.neurosquad.ai/en/cards/budget) card. | | `BUSY` | The agent is mid-turn and you asked `whenBusy: 'fail'`. | | | `HOST_NOT_ALLOWED` | `net.fetch` to a host outside the grant, or one that resolves to a blocked address. | Add the host to the `network` permission. | | `NETWORK_ERROR` | DNS, connection, TLS or stream failure. | | | `FS_DENIED` | A path outside the workspace folder, inside `.git/`, or through a link that leaves it. | Use a relative path. | | `FS_ERROR` | Any other file problem; `data.conflict` when `ifMtimeMs` did not match. | | | `NOT_VISIBLE` | Needs the card on screen: dialogs, links, focus, permission requests, prompts to an agent in dangerous mode. | Try again when `card.visibility === 'visible'`. | | `USER_CANCELLED` | The user said no (a confirm, a prompt to a dangerous-mode agent), or a call was cancelled. | | | `UNAVAILABLE` | The target is not running, the workspace is not open, the card is suspended, or the connection closed. | | | `PROTOCOL_MISMATCH` | The card was built for a newer protocol than the app speaks. | The user updates NeuroSquad. | | `NOT_READY` | A call was made before the handshake finished. | Wait for `connect()`. | | `INTERNAL` | A bug in the app. | Report it with the card log. | ### Limits All limits are in `card.limits` (the `LIMITS` constant of the SDK). The SDK checks the cheap ones before sending; the app enforces all of them. | Area | Limit | | --- | --- | | **Messages** | ≤ 1 MB each (`fs.write` and `net.fetch` requests, and `fs.read`, `fs.list`, `net.fetch` responses: ≤ 12 MB); ≤ 64 calls in flight (the SDK queues beyond that); 200 calls/s, bursts of 400; values ≤ 64 levels deep and ≤ 200 000 nodes | | **Package** | archive ≤ 50 MB; unpacked ≤ 100 MB; ≤ 5 000 files; each ≤ 20 MB; paths ≤ 240 characters and 20 levels; manifest ≤ 256 KB; icon ≤ 128 KB | | **Manifest** | ≤ 40 settings; ≤ 16 inputs and 16 outputs; ≤ 32 tools; ≤ 32 network hosts; schemas ≤ 500 nodes, 16 levels, `enum` ≤ 256 options and 16 KB, `const` ≤ 4 KB | | **Storage** | key ≤ 256 characters; value ≤ 1 MB; ≤ 10 000 keys; 5 MB per card, 20 MB per package | | **Network** | body ≤ 5 MB; response ≤ 10 MB; 6 at once; 120 a minute; ≤ 5 redirects; timeout 30 s (max 120 s), body included; ≤ 4 streams, each closed after 5 min of silence or 256 MB | | **Files** | read and write ≤ 10 MB; list ≤ 5 000 entries; ≤ 20 watchers | | **Agents** | prompt ≤ 20 000 characters, 6 a minute per card (method and port together), ≤ 10 queued per agent; command ≤ 20 000 characters; 30 commands a minute per card (`run` and the terminal port together, timeout ≤ 120 s), `write` 60 a minute; screen ≤ 500 lines; output delivered every 100 ms or 64 KB | | **Tools** | result ≤ 1 MB; timeout 30 s (max 120 s); progress 4 a second | | **Ports** | 20 messages/s per output; retained value ≤ 256 KB; request timeout 30 s (max 120 s) | | **Card UI** | title ≤ 120 (30 a minute); status ≤ 80, status/badge/overview 120 a minute each; overview lines ≤ 160; toast ≤ 280 (one per 2 s); confirm text ≤ 1 000 (10 a minute); ≤ 12 menu items (30 changes a minute); `settings.set` 60 a minute; `tools.setEnabled` 30 a minute; `usage.summary` 6 a minute; attention every 10 s; focus every 5 s; resize every 500 ms; ≤ 4 spawned cards; clipboard once a second, ≤ 1 MB | | **Log** | line ≤ 2 000 characters; 50 lines a second | | **Frames** | ≤ 24 card pages running app-wide; ≤ 8 of them in the background; suspended after 60 s hidden, with 1 s to save; heartbeat every 5 s, "not responding" after 15 s; ready within 10 s of starting | --- ## React bindings > CardProvider and the hooks of @neurosquad/card-sdk/react — context, settings, storage, agents, ports, tools, theme, language and visibility. Source: https://docs.neurosquad.ai/en/card-sdk/react `@neurosquad/card-sdk/react` wraps the card in a provider and exposes its live state as hooks. React 18.2+ or 19 is a peer dependency; the React template sets everything up. ```tsx import { createRoot } from 'react-dom/client' import { CardProvider, useCardContext, useStorage } from '@neurosquad/card-sdk/react' function App() { const { instance, workspace } = useCardContext() const [count, setCount] = useStorage('count', 0) return ( ) } createRoot(document.getElementById('root')!).render( Connecting…

}>
) ``` ### `CardProvider` | Prop | Meaning | | --- | --- | | `card` | A card you connected yourself — for example from the [mock host](https://docs.neurosquad.ai/en/card-sdk/testing). Without it the provider calls `connect()`. | | `connectOptions` | Options for `connect()`. | | `fallback` | Rendered while connecting. | | `errorFallback` | `(error) => ReactNode`, rendered if connecting fails. Default: the error message. | The React template connects first and then passes `card` — so the same entry works inside the app and, with the mock host, in a browser preview. ### Hooks | Hook | Returns | | --- | --- | | `useCard()` | The [`Card`](https://docs.neurosquad.ai/en/card-sdk/api#the-card-object) — for anything without a dedicated hook. | | `useCardContext()` | The live [`HostContext`](https://docs.neurosquad.ai/en/card-sdk/api#context); re-renders on any change. | | `useSettings()` | `[settings, setSettings]` — `settings.values`, `settings.secrets`; the setter changes non-secret values. | | `useStorage(key, initial, { scope? })` | `[value, setValue, { loading, error }]` — like `useState`, persisted. The setter updates at once and writes in the background; accepts a function. `scope: 'package'` follows writes from other copies of the card. | | `useAgents()` | `{ agents, loading, error, refresh }` — kept current from status and change events. Needs `agents.read`. | | `useAgentStatus(agentId)` | One agent's status, or `undefined`. | | `usePort(input?)` | `{ data, message }` — the last value that arrived on an input (or any input). | | `useEmit(output)` | A stable `(data) => Promise` that emits on an output. | | `usePortRequest(input, handler)` | Answers a request input while mounted. | | `usePeers()` | Connected cards and their ports, live. | | `useTool(name, handler)` | Implements a manifest tool while mounted; always calls the latest handler. | | `useCardEvent(event, handler)` | Any event while mounted; always calls the latest handler. | | `useTheme()` | The `ThemeSnapshot`, live (the CSS variables are applied already). | | `useLanguage()` | `{ language, locale }`, live. | | `useTranslator(catalog)` | A [translator](https://docs.neurosquad.ai/en/card-sdk/api/environment#i18n) that re-renders on a language switch. Define the catalog outside the component. | | `useVisibility()` | `visible`, `offscreen`, `overview` or `hidden`. | | `usePaused()` | `true` when nobody can see the card's body — pause animations and polling. | | `useExpanded()` | Whether the card is expanded. | ### A fuller example ```tsx import type { Catalog } from '@neurosquad/card-sdk' import { useAgents, useCard, useEmit, usePaused, usePort, useTool, useTranslator } from '@neurosquad/card-sdk/react' import { useEffect } from 'react' const catalog: Catalog = { en: { waiting_one: '{{count}} agent waits for you', waiting_other: '{{count}} agents wait for you' }, ru: { waiting_one: '{{count}} агент ждёт вас', waiting_few: '{{count}} агента ждут вас', waiting_many: '{{count}} агентов ждут вас', waiting_other: '{{count}} агента ждут вас' }, zh: { waiting_other: '{{count}} 个智能体在等你' } } export function Waiting() { const card = useCard() const t = useTranslator(catalog) const paused = usePaused() const { agents } = useAgents() const waiting = agents.filter((a) => a.status === 'needs-input') const { data: note } = usePort('notes') const emit = useEmit('digest') // Keep the overview tile and attention in step with the data. useEffect(() => { void card.setOverview({ primary: t('waiting', { count: waiting.length }), icon: 'bell' }) void card.attention(waiting.length > 0 ? 'needs-input' : 'none').catch(() => undefined) }, [card, t, waiting.length]) useTool('list_waiting', () => waiting.map((a) => a.name)) return (

{t('waiting', { count: waiting.length })}

{note ?
{note}
: null}
) } ``` > Hooks that call the app (`useAgents`, `useStorage`) report failures in their `error` field instead > of throwing — a missing permission shows up there as a `CardSdkError` with `PERMISSION_DENIED`. ### Using a local SDK checkout If your card depends on the SDK through a `file:` link, npm creates a symlink and Vite may load a second copy of React next to the SDK — hooks then fail with "Invalid hook call". The React template's `vite.config.ts` already has `resolve: { dedupe: ['react', 'react-dom'] }`; in your own setup, add it, or set `install-links=true` in the card's `.npmrc`. --- ## UI kit & styling > Style a card any way you like, or look native with the optional ui.css kit on the app's live theme — classes, variables and the sandbox rules for styles, fonts and images. Source: https://docs.neurosquad.ai/en/card-sdk/styling Inside its box, a card is an ordinary web page: any framework, any CSS, canvas, WebGL, WebAssembly. Two ways to style it: - **Native look** — the optional kit `ui.css`: a small dark set of buttons, fields, lists and badges on the app's live theme. Cards built with it look like part of NeuroSquad and follow its theme. - **Your own design** — ignore the kit. The theme variables are still there if you want to borrow a colour. ### The UI kit ```html ``` ```ts import '@neurosquad/card-sdk/ui.css' // with a bundler (React template) ``` Put `class="ns-kit"` on `` for the base typography, background and scrollbars, then use the classes: ```html

Test radar

3 failed
  • checkout › pays
  • auth › logs in
``` | Group | Classes | | --- | --- | | Layout | `ns-kit`, `ns-stack` (vertical), `ns-row` (horizontal), `ns-spread` (space-between), `ns-grow`, `ns-scroll`, `ns-pad`, `ns-divider` | | Surfaces | `ns-surface`, `ns-surface--inset`, `ns-callout`, `ns-callout--success`, `ns-callout--danger`, `ns-empty` | | Text | `ns-title`, `ns-subtitle`, `ns-muted`, `ns-small`, `ns-mono`, `ns-truncate`, `ns-kbd`, `ns-help`, `ns-error` | | Buttons | `ns-btn` + `--primary`, `--secondary`, `--outline`, `--ghost`, `--danger`, `--sm`, `--lg`, `--icon` | | Fields | `ns-field`, `ns-label`, `ns-input`, `ns-textarea`, `ns-select`, `ns-switch` | | Lists | `ns-list`, `ns-list-item` | | Status | `ns-badge` + `--accent`, `--success`, `--warning`, `--danger`; `ns-dot` + the same; `ns-spinner`, `ns-progress` | Outside the app (a browser preview), the kit falls back to the app's dark theme, so the preview looks right too. ### Theme variables `connect()` puts the app's live theme on `` as `--ns-` variables — `--ns-background`, `--ns-surface`, `--ns-foreground`, `--ns-muted`, `--ns-accent`, `--ns-success`, `--ns-warning`, `--ns-danger`, their `-foreground` and `-soft` variants, `--ns-border`, `--ns-focus`, `--ns-field-*`, `--ns-radius`, `--ns-font-sans`, `--ns-font-mono` and more (the full list is on [Theme](https://docs.neurosquad.ai/en/card-sdk/api/environment#theme)). Use them in your own CSS and your card follows the app: ```css :root { color-scheme: dark; } body { margin: 0; background: var(--ns-background, #0b0b0f); color: var(--ns-foreground, #fafafa); font: 13px/1.45 var(--ns-font-sans, system-ui, sans-serif); } .chip { border-radius: calc(var(--ns-radius, 0.5rem) * 2); background: var(--ns-accent-soft); color: var(--ns-accent-soft-foreground); } ``` Give the variables fallbacks (as above) if your page must also render outside the app. To keep your own colours untouched, connect with `connect({ theme: false })`. ### Sandbox rules for pages Your page is served from its own package with a strict content security policy. In practice: - **No inline scripts or `onclick="…"` attributes** — put code in `.js` files. `eval` and `new Function` are blocked too (WebAssembly is allowed). - **No external files.** Scripts, styles, fonts and images must be inside the package; a `` or `` is blocked. `data:` and `blob:` images work. For remote data, use [`card.net.fetch`](https://docs.neurosquad.ai/en/card-sdk/api/network) and turn images into `blob:` URLs. - **Inline styles are fine** (`style="…"` and `