Да, я убрал из заголовка «за выходные», потому что проект чутка растянулся. Но идёт весело!
У него и веб-версия теперь есть: https://mini.qyp.ai

Напомню: я давно хотел пощупать Tauri v2, и новомодные фреймворки для построения AI-агентов (ai-sdk / mastra / llamaindex).
Идея простая: десктопное приложение, дешборд на весь экран, справа интерфейс чата. Просим ИИ вывести на дешборд какую-то информацию в духе «сколько новых юзеров за последнюю неделю» — ИИ пишет код виджета, и размещает его на дешборде. Под капотом — runtime компиляция React.js + sql-коннекторы.
Полный open-source, весь код в репозитории: https://github.com/ElKornacio/qyp-mini
Всего будет 5.5 частей:
-
Делаем runtime-компиляцию TSX-компонентов (предыдущая часть) 2.5. Причесываем интерфейс и подключение к БД, сетапим Claude Code (эта часть)
-
Делаем AI-агента и сравниваем AI-фреймворки
-
Учим агента писать код и делать SQL-запросы
-
Собираем всё в кучу и причёсываем
Поехали!
Причесываем рантайм среду
Как вы может помните, наши виджеты умеют делать так:
import { runSql } from '@/lib/utils'; await runSql('select * from users');
Коннект к базе у нас привязан к дешборду. Один и тот же виджет может быть размещён на разных дешбордах, и, соответственно, runSql должен выполняться на разных базах. Соответственно, нам надо чтобы runtime-контекст виджета был привязан к дешборду, чтобы на этапе инициализации рантайма, мы сразу могли пробросить конкретную функцию с привязанной БД.
Завёл под это отдельный класс WidgetRuntime, который инкапсулирует все стадии обработки виджета:
-
Получили исходный код
-
Скомпилировали код, получили
jsBundle,cssBundle -
Подключили текущий контекст (коннект к БД)
-
Собрали компонент (пробросили контекст, выполнили код модуля, вытащили из
exports.defaultкомпонент)

Эта рантайм-обертка собрана с небольшим заделом на будущее — далее, когда код виджетов будет писать ИИ, нам важно сразу же собрать виджет в изолированной среде, и в случае ошибок и багов — автоматически давать фидбек ИИ, чтобы он мог автономно править код.
Изучаем Claude Code, чтобы он сделал нам дешборды
Мне хотелось дешборд со строгой сеткой, в которую и будут встраиваться виджеты. Чтобы можно было их перетягивать, ресайзить, и они подстраивались под размер своего контейнера.

Писать руками не хотелось, затаскивать какой-то сложный внешний layout engine — тоже не хотелось.
Завёл под это дело Claude Code — давно хотел сравнить его с Cursor. По началу шло туго. После того, как я сконвертировал global.mdc (моё always-apply правило) из Cursor в CLAUDE.md, и перетащил свой analyze-and-implement workflow из Supercode в subagent + custom slash команду для Claude Code — стало пободрее. Детально рассказывать про конвертацию workflow из Суперкода в Claude Code мне в этой статье не хочется, думаю, я про это как-нибудь отдельный гайд напишу.
Если вам хочется почитать официальные гайды, то вот:
-
Гайд Supercode по Smart Actions (суперкод работает только в. Cursor, поэтому их я и переделывал под Claude Code)
-
Гайд Claude Code по Subagents
-
Гайд Claude Code по Custom Slash Commands
Здесь мне хочется просто в целом рассказать про то, как Subagents и Custom Slash Commands в Claude Code устроены, и как можно их настроить под подобный проект.
Subagents
Субагенты — это преднастроенные «личности» Claude Code для конкретных задач. У каждого свой системный промпт, отдельное окно контекста и инструменты. Он может автоматом делегировать им часть работы или их можно дёрнуть явно. Они помогают разгрузить контекст основного диалога, и и повысить точность на изолированных тасках. Плюсы:
-
Изоляция контекста: каждый субагент мыслит в собственной песочнице, не засоряя контекст основной ветки рассуждений. Полезно при длинных сессиях, пошаговой отладке, анализе больших кодовых баз.
-
Отдельные роли: отдельный промпт и набор инструментов под ревью, миграции, работу с БД, генерацию тестов, CI и т.д.
-
Субагенты могут быть описаны как в проекте, так и быть глобальными (в папке home), что довольно удобно для переиспользования.
Субагенты описываются Markdown-файлами с фронтматтером (текстовым заголовком файла). Проектные лежат в .claude/agents/…, глобальные в ~/.claude/agents/…
Формат файла:
--- name: code-reviewer description: Use proactively to review changed TS files and enforce our style guide tools: Bash(git diff:*), Bash(npm run lint:*), Bash(npm run test:*) --- You are a principled code reviewer for a TypeScript monorepo. Focus on readability, public API stability, and performance. When violations are found, propose minimal diffs and explain trade-offs.
Поля:
-
name— имя (kebab-case). -
description— когда и зачем вызывать агента; можно явно писать штуки типа «use PROACTIVELY», чтобы основной агент почаще дёргал этого субагента -
tools— можно сузить доступ к конкретным инструментам (иначе унаследует их от основной сессии, включая MCP).
Но вообще удобнее настраивать субагентов через /agents: появится интерактивный менеджер со списком всех доступных инструментов (включая MCP), правами и подсказками.
Как вызвать:
-
Автоматом: Claude сам делегирует задачу, если на основе вашего запроса и description субагента он сочтёт это нужным. Как я писал выше — фразы вроде «use PROACTIVELY» в описании агента повышают шанс автозапуска.
-
Явно: ну, просто скажите: «Use the code-reviewer subagent to check my last commits.» и Claude не устоит.
Из популярных в коммьюнити идей, обычно делают что-то типа такого:
-
code-reviewer — ревью изменений, прогон
tsc --noEmit,eslint --fix, тесты, предложения диффов. -
perf-auditor — фокус на перфомансе, сборка версии проекта со статистикой по скорости, подсказки по бандлу и
@typescript-eslint. -
docs-writer — обновление README/Storybook/докблоков по диффам, генерирует доки в бекграунде, пока основные агенты пишут код
В качестве вдохновения можно посмотреть готовые коллекции, они быстро гуглятся и их много.
Небольшие советы на основе официального гайда:
-
«Короткий input -> длинная работа»: старайтесь выносить всякие «поисковые» и «обзорные» задачи (прогон тестов, анализ артефактов билда) субагентам, чтобы не засорять основной контекст.
-
Описывайте стиль и границы: прямо в системном промпте прописывайте какими вы хотите видеть стиль правок, доступы, формат диффов, критерии завершения, и прочее.
Теперь немного про Custom Slash Commands
Custom Slash Commands — это настраиваемые команды в Claude Code. По сути, это Markdown-шаблоны с фронтматтером, которые можно запускать как /name [args]. По аналогии с субагентами — их можно держать как в проекте, так и глобально. Но команды ещё и поддерживают неймспейсы через подпапки, аргументы, вставку файлов и выполнение ограниченных bash-команд до запуска промпта.
Проектные лежат в .claude/commands/… — отображаются в /help с пометкой (project), а глобальные лежат в ~/.claude/commands/… — и показываются с пометкой (user).
Немного про аргументы: всё то, что вы передали в команду в качестве аргументов через /<command-name> [arguments] будет подставлено внутрь markdown-файла команды, вместо $ARGUMENTS. В целом, если вы юзали в Курсоре smart actions через supercode — принцип точно такой же как там с $prompt / $systemPrompt, концепция та же.
Создать новую команду можно так:
mkdir -p .claude/commands echo "Analyze this code for performance issues and suggest optimizations:" \ > .claude/commands/optimize.md # Теперь доступно: /optimize
Подпапки превращаются в префиксы, к примеру, файл .claude/commands/frontend/component.md создаст команду /frontend:component. Что касается аргументов, то их использование может выглядеть так:
# .claude/commands/fix-issue.md Fix issue #$ARGUMENTS following our coding standards # И вызов через: # /fix-issue 123
Но самый сок в том, что в аргументы можно закидывать содержимое целых файлов через @:
Compare @packages/ui/src/Button.tsx with @packages/ui/src/IconButton.tsx
А ! позволяет выполнить bash-команды до запуска промпта, добавив их вывод в контекст. В фронтматтере явно пропишите разрешённые команды через allowed-tools с префиксом Bash(…), и дальше прям в тексте используйте команды, вот так:
--- allowed-tools: Bash(git status:*), Bash(git diff:*), Bash(npm run build:*) description: Prepare release notes from the latest changes argument-hint: [sinceTag] --- ## Context - Git status: !`git status` - Diff since tag: !`git log --oneline $ARGUMENTS..HEAD` ## Task Generate release notes grouped by package with breaking changes first.
Вновь же, если вы раньше юзали суперкодовские smart actions в Курсоре — то конструкция выше вам явно может напомнить там этот формат:
{ "Load Git Status to Prompt": { "prompt": { "command": "echo \"Prepare release notes: \" && git status" } } }
А ещё, подключённые MCP-серверы могут публиковать собственные промпты как slash-команды для Claude Code (собственно, для этого в MCP и заводили промпты, самое время напомнить, что Anthropic — и есть авторы протокола MCP).
Примеры полезных команд:
1) /build — собрать проект и поправить типовые ошибки
~/.claude/commands/build.md:
--- allowed-tools: Bash(npm ci:*), Bash(npm run build:*), Bash(git add:*), Bash(git commit:*) description: Build the repo and fix errors --- ## Context - Current branch: !`git branch --show-current` - Build output: !`npm run -s build` ## Task If the build fails, identify minimal code changes to fix type/lint errors.
2) /frontend:component — неймспейс для UI, .claude/commands/frontend/component.md:
--- description: Scaffold or refactor React component with tests and stories --- Read @packages/ui/CONTRIBUTING.md and follow patterns. Generate a component skeleton or refactor based on the user's request.
Собираем веб-версию
В общем, попинав Claude Code в течение минут 30, я получил вполне хороший результат, который сам бы писал пару-тройку часов. Он справился раза с 5, но это в целом совершенно нормальный результат для ИИ, да ещё и нового для меня агента, к которому я не привык.
Теперь, когда дешборды были готовы, компоненты рендерились корректно, запросы в Postgres летели, и всё было здорово, мне захотелось упаковать фронт, который я использовал в Tauri, под веб. Исключительно для демки.
К сожалению, секьюрно ходить во многие БД через веб никак не получится: только проксируя запросы через собственный сервер, и, соответственно, все доступы тоже будут проходить через сервер. Мне показалось, что для демо-версии это небольшая проблема: основная ставка у нас на десктоп, а там всё локально.
Дополнительно, я решил поднять свою example-базу, с readonly юзером, и накатить туда каких-нибудь разношерстных данных, чтобы и тестить было веселее, и чтоб ИИ-агенту потом было где развернуться.
Дабы веб-версия работала, нам надо было вытащить все зависимости от Tauri в отдельный слой абстракции. Накидал Claude Code (далее — CC) задачку по созданию такой абстракции, бахнул имплементационный план через Opus, далее внёс изменения в код через Sonnet — завелось с полпинка, и заработало отлично.
Тут же заставил CC сделать мне в src-back простенький Node.js-сервер для проксирования запросов в БД через TypeORM, и подключить к нему фронт. Это уж совсем детская задача, и тут ИИ справился с первой попытки.
Немножко причесываем, подключаем Cloudflare Pages, Wrangler, сетапим самый дешевый сервачок на DigitalOcean, и вуаля, наша веб-версия готова:
Думаю, так следить за прогрессом будет гораздо нагляднее.
Заключение
Спасибо, что читаете! Небольшой выходной проектик чутка разросся, но, думаю, половина пути уже позади.
Впереди самое интересное — делаем интерфейс чата (скучно) и тестируем разные фреймворки для создания ИИ-агентов (весело). Следующая часть как раз будет со сравнением фреймворков, stay tuned!
А ещё, я очень много пишу про стартапы, новости ИИ, разработку с ИИ, и многое другое у себя в телеграм-канале. Даже про этот проект я пишу там обычно на несколько дней раньше Хабра. В общем, там здорово!
ссылка на оригинал статьи https://habr.com/ru/articles/933032/
Добавить комментарий