Skip to Content
Card SDKManifest reference

Manifest reference

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

{ "$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

FieldRequiredRuleMeaning
$schemastringFor your editor. Ignored by the app.
manifestVersionyes1The manifest format.
nameyesa-z, digits and -, starts with a letter, 2–48 charsThe package slug. It prefixes the card’s tool names 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.
displayNameyeslocalized text, ≤ 80The card’s name in menus, the header and the install dialog.
versionyesSemVer (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.
protocolyesintegerThe 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”.
descriptionlocalized text, ≤ 300Shown in the install dialog and the card picker.
author{ "name", "url"? }url must be https://. Shown as self-declared.
licensestring ≤ 100An SPDX id such as MIT.
homepagehttps:// URL
keywords≤ 20 unique strings, ≤ 40 chars each
iconpath to a .png or .webp in the packageSquare, ≤ 128 KB (128×128 or larger looks sharp). Checked by its bytes at install. Without one the card shows a puzzle piece.
minAppVersionSemVerThe lowest NeuroSquad version that can run the card.
entrypath to an .html file, default index.htmlThe 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

"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() is clamped to them too.

Permissions — permissions

A list (≤ 32) of permission ids, or objects that add details:

"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 } ]
KeyMeaning
idOne of the ids on Permissions.
hostsnetwork only, and required there: ≤ 32 host patterns.
reasonLocalized text ≤ 300, shown under the permission in the install dialog. Say why.
optionaltrue = not asked at install; the card asks at runtime with card.permissions.request().

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()); the card reads the values.

"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" } ]
KeyMeaning
keyStarts with a letter; letters, digits, _, -; ≤ 64. Unique.
typestring (one line), text (several lines), number, boolean, select, color (#rrggbb), secret.
label, description, placeholderLocalized text (≤ 80, ≤ 300, ≤ 80).
defaultOf the field’s type. Must be one of the options for select, #rrggbb for color, within min/max for number. Not allowed for secret.
requiredThe form will not save without it.
scopeinstance (default): per card on the canvas. package: shared by every card of this package.
maxLengthstring, text, secret. Defaults: 2 000 for string, 20 000 for text.
min, max, stepnumber.
optionsselect 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:<key>}} placeholder in network request headers.

Ports — ports

Typed data connections over arrows: up to 16 inputs and 16 outputs. Full guide: Ports.

"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 } } } ] }
KeyApplies toMeaning
idbotha-z, digits, -, starts with a letter, ≤ 32. Unique per direction.
label, descriptionbothLocalized text (≤ 80, ≤ 500). Shown to users, peer cards and agents discovering the port.
typebothA well-known ns:* type or a custom <package-name>/<type-name>.
schemabothExtra JSON Schema the value must also match. Required for custom types.
modeinputsstream (default): fire-and-forget messages. request: the sender waits for a reply.
responserequest inputs{ "type", "schema"? } — the reply’s type. Required for mode: "request".
defaultinputsThe preferred input when a peer’s output fits several. At most one.
retainoutputsThe 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.

KeyMeaning
namea-z, digits, _, starts with a letter, ≤ 40. The agent sees <name with - → _>_<tool>, 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.
inputSchemaJSON Schema with "type": "object". The property card is reserved (the app adds it).
readOnlytrue when the tool changes nothing — a hint shown to the agent.
timeoutMs1 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/<name>), $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.