Расширение для Chrome с ИИ — один из самых лёгких путей в vibe coding: расширение состоит из нескольких небольших файлов, его можно тестировать в собственном браузере без всякого сервера, а кодинг-агенты вроде Claude Code или Codex хорошо знают структуру Manifest V3. Сложность не в коде, а в выборе нужной части (content-скрипт, service worker, popup), в просьбе о минимуме разрешений и в том, чтобы никогда не класть API-ключи внутрь расширения. Статья описывает путь, которым я иду от пустой папки до Chrome Web Store.
В качестве примера сделаем небольшое, но настоящее расширение: оно пересказывает статью на текущей странице с помощью AI API. С vibe coding первую версию можно собрать за вечер; версии для публикации нужно ещё несколько правил.
Сначала узнайте части
Чтобы объяснить агенту, что вам нужно, достаточно знать четыре строительных блока расширения Chrome:
manifest.json: Паспорт расширения. Название, версия, какой файл что делает и каких разрешений просит расширение. Новые расширения используют Manifest V3.- Content-скрипт: JavaScript, который работает внутри посещаемой страницы. Он может читать текст страницы, добавлять кнопку, скрывать элемент. Напрямую обратиться к переменным JavaScript самой страницы он не может: он работает в изолированном «мире».
- Service worker (фон): Код, который работает независимо от страниц. Он реагирует на события вроде клика по значку на панели, смены вкладок или будильников и делает сетевые запросы. Важное свойство: Chrome останавливает его в простое, поэтому всё, что лежит в глобальной переменной, может пропасть.
- Popup и страница настроек: Небольшое окно, которое открывается по клику на значок, и отдельная страница для настроек. Обе — обычные HTML-страницы.
Эти части общаются через chrome.runtime.sendMessage и chrome.tabs.sendMessage. Когда написанное агентом «не работает», причина очень часто в том, что код выполняется не в той части, например, document пытаются использовать в service worker.
1. Подготовка и структура проекта
Вам нужны Chrome (или другой браузер на Chromium), Git, редактор кода и кодинг-агент. Для первого расширения инструмент сборки не нужен; хватит чистого JavaScript. Когда проект вырастет, фреймворки для расширений на Vite вроде WXT добавят TypeScript и автоперезагрузку, но для первой версии я бы обошёлся без лишнего слоя. Без него ошибки агента лучше видны.
mkdir page-summarizer && cd page-summarizer
git init
Затем положите в корень проекта короткий файл правил, который агент читает в каждой сессии (CLAUDE.md или AGENTS.md):
# Page Summarizer (Chrome extension)
- Manifest V3, plain JavaScript, no build step.
- Minimal permissions: activeTab, scripting, storage. No <all_urls>.
- No remote code; no eval, no remote <script>.
- No API key in the extension; requests go to our own server.
- Persistent state in chrome.storage, not in service worker globals.
- Ask before adding a permission or a package.
2. Первый промпт
В первом сообщении я прошу агента объяснить, что он собирается сделать и какие файлы создаст, а потом написать код:
Read CLAUDE.md. Build a Manifest V3 Chrome extension:
- Clicking the toolbar icon opens a popup with a "Summarize" button.
- Pressing it grabs the article text from the active tab (use activeTab +
scripting and inject the content script only at that moment).
- The text goes to the service worker, which POSTs it to
https://api.my-server.example/summarize.
- Show the summary in the popup; on error show a readable message.
- Keep the last 10 summaries in chrome.storage.local.
First list the files and what each one does, then create them.
Finish with step-by-step instructions to load and test it.
manifest.json, который выдаст агент, должен выглядеть примерно так:
{
"manifest_version": 3,
"name": "Page Summarizer",
"version": "0.1.0",
"description": "Summarizes the article on the current page in one click.",
"action": { "default_popup": "popup.html" },
"background": { "service_worker": "background.js" },
"permissions": ["activeTab", "scripting", "storage"],
"host_permissions": ["https://api.my-server.example/*"]
}
Здесь я проверяю список разрешений. activeTab даёт временный доступ только к текущей вкладке, когда пользователь нажимает на значок. Агенты часто добавляют "<all_urls>" или "tabs" для удобства; это показывает пользователям пугающее предупреждение и замедляет проверку в магазине.
3. Загрузка, тесты, отладка
Прежде чем идти в магазин, проверьте расширение в собственном браузере:
- Откройте
chrome://extensions. - Включите Developer mode в правом верхнем углу.
- Нажмите Load unpacked и выберите папку проекта.
- Закрепите значок на панели и попробуйте расширение на статье.
После изменения кода нажмите кнопку перезагрузки на карточке расширения в chrome://extensions. Если менялся content-скрипт, перезагрузите и страницу, на которой вы тестируете.
Три места, которые больше всего помогают при отладке:
- Service worker: Ссылка «service worker» на карточке расширения открывает собственные DevTools. Здесь видны сетевые запросы и фоновые ошибки.
- Popup: Когда popup открыт, щёлкните по нему правой кнопкой и выберите Inspect.
- Content-скрипт: Логи появляются в консоли DevTools самой страницы; ваше расширение можно выбрать в выпадающем списке контекстов вверху консоли.
Если на карточке расширения есть кнопка Errors, скопируйте её содержимое как есть и передайте агенту:
I loaded the extension. Pressing "Summarize" in the popup shows this error:
[error text]
The service worker console also shows:
[log]
Explain the cause, fix it, and list what you changed in which file.
Когда вы говорите, где сломалось, на что вы нажимали и что показывает каждая консоль, агент исправляет проблему, а не гадает.
4. Хранилище: выберите правильное место
chrome.storage.local: Данные на этом устройстве, например история пересказов.chrome.storage.sync: Синхронизируется между устройствами через профиль Chrome пользователя. Квота небольшая; используйте только для настроек.chrome.storage.session: Очищается при закрытии браузера; подходит для временного состояния, которое должно пережить перезапуск service worker.
В service worker нет localStorage. Если агент пытается его использовать, по этой причине код падает. И не забудьте разрешение storage в manifest.json.
5. Не держите API-ключи в расширении
Это самая частая ошибка в расширениях, созданных с ИИ. Агент пишет «вставьте сюда ваш ключ OpenAI» и кладёт константу в background.js. Опубликованное расширение — это ZIP-файл; любой может скачать его, распаковать и прочитать ваш ключ. Минификация и обфускация этого не меняют.
Правильная структура — небольшой прокси:
- Расширение обращается к вашему серверу (
https://api.my-server.example/summarize). - Сервер хранит ключ в своём окружении и вызывает настоящий AI API.
- Сервер ограничивает частоту запросов (по пользователю или IP) и отклоняет слишком большие тексты.
Откройте отдельный проект для этого сервера и скажите агенту:
Write a small HTTP service: POST /summarize takes { text } in the body.
Cap the text at 20,000 characters, call the AI API with the key from an
environment variable, return { summary }. Allow CORS only for the
chrome-extension://<EXTENSION_ID> origin. Add a simple rate limit.
Never log the key. Create a .env.example file.
Идентификатор расширения показывается на chrome://extensions, когда вы загружаете его как распакованное; после публикации в магазине он может быть другим. Обновите настройку CORS перед публикацией. Если пользователи приносят свой ключ (это обычное дело для инструментов разработчика), запрашивайте его на странице настроек и храните в chrome.storage.local; свой ключ никогда не поставляйте.
В чём ИИ ошибается
- Пишет код для Manifest V2.
background.page,chrome.browserAction, постоянная фоновая страница илиwebRequestBlockingпришли из старых примеров. Скажите агенту: «используй эквивалент из Manifest V3». - Считает, что service worker работает всегда. Счётчик в глобальной переменной или
setIntervalчерез какое-то время останавливаются. Для работы по расписанию используйтеchrome.alarms, а для состоянияchrome.storage. - Просит слишком много разрешений.
<all_urls>,tabs,historyобычно не нужны. Попросите агента обосновать каждое разрешение одним предложением; уберите те, которые он обосновать не может. - Загружает удалённый код. Подключение библиотеки с CDN через
<script>или использованиеevalв Manifest V3 не разрешены. Включите библиотеку в пакет. - Тянется к переменным страницы из content-скрипта. Так как он работает в изолированном мире, он не видит
window.someApp; работать нужно через DOM. - Забывает об асинхронных ответах в сообщениях. Если слушатель
onMessageотвечает асинхронно, он должен вернутьreturn true, иначе popup получит пустой ответ. - Считает, что у всех сайтов одинаковый HTML. Чтобы получить текст статьи, сначала ищите элемент
articleилиmainи разумно переходите к запасному варианту. Проверьте на трёх разных сайтах.
Безопасность
- Секреты хранятся в
.envна сервере. Никакого.envв папке расширения; он попал бы в ZIP. - Никогда не вставляйте API-ключи в чат. Агенту нужно имя переменной, а не ключ.
- Читайте команды, которые запускает агент. Особенно установку пакетов и всё вроде
curl … | sh. - Не доверяйте данным страницы. Не выводите текст, прочитанный content-скриптом, в popup через
innerHTML; используйтеtextContent. Иначе вредоносная страница сможет внедрить код в ваше расширение. - Проверяйте, от кого пришло сообщение. Если сообщения извне не нужны, не добавляйте
externally_connectable; если нужны, держите список разрешённых источников узким. - Собирайте только необходимое. Если текст страницы уходит на ваш сервер, скажите об этом прямо и не храните его там.
6. Публикация в Chrome Web Store
Публикация выглядит примерно так:
- Создайте аккаунт разработчика. Зарегистрируйтесь в панели разработчика Chrome Web Store; регистрация требует единоразового взноса.
- Упакуйте проект. Заархивируйте папку проекта в ZIP так, чтобы манифест лежал в корне. Не включайте
.git,node_modules, тестовые файлы и.env. - Заполните карточку. Описание, скриншоты, значки, категория.
- Заполните раздел о конфиденциальности. Укажите единственное назначение расширения, обоснуйте каждое разрешение и объявите, какие пользовательские данные вы собираете. Если вы собираете данные, нужен общедоступный URL политики конфиденциальности.
- Отправьте на проверку. Срок разный. Широкие разрешения для хостов и трудночитаемый код могут её замедлить; при отказе в письме указано, какую политику вы нарушили.
И здесь поможет агент:
I'm submitting this extension to the Chrome Web Store. For each
permission in manifest.json, write a one-sentence justification for the
store form, write the single-purpose description and list the user data
we collect. Tell me if any permission looks unnecessary. Give me a command
that builds the release ZIP without .git, .env and test files.
Для обновлений повышайте version в manifest.json. Добавление нового разрешения может отключить расширение у существующих пользователей, пока они его не одобрят, поэтому подумайте дважды, прежде чем его добавлять.
Как я делаю это в AgentVera
Расширение можно собрать с одним терминалом и браузером. AgentVera я использую, когда делаю расширение и прокси-сервер одновременно:
- Два агента, две задачи. В рабочем пространстве я открываю агента Claude Code для расширения и агента Codex для прокси-сервера, каждого в своей папке или git worktree.
- Проба сервера. API-клиент умеет находить конечные точки сервера по его коду; я проверяю там
/summarize, прежде чем подключать её к расширению. - Отправка ошибок агенту. Вывод ошибок из терминала я отправляю выбранному агенту через Send to agent вместо копирования и вставки.
- Ревью перед слиянием. Ревью кода проверяет каждый завершённый ход, а панель Git показывает diff. Лишнее разрешение или встроенный ключ обычно ловятся здесь.
- Учёт токенов. Каждая панель показывает размер контекста в реальном времени; маленькому расширению не нужна раздутая сессия.
Загрузить расширение в Chrome и попробовать его по-прежнему должны вы; AgentVera этого за вас не делает.
Подводим итоги
Чтобы создать расширение для Chrome с ИИ, изучите части (манифест, content-скрипт, service worker, popup), дайте агенту письменные правила, начните с минимума разрешений, загрузите расширение как распакованное и отлаживайте из нужной консоли, а API-ключи держите за прокси-сервером. Перед отправкой в магазин убедитесь, что можете обосновать каждое разрешение. Больше о проверке того, что создают агенты, читайте в статье ревью кода с ИИ, а о выборе инструментов — в лучших ИИ-инструментах для кода.