# Расширение для Chrome с ИИ: пошагово (Manifest V3)

URL: https://agentvera.dev/ru/blog/build-chrome-extension-with-ai/ · Опубликовано: 2026-10-11

Расширение для Chrome с ИИ по шагам: Manifest V3, content-скрипты, service worker, минимум разрешений, защита API-ключей и публикация в Chrome Web Store.

**Коротко:**

- У расширения на Manifest V3 четыре части: manifest.json, content-скрипт, service worker и popup или страница настроек; service worker останавливается в простое, поэтому держите состояние в chrome.storage.
- Просите минимум разрешений вроде activeTab, scripting и storage, избегайте <all_urls> и никогда не кладите API-ключ в расширение; обращайтесь к модели через прокси-сервер.
- Тестируйте через Load unpacked на chrome://extensions; Chrome Web Store берёт единоразовый взнос и просит обоснование каждого разрешения, а новое разрешение может отключить расширение, пока пользователи его не одобрят.

Расширение для Chrome с ИИ — один из самых лёгких путей в vibe coding: расширение состоит из нескольких небольших файлов, его можно тестировать в собственном браузере без всякого сервера, а кодинг-агенты вроде Claude Code или Codex хорошо знают структуру Manifest V3. Сложность не в коде, а в выборе нужной части (content-скрипт, service worker, popup), в просьбе о минимуме разрешений и в том, чтобы никогда не класть API-ключи внутрь расширения. Статья описывает путь, которым я иду от пустой папки до Chrome Web Store.

В качестве примера сделаем небольшое, но настоящее расширение: оно пересказывает статью на текущей странице с помощью AI API. С [vibe coding](/ru/glossary/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, редактор кода и [кодинг-агент](/ru/glossary/coding-agent/). Для первого расширения инструмент сборки не нужен; хватит чистого JavaScript. Когда проект вырастет, фреймворки для расширений на Vite вроде WXT добавят TypeScript и автоперезагрузку, но для первой версии я бы обошёлся без лишнего слоя. Без него ошибки агента лучше видны.

```bash
mkdir page-summarizer && cd page-summarizer
git init
```

Затем положите в корень проекта короткий файл правил, который агент читает в каждой сессии (`CLAUDE.md` или `AGENTS.md`):

```markdown
# 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. Первый промпт

В первом сообщении я прошу агента объяснить, что он собирается сделать и какие файлы создаст, а потом написать код:

```text
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`, который выдаст агент, должен выглядеть примерно так:

```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. Загрузка, тесты, отладка

Прежде чем идти в магазин, проверьте расширение в собственном браузере:

1. Откройте `chrome://extensions`.
2. Включите **Developer mode** в правом верхнем углу.
3. Нажмите **Load unpacked** и выберите папку проекта.
4. Закрепите значок на панели и попробуйте расширение на статье.

После изменения кода нажмите кнопку перезагрузки на карточке расширения в `chrome://extensions`. Если менялся content-скрипт, перезагрузите и страницу, на которой вы тестируете.

Три места, которые больше всего помогают при отладке:

- **Service worker:** Ссылка «service worker» на карточке расширения открывает собственные DevTools. Здесь видны сетевые запросы и фоновые ошибки.
- **Popup:** Когда popup открыт, щёлкните по нему правой кнопкой и выберите **Inspect**.
- **Content-скрипт:** Логи появляются в консоли DevTools самой страницы; ваше расширение можно выбрать в выпадающем списке контекстов вверху консоли.

Если на карточке расширения есть кнопка **Errors**, скопируйте её содержимое как есть и передайте агенту:

```text
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-файл; любой может скачать его, распаковать и прочитать ваш ключ. Минификация и обфускация этого не меняют.

Правильная структура — небольшой прокси:

1. Расширение обращается к вашему серверу (`https://api.my-server.example/summarize`).
2. Сервер хранит ключ в своём окружении и вызывает настоящий AI API.
3. Сервер ограничивает частоту запросов (по пользователю или IP) и отклоняет слишком большие тексты.

Откройте отдельный проект для этого сервера и скажите агенту:

```text
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

Публикация выглядит примерно так:

1. **Создайте аккаунт разработчика.** Зарегистрируйтесь в панели разработчика Chrome Web Store; регистрация требует единоразового взноса.
2. **Упакуйте проект.** Заархивируйте папку проекта в ZIP так, чтобы манифест лежал в корне. Не включайте `.git`, `node_modules`, тестовые файлы и `.env`.
3. **Заполните карточку.** Описание, скриншоты, значки, категория.
4. **Заполните раздел о конфиденциальности.** Укажите единственное назначение расширения, обоснуйте каждое разрешение и объявите, какие пользовательские данные вы собираете. Если вы собираете данные, нужен общедоступный URL политики конфиденциальности.
5. **Отправьте на проверку.** Срок разный. Широкие разрешения для хостов и трудночитаемый код могут её замедлить; при отказе в письме указано, какую политику вы нарушили.

И здесь поможет агент:

```text
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 я использую, когда делаю расширение и прокси-сервер одновременно:

- **Два агента, две задачи.** В [рабочем пространстве](/ru/features/workspace/) я открываю агента Claude Code для расширения и агента Codex для прокси-сервера, каждого в своей папке или [git worktree](/ru/glossary/git-worktree/).
- **Проба сервера.** [API-клиент](/ru/features/api-client/) умеет находить конечные точки сервера по его коду; я проверяю там `/summarize`, прежде чем подключать её к расширению.
- **Отправка ошибок агенту.** Вывод ошибок из терминала я отправляю выбранному агенту через [Send to agent](/ru/features/send-to-agent/) вместо копирования и вставки.
- **Ревью перед слиянием.** [Ревью кода](/ru/features/code-review/) проверяет каждый завершённый ход, а [панель Git](/ru/features/git-and-github/) показывает diff. Лишнее разрешение или встроенный ключ обычно ловятся здесь.
- **Учёт [токенов](/ru/glossary/token/).** Каждая панель показывает размер контекста в реальном времени; маленькому расширению не нужна раздутая сессия.

Загрузить расширение в Chrome и попробовать его по-прежнему должны вы; AgentVera этого за вас не делает.

## Подводим итоги

Чтобы создать расширение для Chrome с ИИ, изучите части (манифест, content-скрипт, service worker, popup), дайте агенту письменные правила, начните с минимума разрешений, загрузите расширение как распакованное и отлаживайте из нужной консоли, а API-ключи держите за прокси-сервером. Перед отправкой в магазин убедитесь, что можете обосновать каждое разрешение. Больше о проверке того, что создают агенты, читайте в статье [ревью кода с ИИ](/ru/blog/ai-code-review/), а о выборе инструментов — в [лучших ИИ-инструментах для кода](/ru/blog/best-ai-coding-cli-tools/).

## Частые вопросы

**Можно ли создать расширение для Chrome с ИИ, не умея программировать?** Простое расширение можно: большинство расширений состоит из нескольких небольших файлов, которые кодинг-агент способен написать. Но знание основ, таких как манифест, разрешения и обмен сообщениями между частями, помогает точно описывать агенту ошибки.

**Чем content-скрипт отличается от service worker?** Content-скрипт работает внутри посещаемой страницы и может читать и менять её DOM. Service worker работает в фоне, независимо от страниц; он реагирует на события, делает сетевые запросы, а Chrome останавливает его в простое.

**Как спрятать API-ключ в расширении Chrome?** Никак: всё, что вы поставляете внутри расширения, пользователь может прочитать. Держите ключ на своём сервере, пусть расширение обращается к вашему серверу, а сервер вызывает настоящий API.

**Сколько длится проверка в Chrome Web Store?** Точного срока нет: от нескольких часов до нескольких дней, иногда дольше. Расширения с широкими разрешениями или трудночитаемым минифицированным кодом обычно проверяют подробнее.

**Может ли ИИ перевести расширение с Manifest V2 на Manifest V3?** Да, агенты хорошо справляются с такой миграцией: фоновая страница становится service worker, удалённый код попадает в пакет, постоянные переменные переезжают в chrome.storage. После этого проверьте каждую функцию вручную, потому что остановка service worker меняет поведение.

---

**Об AgentVera.** AgentVera — настольное приложение для macOS, Windows и Linux от Solviera Teknoloji. Оно запускает 18 ИИ-агентов для программирования (Claude Code, Codex, Gemini CLI, Copilot, Cursor, Antigravity, opencode, Hermes, Qwen Code, Kimi Code, Kiro, Amp, Droid, Goose, Vibe, Crush, Aider, Cline) рядом, по проектам, в настоящих терминалах с собственными установками CLI и входами пользователя. В бесплатном тарифе количество агентов не ограничено. Скачать: https://agentvera.dev/ru/download/ · Цены: https://agentvera.dev/ru/pricing/
