@extension.dev/mcp 3.17.0-canary.1779905934.1151df3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/README.md +101 -0
- package/bin/extension-mcp.js +3 -0
- package/claude/ARCHITECTURE.md +161 -0
- package/claude/CLAUDE.md +264 -0
- package/claude/README.md +72 -0
- package/claude/commands/extension-add.md +63 -0
- package/claude/commands/extension-debug.md +43 -0
- package/claude/commands/extension-publish.md +62 -0
- package/claude/commands/extension.md +76 -0
- package/claude/examples/add-sidebar.md +56 -0
- package/claude/examples/create-extension.md +49 -0
- package/claude/rules/cross-browser.md +84 -0
- package/claude/rules/extension-dev.md +83 -0
- package/claude/rules/mcp-tools.md +889 -0
- package/dist/module.cjs +2979 -0
- package/dist/module.d.ts +1 -0
- package/dist/rslib.config.d.ts +2 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/lib/act.d.ts +21 -0
- package/dist/src/lib/cdp.d.ts +48 -0
- package/dist/src/lib/exec.d.ts +13 -0
- package/dist/src/lib/process-manager.d.ts +5 -0
- package/dist/src/lib/templates-cache.d.ts +11 -0
- package/dist/src/lib/types.d.ts +68 -0
- package/dist/src/tools/add-feature.d.ts +29 -0
- package/dist/src/tools/build.d.ts +36 -0
- package/dist/src/tools/create.d.ts +29 -0
- package/dist/src/tools/detect-browsers.d.ts +20 -0
- package/dist/src/tools/dev.d.ts +34 -0
- package/dist/src/tools/dom-inspect.d.ts +56 -0
- package/dist/src/tools/eval.d.ts +44 -0
- package/dist/src/tools/get-template-source.d.ts +25 -0
- package/dist/src/tools/inspect.d.ts +29 -0
- package/dist/src/tools/install-browser.d.ts +18 -0
- package/dist/src/tools/list-browsers.d.ts +9 -0
- package/dist/src/tools/list-templates.d.ts +41 -0
- package/dist/src/tools/logs.d.ts +80 -0
- package/dist/src/tools/manifest-validate.d.ts +26 -0
- package/dist/src/tools/open.d.ts +31 -0
- package/dist/src/tools/preview.d.ts +23 -0
- package/dist/src/tools/publish.d.ts +32 -0
- package/dist/src/tools/reload.d.ts +33 -0
- package/dist/src/tools/source-inspect.d.ts +57 -0
- package/dist/src/tools/start.d.ts +29 -0
- package/dist/src/tools/storage.d.ts +51 -0
- package/dist/src/tools/wait.d.ts +29 -0
- package/dist/vitest.config.d.ts +3 -0
- package/package.json +84 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Add a feature surface (sidebar, popup, content script, etc.) to an existing extension
|
|
3
|
+
argument-hint: "<feature> [framework]"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Add a new feature surface to the current extension project. The user said: $ARGUMENTS
|
|
7
|
+
|
|
8
|
+
## Parse arguments
|
|
9
|
+
|
|
10
|
+
- First argument: feature type — one of: `sidebar`, `popup`, `content-script`, `background`, `newtab`, `options`, `devtools`
|
|
11
|
+
- Second argument (optional): framework — one of: `react`, `vue`, `svelte`, `preact`, `vanilla`. Default: detect from existing project, fall back to `react`
|
|
12
|
+
|
|
13
|
+
## Steps
|
|
14
|
+
|
|
15
|
+
1. **Validate the project**
|
|
16
|
+
- Check that `src/manifest.json` exists
|
|
17
|
+
- Read it to understand what's already configured
|
|
18
|
+
- Detect the framework from existing dependencies in `package.json`
|
|
19
|
+
|
|
20
|
+
2. **Get the reference pattern**
|
|
21
|
+
If MCP tool `extension_add_feature` is available, use it — it returns the exact manifest additions, files to create, and reference template.
|
|
22
|
+
|
|
23
|
+
If MCP tool `extension_get_template_source` is available, read the reference template source to get real implementation patterns.
|
|
24
|
+
|
|
25
|
+
3. **Update manifest.json**
|
|
26
|
+
Add the required fields to `src/manifest.json`. Use the extension.dev cross-browser format:
|
|
27
|
+
|
|
28
|
+
| Feature | Chromium | Firefox |
|
|
29
|
+
| -------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
|
|
30
|
+
| Sidebar | `"chromium:side_panel": {"default_path": "sidebar/index.html"}` + `"chromium:permissions": ["sidePanel"]` | `"firefox:sidebar_action": {"default_panel": "sidebar/index.html"}` |
|
|
31
|
+
| Popup | `"chromium:action": {"default_popup": "action/index.html"}` | `"firefox:browser_action": {"default_popup": "action/index.html"}` |
|
|
32
|
+
| Content script | `"content_scripts": [{"matches": ["<all_urls>"], "js": ["content/scripts.ts"]}]` | Same |
|
|
33
|
+
| Background | `"background": {"chromium:service_worker": "background.ts", "firefox:scripts": ["background.ts"]}` | Same (prefixed) |
|
|
34
|
+
| New tab | `"chrome_url_overrides": {"newtab": "newtab/index.html"}` | Same |
|
|
35
|
+
| Options | `"options_ui": {"page": "options/index.html", "open_in_tab": true}` | Same |
|
|
36
|
+
| DevTools | `"devtools_page": "devtools/index.html"` | Same |
|
|
37
|
+
|
|
38
|
+
4. **Create the files**
|
|
39
|
+
For HTML-based features (sidebar, popup, newtab, options, devtools):
|
|
40
|
+
- `src/<feature>/index.html` — HTML entry with script tag
|
|
41
|
+
- `src/<feature>/scripts.tsx` — Framework mount point (or `.ts` for vanilla)
|
|
42
|
+
- `src/<feature>/styles.css` — Stylesheet
|
|
43
|
+
- `src/<feature>/<Feature>App.tsx` — Main component (non-vanilla only)
|
|
44
|
+
|
|
45
|
+
For content scripts:
|
|
46
|
+
- `src/content/scripts.ts` — Entry point
|
|
47
|
+
- `src/content/styles.css` — Injected styles
|
|
48
|
+
|
|
49
|
+
For background:
|
|
50
|
+
- `src/background.ts` — Service worker / background script
|
|
51
|
+
|
|
52
|
+
5. **Handle sidebar specifically**
|
|
53
|
+
If adding a sidebar, also create/update `src/background.ts`:
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// Chromium: open sidebar on action click
|
|
57
|
+
chrome.sidePanel?.setPanelBehavior?.({ openPanelOnActionClick: true });
|
|
58
|
+
|
|
59
|
+
// Firefox: sidebar_action handles this automatically
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
6. **Report what was done**
|
|
63
|
+
List all files created and manifest changes made. Suggest `npm run dev` to test.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Debug a running extension — inspect DOM, console, content script injection
|
|
3
|
+
argument-hint: "[url] [selectors...]"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Debug the currently running extension dev session. The user said: $ARGUMENTS
|
|
7
|
+
|
|
8
|
+
## Steps
|
|
9
|
+
|
|
10
|
+
1. **Check for a running dev session**
|
|
11
|
+
- Look for `dist/extension-js/chrome/ready.json` in the project root
|
|
12
|
+
- If MCP tool `extension_wait` is available, use it with a short timeout (3s) to check
|
|
13
|
+
- If no session: tell the user to start one with `/extension dev` or `npm run dev`
|
|
14
|
+
|
|
15
|
+
2. **Inspect the live state**
|
|
16
|
+
If MCP tool `extension_source_inspect` is available:
|
|
17
|
+
- Pass `include: ["html", "summary", "meta", "console", "extension_roots"]`
|
|
18
|
+
- If the user provided a URL in `$ARGUMENTS`, pass it as `url`
|
|
19
|
+
- If the user provided CSS selectors (strings starting with `#`, `.`, or `[`), pass them as `probe`
|
|
20
|
+
- Report the results in a structured way
|
|
21
|
+
|
|
22
|
+
If MCP is not available:
|
|
23
|
+
- Suggest the CLI equivalent: `npx extension dev --source <url> --source-format json --source-console`
|
|
24
|
+
- Read `dist/extension-js/chrome/ready.json` to get the CDP port
|
|
25
|
+
- Report the port and suggest Chrome DevTools inspection
|
|
26
|
+
|
|
27
|
+
3. **Diagnose common issues**
|
|
28
|
+
Based on what you find, check for:
|
|
29
|
+
- **"It didn't load"**: Check extension root count. If 0, content scripts may not be injecting. Check manifest `content_scripts` matches patterns and the target URL.
|
|
30
|
+
- **Console errors**: Report top errors. Common ones:
|
|
31
|
+
- `Uncaught TypeError` — likely a missing import or wrong module format
|
|
32
|
+
- `Content Security Policy` — extension CSP blocking inline scripts
|
|
33
|
+
- `chrome.runtime.lastError` — API permission missing
|
|
34
|
+
- **Wrong page**: Check if the content script `matches` pattern in manifest covers the target URL
|
|
35
|
+
- **Shadow DOM empty**: Extension root exists but shadow content is empty — likely a CSS or framework mounting issue
|
|
36
|
+
|
|
37
|
+
4. **Suggest fixes** based on the diagnosis
|
|
38
|
+
|
|
39
|
+
## Examples
|
|
40
|
+
|
|
41
|
+
- `/extension-debug` — inspect the default page target
|
|
42
|
+
- `/extension-debug https://example.com` — inspect a specific URL
|
|
43
|
+
- `/extension-debug https://example.com #my-root .sidebar` — inspect URL and probe selectors
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Prepare an extension for store submission (Chrome Web Store, Firefox Add-ons)
|
|
3
|
+
argument-hint: "[chrome|firefox|both]"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Prepare the current extension for store submission. The user said: $ARGUMENTS
|
|
7
|
+
|
|
8
|
+
## Parse arguments
|
|
9
|
+
|
|
10
|
+
Default to `both` (Chrome + Firefox). If the user specifies `chrome` or `firefox`, target only that store.
|
|
11
|
+
|
|
12
|
+
## Steps
|
|
13
|
+
|
|
14
|
+
1. **Validate the manifest**
|
|
15
|
+
If MCP tool `extension_manifest_validate` is available, use it with the target browsers.
|
|
16
|
+
Otherwise, read `src/manifest.json` and check:
|
|
17
|
+
- Has `name`, `version`, `description`
|
|
18
|
+
- Has appropriate `manifest_version` for each target
|
|
19
|
+
- Permissions are minimal (no unnecessary permissions)
|
|
20
|
+
- Has icons (at least 16x16, 48x48, 128x128)
|
|
21
|
+
|
|
22
|
+
2. **Build for each target browser**
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx extension build --browser=chrome --zip
|
|
26
|
+
npx extension build --browser=firefox --zip
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
3. **Inspect the builds**
|
|
30
|
+
If MCP tool `extension_inspect` is available, use it for each browser build.
|
|
31
|
+
Check:
|
|
32
|
+
- Total size under 10MB (store limit)
|
|
33
|
+
- No source maps in production build
|
|
34
|
+
- Has manifest.json in dist
|
|
35
|
+
- Has icons
|
|
36
|
+
|
|
37
|
+
4. **Report store readiness**
|
|
38
|
+
|
|
39
|
+
### Chrome Web Store
|
|
40
|
+
- Zip location: `dist/chrome/<name>.zip`
|
|
41
|
+
- Submit at: https://chrome.google.com/webstore/devconsole
|
|
42
|
+
- Checklist:
|
|
43
|
+
- [ ] manifest_version: 3
|
|
44
|
+
- [ ] Icons: 128x128 PNG
|
|
45
|
+
- [ ] Description under 132 characters (for listing)
|
|
46
|
+
- [ ] Screenshots: 1280x800 or 640x400
|
|
47
|
+
- [ ] Privacy policy URL (if using sensitive permissions)
|
|
48
|
+
|
|
49
|
+
### Firefox Add-ons (AMO)
|
|
50
|
+
- Zip location: `dist/firefox/<name>.zip`
|
|
51
|
+
- Submit at: https://addons.mozilla.org/developers/
|
|
52
|
+
- Checklist:
|
|
53
|
+
- [ ] manifest_version: 2 (recommended for broadest compat) or 3
|
|
54
|
+
- [ ] No Chrome-only APIs without polyfill
|
|
55
|
+
- [ ] Source code zip if using a bundler: `npx extension build --browser=firefox --zip --zip-source`
|
|
56
|
+
- [ ] AMO requires source code review for minified/bundled code
|
|
57
|
+
|
|
58
|
+
5. **Flag issues** that would cause store rejection:
|
|
59
|
+
- `<all_urls>` host permission without justification
|
|
60
|
+
- `activeTab` + `scripting` without clear use case
|
|
61
|
+
- Remote code loading (eval, Function constructor, remote scripts)
|
|
62
|
+
- Excessive permissions for the extension's functionality
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Create, develop, or build a browser extension with extension.dev
|
|
3
|
+
argument-hint: "<action> [options]"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are helping build a browser extension with the extension.dev platform. The user said: $ARGUMENTS
|
|
7
|
+
|
|
8
|
+
## Actions
|
|
9
|
+
|
|
10
|
+
Parse the user's intent from `$ARGUMENTS` and execute the matching action:
|
|
11
|
+
|
|
12
|
+
### "create <name>" or "new <name>" — Scaffold a new extension
|
|
13
|
+
|
|
14
|
+
1. If MCP tool `extension_list_templates` is available, use it to find the best template matching the user's description (check for surface type, framework, and keywords)
|
|
15
|
+
2. If not, check the template catalog: `curl -sL https://github.com/extension-js/examples/releases/download/nightly/templates-meta.json | jq '.templates[] | {slug, description, uiFramework, surfaces}'`
|
|
16
|
+
3. Run `npx extension@latest create <name> --template=<best-match>`
|
|
17
|
+
4. Report what was created and suggest `npm run dev`
|
|
18
|
+
|
|
19
|
+
### "dev" or "run" — Start development
|
|
20
|
+
|
|
21
|
+
1. Run `npm run dev` (or `npx extension dev`) in the project root
|
|
22
|
+
2. Tell the user the browser will open with their extension loaded
|
|
23
|
+
3. Mention HMR is active — changes will hot-reload
|
|
24
|
+
|
|
25
|
+
### "build" — Build for production
|
|
26
|
+
|
|
27
|
+
1. Run `npm run build` (or `npx extension build`)
|
|
28
|
+
2. After success, report the output in `dist/chrome/`
|
|
29
|
+
3. If the user mentions "firefox" or "both", also build with `--browser=firefox`
|
|
30
|
+
4. If they mention "zip" or "store", add `--zip`
|
|
31
|
+
|
|
32
|
+
### "add <feature>" — Add a feature surface
|
|
33
|
+
|
|
34
|
+
1. If MCP tool `extension_add_feature` is available, use it to get the manifest additions and file list
|
|
35
|
+
2. Otherwise, determine what's needed from the feature type:
|
|
36
|
+
- **sidebar**: `chromium:side_panel` + `firefox:sidebar_action` + `sidePanel` permission + background handler
|
|
37
|
+
- **popup**: `chromium:action` + `firefox:browser_action`
|
|
38
|
+
- **content-script**: `content_scripts` array in manifest
|
|
39
|
+
- **newtab**: `chrome_url_overrides.newtab`
|
|
40
|
+
- **background**: `background.service_worker` (Chromium) + `background.scripts` (Firefox)
|
|
41
|
+
3. Create the files and update `src/manifest.json`
|
|
42
|
+
|
|
43
|
+
### "debug" or "inspect" — Debug a running extension
|
|
44
|
+
|
|
45
|
+
1. If MCP tool `extension_source_inspect` is available, use it with `include: ["html", "console", "extension_roots"]`
|
|
46
|
+
2. If there's a URL mentioned, pass it as the target
|
|
47
|
+
3. If there are CSS selectors mentioned, pass them as `probe`
|
|
48
|
+
4. Report: injected HTML, console errors, extension root state
|
|
49
|
+
|
|
50
|
+
### "validate" — Check manifest for issues
|
|
51
|
+
|
|
52
|
+
1. If MCP tool `extension_manifest_validate` is available, use it
|
|
53
|
+
2. Otherwise, read `src/manifest.json` and check:
|
|
54
|
+
- Required fields: `name`, `manifest_version`
|
|
55
|
+
- Cross-browser: `chromium:` and `firefox:` prefixed fields match
|
|
56
|
+
- Permissions: `sidePanel` present if `side_panel` is declared
|
|
57
|
+
- Background: `service_worker` (Chromium) and `scripts` (Firefox) both present
|
|
58
|
+
|
|
59
|
+
### "template <query>" — Search for a template
|
|
60
|
+
|
|
61
|
+
1. If MCP tool `extension_list_templates` is available, use it with the query
|
|
62
|
+
2. Otherwise, search the catalog JSON
|
|
63
|
+
3. Show matching templates with slug, description, framework, and surfaces
|
|
64
|
+
|
|
65
|
+
### No action / general question
|
|
66
|
+
|
|
67
|
+
If the user's input doesn't match an action, treat it as a description of what they want to build. Recommend the best template and offer to create it.
|
|
68
|
+
|
|
69
|
+
## Cross-browser rules
|
|
70
|
+
|
|
71
|
+
Always use the extension.dev cross-browser manifest format:
|
|
72
|
+
|
|
73
|
+
- `chromium:manifest_version: 3`, `firefox:manifest_version: 2`
|
|
74
|
+
- `chromium:action` vs `firefox:browser_action`
|
|
75
|
+
- `chromium:side_panel` vs `firefox:sidebar_action`
|
|
76
|
+
- `background.chromium:service_worker` vs `background.firefox:scripts`
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Example: Add a sidebar panel to an existing extension
|
|
2
|
+
|
|
3
|
+
## Prompt
|
|
4
|
+
|
|
5
|
+
> Add a sidebar panel to my extension that shows a settings page.
|
|
6
|
+
|
|
7
|
+
## How Claude should approach this
|
|
8
|
+
|
|
9
|
+
1. **Update manifest.json** — add side panel config for both browsers:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"chromium:side_panel": {
|
|
14
|
+
"default_path": "sidebar/index.html"
|
|
15
|
+
},
|
|
16
|
+
"firefox:sidebar_action": {
|
|
17
|
+
"default_panel": "sidebar/index.html"
|
|
18
|
+
},
|
|
19
|
+
"chromium:permissions": ["sidePanel"]
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
2. **Add action button** to trigger the sidebar:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"chromium:action": { "default_title": "Open Settings" },
|
|
28
|
+
"firefox:browser_action": { "default_title": "Open Settings" }
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
3. **Create background.ts** to handle the action click:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
const isFirefoxLike =
|
|
36
|
+
import.meta.env.EXTENSION_PUBLIC_BROWSER === "firefox" ||
|
|
37
|
+
import.meta.env.EXTENSION_PUBLIC_BROWSER === "gecko-based";
|
|
38
|
+
|
|
39
|
+
if (isFirefoxLike) {
|
|
40
|
+
browser.browserAction.onClicked.addListener(() => {
|
|
41
|
+
browser.sidebarAction.open();
|
|
42
|
+
});
|
|
43
|
+
} else {
|
|
44
|
+
chrome.action.onClicked.addListener(() => {
|
|
45
|
+
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true });
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
4. **Create the sidebar UI** — `src/sidebar/index.html`, `src/sidebar/scripts.tsx`, `src/sidebar/styles.css`
|
|
51
|
+
|
|
52
|
+
5. **Test both browsers:**
|
|
53
|
+
```bash
|
|
54
|
+
npm run dev -- --browser=chrome
|
|
55
|
+
npm run dev -- --browser=firefox
|
|
56
|
+
```
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Example: Create a new extension from scratch
|
|
2
|
+
|
|
3
|
+
## Prompt
|
|
4
|
+
|
|
5
|
+
> Create a Chrome extension that adds a floating button to every page. When clicked, it summarizes the page content and shows the summary in a popup overlay.
|
|
6
|
+
|
|
7
|
+
## How Claude should approach this
|
|
8
|
+
|
|
9
|
+
1. **Scaffold with extension.js:**
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx extension@latest create page-summarizer --template=react
|
|
13
|
+
cd page-summarizer
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
2. **Define the manifest** — content script for the floating button, background script for orchestration:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"chromium:manifest_version": 3,
|
|
21
|
+
"firefox:manifest_version": 2,
|
|
22
|
+
"name": "Page Summarizer",
|
|
23
|
+
"content_scripts": [
|
|
24
|
+
{
|
|
25
|
+
"matches": ["<all_urls>"],
|
|
26
|
+
"js": ["content/scripts.tsx"],
|
|
27
|
+
"css": ["content/styles.css"]
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"background": {
|
|
31
|
+
"chromium:service_worker": "background.ts",
|
|
32
|
+
"firefox:scripts": ["background.ts"]
|
|
33
|
+
},
|
|
34
|
+
"permissions": ["activeTab"]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
3. **Build the content script** — inject a floating button, handle click to extract `document.body.innerText`, send to background for processing.
|
|
39
|
+
|
|
40
|
+
4. **Test it:**
|
|
41
|
+
```bash
|
|
42
|
+
npm run dev
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Key decisions Claude should make
|
|
46
|
+
|
|
47
|
+
- Content script for page injection (not popup, since it needs page context)
|
|
48
|
+
- Background script for any API calls (content scripts have CORS restrictions)
|
|
49
|
+
- Use `chrome.runtime.sendMessage` for content <-> background communication
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Cross-Browser Rules for Claude
|
|
2
|
+
|
|
3
|
+
## Manifest field mapping
|
|
4
|
+
|
|
5
|
+
| Feature | Chromium | Firefox |
|
|
6
|
+
| --------------------- | ------------------------------------- | ----------------------------- |
|
|
7
|
+
| Manifest version | `chromium:manifest_version: 3` | `firefox:manifest_version: 2` |
|
|
8
|
+
| Toolbar button | `chromium:action` | `firefox:browser_action` |
|
|
9
|
+
| Side panel | `chromium:side_panel` | `firefox:sidebar_action` |
|
|
10
|
+
| Background | `chromium:service_worker` (string) | `firefox:scripts` (array) |
|
|
11
|
+
| Side panel permission | `chromium:permissions: ["sidePanel"]` | Not needed |
|
|
12
|
+
|
|
13
|
+
## Side panel / Sidebar
|
|
14
|
+
|
|
15
|
+
Chromium:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"chromium:side_panel": {
|
|
20
|
+
"default_path": "sidebar/index.html"
|
|
21
|
+
},
|
|
22
|
+
"chromium:permissions": ["sidePanel"]
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Firefox:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"firefox:sidebar_action": {
|
|
31
|
+
"default_panel": "sidebar/index.html"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Background script to open:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
if (isFirefoxLike) {
|
|
40
|
+
browser.browserAction.onClicked.addListener(() => {
|
|
41
|
+
browser.sidebarAction.open();
|
|
42
|
+
});
|
|
43
|
+
} else {
|
|
44
|
+
chrome.action.onClicked.addListener(() => {
|
|
45
|
+
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true });
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Content scripts with world: "MAIN"
|
|
51
|
+
|
|
52
|
+
`world: "MAIN"` only works on Chromium. Must be prefixed:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"content_scripts": [
|
|
57
|
+
{
|
|
58
|
+
"matches": ["<all_urls>"],
|
|
59
|
+
"js": ["content/scripts.ts"],
|
|
60
|
+
"chromium:world": "MAIN"
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Firefox will ignore the `chromium:world` field and run in the default isolated world.
|
|
67
|
+
|
|
68
|
+
## API differences
|
|
69
|
+
|
|
70
|
+
- Chromium: use `chrome.*` namespace for Chrome-specific APIs (sidePanel, etc.)
|
|
71
|
+
- Firefox: use `browser.*` namespace (auto-polyfilled by the framework)
|
|
72
|
+
- For cross-browser code: use `browser.*` when possible — the polyfill maps it to `chrome.*` on Chromium
|
|
73
|
+
|
|
74
|
+
## Testing across browsers
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Dev mode
|
|
78
|
+
npm run dev -- --browser=chrome
|
|
79
|
+
npm run dev -- --browser=firefox
|
|
80
|
+
npm run dev -- --browser=edge
|
|
81
|
+
|
|
82
|
+
# Build for multiple browsers
|
|
83
|
+
npm run build -- --browser=chrome,firefox
|
|
84
|
+
```
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# extension.dev Development Rules for Claude
|
|
2
|
+
|
|
3
|
+
## File creation order
|
|
4
|
+
|
|
5
|
+
When Claude creates a new extension, follow this order:
|
|
6
|
+
|
|
7
|
+
1. `manifest.json` — always first, defines the extension surface
|
|
8
|
+
2. Background script (if needed) — handles browser events
|
|
9
|
+
3. UI entry points — HTML files referenced by manifest
|
|
10
|
+
4. UI scripts — React/Vue/Svelte components mounted into HTML
|
|
11
|
+
5. Styles — CSS/Tailwind files imported by scripts
|
|
12
|
+
6. `package.json` — dependencies based on what was used above
|
|
13
|
+
7. Config files — tsconfig.json, postcss.config.js, extension.config.js only if needed
|
|
14
|
+
|
|
15
|
+
## manifest.json rules
|
|
16
|
+
|
|
17
|
+
- Always use the `$schema` field for validation: `"$schema": "https://json.schemastore.org/chrome-manifest.json"`
|
|
18
|
+
- Use `chromium:manifest_version: 3` and `firefox:manifest_version: 2` for cross-browser
|
|
19
|
+
- Icon paths are relative to `src/` (where manifest.json lives)
|
|
20
|
+
- Entry point paths (HTML, scripts) are relative to `src/`
|
|
21
|
+
- Always include icons at sizes: 16, 32, 48, 64, 128
|
|
22
|
+
|
|
23
|
+
## Script entry points
|
|
24
|
+
|
|
25
|
+
- Background: referenced in `manifest.json` under `background`
|
|
26
|
+
- Content scripts: referenced in `manifest.json` under `content_scripts`
|
|
27
|
+
- UI pages (popup, sidebar, options, newtab): referenced as HTML files in manifest, include a `<script src="./scripts.tsx">` tag
|
|
28
|
+
|
|
29
|
+
## HTML page pattern
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<!DOCTYPE html>
|
|
33
|
+
<html lang="en">
|
|
34
|
+
<head>
|
|
35
|
+
<meta charset="utf-8" />
|
|
36
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
37
|
+
<title>Page Title</title>
|
|
38
|
+
</head>
|
|
39
|
+
<body>
|
|
40
|
+
<noscript>You need to enable JavaScript to run this extension.</noscript>
|
|
41
|
+
<div id="root"></div>
|
|
42
|
+
</body>
|
|
43
|
+
<script src="./scripts.tsx"></script>
|
|
44
|
+
</html>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## React mounting pattern
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
import React from "react";
|
|
51
|
+
import ReactDOM from "react-dom/client";
|
|
52
|
+
import App from "./App";
|
|
53
|
+
import "./styles.css";
|
|
54
|
+
|
|
55
|
+
const root = ReactDOM.createRoot(document.getElementById("root")!);
|
|
56
|
+
root.render(
|
|
57
|
+
<React.StrictMode>
|
|
58
|
+
<App />
|
|
59
|
+
</React.StrictMode>,
|
|
60
|
+
);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Browser detection
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
const isFirefoxLike =
|
|
67
|
+
import.meta.env.EXTENSION_PUBLIC_BROWSER === "firefox" ||
|
|
68
|
+
import.meta.env.EXTENSION_PUBLIC_BROWSER === "gecko-based";
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Storage API
|
|
72
|
+
|
|
73
|
+
Use `chrome.storage.local` for persistent data. It works cross-browser when the polyfill is active (default).
|
|
74
|
+
|
|
75
|
+
## Permissions
|
|
76
|
+
|
|
77
|
+
Only request permissions the extension actually needs. Common ones:
|
|
78
|
+
|
|
79
|
+
- `sidePanel` — Chromium only, for side panel UI
|
|
80
|
+
- `storage` — for chrome.storage API
|
|
81
|
+
- `activeTab` — for accessing the current tab
|
|
82
|
+
- `tabs` — for tab management
|
|
83
|
+
- `scripting` — for programmatic script injection
|