Сделайте карточку.Поставьте её на любой холст.
Карточка — это маленькое веб-приложение, которое живёт на холсте NeuroSquad рядом с агентами. Опубликуйте её на GitHub — и любой поставит её, вставив адрес. Она умеет слушать агентов, давать им инструменты, отправлять им промпты и обмениваться типизированными данными с другими карточками по стрелкам — ровно с теми разрешениями, которые дал пользователь.
Обычный HTML и JS или React с Vite. У SDK нет зависимостей во время работы, лицензия MIT.
Вставили owner/repo
Карточка работает вместе с агентами
Карточка видит, какие агенты есть на холсте и чем они заняты. Соедините её с агентом стрелкой — и она сможет реагировать на его ходы, дать ему инструмент или выдать следующую задачу.
Реагирует, когда агент закончил
Карточка подписывается на события агентов: смена статуса, начало и конец хода, новый вывод. Здесь радар тестов заново гоняет тесты каждый раз, когда подключённый агент заканчивает ход.
card.agents.onTurn(({ agentId, phase }) => { if (phase === 'end') runTests()})Карточки говорят по стрелкам — типизированными данными
Карточка объявляет свои входы и выходы с типом: текст, Markdown, задачи, таблицы, события — или свой тип со схемой. Проведите стрелку, и значение пойдёт. Приложение проверяет его с обеих сторон и само конвертирует, если встроенная карточка ждёт другой формат.
Включайте и выключайте стрелки, потом прогоните тесты.
Встроенные карточки тоже в деле
Заметка дописывает Markdown, чек-лист добавляет задачи, доска — карточки задач, агент принимает промпт, терминал выполняет команду. Ваша карточка говорит со всеми одинаково.
Типы, а не догадки
Общие типы (ns:text, ns:markdown, ns:tasks, ns:table, ns:event…) или свой your-card/your-type со схемой JSON. Приложение проверяет каждое значение до доставки.
Не только поток, но и запрос
Вход умеет отвечать: ports.request спрашивает подключённую карточку и ждёт ответа. Сохраняемый выход отдаёт последнее значение карточке в момент подключения.
Код сообщества — на коротком поводке
До установки вы видите, кто сделал карточку, откуда она и с какого коммита, и простыми словами — что она сможет делать. После этого приложение следит ровно за этим.
Установить Радар тестов?
Код сообщества, NeuroSquad его не писал и не проверял. Ставьте карточки только от тех, кому доверяете.
Всё внутри карточки принадлежит самой карточке. NeuroSquad никогда не спрашивает там пароли или ключи.
Карточка сможет
Запускать команды в подключённых к ней терминалах
Высокий рискНабирать и выполнять команды в карточках терминалов, соединённых с ней стрелкой, — всё, что могли бы запустить вы сами.
Читать и менять подключённые к ней карточки
СреднийЗаметки, чек-листы, доски задач и стикеры, соединённые с ней стрелкой.
Даёт инструменты агентам, которых вы к ней подключите: run_tests
Обменивается данными по стрелкам: 1 вх., 1 вых.
Заперта в своём фрейме
Каждая карточка работает в изолированном фрейме со своим происхождением. Нет доступа к приложению, к Node, к другим карточкам и к вашим файлам сверх разрешённого.
Не выходит за холст
Никаких всплывающих окон, новых окон, диалогов поверх приложения и загрузок. Карточка рисует только внутри своей рамки и масштабируется вместе с холстом.
Только то, что вы разрешили
Каждый вызов приложение сверяет с разрешением. Необязательные разрешения карточка просит позже, прямо на себе, а любое можно отозвать.
Стрелка — это согласие
Карточка дотягивается до другой карточки, агента или терминала, только если вы провели между ними стрелку, и только с нужным разрешением.
Сеть — через прокси
Только к адресам, которые карточка объявила. Секреты, которые вы ввели, подставляет в запросы приложение; карточка их не видит.
Привязка к коммиту, без автообновлений
Установка привязана к коммиту. Новая версия показывает, что изменилось и какие разрешения добавились, и ждёт вашего клика.
Целая карточка в одном коротком файле
Это готовая карточка. Она гоняет тесты в подключённом терминале, отправляет упавшие по стрелке, даёт агентам инструмент run_tests и перезапускает прогон, когда подключённый агент закончил. Рядом — манифест, где сказано, что ей нужно.
1import { connect } from '@neurosquad/card-sdk'2 3const card = await connect()4 5/** Runs the suite in the terminal this card is wired to and sends out what broke. */6async function runTests(filter = ''): Promise<string[]> {7 const shell = card.ports.peers.find((peer) => peer.kind === 'terminal')8 if (!shell) throw new Error('Draw an arrow from this card to a terminal')9 10 await card.setStatus('Running tests…', { busy: true })11 const { output } = await card.terminals.run(shell.cardId, `npm test -- ${filter}`)12 const failed = output.split('\n').filter((line) => line.includes('✗'))13 14 const tone = failed.length ? 'danger' : 'success'15 await card.setStatus(failed.length ? `${failed.length} failed` : 'Passing', { tone })16 // ns:tasks: a checklist adds them, a note gets a Markdown list17 await card.ports.emit('failures', failed.map((text) => ({ text, status: 'error' })))18 return failed19}20 21// Connected agents see this as test_radar_run_tests over MCP22card.tools.handle<{ filter?: string }>('run_tests', async ({ filter }, call) => {23 call.progress('running…')24 const failed = await runTests(filter)25 return failed.length ? failed.join('\n') : 'All tests passed'26})27 28// A connected agent finished its turn: check its work29card.agents.onTurn(({ agentId, phase }) => {30 const wired = card.ports.peers.some((peer) => peer.cardId === agentId)31 if (phase === 'end' && wired) runTests().catch((error) => card.log.error(error))32})33 34// Anything on the "run" input (a button, a schedule) starts a run35card.ports.onMessage(() => void runTests(), { input: 'run' })Один connect()
Дожидается рукопожатия с приложением и возвращает типизированный клиент: у каждого метода, события и данных есть тип.
Манифест — это договор
Разрешения, порты, инструменты и настройки объявлены заранее — именно их и показывает окно установки.
Тесты без приложения
createMockHost() запускает карточку против хоста в памяти, который делает те же проверки, что и приложение, в том же порядке.
Что умеет клиент
card.setStatus()Заголовок, статус, бейдж, плитка обзора, вниманиеcard.uiВсплывашки, подтверждения и меню карточкиcard.storageХранилище на карточку и на пакетcard.settingsФорма настроек, которую рисует приложение, включая секретыcard.agentsСписок агентов, слежение, чтение экрана, промптыcard.terminalsКоманды в подключённых терминалахcard.portsТипизированные входы и выходы по стрелкамcard.toolsИнструменты для подключённых агентовcard.netЗапросы через прокси приложения, с потокамиcard.fsФайлы в папке воркспейсаcard.lifecycleВидимость, пауза, изменение размераcreateTranslator()Английский, русский и китайский, с живым переключением
Первая карточка — за три команды
Нужны Node.js 18.17 или новее и NeuroSquad с включённым режимом разработчика в «Настройки → Свои карточки».
- 1
Создайте
$npx @neurosquad/card-sdk create my-cardРабочая заготовка: живые статусы агентов, черновик с сохранением, порт и инструмент. Добавьте
--template react, чтобы взять React и Vite. - 2
Запустите вживую
$cd my-card && npx @neurosquad/card-sdk devПодключает папку к приложению после вашего подтверждения, перезагружает карточку на каждое сохранение и показывает её лог.
- 3
Проверьте
$npx @neurosquad/card-sdk validateПрогоняет собственные валидаторы приложения и печатает окно установки, которое увидят ваши пользователи.
Потом поделитесь
Залейте папку на GitHub. Любой поставит карточку, вставив owner/repo в «Настройки → Свои карточки». Обновления никогда не ставятся сами: каждый новый коммит показывается с изменениями разрешений и применяется по клику.
Выглядит так, как вы захотите
Шапка, рамка и меню — от приложения. Всё внутри — ваше: любой HTML, CSS, холст или 3D. Если нужен родной вид, есть необязательный набор стилей, который следует живой теме приложения.
Перед стартом
Сделайте карточку, которой не хватает вашему холсту
Начните с шаблона, запустите вживую в приложении, опубликуйте на GitHub.