@extension.dev/mcp 4.8.0 → 5.1.0
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +198 -20
- package/README.md +3 -3
- package/claude/ARCHITECTURE.md +2 -2
- package/claude/CLAUDE.md +15 -15
- package/claude/README.md +8 -8
- package/claude/commands/extension-add.md +10 -10
- package/claude/commands/extension-debug.md +10 -10
- package/claude/commands/extension.md +8 -8
- package/claude/examples/add-sidebar.md +2 -2
- package/claude/examples/create-extension.md +2 -2
- package/claude/rules/cross-browser.md +1 -1
- package/claude/rules/extension-dev.md +12 -12
- package/claude/rules/mcp-tools.md +45 -45
- package/dist/module.js +1378 -360
- package/dist/src/lib/exec.d.ts +6 -1
- package/dist/src/lib/session-browser.d.ts +11 -1
- package/dist/src/lib/types.d.ts +3 -1
- package/dist/src/tools/build.d.ts +6 -0
- package/dist/src/tools/doctor.d.ts +1 -0
- package/dist/src/tools/dom-inspect.d.ts +13 -2
- package/dist/src/tools/manifest-validate.d.ts +5 -0
- package/dist/src/tools/open.d.ts +17 -1
- package/package.json +6 -4
- package/server.json +2 -2
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"name": "extension-mcp",
|
|
11
11
|
"source": "./",
|
|
12
12
|
"description": "MCP tools for browser extension development: scaffold from 60+ templates, run the dev server with HMR, inspect the live DOM and logs, and publish store-ready builds for Chrome, Edge, and Firefox.",
|
|
13
|
-
"version": "
|
|
13
|
+
"version": "5.1.0",
|
|
14
14
|
"category": "development",
|
|
15
15
|
"author": {
|
|
16
16
|
"name": "Cezar Augusto"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "extension-mcp",
|
|
3
3
|
"description": "MCP tools for browser extension development: scaffold from 60+ templates, run the dev server with HMR, inspect the live DOM and logs, and publish store-ready builds for Chrome, Edge, and Firefox. Ships /extension, /extension-add, /extension-debug, and /extension-publish commands.",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "5.1.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cezar Augusto",
|
|
7
7
|
"email": "boss@cezaraugusto.net",
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,183 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.1.0
|
|
4
|
+
|
|
5
|
+
The engine closed its entire open bug range (Extension.js 61-73) in the
|
|
6
|
+
4.0.14 canary line. This release re-aligns the MCP with the fixed engine,
|
|
7
|
+
finishes the MCP-side half of those bugs, and continues the
|
|
8
|
+
report-failure-not-false-success program that 5.0.0 started. 5.0.0 was never
|
|
9
|
+
published to npm; installing 5.1.0 picks up both.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **Sessions now genuinely survive the MCP process.** `detached: true` alone
|
|
14
|
+
never did it: the child held pipes to the MCP, so when the MCP exited the
|
|
15
|
+
next compile log line killed the dev server with EPIPE. Launch tools
|
|
16
|
+
(`extension_dev`/`start`/`preview`) now stream the child's output to a
|
|
17
|
+
session log file (returned as `logPath`) instead of pipes. A detached
|
|
18
|
+
session outlives the MCP and a fresh MCP process rediscovers it through
|
|
19
|
+
`ready.json` and can stop it. Pinned by a detach-contract test.
|
|
20
|
+
- **`extension_preview` no longer reports `launched` for a process that died
|
|
21
|
+
in seconds.** It health-checks the child like `dev`/`start` (the MCP half of
|
|
22
|
+
engine bug 72), and all three launch tools read the engine's new
|
|
23
|
+
`browser_exited` stamp, so a browser that dies after launch (for example a
|
|
24
|
+
rejected add-on) returns `status:"browser-exited"` instead of success.
|
|
25
|
+
- **`extension_doctor` names a dead browser.** A `browser_exited` ready
|
|
26
|
+
contract now produces a runtime-errors failure that says the browser died,
|
|
27
|
+
with the matching remedy, instead of the generic "fix the build error"
|
|
28
|
+
wording that pointed at a build that was fine.
|
|
29
|
+
- **`extension_create` verifies the scaffold.** A resolved create over a
|
|
30
|
+
partial tree (an interrupted template download) returned `nextSteps`
|
|
31
|
+
pointing at a project that could not compile. It now checks the manifest
|
|
32
|
+
exists and returns `status:"incomplete"` when it does not.
|
|
33
|
+
- **`extension_manifest_validate` is per-target honest.** `chromium:`/
|
|
34
|
+
`firefox:` prefixed keys resolve per target, `edge` joins the default
|
|
35
|
+
matrix, `manifest_version` must be 2 or 3, a `default_locale` without its
|
|
36
|
+
`_locales` catalog blocks, and a missing 128px store icon warns
|
|
37
|
+
(`extension_inspect` reports `has128Icon`).
|
|
38
|
+
- **Stale state stops being served as live.** `extension_logs` stamps
|
|
39
|
+
`stale:true` when the producing session is dead or from a different run;
|
|
40
|
+
`extension_wait` returns `runtimeErrors` alongside ready instead of a bare
|
|
41
|
+
green over a crashing worker; `extension_build` reports
|
|
42
|
+
`productionDivergence` when the production manifest lost permissions or
|
|
43
|
+
resources relative to source.
|
|
44
|
+
- **`extension_open`'s `asTab` fallback fires on the user-gesture wall**, and
|
|
45
|
+
`extension_storage` set without a `key` answers in MCP vocabulary rather
|
|
46
|
+
than CLI flags.
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
|
|
50
|
+
- **Structured bundler warnings on `extension_build`.** The engine now
|
|
51
|
+
persists its build summary to `dist/extension-js/<browser>/
|
|
52
|
+
build-summary.json` (the transport half of engine bug 73), and the tool
|
|
53
|
+
returns it as `buildWarnings` (with `buildWarningsTruncated` naming the
|
|
54
|
+
true count when the engine capped the list). Older engines simply omit the
|
|
55
|
+
field; nothing is scraped from stdout.
|
|
56
|
+
- **Popup-faithful headless rendering.** A popup rendered as a tab is now
|
|
57
|
+
sized like the real popup: the document's content size is measured over
|
|
58
|
+
CDP, clamped to Chrome's 25x25-800x600 popup bounds, and the window is
|
|
59
|
+
resized to it (reported as `renderedAsTab.popupBounds`). If the browser
|
|
60
|
+
does not verifiably honor the resize, the tool keeps saying "no popup
|
|
61
|
+
sizing" instead of implying fidelity. Note headless-new is one such
|
|
62
|
+
browser: it accepts `Browser.setWindowBounds` and changes nothing, so
|
|
63
|
+
headless sessions get the honest fallback, not a resized window. The
|
|
64
|
+
measurement also leaves `body`'s authored width alone; only the root takes
|
|
65
|
+
the temporary fit-content override, so a popup that sizes itself through
|
|
66
|
+
`body { width }` measures at its real width.
|
|
67
|
+
- **CI typechecks the tests.** `pnpm typecheck` covers `src/` and the test
|
|
68
|
+
tsconfig, wired into the CI matrix, so type drift between tools and their
|
|
69
|
+
tests cannot accumulate silently again.
|
|
70
|
+
|
|
71
|
+
### Changed
|
|
72
|
+
|
|
73
|
+
- **Tool prose caught up with the fixed engine.** `extension_eval` and
|
|
74
|
+
`extension_dom_inspect` now advertise the surface contexts
|
|
75
|
+
(`popup`/`options`/`sidebar`/`devtools`) and override pages
|
|
76
|
+
(`newtab`/`history`/`bookmarks`) the engine's relay serves, needing no tab
|
|
77
|
+
id. The "content eval is known-broken" guard is version-honest: on
|
|
78
|
+
Extension.js >= 4.0.14 a null is the expression's real result, and the note
|
|
79
|
+
says so instead of condemning a repaired path. Firefox hints name every
|
|
80
|
+
working route.
|
|
81
|
+
|
|
82
|
+
A pass focused on a single question: when something has gone wrong, does the
|
|
83
|
+
tool say so? Five tools were reporting success over a failure. All five now
|
|
84
|
+
verify before they claim anything.
|
|
85
|
+
|
|
86
|
+
### Breaking
|
|
87
|
+
|
|
88
|
+
- **`extension_build` refuses a broken build.** It runs the
|
|
89
|
+
`extension_manifest_validate` checks as a preflight and returns
|
|
90
|
+
`status:"blocked"` on build-blocking errors instead of shelling out to a build
|
|
91
|
+
it knows is broken. Pass `skipValidation: true` for the old behavior. It also
|
|
92
|
+
returns `success:false` with `status:"incomplete"` when the bundler exits 0 but
|
|
93
|
+
a declared entrypoint never reached `dist/`, because the browser refuses to
|
|
94
|
+
load that artifact. Non-blocking findings ride along as `manifestWarnings`.
|
|
95
|
+
- **Browser resolution defaults to `chrome`, not `chromium`.** A dead session
|
|
96
|
+
used to fall through to a blind default, so every call after a dev server
|
|
97
|
+
exited silently retargeted a browser the caller never ran. A dead session now
|
|
98
|
+
resolves to its own browser with `source:"stale"`.
|
|
99
|
+
- **`extension_open` renames `tab` to `target`.** The value is a CDP target id,
|
|
100
|
+
not a `chrome.tabs` id, and the old name invited callers to pass it straight
|
|
101
|
+
into tools that need a numeric tab id.
|
|
102
|
+
|
|
103
|
+
### Fixed
|
|
104
|
+
|
|
105
|
+
- **`extension_doctor` no longer reports `healthy:true` over a crashing
|
|
106
|
+
extension.** Its runtime-error check read the wrong field, so every error row
|
|
107
|
+
in `logs.ndjson` collapsed to an empty string and was skipped. It now reads the
|
|
108
|
+
engine's `messageParts` payload, with an `errorName`/`stack` fallback, and
|
|
109
|
+
collapses a throw that repeats on every event.
|
|
110
|
+
- **`extension_dev` and `extension_start` no longer report `status:"started"`
|
|
111
|
+
for a server that already exited.** Both health-check the child process and
|
|
112
|
+
return `status:"exited"` with the exit code, signal, and the child's own output
|
|
113
|
+
as evidence.
|
|
114
|
+
- **`extension_open` no longer reports success for a navigation that failed.**
|
|
115
|
+
Navigating to a `chrome-extension://` origin is cross process and swaps the
|
|
116
|
+
render frame, so the pre-navigation session reported a stale error URL on
|
|
117
|
+
success and success on failure. It now confirms against a fresh target list.
|
|
118
|
+
This affected the `url` navigation path shipped in 4.9.0, not only the new
|
|
119
|
+
surface rendering.
|
|
120
|
+
- **`extension_open` targets the right extension.** A dev session also loads
|
|
121
|
+
Extension.js's own manager extension, and taking the first extension target
|
|
122
|
+
navigated against the wrong origin. The id is now derived from the dist path
|
|
123
|
+
the session actually loaded.
|
|
124
|
+
|
|
125
|
+
### Added
|
|
126
|
+
|
|
127
|
+
- **Headless surface rendering.** `extension_open` accepts `asTab` for
|
|
128
|
+
`popup`/`options`/`sidebar`, rendering the surface document in a real tab so it
|
|
129
|
+
can be inspected where no window exists to host a popup. It is applied
|
|
130
|
+
automatically when a headless session refuses to open the surface, with a note
|
|
131
|
+
saying what was substituted.
|
|
132
|
+
- **Tab targeting by url.** `extension_eval` and `extension_dom_inspect` take a
|
|
133
|
+
`url` and otherwise default to the active tab, and `extension_dom_inspect`
|
|
134
|
+
gains `listTabs` for discovery. The engine gained this in 4.0.13; the tool
|
|
135
|
+
descriptions had been telling callers a numeric tab id was required.
|
|
136
|
+
- **Friendlier arguments.** `timeoutMs`, `lines`, `tabId`, `href` and
|
|
137
|
+
`browserName` fold onto their canonical names, `withConsole` accepts `true`,
|
|
138
|
+
and the input validator understands union types.
|
|
139
|
+
- **`extension_create` matches your package manager.** Hints and the engine
|
|
140
|
+
warning now use bun, pnpm or yarn when that is what the scaffold used, and the
|
|
141
|
+
warning reads the pin the scaffold actually wrote.
|
|
142
|
+
|
|
143
|
+
## 4.9.0
|
|
144
|
+
|
|
145
|
+
A second pass from the persona swarm, closing the gaps 4.8.0 left and the top
|
|
146
|
+
new blockers it surfaced.
|
|
147
|
+
|
|
148
|
+
- **Honest `extension_manifest_validate`.** It now scans the project source for
|
|
149
|
+
permission-gated `chrome.*`/`browser.*` calls and flags any the manifest does
|
|
150
|
+
not declare, an API used without its permission is `undefined` at runtime and
|
|
151
|
+
crashes the context, the exact case where validate used to report `valid:true`.
|
|
152
|
+
The headline is now honest (`valid:false` + `buildBlocking:true` on any error),
|
|
153
|
+
and it accepts singular `browser` as an alias for `browsers`.
|
|
154
|
+
- **`extension_open` can navigate a tab.** Pass a `url` (Chromium, via CDP) to
|
|
155
|
+
drive a content-script test page, a `webNavigation` target, or the popup as a
|
|
156
|
+
page (`chrome-extension://<id>/popup.html`), the loop the surface-only open
|
|
157
|
+
could not do. `target` is accepted as an alias for `surface`.
|
|
158
|
+
- **`extension_stop` actually reaps the session.** It now terminates the dev CLI
|
|
159
|
+
and both browser families (gecko profile + chromium `--load-extension`, under
|
|
160
|
+
the project's dist) and refuses to report `stopped:true` while any survive.
|
|
161
|
+
- **`extension_wait` won't lie about a dead session.** A `ready.json` whose pid
|
|
162
|
+
is dead now returns `status:"stale"` instead of `ready`, so you don't walk into
|
|
163
|
+
a reload/eval that fails with a misleading control-channel error.
|
|
164
|
+
- **Dropped-channel errors name the real cause.** A `1006` / "no control channel"
|
|
165
|
+
now detects an exited dev server (stale ready.json + dead pid) and says so,
|
|
166
|
+
instead of asking "is the session started with allowControl?" when it was.
|
|
167
|
+
- **`extension_doctor`** surfaces recent error-level logs as a `runtime-errors`
|
|
168
|
+
check (so a background throwing on every event isn't `healthy:true`), keeps the
|
|
169
|
+
project-local engine version in project mode, and flags when that engine
|
|
170
|
+
differs from a pinned `EXTENSION_MCP_CLI_VERSION`.
|
|
171
|
+
- **`extension_build`** lists declared entrypoints in its success output, so a
|
|
172
|
+
content script no longer reads as "didn't build".
|
|
173
|
+
- **`extension_create`** forces non-interactive git (`GIT_TERMINAL_PROMPT=0`) so a
|
|
174
|
+
credential prompt can't hang the template download, retries once on a transient
|
|
175
|
+
network/timeout failure (cleaning the partial dir first), reports a download
|
|
176
|
+
failure as such instead of "choose a valid template name", and warns when the
|
|
177
|
+
scaffold's `extension@latest` pin will win over your pinned CLI.
|
|
178
|
+
- Eval/inspect error guidance now speaks MCP JSON args (`context`, `tab`, `url`)
|
|
179
|
+
instead of CLI flags.
|
|
180
|
+
|
|
3
181
|
## 4.8.0
|
|
4
182
|
|
|
5
183
|
Dev-session ergonomics hardened from a 30-persona agent walk of the toolchain.
|
|
@@ -146,12 +324,12 @@ that removed nearly all friction a real MCP client hit.
|
|
|
146
324
|
--browser=chromium --allow-control` `` becomes `extension_dev with
|
|
147
325
|
{ browser: "chromium", allowControl: true }`, and stray
|
|
148
326
|
`--allow-control` / `--allow-eval` / `--browser=<x>` mentions become
|
|
149
|
-
their tool-argument names. Result data is never touched
|
|
327
|
+
their tool-argument names. Result data is never touched, only
|
|
150
328
|
error/hint prose. Tool descriptions now name `allowControl` /
|
|
151
329
|
`allowEval` directly, so agents no longer discover the gates by
|
|
152
330
|
fuzzing the schema.
|
|
153
331
|
- The no-channel error now names the session that IS running ("Active
|
|
154
|
-
session browser(s) for this project: chrome
|
|
332
|
+
session browser(s) for this project: chrome, pass that as `browser`"),
|
|
155
333
|
so an agent retargets instead of spawning a second, conflicting
|
|
156
334
|
session. Same for the `extension_logs` follow miss.
|
|
157
335
|
- `extension_list_extensions` / `extension_source_inspect` accept
|
|
@@ -187,7 +365,7 @@ Session lifecycle + determinism release. Tool count 27 -> 28.
|
|
|
187
365
|
- CLI spawns are deterministic: dev/start/preview and the act tools now
|
|
188
366
|
prefer the project's own `node_modules/.bin/extension`, falling back to
|
|
189
367
|
`npx extension@<pinned>` where the pin derives from the vendored
|
|
190
|
-
`extension-develop` version
|
|
368
|
+
`extension-develop` version, never a floating `latest`.
|
|
191
369
|
- Session registry keys are path-normalized, so a stop with an absolute
|
|
192
370
|
path matches a session registered with a relative one.
|
|
193
371
|
- Tests: registry suite now asserts against the exported `tools` array
|
|
@@ -262,9 +440,9 @@ this release graduates that line to stable and becomes `latest`.
|
|
|
262
440
|
@extension.dev/skill pairing.
|
|
263
441
|
- MIT license shipped; repository moved to extensiondev/mcp.
|
|
264
442
|
|
|
265
|
-
# @extension.dev/mcp
|
|
443
|
+
# @extension.dev/mcp, Changelog
|
|
266
444
|
|
|
267
|
-
## Unreleased
|
|
445
|
+
## Unreleased, agent-bridge tools
|
|
268
446
|
|
|
269
447
|
Adds the MCP client surface for the Extension.js **agent bridge** (dev-time
|
|
270
448
|
observe + act + inspect). All new tools shell out to the `extension` CLI verbs
|
|
@@ -274,32 +452,32 @@ a recent **`extension` CLI that ships the bridge verbs** (`logs`, `eval`,
|
|
|
274
452
|
|
|
275
453
|
> ⚠️ **Release order:** publish this package ONLY after the `extension` /
|
|
276
454
|
> `extension-develop` suite that ships those verbs is on npm. The published CLI
|
|
277
|
-
> at the time of writing (`3.17.0`) does NOT have them
|
|
455
|
+
> at the time of writing (`3.17.0`) does NOT have them, publishing this package
|
|
278
456
|
> before the suite would ship tools that fail with "unknown command". Bump the
|
|
279
457
|
> version + `extension-*` deps to that suite release, then publish.
|
|
280
458
|
|
|
281
459
|
New tools (22 total):
|
|
282
460
|
|
|
283
|
-
- **`extension_logs
|
|
461
|
+
- **`extension_logs`**, read/stream logs from every extension context
|
|
284
462
|
(background, content, popup/options/sidebar/devtools); filters
|
|
285
463
|
`level`/`context`/`url`/`tab`/`since`, bounded `follow` window.
|
|
286
|
-
- **`extension_eval
|
|
464
|
+
- **`extension_eval`**, evaluate an expression in a context (requires the dev
|
|
287
465
|
session started with `--allow-eval`; MV3 service worker is CSP-gated).
|
|
288
|
-
- **`extension_storage
|
|
289
|
-
- **`extension_reload
|
|
290
|
-
- **`extension_open
|
|
291
|
-
- **`extension_dom_inspect
|
|
466
|
+
- **`extension_storage`**, read/write `chrome.storage` (requires `--allow-control`).
|
|
467
|
+
- **`extension_reload`**, reload the extension or a tab (`--allow-control`).
|
|
468
|
+
- **`extension_open`**, open popup/options/sidebar (`--allow-control`).
|
|
469
|
+
- **`extension_dom_inspect`**, CDP-free DOM snapshot of content/page or an open
|
|
292
470
|
surface (popup/options/sidebar/devtools); `withConsole` merges recent logs.
|
|
293
|
-
- **`extension_publish
|
|
471
|
+
- **`extension_publish`**, publish to extension.dev and return a shareable URL
|
|
294
472
|
(auth-gated; requires `EXTENSION_DEV_TOKEN`).
|
|
295
|
-
- **`extension_source_inspect`** gains **`deepDom
|
|
473
|
+
- **`extension_source_inspect`** gains **`deepDom`**, pierce CLOSED shadow roots
|
|
296
474
|
via CDP (Chromium only).
|
|
297
475
|
|
|
298
476
|
Internal: `lib/act` (CLI shell-out helper), `lib/exec.runExtensionCli` (capture),
|
|
299
477
|
`lib/cdp.getClosedShadowRoots`. Test infra aligned to the workspace vitest
|
|
300
478
|
catalog.
|
|
301
479
|
|
|
302
|
-
## Unreleased
|
|
480
|
+
## Unreleased, login (auth tools)
|
|
303
481
|
|
|
304
482
|
Adds the missing `login` flow so `extension_publish` no longer requires the user
|
|
305
483
|
to mint and export `EXTENSION_DEV_TOKEN` by hand. Auth stays auth-AWARE: the
|
|
@@ -307,13 +485,13 @@ token lives in a local credentials file, never in the MCP process state or logs.
|
|
|
307
485
|
|
|
308
486
|
New tools (25 total):
|
|
309
487
|
|
|
310
|
-
- **`extension_login
|
|
488
|
+
- **`extension_login`**, GitHub **device-code** flow (no local server; works
|
|
311
489
|
headless). Two-phase: call with `project` (`<workspace>/<project>`) to get a
|
|
312
490
|
code + URL, call again with the returned `deviceCode` to finish. On success it
|
|
313
491
|
writes a project-scoped token to the credentials file. Never returns the token.
|
|
314
|
-
- **`extension_whoami
|
|
492
|
+
- **`extension_whoami`**, report the stored workspace/project and token expiry
|
|
315
493
|
without revealing the token.
|
|
316
|
-
- **`extension_logout
|
|
494
|
+
- **`extension_logout`**, delete the local credentials file.
|
|
317
495
|
|
|
318
496
|
Token resolution for publish is now `EXTENSION_DEV_TOKEN` env **>** the
|
|
319
497
|
credentials file (expired file tokens are ignored).
|
|
@@ -323,8 +501,8 @@ Credentials file (versioned, `0600`): `$XDG_CONFIG_HOME/extension-dev/auth.json`
|
|
|
323
501
|
|
|
324
502
|
Platform endpoints this depends on (in `apps/www.extension.dev`):
|
|
325
503
|
|
|
326
|
-
- `GET /api/cli/login/config
|
|
327
|
-
- `POST /api/cli/login/exchange
|
|
504
|
+
- `GET /api/cli/login/config`, public GitHub OAuth client id + scope.
|
|
505
|
+
- `POST /api/cli/login/exchange`, trades a GitHub **user** token for a
|
|
328
506
|
project-scoped access token after checking workspace membership. Modeled on
|
|
329
507
|
`/api/oidc/exchange`; tokens are recorded so they stay revocable.
|
|
330
508
|
|
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ Built on [Extension.js](https://extension.js.org), the open-source cross-browser
|
|
|
41
41
|
claude mcp add extension-dev npx @extension.dev/mcp
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
Or install it as a plugin
|
|
44
|
+
Or install it as a plugin, the MCP server plus the `/extension`, `/extension-add`, `/extension-debug`, and `/extension-publish` commands in one step:
|
|
45
45
|
|
|
46
46
|
```
|
|
47
47
|
/plugin marketplace add extensiondev/mcp
|
|
@@ -123,11 +123,11 @@ cp node_modules/@extension.dev/mcp/claude/commands/*.md ~/my-extension/.claude/c
|
|
|
123
123
|
| platform | `extension_release_promote` | Promote a build to a release channel, headless |
|
|
124
124
|
| platform | `extension_deploy` | Submit to the Chrome, Firefox, and Edge stores through extension.dev |
|
|
125
125
|
|
|
126
|
-
Browser-launching tools (`dev`, `start`, `preview`) shell out to the `extension` CLI
|
|
126
|
+
Browser-launching tools (`dev`, `start`, `preview`) shell out to the `extension` CLI, the project's own `node_modules/.bin/extension` when present, otherwise `npx extension@<pinned>` at the version this package is verified against; everything else runs in-process.
|
|
127
127
|
|
|
128
128
|
## From preview to store
|
|
129
129
|
|
|
130
|
-
The platform tools connect agents to [extension.dev](https://extension.dev): `extension_login` runs a GitHub device-code flow and stores a project-scoped token locally (never returned to the agent), `extension_publish` turns a build into a shareable preview URL, and `extension_release_promote` promotes a tested build to a release channel from CI or an agent session, no browser required. `extension_deploy` submits a built extension to the Chrome Web Store, Edge Add-ons, and Firefox AMO through extension.dev, which holds your store credentials and dispatches the release from your project's mirror CI
|
|
130
|
+
The platform tools connect agents to [extension.dev](https://extension.dev): `extension_login` runs a GitHub device-code flow and stores a project-scoped token locally (never returned to the agent), `extension_publish` turns a build into a shareable preview URL, and `extension_release_promote` promotes a tested build to a release channel from CI or an agent session, no browser required. `extension_deploy` submits a built extension to the Chrome Web Store, Edge Add-ons, and Firefox AMO through extension.dev, which holds your store credentials and dispatches the release from your project's mirror CI, it defaults to a dry run and store credentials are never tool arguments.
|
|
131
131
|
|
|
132
132
|
## The extension.dev stack
|
|
133
133
|
|
package/claude/ARCHITECTURE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# How the pieces connect
|
|
2
2
|
|
|
3
|
-
This document explains how the three Claude integration layers
|
|
3
|
+
This document explains how the three Claude integration layers (the template, the Claude Code rules, and the MCP tools) connect through the [examples](https://github.com/extension-js/examples) repo.
|
|
4
4
|
|
|
5
5
|
## The examples repo is the backbone
|
|
6
6
|
|
|
@@ -154,7 +154,7 @@ MCP server calls extensionCreate() → same go-git-it flow as CLI
|
|
|
154
154
|
|
|
155
155
|
1. **Single source of truth.** `templates-meta.json` is generated from the actual examples. No manual sync needed. Add a template to `examples/`, run `pnpm run generate`, and all three layers pick it up.
|
|
156
156
|
|
|
157
|
-
2. **The examples repo is the knowledge base.** The MCP server doesn't hard-code extension patterns
|
|
157
|
+
2. **The examples repo is the knowledge base.** The MCP server doesn't hard-code extension patterns, it reads them from examples. This means new patterns (like `sidebar-claude`) are immediately available to Claude without updating the MCP server.
|
|
158
158
|
|
|
159
159
|
3. **Graceful degradation.** Users who don't use MCP still benefit from CLAUDE.md. Users who don't use Claude Code still benefit from the template. Each layer works independently.
|
|
160
160
|
|
package/claude/CLAUDE.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# extension.dev
|
|
1
|
+
# extension.dev, Claude Code Instructions
|
|
2
2
|
|
|
3
3
|
You are working on a browser extension project built with the [extension.dev](https://extension.dev) platform, a zero-config cross-browser extension framework.
|
|
4
4
|
|
|
@@ -23,11 +23,11 @@ The extension.dev platform ships 60+ templates in the [examples](https://github.
|
|
|
23
23
|
|
|
24
24
|
| Surface | Vanilla | React | Vue | Svelte | AI |
|
|
25
25
|
| -------------- | ------------ | ---------------- | ------------- | ---------------- | ---------------- |
|
|
26
|
-
| Content script | `content` | `content-react` | `content-vue` | `content-svelte` |
|
|
27
|
-
| Sidebar | `sidebar` | `sidebar-shadcn` |
|
|
28
|
-
| Action popup | `action` |
|
|
29
|
-
| New tab | `new` | `new-react` | `new-vue` | `new-svelte` |
|
|
30
|
-
| Full framework | `javascript` | `react` | `vue` | `svelte` |
|
|
26
|
+
| Content script | `content` | `content-react` | `content-vue` | `content-svelte` | n/a |
|
|
27
|
+
| Sidebar | `sidebar` | `sidebar-shadcn` | n/a |, | `sidebar-claude` |
|
|
28
|
+
| Action popup | `action` | n/a |, | n/a | `action-chatgpt` |
|
|
29
|
+
| New tab | `new` | `new-react` | `new-vue` | `new-svelte` | n/a |
|
|
30
|
+
| Full framework | `javascript` | `react` | `vue` | `svelte` | n/a |
|
|
31
31
|
|
|
32
32
|
**When recommending a template:**
|
|
33
33
|
|
|
@@ -56,7 +56,7 @@ A typical extension.dev project:
|
|
|
56
56
|
```
|
|
57
57
|
my-extension/
|
|
58
58
|
src/
|
|
59
|
-
manifest.json # Required
|
|
59
|
+
manifest.json # Required: the source of truth
|
|
60
60
|
background.ts # Service worker (Chromium) / background script (Firefox)
|
|
61
61
|
content/ # Content scripts
|
|
62
62
|
scripts.tsx
|
|
@@ -151,16 +151,16 @@ export default {
|
|
|
151
151
|
3. **Service workers vs background scripts.** Chromium uses `service_worker` (single file). Firefox uses `scripts` (array).
|
|
152
152
|
4. **Environment variables.** Use `EXTENSION_PUBLIC_*` prefix for variables accessible in extension code. `import.meta.env.EXTENSION_PUBLIC_BROWSER` gives the current browser.
|
|
153
153
|
5. **Asset imports.** Import images/fonts directly in your code. The build system handles bundling.
|
|
154
|
-
6. **CSS Modules.** Use `*.module.css` / `*.module.scss`. Never use the `?url` suffix for CSS module imports
|
|
154
|
+
6. **CSS Modules.** Use `*.module.css` / `*.module.scss`. Never use the `?url` suffix for CSS module imports, it breaks class name hashing.
|
|
155
155
|
|
|
156
156
|
## When creating new extensions
|
|
157
157
|
|
|
158
158
|
1. Check if an existing template matches the use case (see template catalog above)
|
|
159
159
|
2. If yes: `npx extension@latest create my-ext --template=<slug>`
|
|
160
|
-
3. If no: start from `manifest.json
|
|
160
|
+
3. If no: start from `manifest.json`, define what the extension needs
|
|
161
161
|
4. Add entry points referenced by the manifest (background, content scripts, UI pages)
|
|
162
|
-
5. Install framework deps if needed (React, Vue, etc.)
|
|
163
|
-
6. Run `npm run dev
|
|
162
|
+
5. Install framework deps if needed (React, Vue, etc.), the framework auto-detects them
|
|
163
|
+
6. Run `npm run dev`, the dev server handles the rest
|
|
164
164
|
|
|
165
165
|
**Learning from examples:** When building a feature you haven't done before, read the source of a relevant template from the examples repo. The source for any template is at:
|
|
166
166
|
|
|
@@ -234,11 +234,11 @@ npm run dev -- --logs info --log-url "example.com"
|
|
|
234
234
|
|
|
235
235
|
### Triggering events without clicking (requires `--allow-control`)
|
|
236
236
|
|
|
237
|
-
- `extension open action
|
|
238
|
-
- `extension open command --name <cmd
|
|
239
|
-
- `extension_list_extensions` (MCP tool; no CLI verb)
|
|
237
|
+
- `extension open action`, fire the toolbar action (opens its popup, or replays `chrome.action.onClicked`).
|
|
238
|
+
- `extension open command --name <cmd>`, replay a `chrome.commands.onCommand` keyboard shortcut.
|
|
239
|
+
- `extension_list_extensions` (MCP tool; no CLI verb), list extensions with a live context in the browser (Chromium, read-only).
|
|
240
240
|
|
|
241
|
-
These replay your captured listeners, so they work on Chrome and Firefox
|
|
241
|
+
These replay your captured listeners, so they work on Chrome and Firefox, but carry **no user gesture**, so `activeTab` is not granted (the result reports `gesture: false`, plus a `warning` when the manifest declares `activeTab`). If you need a genuine-gesture click (activeTab granted), use [chrome-devtools-mcp](https://github.com/ChromeDevTools/chrome-devtools-mcp)'s `trigger_extension_action` (Chromium only) alongside this server.
|
|
242
242
|
|
|
243
243
|
## Contributing templates to the examples repo
|
|
244
244
|
|
package/claude/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# extension.dev
|
|
1
|
+
# extension.dev, Claude Code Integration
|
|
2
2
|
|
|
3
3
|
Drop-in instructions, rules, and example prompts for building browser extensions with the [extension.dev](https://extension.dev) platform using Claude Code.
|
|
4
4
|
|
|
@@ -11,10 +11,10 @@ claude/
|
|
|
11
11
|
CLAUDE.md Drop-in Claude Code instructions for any extension project
|
|
12
12
|
ARCHITECTURE.md How the template, CLAUDE.md, and MCP layers connect
|
|
13
13
|
commands/
|
|
14
|
-
extension.md /extension
|
|
15
|
-
extension-add.md /extension-add
|
|
16
|
-
extension-debug.md /extension-debug
|
|
17
|
-
extension-publish.md /extension-publish
|
|
14
|
+
extension.md /extension: create, dev, build, add features, debug
|
|
15
|
+
extension-add.md /extension-add: add sidebar, popup, content script, etc.
|
|
16
|
+
extension-debug.md /extension-debug: live DOM/console inspection
|
|
17
|
+
extension-publish.md /extension-publish: store submission prep
|
|
18
18
|
rules/
|
|
19
19
|
extension-dev.md Core rules: project structure, manifest, commands
|
|
20
20
|
cross-browser.md Cross-browser manifest field mapping
|
|
@@ -61,9 +61,9 @@ Claude Code will automatically pick up the instructions and know how to:
|
|
|
61
61
|
|
|
62
62
|
The [examples repo](https://github.com/extension-js/examples) publishes `templates-meta.json` as a nightly release asset. This file is the single source of truth for:
|
|
63
63
|
|
|
64
|
-
- **CLAUDE.md
|
|
65
|
-
- **MCP tools
|
|
66
|
-
- **`extension create
|
|
64
|
+
- **CLAUDE.md**, references it so Claude knows all available templates
|
|
65
|
+
- **MCP tools**, `extension_list_templates` fetches and queries it at runtime
|
|
66
|
+
- **`extension create`**, resolves template slugs to repo URLs via the same naming convention
|
|
67
67
|
|
|
68
68
|
When a new template is added to the examples repo, all three layers pick it up automatically.
|
|
69
69
|
|
|
@@ -7,8 +7,8 @@ Add a new feature surface to the current extension project. The user said: $ARGU
|
|
|
7
7
|
|
|
8
8
|
## Parse arguments
|
|
9
9
|
|
|
10
|
-
- First argument: feature type
|
|
11
|
-
- Second argument (optional): framework
|
|
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
12
|
|
|
13
13
|
## Steps
|
|
14
14
|
|
|
@@ -18,7 +18,7 @@ Add a new feature surface to the current extension project. The user said: $ARGU
|
|
|
18
18
|
- Detect the framework from existing dependencies in `package.json`
|
|
19
19
|
|
|
20
20
|
2. **Get the reference pattern**
|
|
21
|
-
If MCP tool `extension_add_feature` is available, use it
|
|
21
|
+
If MCP tool `extension_add_feature` is available, use it. It returns the exact manifest additions, files to create, and reference template.
|
|
22
22
|
|
|
23
23
|
If MCP tool `extension_get_template_source` is available, read the reference template source to get real implementation patterns.
|
|
24
24
|
|
|
@@ -37,17 +37,17 @@ Add a new feature surface to the current extension project. The user said: $ARGU
|
|
|
37
37
|
|
|
38
38
|
4. **Create the files**
|
|
39
39
|
For HTML-based features (sidebar, popup, newtab, options, devtools):
|
|
40
|
-
- `src/<feature>/index.html
|
|
41
|
-
- `src/<feature>/scripts.tsx
|
|
42
|
-
- `src/<feature>/styles.css
|
|
43
|
-
- `src/<feature>/<Feature>App.tsx
|
|
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
44
|
|
|
45
45
|
For content scripts:
|
|
46
|
-
- `src/content/scripts.ts
|
|
47
|
-
- `src/content/styles.css
|
|
46
|
+
- `src/content/scripts.ts`, Entry point
|
|
47
|
+
- `src/content/styles.css`, Injected styles
|
|
48
48
|
|
|
49
49
|
For background:
|
|
50
|
-
- `src/background.ts
|
|
50
|
+
- `src/background.ts`, Service worker / background script
|
|
51
51
|
|
|
52
52
|
5. **Handle sidebar specifically**
|
|
53
53
|
If adding a sidebar, also create/update `src/background.ts`:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Debug a running extension
|
|
2
|
+
description: Debug a running extension, inspect DOM, console, content script injection
|
|
3
3
|
argument-hint: "[url] [selectors...]"
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -25,8 +25,8 @@ Debug the currently running extension dev session. The user said: $ARGUMENTS
|
|
|
25
25
|
|
|
26
26
|
3. **Exercise event handlers (when the bug is in an action / command / shortcut)**
|
|
27
27
|
If the session was started with `--allow-control`, fire the events a user would, without clicking:
|
|
28
|
-
- `extension_open` with `surface: "action"
|
|
29
|
-
- `extension_open` with `surface: "command"` and `name: "<cmd>"
|
|
28
|
+
- `extension_open` with `surface: "action"`, triggers the toolbar action (opens its popup, or replays `chrome.action.onClicked`).
|
|
29
|
+
- `extension_open` with `surface: "command"` and `name: "<cmd>"`, replays a `chrome.commands.onCommand` keyboard shortcut.
|
|
30
30
|
- Then re-inspect or read `extension_logs` to see what the handler did.
|
|
31
31
|
|
|
32
32
|
**Caveat:** replay carries no user gesture, so `activeTab` is NOT granted. If the handler depends on `activeTab` (e.g. `chrome.scripting.executeScript` on the active tab, `captureVisibleTab`), the result includes `gesture: false` and a `warning`, and behavior differs from a real click. For a genuine-gesture click (activeTab granted), use chrome-devtools-mcp's `trigger_extension_action` (Chromium only) alongside this server.
|
|
@@ -37,16 +37,16 @@ Debug the currently running extension dev session. The user said: $ARGUMENTS
|
|
|
37
37
|
Based on what you find, check for:
|
|
38
38
|
- **"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.
|
|
39
39
|
- **Console errors**: Report top errors. Common ones:
|
|
40
|
-
- `Uncaught TypeError
|
|
41
|
-
- `Content Security Policy
|
|
42
|
-
- `chrome.runtime.lastError
|
|
40
|
+
- `Uncaught TypeError`, likely a missing import or wrong module format
|
|
41
|
+
- `Content Security Policy`, extension CSP blocking inline scripts
|
|
42
|
+
- `chrome.runtime.lastError`, API permission missing
|
|
43
43
|
- **Wrong page**: Check if the content script `matches` pattern in manifest covers the target URL
|
|
44
|
-
- **Shadow DOM empty**: Extension root exists but shadow content is empty
|
|
44
|
+
- **Shadow DOM empty**: Extension root exists but shadow content is empty, likely a CSS or framework mounting issue
|
|
45
45
|
|
|
46
46
|
5. **Suggest fixes** based on the diagnosis
|
|
47
47
|
|
|
48
48
|
## Examples
|
|
49
49
|
|
|
50
|
-
- `/extension-debug
|
|
51
|
-
- `/extension-debug https://example.com
|
|
52
|
-
- `/extension-debug https://example.com #my-root .sidebar
|
|
50
|
+
- `/extension-debug`, inspect the default page target
|
|
51
|
+
- `/extension-debug https://example.com`, inspect a specific URL
|
|
52
|
+
- `/extension-debug https://example.com #my-root .sidebar`, inspect URL and probe selectors
|
|
@@ -9,27 +9,27 @@ You are helping build a browser extension with the extension.dev platform. The u
|
|
|
9
9
|
|
|
10
10
|
Parse the user's intent from `$ARGUMENTS` and execute the matching action:
|
|
11
11
|
|
|
12
|
-
### "create <name>" or "new <name>"
|
|
12
|
+
### "create <name>" or "new <name>", Scaffold a new extension
|
|
13
13
|
|
|
14
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
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
16
|
3. Run `npx extension@latest create <name> --template=<best-match>`
|
|
17
17
|
4. Report what was created and suggest `npm run dev`
|
|
18
18
|
|
|
19
|
-
### "dev" or "run"
|
|
19
|
+
### "dev" or "run", Start development
|
|
20
20
|
|
|
21
21
|
1. Run `npm run dev` (or `npx extension dev`) in the project root
|
|
22
22
|
2. Tell the user the browser will open with their extension loaded
|
|
23
|
-
3. Mention HMR is active
|
|
23
|
+
3. Mention HMR is active, changes will hot-reload
|
|
24
24
|
|
|
25
|
-
### "build"
|
|
25
|
+
### "build", Build for production
|
|
26
26
|
|
|
27
27
|
1. Run `npm run build` (or `npx extension build`)
|
|
28
28
|
2. After success, report the output in `dist/chrome/`
|
|
29
29
|
3. If the user mentions "firefox" or "both", also build with `--browser=firefox`
|
|
30
30
|
4. If they mention "zip" or "store", add `--zip`
|
|
31
31
|
|
|
32
|
-
### "add <feature>"
|
|
32
|
+
### "add <feature>", Add a feature surface
|
|
33
33
|
|
|
34
34
|
1. If MCP tool `extension_add_feature` is available, use it to get the manifest additions and file list
|
|
35
35
|
2. Otherwise, determine what's needed from the feature type:
|
|
@@ -40,14 +40,14 @@ Parse the user's intent from `$ARGUMENTS` and execute the matching action:
|
|
|
40
40
|
- **background**: `background.service_worker` (Chromium) + `background.scripts` (Firefox)
|
|
41
41
|
3. Create the files and update `src/manifest.json`
|
|
42
42
|
|
|
43
|
-
### "debug" or "inspect"
|
|
43
|
+
### "debug" or "inspect", Debug a running extension
|
|
44
44
|
|
|
45
45
|
1. If MCP tool `extension_source_inspect` is available, use it with `include: ["html", "console", "extension_roots"]`
|
|
46
46
|
2. If there's a URL mentioned, pass it as the target
|
|
47
47
|
3. If there are CSS selectors mentioned, pass them as `probe`
|
|
48
48
|
4. Report: injected HTML, console errors, extension root state
|
|
49
49
|
|
|
50
|
-
### "validate"
|
|
50
|
+
### "validate", Check manifest for issues
|
|
51
51
|
|
|
52
52
|
1. If MCP tool `extension_manifest_validate` is available, use it
|
|
53
53
|
2. Otherwise, read `src/manifest.json` and check:
|
|
@@ -56,7 +56,7 @@ Parse the user's intent from `$ARGUMENTS` and execute the matching action:
|
|
|
56
56
|
- Permissions: `sidePanel` present if `side_panel` is declared
|
|
57
57
|
- Background: `service_worker` (Chromium) and `scripts` (Firefox) both present
|
|
58
58
|
|
|
59
|
-
### "template <query>"
|
|
59
|
+
### "template <query>", Search for a template
|
|
60
60
|
|
|
61
61
|
1. If MCP tool `extension_list_templates` is available, use it with the query
|
|
62
62
|
2. Otherwise, search the catalog JSON
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## How Claude should approach this
|
|
8
8
|
|
|
9
|
-
1. **Update manifest.json
|
|
9
|
+
1. **Update manifest.json**, add side panel config for both browsers:
|
|
10
10
|
|
|
11
11
|
```json
|
|
12
12
|
{
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
}
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
4. **Create the sidebar UI
|
|
50
|
+
4. **Create the sidebar UI**, `src/sidebar/index.html`, `src/sidebar/scripts.tsx`, `src/sidebar/styles.css`
|
|
51
51
|
|
|
52
52
|
5. **Test both browsers:**
|
|
53
53
|
```bash
|