Eine Chrome-Erweiterung mit KI zu bauen ist einer der einfachsten Einstiege ins Vibe Coding: Eine Erweiterung besteht aus ein paar kleinen Dateien, du testest sie ohne Server im eigenen Browser, und Coding-Agenten wie Claude Code oder Codex kennen die Struktur von Manifest V3 gut. Das Schwierige ist nicht der Code, sondern das richtige Teil zu wählen (Content Script, Service Worker, Popup), so wenige Berechtigungen wie möglich zu verlangen und nie API-Schlüssel in die Erweiterung zu legen. Dieser Beitrag beschreibt den Weg, den ich von einem leeren Ordner bis zum Chrome Web Store gehe.
Als Beispiel bauen wir etwas Kleines, aber Echtes: eine Erweiterung, die den Artikel auf der aktuellen Seite mit einer KI-API zusammenfasst. Mit Vibe Coding hast du an einem Nachmittag eine erste Version; die Version, die du veröffentlichst, braucht ein paar Regeln mehr.
Kenne zuerst die Teile
Um dem Agenten zu sagen, was du willst, musst du nur die vier Bausteine einer Chrome-Erweiterung kennen:
manifest.json: Die Identität der Erweiterung. Name, Version, welche Datei was tut und welche Berechtigungen sie verlangt. Neue Erweiterungen nutzen Manifest V3.- Content Script: JavaScript, das in der besuchten Seite läuft. Es kann den Text der Seite lesen, einen Button hinzufügen, ein Element ausblenden. Auf die JavaScript-Variablen der Seite selbst kommt es nicht direkt zu; es läuft in einer isolierten „World“.
- Service Worker (Hintergrund): Code, der unabhängig von jeder Seite läuft. Er reagiert auf Ereignisse wie einen Klick auf das Symbol in der Symbolleiste, Tab-Wechsel oder Alarme und stellt Netzwerkanfragen. Eine wichtige Eigenschaft: Chrome beendet ihn im Leerlauf, alles in einer globalen Variable kann also verschwinden.
- Popup und Optionsseite: Das kleine Fenster, das sich beim Klick auf das Symbol öffnet, und eine eigene Seite für Einstellungen. Beide sind einfache HTML-Seiten.
Diese Teile sprechen über chrome.runtime.sendMessage und chrome.tabs.sendMessage miteinander. Wenn etwas, das der Agent geschrieben hat, „nicht funktioniert“, liegt die Ursache sehr oft darin, dass Code im falschen Teil läuft, etwa wenn im Service Worker document benutzt werden soll.
1. Einrichtung und Projektstruktur
Was du brauchst: Chrome (oder einen anderen Chromium-Browser), Git, einen Code-Editor und einen Coding-Agenten. Ein Build-Tool ist für eine erste Erweiterung nicht nötig; einfaches JavaScript reicht. Wächst das Projekt, bringen Vite-basierte Erweiterungs-Frameworks wie WXT TypeScript und automatisches Neuladen mit, aber für Version eins würde ich die zusätzliche Schicht weglassen. Die Fehler des Agenten sind ohne sie leichter zu erkennen.
mkdir page-summarizer && cd page-summarizer
git init
Lege dann im Projektstamm eine kurze Regeldatei an, die der Agent in jeder Sitzung liest (CLAUDE.md oder 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. Der erste Prompt
In der ersten Nachricht bitte ich den Agenten zu erklären, was er baut und welche Dateien er anlegt, und dann den Code zu schreiben:
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.
Die manifest.json, die der Agent erzeugt, sollte ungefähr so aussehen:
{
"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/*"]
}
Das Erste, was ich hier prüfe, ist die Berechtigungsliste. activeTab gewährt temporären Zugriff nur auf den aktuellen Tab, wenn der Nutzer auf das Symbol klickt. Agenten fügen oft aus Bequemlichkeit "<all_urls>" oder "tabs" hinzu; das zeigt Nutzern eine beängstigende Warnung und verlangsamt die Prüfung im Store.
3. Laden, testen, debuggen
Bevor du dich dem Store näherst, teste die Erweiterung im eigenen Browser:
- Öffne
chrome://extensions. - Schalte oben rechts Developer mode (Entwicklermodus) ein.
- Klicke auf Load unpacked (Entpackte Erweiterung laden) und wähle den Projektordner.
- Hefte das Symbol an die Symbolleiste und probiere es an einem Artikel aus.
Nach Codeänderungen drückst du auf der Karte der Erweiterung unter chrome://extensions den Button zum Neuladen. Hat sich ein Content Script geändert, lade auch die Seite neu, auf der du testest.
Die drei Orte, die beim Debuggen am meisten helfen:
- Service Worker: Der Link „service worker“ auf der Karte der Erweiterung öffnet eigene DevTools. Netzwerkanfragen und Hintergrundfehler erscheinen hier.
- Popup: Klicke bei geöffnetem Popup mit der rechten Maustaste darauf und wähle Inspect (Untersuchen).
- Content Script: Logs erscheinen in der DevTools-Konsole der Seite selbst; oben in der Konsole kannst du im Kontext-Dropdown deine Erweiterung auswählen.
Zeigt die Karte der Erweiterung einen Button Errors, kopiere dessen Inhalt unverändert und gib ihn dem Agenten:
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.
Wenn du sagst, wo es kaputtging, worauf du geklickt hast und was jede Konsole zeigt, kann der Agent das Problem beheben, statt zu raten.
4. Speicher: Wähle den richtigen Ort
chrome.storage.local: Daten auf diesem Gerät, etwa der Zusammenfassungsverlauf.chrome.storage.sync: Wird über das Chrome-Profil des Nutzers zwischen Geräten synchronisiert. Das Kontingent ist klein; nutze es nur für Einstellungen.chrome.storage.session: Wird geleert, wenn der Browser schließt; gut für temporären Zustand, der einen Neustart des Service Workers überstehen muss.
Im Service Worker gibt es kein localStorage. Versucht der Agent es zu nutzen, ist das der Grund, warum es scheitert. Und vergiss die Berechtigung storage in manifest.json nicht.
5. API-Schlüssel aus der Erweiterung heraushalten
Das ist der Fehler, den ich bei KI-gebauten Erweiterungen am häufigsten sehe. Der Agent schreibt „füge hier deinen OpenAI-Schlüssel ein“ und legt eine Konstante in background.js ab. Eine veröffentlichte Erweiterung ist eine ZIP-Datei; jeder kann sie herunterladen, entpacken und deinen Schlüssel lesen. Minifizieren oder Verschleiern ändert daran nichts.
Die richtige Struktur ist ein kleiner Proxy:
- Die Erweiterung ruft deinen eigenen Server auf (
https://api.my-server.example/summarize). - Der Server hält den Schlüssel in seiner Umgebung und ruft die echte KI-API auf.
- Der Server begrenzt die Anfragen (pro Nutzer oder IP) und weist zu großen Text zurück.
Öffne für diesen Server ein eigenes Projekt und sag dem Agenten:
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.
Die Erweiterungs-ID zeigt chrome://extensions an, wenn du sie entpackt lädst; nach der Veröffentlichung im Store kann sie anders lauten. Aktualisiere die CORS-Einstellung vor der Veröffentlichung. Bringen Nutzer ihren eigenen Schlüssel mit (üblich bei Entwickler-Tools), frage ihn auf der Optionsseite ab und halte ihn in chrome.storage.local; liefere nie deinen eigenen aus.
Was die KI falsch macht
- Manifest-V2-Code schreiben.
background.page,chrome.browserAction, eine persistente Hintergrundseite oderwebRequestBlockingstammen aus alten Beispielen. Sag dem Agenten „nutze das Manifest-V3-Äquivalent“. - Annehmen, der Service Worker laufe immer. Ein Zähler in einer globalen Variable oder ein
setIntervalhört nach einer Weile auf. Nutzechrome.alarmsfür geplante Arbeit undchrome.storagefür den Zustand. - Zu viele Berechtigungen verlangen.
<all_urls>,tabs,historysind meist unnötig. Bitte den Agenten, jede Berechtigung in einem Satz zu begründen; streiche, was er nicht begründen kann. - Remote-Code laden. Eine Bibliothek per
<script>von einem CDN zu ziehen oderevalzu nutzen ist in Manifest V3 nicht erlaubt. Bündle die Bibliothek ins Paket. - Aus einem Content Script auf Seitenvariablen zugreifen. Weil es in einer isolierten World läuft, sieht es
window.someAppnicht; es muss über das DOM arbeiten. - Asynchrone Antworten beim Messaging vergessen. Antwortet ein
onMessage-Listener asynchron, muss erreturn trueliefern, sonst bekommt das Popup eine leere Antwort. - Annehmen, jede Seite habe dasselbe HTML. Suche beim Holen von Artikeltext zuerst nach einem
article- odermain-Element und weiche sinnvoll aus. Teste auf drei verschiedenen Seiten.
Sicherheit
- Secrets liegen in
.env, auf dem Server. Keine.envim Ordner der Erweiterung; sie würde in der ZIP landen. - Füge nie API-Schlüssel in den Chat ein. Der Agent braucht den Variablennamen, nicht den Schlüssel.
- Lies die Befehle, die der Agent ausführt. Besonders Paketinstallationen und alles wie
curl … | sh. - Vertraue Seitendaten nicht. Rendere Text, den das Content Script gelesen hat, im Popup nicht mit
innerHTML; nimmtextContent. Sonst kann eine bösartige Seite Code in deine Erweiterung einschleusen. - Prüfe, von wem eine Nachricht kommt. Brauchst du keine Nachrichten von außen, füge
externally_connectablenicht hinzu; brauchst du sie, halte die erlaubten Origins eng. - Sammle nur, was du brauchst. Geht Seitentext an deinen Server, sag das deutlich und speichere ihn dort nicht.
6. Veröffentlichung im Chrome Web Store
Grob läuft die Veröffentlichung so ab:
- Entwicklerkonto anlegen. Registriere dich im Entwickler-Dashboard des Chrome Web Store; es gibt eine einmalige Registrierungsgebühr.
- Verpacken. Packe den Projektordner mit dem Manifest im Stamm in eine ZIP. Lass
.git,node_modules, Testdateien und.envweg. - Eintrag ausfüllen. Beschreibung, Screenshots, Symbole, Kategorie.
- Datenschutzabschnitt ausfüllen. Nenne den einzigen Zweck der Erweiterung, begründe jede Berechtigung und gib an, welche Nutzerdaten du sammelst. Sammelst du Daten, brauchst du eine öffentlich erreichbare URL zur Datenschutzerklärung.
- Zur Prüfung einreichen. Die Dauer schwankt. Weitreichende Host-Berechtigungen und schwer lesbarer Code können sie verlängern; wirst du abgelehnt, nennt die E-Mail die verletzte Richtlinie.
Auch hier hilft der Agent:
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.
Erhöhe für Updates version in manifest.json. Eine neue Berechtigung kann die Erweiterung für bestehende Nutzer deaktivieren, bis sie zustimmen; überlege es dir also zweimal, bevor du eine hinzufügst.
So mache ich das mit AgentVera
Du kannst eine Erweiterung mit einem Terminal und einem Browser bauen. Ich nutze AgentVera, wenn ich die Erweiterung und den Proxy-Server gleichzeitig baue:
- Zwei Agenten, zwei Aufgaben. Im Workspace öffne ich einen Claude-Code-Agenten für die Erweiterung und einen Codex-Agenten für den Proxy-Server, jeden in einem eigenen Ordner oder Git-Worktree.
- Den Server ausprobieren. Der API-Client kann die Endpunkte des Servers aus dessen Code finden; ich probiere dort
/summarizeaus, bevor ich es mit der Erweiterung verbinde. - Fehler an den Agenten schicken. Fehlerausgaben aus einem Terminal schicke ich mit Send to agent an den gewählten Agenten, statt zu kopieren und einzufügen.
- Review vor dem Merge. Das Code-Review prüft jeden abgeschlossenen Zug, und das Git-Panel zeigt den Diff. Eine zusätzliche Berechtigung oder ein eingebetteter Schlüssel fällt hier meist auf.
- Token-Verfolgung. Jedes Pane zeigt die aktuelle Kontextgröße; eine kleine Erweiterung braucht keine aufgeblähte Sitzung.
Die Erweiterung in Chrome zu laden und auszuprobieren bleibt deine Sache; AgentVera nimmt dir das nicht ab.
Fazit
Um eine Chrome-Erweiterung mit KI zu bauen, lerne die Teile (Manifest, Content Script, Service Worker, Popup), gib dem Agenten schriftliche Regeln, beginne mit minimalen Berechtigungen, lade sie entpackt und debugge in der richtigen Konsole, und halte API-Schlüssel hinter einem Proxy-Server. Stelle vor dem Einreichen im Store sicher, dass du jede Berechtigung begründen kannst. Mehr dazu, wie du prüfst, was Agenten erzeugen, liest du unter KI-Code-Review, und zur Wahl der Tools unter Die besten KI-Coding-CLI-Tools.