From 7e66f34158c4bffc86a67e957031d0d49ae17cf6 Mon Sep 17 00:00:00 2001
From: Claude
Date: Mon, 2 Nov 2026 17:48:04 +0000
Subject: [PATCH 01/11] The open-source setup is two commands: init --agent,
and the docs, the MCP server's setup text and /start/open-source say so
init --agent adds the dev-only agent link next to the import it writes (every framework; one if block in the files
it creates for Next.js; plain HTML gets a module script after the tag that loads dist/agent.js from the script URL's
directory on localhost), and remove takes it out, wrapped by a formatter or not. The READMEs' quick start, INSTALL.md
("How do I set up the open-source parts only?"), the FAQ, AGENT.md, the MCP server's README and setup text, and the
start page's prompt and commands name the two commands (npx @genclass/runtime@beta init --no-telemetry --agent, then
npx -y @genclass/mcp@0.2.1 init) instead of a nine-step hand edit; every @genclass/mcp launcher stays pinned, with
INSTALL.md and FAQ.md added to the sync list.
Co-Authored-By: Claude Fable 5.1
Claude-Session: https://claude.ai/code/session_01Fqwfq3CizvxvgyXp6wY8WR
---
FAQ.md | 7 ++
README.md | 12 ++++
docs/runtime/AGENT.md | 4 +-
docs/runtime/INSTALL.md | 25 +++++++
packages/mcp/README.md | 7 +-
packages/mcp/src/tools.ts | 1 +
packages/mcp/test/manifests.test.ts | 2 +
packages/runtime/CHANGELOG.md | 14 ++++
packages/runtime/README.md | 23 +++++-
packages/runtime/bin/genclass-runtime.mjs | 4 +-
packages/runtime/bin/lib/edit.mjs | 21 ++++--
packages/runtime/bin/lib/init.mjs | 13 +++-
packages/runtime/bin/lib/plan.mjs | 63 +++++++++++-----
packages/runtime/test/install/cli.test.ts | 85 ++++++++++++++++++++++
telemetry-worker/src/pages.ts | 82 +++++++--------------
telemetry-worker/test/bundle.test.ts | 2 +-
telemetry-worker/test/pages.test.ts | 87 +++++++++++------------
17 files changed, 314 insertions(+), 138 deletions(-)
diff --git a/FAQ.md b/FAQ.md
index d27cda35..3696f3dc 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -171,6 +171,13 @@ Nothing is sold on the site. The pricing page shows the plans in force.
Details: [genclass.dev/pricing](https://genclass.dev/pricing),
[billing/plans.json](https://github.com/genclass-dev/GenClass-lib/blob/main/billing/plans.json).
+## Can I use it without an account?
+
+Yes. Two commands set up every open-source part with nothing sent to genclass.dev:
+`npx @genclass/runtime@beta init --no-telemetry --agent` (the runtime in observe mode, the dev-only overlay and agent
+link, no token) and `npx -y @genclass/mcp@0.2.1 init` (the MCP server and the `genclass` skill for Claude Code). Details:
+[INSTALL.md](https://github.com/genclass-dev/GenClass-lib/blob/main/docs/runtime/INSTALL.md#how-do-i-set-up-the-open-source-parts-only).
+
## How is it different from Sentry, Datadog or my tests?
Error trackers and APM collect exceptions, traces and timings; a stale response or a double submit usually throws
diff --git a/README.md b/README.md
index 9dd8c468..16b122a3 100644
--- a/README.md
+++ b/README.md
@@ -37,6 +37,18 @@ Once you approve, `init` installs the package, adds one import first in your ent
devtools overlay in development only) and creates your app's dashboard token (`--no-token` skips it; every flag:
[INSTALL.md](docs/runtime/INSTALL.md)).
+**Open source only, no account.** Two commands set up every open-source part, with nothing sent to genclass.dev:
+
+```bash
+npx @genclass/runtime@beta init --no-telemetry --agent # the runtime (observe), the dev-only overlay and agent link; no token
+npx -y @genclass/mcp@0.2.1 init # the GenClass MCP server and the `genclass` skill for Claude Code
+```
+
+The first adds one marked import (or script tag) plus an option file with `telemetry: false`; the second writes
+`.mcp.json` and `.claude/skills/genclass/SKILL.md` (other agents: `npx -y @genclass/mcp@0.2.1 config `). Nothing
+else is needed; `npx @genclass/runtime@beta remove` undoes the first
+([the open-source setup](docs/runtime/INSTALL.md#how-do-i-set-up-the-open-source-parts-only)).
+
Or by hand: `npm install @genclass/runtime@beta`, then first in your entry file (any bundler; Next.js 15.3 or later:
`instrumentation-client.ts`, earlier versions: a client component in the root layout or `pages/_app`):
diff --git a/docs/runtime/AGENT.md b/docs/runtime/AGENT.md
index 52e23da7..ffef4fbc 100644
--- a/docs/runtime/AGENT.md
+++ b/docs/runtime/AGENT.md
@@ -57,7 +57,9 @@ Every launcher is pinned to the release. `packages/mcp/server.json` is the entry
(published by the release workflow with GitHub OIDC after the npm package); the listings for other directories are
drafted in [docs/adoption/listings/mcp.md](../adoption/listings/mcp.md).
-In the app's browser entry, development builds only (`@genclass/runtime` 0.3.0-beta.1 or later):
+`npx @genclass/runtime@beta init --agent` (0.3.0-beta.6) adds the line for you, next to the import it writes (plain HTML: a
+module script after the tag). By hand, in the app's browser entry, development builds only (`@genclass/runtime`
+0.3.0-beta.1 or later):
```ts
import { GenClass } from "@genclass/runtime";
diff --git a/docs/runtime/INSTALL.md b/docs/runtime/INSTALL.md
index c71c1fa0..5febcb77 100644
--- a/docs/runtime/INSTALL.md
+++ b/docs/runtime/INSTALL.md
@@ -60,6 +60,7 @@ Content-Security-Policy (`next.config` headers, a proxy or middleware, a ` ` | both | the project directory (default: the current directory) |
| `--from ` | init | install `@genclass/runtime` from this spec (a version, tag or tarball path) |
| `--cdn ` | init | plain HTML: the script URL (default: jsDelivr, this version, with an SRI hash; this version's unpkg URL gets one too; other URLs get no hash) |
@@ -136,6 +137,30 @@ reached, `init` says so, sets GenClass up without a token, and points you to
[genclass.dev/start](https://genclass.dev/start); run `init --token gc_...` later. `--dry-run` sends nothing and
installs nothing.
+## How do I set up the open-source parts only?
+
+Two commands, no account, no token, nothing sent to genclass.dev:
+
+```bash
+npx @genclass/runtime@beta init --no-telemetry --agent # the runtime in observe, the dev-only overlay and agent link
+npx -y @genclass/mcp@0.2.1 init # the GenClass MCP server and the `genclass` skill for Claude Code
+```
+
+The first finds your framework, installs `@genclass/runtime`, adds one marked import (plain HTML: the script tag,
+pinned with an integrity hash) with the dev-only devtools and agent lines, and writes `telemetry: false` into a
+marked `genclass.config.ts` (or `.js`) next to your entry (`data-telemetry="off"` on a script tag), so GenClass's
+anonymous diagnostics are off; `--no-telemetry` implies `--no-token`. Browsers still download the model and
+onnxruntime-web, public files, from jsDelivr unless you serve them (`--model-url`,
+[Content-Security-Policy and self-hosting](../../packages/runtime/README.md#content-security-policy-and-self-hosting)).
+Add `--mode guard` to let GenClass act, `--sink console-json` for findings in your own logs.
+
+The second writes the server into `.mcp.json` and the `genclass` skill (the procedure Claude Code follows for timing
+bugs) to `.claude/skills/genclass/SKILL.md`; it runs on your machine and needs no account
+([`@genclass/mcp`](../../packages/mcp/README.md); other agents: `npx -y @genclass/mcp@0.2.1 config `). Run the dev
+server: until the MCP server runs, the page logs one failed request to `127.0.0.1:47357`, the agent link finding no
+server. `npx @genclass/runtime@beta remove` takes the first command's changes out; delete `.mcp.json`'s entry and
+`.claude/skills/genclass/` for the second.
+
## How do I install it by hand?
**One import** (any bundler; the package is ESM only, there is no `require` build), first in your entry file, so it
diff --git a/packages/mcp/README.md b/packages/mcp/README.md
index 8e2c4ad8..5823f316 100644
--- a/packages/mcp/README.md
+++ b/packages/mcp/README.md
@@ -307,9 +307,10 @@ read a report, what to say when done, what to do when the tools are missing) is
To remove it: delete `.claude/skills/genclass/` (or the directory the skill tool wrote to); with the plugin,
`/plugin uninstall genclass@genclass`.
-Then connect the app's development build (once). The agent link needs the newest runtime line, `@genclass/runtime`
-0.3.0-beta.1 or later: `npm install @genclass/runtime@beta` (a bare `npm install @genclass/runtime` gets npm's
-`latest`, the older 0.2.x, which has no agent entry):
+Then connect the app's development build (once): `npx @genclass/runtime@beta init --agent` adds a dev-only line next to
+the import it writes (plain HTML: a module script after the tag), installing the runtime first if needed. By hand, the
+agent link needs the newest runtime line, `@genclass/runtime` 0.3.0-beta.1 or later: `npm install @genclass/runtime@beta`
+(a bare `npm install @genclass/runtime` gets npm's `latest`, the older 0.2.x, which has no agent entry):
```ts
import { GenClass } from "@genclass/runtime";
diff --git a/packages/mcp/src/tools.ts b/packages/mcp/src/tools.ts
index 47aa1314..380e8390 100644
--- a/packages/mcp/src/tools.ts
+++ b/packages/mcp/src/tools.ts
@@ -559,6 +559,7 @@ export function setupText(cwd: string, client?: string | null): string {
const guard = next ? `process.env.NODE_ENV === "development"` : vite ? "import.meta.env.DEV" : `process.env.NODE_ENV !== "production"`;
const where = next ? "a client component loaded once from the root layout (\"use client\")" : vite ? "the app's entry (src/main.tsx or src/main.ts), before the app renders" : "the app's browser entry, before the app starts";
const lines = [
+ "One command does the app side: npx @genclass/runtime@beta init --agent (it installs the runtime if needed and adds a dev-only agent line next to the import it writes; --no-telemetry too for no diagnostics). By hand:",
installed
? "@genclass/runtime is installed."
: `1. Install the newest runtime, 0.3.0-beta.1 or later (the agent entry and analytics; 0.2.x has neither${has("@genclass/runtime") ? `; this project has ${JSON.stringify(range)}${have !== range ? `, installed ${have}` : ""}` : ""}): npm install @genclass/runtime@beta`,
diff --git a/packages/mcp/test/manifests.test.ts b/packages/mcp/test/manifests.test.ts
index c8204f2c..787b3ab9 100644
--- a/packages/mcp/test/manifests.test.ts
+++ b/packages/mcp/test/manifests.test.ts
@@ -76,6 +76,8 @@ const PINS: Pin[] = [
{ file: "docs/runtime/AGENT.md", text: (s) => s.replace(PINNED, pinned(V)) },
{ file: "README.md", text: (s) => s.replace(PINNED, pinned(V)) },
{ file: "packages/runtime/README.md", text: (s) => s.replace(PINNED, pinned(V)) },
+ { file: "docs/runtime/INSTALL.md", text: (s) => s.replace(PINNED, pinned(V)) },
+ { file: "FAQ.md", text: (s) => s.replace(PINNED, pinned(V)) },
];
function read(file: string): string {
diff --git a/packages/runtime/CHANGELOG.md b/packages/runtime/CHANGELOG.md
index 3cdd1fd8..42d2bf81 100644
--- a/packages/runtime/CHANGELOG.md
+++ b/packages/runtime/CHANGELOG.md
@@ -1,5 +1,19 @@
# Changelog
+## Unreleased (0.3.0-beta.6)
+
+- **The open-source setup is two commands** (`bin/lib/`, owner request 2026-11-02). `init --agent` adds the dev-only
+ agent link next to the import it writes, the same way it adds the devtools line: `if ()
+ import("@genclass/runtime/agent").then((a) => a.connectAgent(genclass))` in every framework it knows (one `if` block
+ in the files it creates for Next.js; plain HTML gets a module script after the tag, which loads `dist/agent.js` from
+ the script URL's directory on `localhost` and connects `GenClass.runtime`; module scripts run after deferred ones,
+ in order). `remove` takes it out, wrapped by a formatter or not, and refuses an edited one. So
+ `npx @genclass/runtime@beta init --no-telemetry --agent` and `npx -y @genclass/mcp init` set up every open-source
+ part with no account and nothing sent, and the READMEs, INSTALL.md ("How do I set up the open-source parts only?"),
+ FAQ, AGENT.md, the MCP server's setup text and genclass.dev/start/open-source say so with those two commands instead
+ of a nine-step hand edit. No runtime code, no model-visible text, no change to what is sent. Tests:
+ `test/install/cli.test.ts` ("init --agent").
+
## 0.3.0-beta.5 (2026-11-02)
Security fixes from the adversarial review of the mode-raise fix (`0.3.0-beta.2`); the same four fixes are in `0.2.3`
diff --git a/packages/runtime/README.md b/packages/runtime/README.md
index 2c8b8f4f..965a30e7 100644
--- a/packages/runtime/README.md
+++ b/packages/runtime/README.md
@@ -35,6 +35,18 @@ Once you approve the diff, `init` also creates your app's free dashboard at genc
`package.json` `name`; `--no-token`, `--token`, `--no-telemetry` and `--dry-run` create no dashboard and never contact
genclass.dev ([Your dashboard](#your-dashboard)).
+**Open source only, no account.** Two commands set up every open-source part, with nothing sent to genclass.dev:
+
+```bash
+npx @genclass/runtime@beta init --no-telemetry --agent # the runtime (observe), the dev-only overlay and agent link; no token
+npx -y @genclass/mcp@0.2.1 init # the GenClass MCP server and the `genclass` skill for Claude Code
+```
+
+The first adds one marked import (or script tag) plus an option file with `telemetry: false`; the second writes
+`.mcp.json` and `.claude/skills/genclass/SKILL.md` (other agents: `npx -y @genclass/mcp@0.2.1 config `). Nothing
+else is needed; `npx @genclass/runtime@beta remove` undoes the first
+([the open-source setup](https://github.com/genclass-dev/GenClass-lib/blob/main/docs/runtime/INSTALL.md#how-do-i-set-up-the-open-source-parts-only)).
+
Or by hand:
```bash
@@ -468,7 +480,9 @@ npx @genclass/runtime@beta remove # undo exactly what init added
Other flags: `--yes`, `--no-telemetry` (`--telemetry` undoes it on a later run and writes no telemetry option, so
the default applies: on, but off on local hosts), `--no-token`, `--token gc_...`, `--sink`, `--model-url`, `--no-install`,
-`--no-devtools`, and from `0.3.0-beta.2` `--no-network` and `--sync` (plain HTML).
+`--no-devtools`, `--agent` (from `0.3.0-beta.6`: the dev-only agent link too, so your coding agent sees the dev
+pages; [Your coding agent](#your-coding-agent-replay-and-explore)), and from `0.3.0-beta.2` `--no-network` and
+`--sync` (plain HTML).
**Which version** (from `0.3.0-beta.2`). `init` (and `login`, `connect`) first prints its own version and the npm
dist-tag it came from, asks npm's dist-tags once (`npm view @genclass/runtime dist-tags`, at most 3 s; never with
@@ -675,9 +689,14 @@ Claude Code and other coding agents, and lets the agent:
- **keep the proof:** a generated Playwright test that sets the same order and fails while the bug is there.
```bash
-claude mcp add genclass -- npx -y @genclass/mcp@0.2.1
+npx @genclass/runtime@beta init --agent # the app side: a dev-only line next to the import init writes (0.3.0-beta.6)
+npx -y @genclass/mcp@0.2.1 init # the server in .mcp.json and the `genclass` skill, for Claude Code
```
+Other agents: `npx -y @genclass/mcp@0.2.1 config `, or `claude mcp add genclass -- npx -y @genclass/mcp@0.2.1`. By
+hand, the app side is one line in a development build (plain HTML: a module script after the tag, which `init --agent`
+writes too):
+
```ts
import { GenClass } from "@genclass/runtime";
import { connectAgent } from "@genclass/runtime/agent";
diff --git a/packages/runtime/bin/genclass-runtime.mjs b/packages/runtime/bin/genclass-runtime.mjs
index e635c6c5..b374f389 100755
--- a/packages/runtime/bin/genclass-runtime.mjs
+++ b/packages/runtime/bin/genclass-runtime.mjs
@@ -1,7 +1,7 @@
#!/usr/bin/env node
// genclass-runtime CLI (Node >= 20, no dependencies). Also runs as `npx @genclass/runtime `.
//
-// genclass-runtime init [--mode observe|guard|heal] [--token | --no-token] [--yes] [--dry-run] [--no-install] [--no-devtools]
+// genclass-runtime init [--mode observe|guard|heal] [--token | --no-token] [--agent] [--yes] [--dry-run] [--no-install] [--no-devtools]
// genclass-runtime remove [--yes] [--dry-run] [--keep-package]
// Set GenClass up in a project (framework detection, install, one marked import in the entry file, an app token
// and private dashboard link from genclass.dev) and take it out again. Implemented in bin/lib/ (owner: INSTALL).
@@ -57,7 +57,7 @@ const ORT_FILES = {
const ROLES = ["tokenizer", "calibration", "meta"];
const USAGE = `Usage:
- genclass-runtime init [--mode observe|guard|heal] [--token | --no-token] [--yes] [--dry-run] [--no-install] [--no-devtools]
+ genclass-runtime init [--mode observe|guard|heal] [--token | --no-token] [--agent] [--yes] [--dry-run] [--no-install] [--no-devtools]
genclass-runtime remove [--yes] [--dry-run] [--keep-package]
genclass-runtime login [--yes] [--no-browser] [--no-connect]
genclass-runtime connect [--app ] [--name ] [--yes] [--dry-run] [--no-install]
diff --git a/packages/runtime/bin/lib/edit.mjs b/packages/runtime/bin/lib/edit.mjs
index 94e21997..90ed7542 100644
--- a/packages/runtime/bin/lib/edit.mjs
+++ b/packages/runtime/bin/lib/edit.mjs
@@ -119,6 +119,8 @@ export const AUTO = (mode) => (mode ? `@genclass/runtime/auto/${mode}` : "@gencl
const AUTO_SPEC = String.raw`"@genclass/runtime/auto(?:/(?:observe|guard|heal))?"`;
const DEVTOOLS_CALL = String.raw`import\("@genclass/runtime/devtools"\)\.then\(d=>d\.mountDevtools\(genclass\)\)`;
+// the dev-only agent link (init --agent): the same shape, @genclass/runtime/agent's connectAgent on the runtime
+const AGENT_CALL = String.raw`import\("@genclass/runtime/agent"\)\.then\(a=>a\.connectAgent\(genclass\)\)`;
const COND = String.raw`[^;{}]+?`;
const IMPORT_AUTO = String.raw`import(?:genclassfrom)?${AUTO_SPEC};?`;
// the options file init writes with --no-telemetry / --telemetry / --model-url, imported right before /auto
@@ -126,8 +128,12 @@ const IMPORT_CONFIG = String.raw`import"(?:\.{1,2}/)+(?:[\w.-]+/)*genclass\.conf
const CONFIG_STATEMENT = String.raw`(?:\(globalThisas\{GENCLASS_CONFIG\?:\w+\}\)|globalThis)\.GENCLASS_CONFIG=\{[^;]*\};?`;
const META_CONFIG = String.raw``;
const DEV_LINE = String.raw`if\(${COND}\)${DEVTOOLS_CALL};?`;
-// the same with braces (ESLint's `curly` fix)
-const DEV_BLOCK = String.raw`if\(${COND}\)\{${DEVTOOLS_CALL};?\}`;
+const AGENT_LINE = String.raw`if\(${COND}\)${AGENT_CALL};?`;
+// the same with braces (ESLint's `curly` fix), and the one block Next.js's created files hold both calls in
+const DEV_BLOCK = String.raw`if\(${COND}\)\{(?:${DEVTOOLS_CALL};?)?(?:${AGENT_CALL};?)?\}`;
+const AGENT_BLOCK = String.raw`if\(${COND}\)\{${AGENT_CALL};?\}`;
+// plain HTML with --agent: a module script after the runtime's tag (module scripts run after deferred ones, in order)
+const AGENT_SCRIPT = String.raw`if\(\["localhost","127\.0\.0\.1"\]\.includes\(location\.hostname\)\)import\("[^"]*"\)\.then\(a=>a\.connectAgent\(GenClass\.runtime\)\);?`;
/** Statements init writes on one marked line (normalised, see norm()). */
const LINE_RE = new RegExp(
"^(?:" +
@@ -137,11 +143,13 @@ const LINE_RE = new RegExp(
META_CONFIG,
DEV_LINE,
DEV_BLOCK,
+ AGENT_LINE,
+ AGENT_SCRIPT,
String.raw`import\{isDevModeasgenclassDevMode\}from"@angular/core";?`,
String.raw`import\{GenClassInit\}from"[^"]*genclass-init";?`,
String.raw` `,
String.raw``,
- String.raw``,
+ String.raw``,
].join("|") +
")$",
);
@@ -155,20 +163,23 @@ const BLOCK_RE = new RegExp(
CONFIG_STATEMENT,
DEV_LINE,
DEV_BLOCK,
+ AGENT_LINE,
String.raw`importtype\{AppProps\}from"next/app";?`,
String.raw`exportfunctionGenClassInit\(\)\{returnnull;?\}`,
- String.raw`exportdefaultdefineNuxtPlugin\(\(\)=>\{(?:${DEV_LINE}|${DEV_BLOCK})?\}\);?`,
+ String.raw`exportdefaultdefineNuxtPlugin\(\(\)=>\{(?:${DEV_LINE}|${DEV_BLOCK})?(?:${AGENT_LINE}|${AGENT_BLOCK})?\}\);?`,
String.raw`exportdefaultfunctionApp\(\{Component,pageProps\}(?::AppProps)?\)\{return\(? \)?;?\}`,
].join("|") +
")*$",
);
// Inline forms (init puts them on a line shared with other code); whitespace a formatter adds between the element and
// its marker is taken out with them. `ok` checks the element is still what init wrote (an Astro $`);
+const INLINE_SCRIPT_RE = new RegExp(String.raw`^$`);
+const AGENT_SCRIPT_RE = new RegExp(`^${AGENT_SCRIPT}$`);
const INLINE = [
{ re: / \s*\{\s*\/\*\s*genclass:inline\s*\*\/\s*\}/g },
{ re: /`;
+}
const unpkgUrl = (version, min) => `https://unpkg.com/@genclass/runtime@${version}/dist/genclass.global${min ? ".min" : ""}.js`;
/**
@@ -305,6 +328,7 @@ function planHtml(p, o, ctx) {
const files = htmlFiles(p.dir);
if (!files.length) return { changes: [], manual: "no .html file with a in this directory" };
const tag = scriptTag(o, ctx.pkgDir, ctx.version);
+ const agent = o.agent ? agentTag(o, ctx.version) : null;
const changes = [];
for (const f of files) {
const before = readText(f) ?? "";
@@ -313,14 +337,15 @@ function planHtml(p, o, ctx) {
const line = lines[li];
let after;
if (/<\/head>/i.test(line)) {
- // a one-line head: put the tag right after
+ // a one-line head: put the tag (and the agent script) right after
const m = /]*>/i.exec(before);
const at = m.index + m[0].length;
- after = before.slice(0, at) + `${tag}` + before.slice(at);
+ after = before.slice(0, at) + `${tag}` + (agent ? `${agent}` : "") + before.slice(at);
} else {
const next = lines.slice(li + 1).find((l) => l.trim() !== "");
const indent = next !== undefined ? indentOf(next) : indentOf(line) + indentUnit(before);
after = insertLineAt(before, li + 1, `${indent}${tag} `);
+ if (agent) after = insertLineAt(after, li + 2, `${indent}${agent} `);
}
changes.push({ file: f, kind: "modify", before, after });
}
diff --git a/packages/runtime/test/install/cli.test.ts b/packages/runtime/test/install/cli.test.ts
index b149f9c4..63c0f5ec 100644
--- a/packages/runtime/test/install/cli.test.ts
+++ b/packages/runtime/test/install/cli.test.ts
@@ -1228,3 +1228,88 @@ describe("the newest line: version line, npm dist-tags, older runtimes upgraded
expect(r.out).toContain(`installs @genclass/runtime (this version, ${VERSION}; an older one already in the`);
});
});
+
+describe("init --agent: the dev-only agent link next to the overlay (the open-source setup's app side)", () => {
+ const VITE_TS = {
+ "package.json": pkg({ react: "^19.0.0", vite: "^7.0.0", "@vitejs/plugin-react": "^5" }),
+ "tsconfig.json": "{}\n",
+ "index.html": VITE_HTML,
+ "src/main.tsx": `import { createRoot } from 'react-dom/client'\nimport App from './App.tsx'\n\ncreateRoot(document.getElementById('root')!).render( )\n`,
+ "src/App.tsx": `export default function App() { return hi }\n`,
+ };
+
+ it("Vite: the overlay line, then the agent line, both marked; the top import binds the runtime", () => {
+ const dir = project(VITE_TS);
+ const r = cli(dir, "init", "--yes", "--no-install", "--agent");
+ expect(r.code, r.out).toBe(0);
+ expect(r.out).toContain("npx -y @genclass/mcp init");
+ expect(r.out).toContain("127.0.0.1:47357");
+ const main = readFileSync(join(dir, "src/main.tsx"), "utf8");
+ const lines = main.trimEnd().split("\n");
+ expect(lines[0]).toBe(`import genclass from '@genclass/runtime/auto' // genclass:init`);
+ expect(lines.at(-2)).toBe(`if (import.meta.env.DEV) import('@genclass/runtime/devtools').then((d) => d.mountDevtools(genclass)) // genclass:init`);
+ expect(lines.at(-1)).toBe(`if (import.meta.env.DEV) import('@genclass/runtime/agent').then((a) => a.connectAgent(genclass)) // genclass:init`);
+ expect(cli(dir, "remove", "--yes").code).toBe(0);
+ expect(readFileSync(join(dir, "src/main.tsx"), "utf8")).toBe(VITE_TS["src/main.tsx"]);
+ });
+
+ it("--agent --no-devtools: the runtime is still bound; only the agent line follows", () => {
+ const after = roundTrip(project(VITE_TS), "--agent", "--no-devtools");
+ const lines = after["src/main.tsx"].trimEnd().split("\n");
+ expect(lines[0]).toBe(`import genclass from '@genclass/runtime/auto' // genclass:init`);
+ expect(lines.at(-1)).toBe(`if (import.meta.env.DEV) import('@genclass/runtime/agent').then((a) => a.connectAgent(genclass)) // genclass:init`);
+ expect(after["src/main.tsx"]).not.toContain("devtools");
+ });
+
+ it("Next.js 16: both calls in the one development block of instrumentation-client.ts", () => {
+ const dir = project({
+ "package.json": pkg({ next: "16.0.0", react: "^19" }),
+ "tsconfig.json": "{}\n",
+ "node_modules/next/package.json": JSON.stringify({ name: "next", version: "16.0.1" }),
+ "src/app/layout.tsx": `export default function RootLayout({ children }: { children: React.ReactNode }) {\n return (\n \n {children}\n \n );\n}\n`,
+ });
+ const f = roundTrip(dir, "--agent")["src/instrumentation-client.ts"];
+ expect(f).toContain(`if (process.env.NODE_ENV === "development") {\n import("@genclass/runtime/devtools").then((d) => d.mountDevtools(genclass));\n import("@genclass/runtime/agent").then((a) => a.connectAgent(genclass));\n}`);
+ });
+
+ it("Nuxt 4 and Astro: the agent line in the plugin, and in the inline script", () => {
+ const n4 = project({ "package.json": pkg({ nuxt: "^4.0.0" }), "tsconfig.json": "{}\n", "app/app.vue": "
\n" });
+ const plugin = roundTrip(n4, "--agent")["app/plugins/genclass.client.ts"];
+ expect(plugin).toContain(` if (import.meta.dev) import("@genclass/runtime/devtools").then((d) => d.mountDevtools(genclass));\n if (import.meta.dev) import("@genclass/runtime/agent").then((a) => a.connectAgent(genclass));\n});`);
+ const astro = project({ "package.json": pkg({ astro: "^5" }), "src/pages/index.astro": `x hi\n` });
+ expect(roundTrip(astro, "--agent")["src/pages/index.astro"]).toContain(
+ ``,
+ );
+ });
+
+ it("plain HTML: a module script after the tag, loading the agent entry next to the script URL", () => {
+ const dir = project({
+ "index.html": `\n\n\n \n\n\n\n`,
+ "about.html": `About `,
+ });
+ const after = roundTrip(dir, "--agent", "--cdn", "https://example.test/dist/genclass.global.min.js", "--no-sri");
+ const agent = ``;
+ expect(after["index.html"]).toContain(`\n \n ${agent} \n `);
+ expect(after["about.html"]).toContain(`>${agent}`);
+ const dflt = roundTrip(project({ "index.html": `x \n` }), "--agent")["index.html"];
+ expect(dflt).toContain(`import("https://cdn.jsdelivr.net/npm/@genclass/runtime@${VERSION}/dist/agent.js")`);
+ });
+
+ it("remove takes out a Prettier-wrapped agent line whole, and refuses one that was edited", () => {
+ const dir = viteVue();
+ const before = snapshot(dir);
+ expect(cli(dir, "init", "--yes", "--no-install", "--agent").code).toBe(0);
+ const f = join(dir, "src/main.js");
+ const added = readFileSync(f, "utf8");
+ const line = `if (import.meta.env.DEV) import("@genclass/runtime/agent").then((a) => a.connectAgent(genclass)); // genclass:init`;
+ expect(added).toContain(line);
+ writeFileSync(f, added.replace(line, `if (import.meta.env.DEV)\n import("@genclass/runtime/agent").then((a) =>\n a.connectAgent(genclass),\n ); // genclass:init`));
+ expect(cli(dir, "remove", "--yes").code).toBe(0);
+ expect(snapshot(dir)).toEqual(before);
+ expect(cli(dir, "init", "--yes", "--no-install", "--agent").code).toBe(0);
+ writeFileSync(f, readFileSync(f, "utf8").replace("a.connectAgent(genclass)", "a.connectAgent(genclass, { anyHost: true })"));
+ const r = cli(dir, "remove", "--yes");
+ expect(r.code).not.toBe(0);
+ expect(r.out).toContain("not a statement init writes");
+ });
+});
diff --git a/telemetry-worker/src/pages.ts b/telemetry-worker/src/pages.ts
index 9c55fab7..9ac16baf 100644
--- a/telemetry-worker/src/pages.ts
+++ b/telemetry-worker/src/pages.ts
@@ -369,10 +369,11 @@ export interface OpenSourceChoices {
}
/**
- * The prompt /start/open-source copies: installPrompt's steps without a token, a dashboard or an agent link, with
- * `telemetry: false` (the runtime sends no data anywhere; it still downloads public files from jsDelivr unless the app
- * serves them), the MCP server on the developer's machine and the page check run locally. Pure and self-contained,
- * like installPrompt: the page script runs this same function.
+ * The prompt /start/open-source copies: the two commands (`init --no-telemetry --agent` for the app, `@genclass/mcp
+ * init` for the agent), with `telemetry: false` (the runtime sends no data anywhere; it still downloads public files
+ * from jsDelivr unless the app serves them), no token, the MCP server on the developer's machine and the page check
+ * run locally; the choices are init flags. Pure and self-contained, like installPrompt: the page script runs this
+ * same function.
*/
export function openSourcePrompt(c: OpenSourceChoices = {}, n: PromptNames = PROMPT_NAMES): string {
const guard = !!c.guard;
@@ -380,64 +381,40 @@ export function openSourcePrompt(c: OpenSourceChoices = {}, n: PromptNames = PRO
const logs = !!c.logs;
const own = !!c.selfHost;
const dir = "/genclass-model/";
- // GenClass.init has automatic state discovery off unless asked (autoState: true, with the discover import first)
- const init = ["telemetry: false", "autoState: true"];
- if (guard) init.push('mode: "guard"', ...(eager ? ['aggressiveness: "eager"'] : []), "visual: { on: true, fix: true }");
- if (own) init.push(`model: { baseUrl: "${dir}", ortWasmPaths: "${dir}ort/" }`);
- if (logs) init.push("sinks: [consoleJson()]");
- // the script tag carries all of it but the aggressiveness, which goes in GENCLASS_CONFIG (as in installPrompt)
- const attrs = ['data-telemetry="off"'];
- if (guard) attrs.push('data-mode="guard"', 'data-visual="fix"');
- if (own) attrs.push(`data-model="${dir}"`, `data-ort="${dir}ort/"`);
- if (logs) attrs.push('data-sink="console-json"');
- attrs.push('data-devtools="local"');
- const flags = ["--no-telemetry", ...(guard ? ["--mode guard"] : []), ...(logs ? ["--sink console-json"] : []), ...(own ? [`--model-url ${dir}`] : [])];
- // init writes no visual or aggressiveness option: the prompt says where to add them
+ // every choice is an init flag, except the visual fixes and the aggressiveness, which init does not write
+ const flags = ["--no-telemetry", "--agent", ...(guard ? ["--mode guard"] : []), ...(logs ? ["--sink console-json"] : []), ...(own ? [`--model-url ${dir}`] : []), "--yes"];
const initAdds = guard
- ? `${eager ? 'aggressiveness: "eager" and ' : ""}visual: { on: true, fix: true } to the option file it writes (data-visual="fix" on the tag it writes${eager ? ", and the GENCLASS_CONFIG line above" : ""}; Astro gets a line instead: add visual=fix to its content${eager ? ', and the aggressiveness in a window.GENCLASS_CONFIG script before it' : ""})`
+ ? `add ${eager ? 'aggressiveness: "eager" and ' : ""}visual: { on: true, fix: true } to the option file it writes (data-visual="fix" on the tag it writes${eager ? ', and a line before it' : ""}; Astro gets a line instead: add visual=fix to its content${eager ? ", and the aggressiveness in a window.GENCLASS_CONFIG script before it" : ""})`
: "";
- const local = '["localhost", "127.0.0.1"].includes(location.hostname)';
// A step is a one-element array, numbered at the end (choices add steps); other lines are strings. No named inner
// function: Wrangler's bundler (keepNames) would wrap it in a __name() helper that the page script, which runs this
// function's source, lacks.
const out: (string | [string])[] = [
- "Add GenClass's open-source parts to this web app (Apache-2.0, https://github.com/genclass-dev/GenClass-lib): the @genclass/runtime library in its pages, which reports the bugs that never throw (double submits, stale responses that overwrite newer data, write races, visual bugs), and the @genclass/mcp server on this machine, so you, the coding agent, can see what happens on the dev pages, replay it and prove fixes. No GenClass account and no token: nothing is sent to genclass.dev. Do every step yourself.",
+ "Add GenClass's open-source parts to this web app (Apache-2.0, https://github.com/genclass-dev/GenClass): the @genclass/runtime library in its pages, which reports the bugs that never throw (double submits, stale responses that overwrite newer data, write races, visual bugs), and the @genclass/mcp server on this machine, so you, the coding agent, can see what happens on the dev pages, replay it and prove fixes. No GenClass account and no token: nothing is sent to genclass.dev. Two commands do it; run them yourself.",
"",
- [`Install the runtime with the project's package manager: npm install ${n.pkg} (or pnpm add / yarn add / bun add ${n.pkg}). A site with no build step (plain HTML pages, no bundler) installs nothing: it uses the script tags below.`],
+ ...(own
+ ? [
+ [`Serve the model from the app itself, so its pages download no model from a CDN: npx ${n.pkg} fetch-model public/genclass-model (the folder the project serves as-is: public/ for Vite, Next.js and Astro, static/ for SvelteKit). It downloads the model and onnxruntime-web's files, checks the model files against the sizes and SHA-256 hashes its model card lists, and records onnxruntime-web's hashes in ort/ort.json; the next step's --model-url points at it. On a host with a 25 MiB per-file limit (Cloudflare), run fetch-model public/genclass-model --variant q8 --ort wasm instead (init --model-url adds device: "wasm" when it finds only the WASM build). With a bundler nothing else loads from a CDN. Without one, the runtime's script and what it loads on demand (its model worker, onnxruntime-web's JavaScript, sinks, visual checks, the overlay, the agent link) still come from jsDelivr unless you serve the package's dist/ folder from the app and point the script tag at it (--cdn ; data-base if they are in different folders).`] as [string],
+ ]
+ : []),
[
- "Start it as early as possible, with GenClass's anonymous diagnostics off (telemetry: false), so it sends no data anywhere" +
+ `In the project's root run: npx ${n.pkg} init ${flags.join(" ")} ` +
+ "It finds the framework and package manager, installs the runtime, adds one marked import first in the browser entry (plain HTML pages, no bundler: the script tag, pinned with an integrity hash, in every page's ), the dev-only devtools overlay and the dev-only agent link (which records what happens on local pages for the GenClass MCP server, talks only to 127.0.0.1 and is never part of a production build), and writes telemetry: false into a marked option file next to the entry (data-telemetry=\"off\" on the tag), so GenClass's anonymous diagnostics are off and it sends no data anywhere" +
(own ? "" : "; the browser still downloads its model and onnxruntime-web, public files, from cdn.jsdelivr.net (about 13 MB, 18 MB on WebGPU devices, then cached) unless the app serves them") +
- ". With a bundler, in the browser entry (main.ts, the root layout or the root component), with the discover import first, before React, Redux or Zustand load:",
+ ". It shows the diff; --yes applies it. " +
+ (guard
+ ? `Mode guard: when GenClass is sure, it acts with minimal, reversible steps (it drops a stale response or fixes a CSS bug on the page) and never changes a response${eager ? '; aggressiveness "eager" lets it act on smaller signals' : ""}. Then ${initAdds}.`
+ : "The mode stays observe: GenClass reports and never changes what the app does.") +
+ ' React state, Redux stores (configureStore, or createStore with the Redux DevTools compose) and Zustand stores made with the devtools middleware are found automatically; Pinia, Svelte stores, signals and a plain page\'s DOM are watched only for state the app registers with GenClass.runtime.atom("name", initial) or GenClass.runtime.guard("name", { get, set }), written through the handle (one atom per response, such as a search\'s query and its results): do that only if I ask.',
],
- ' import "@genclass/runtime/discover"; // first: lets GenClass find React, Redux and Zustand state',
- ...(logs ? [' import { consoleJson } from "@genclass/runtime/sinks/console-json";'] : []),
- ' import { GenClass } from "@genclass/runtime";',
- ` const rt = GenClass.init({ ${init.join(", ")} });`,
- " Without a bundler, in the of every HTML page, before the page's own scripts:",
- ...(eager ? [' '] : []),
- ` `,
- " and in the page's scripts the handle (rt below) is GenClass.runtime.",
- ` (Or npx ${n.pkg} init ${flags.join(" ")} --yes does steps 1 and 2 and shows the diff, with a bundler or plain HTML pages: it starts GenClass with its zero-code entry (the /auto import with an option file, or the script tag pinned with an integrity hash), which finds React, Redux and Zustand state by itself, and adds step 3's dev-only overlay; the handle is then GenClass.runtime${guard ? `; add ${initAdds}` : ""}${own ? "; run the fetch-model command below before it" : ""}.)`,
[
- (guard
- ? `Mode guard: when GenClass is sure, it acts with minimal, reversible steps (it drops a stale response or fixes a CSS bug on the page) and never changes a response${eager ? '; aggressiveness "eager" lets it act on smaller signals' : ""}.`
- : "Keep the default mode, observe: GenClass reports and never changes what the app does.") +
- ' In development builds also mount the devtools overlay, which shows what GenClass sees on the page: if (import.meta.env.DEV) import("@genclass/runtime/devtools").then((d) => d.mountDevtools(rt)); (Next.js: process.env.NODE_ENV === "development"; the script tag\'s data-devtools="local" does the same).',
+ `Run: npx -y ${n.mcp} init. It writes the GenClass MCP server into .mcp.json for Claude Code (npx -y ${n.mcp} config prints the block for Cursor, VS Code, Codex, Gemini CLI and others) and the genclass skill, the procedure you follow for timing bugs, to .claude/skills/genclass/SKILL.md; then reload your MCP servers. It runs on this machine, its bridge listens on 127.0.0.1 only, and it needs no account: leave GENCLASS_DASHBOARD and GENCLASS_REPORT unset (either one sends to a GenClass dashboard). The app-side lines it prints are already done by the init command above. Its tools: genclass_status, genclass_findings, genclass_explain, genclass_replay, genclass_explore, genclass_scan.`,
],
- ['Connect the state that responses write (search results, carts, lists, forms), so GenClass sees each write with the response or click that caused it. React state, Redux stores (configureStore, or createStore with the Redux DevTools compose) and Zustand stores made with the devtools middleware are found automatically (the discover import with autoState: true above; the script tag and init\'s /auto import do it by default); otherwise create it with rt.atom("name", initial) or wrap the store you have with rt.guard("name", { get, set }), and write through the handle. Values one response writes together (a search\'s query and its results) go in one atom, written once per response, so GenClass can drop a stale response as one write: const search = rt.atom("search", { query: "", results: [] }); then search.set((s) => ({ ...s, query: data.q, results: data.results })) and render from search.subscribe.'],
- ['Development builds only, add the agent link: import { connectAgent } from "@genclass/runtime/agent"; if (import.meta.env.DEV) connectAgent(rt); (Next.js: process.env.NODE_ENV === "development"). It records what happens on local pages for the GenClass MCP server, talks only to 127.0.0.1 and is never part of a production build.'],
- ` Without a bundler, after the runtime's script tag: `,
- [`Add the GenClass MCP server to yourself: npx -y ${n.mcp} init writes .mcp.json for Claude Code (npx -y ${n.mcp} config prints the block for Cursor, VS Code, Codex, Gemini CLI and others); then reload your MCP servers. It runs on this machine, its bridge listens on 127.0.0.1 only, and it needs no account: leave GENCLASS_DASHBOARD and GENCLASS_REPORT unset (either one sends to a GenClass dashboard). init also prints setup lines for the app with a bare GenClass.init(): keep the setup from steps 2 and 5 instead. Its tools: genclass_status, genclass_findings, genclass_explain, genclass_replay, genclass_explore, genclass_scan.`],
...(logs
? [
['Findings print as [GenClass] lines in the browser console, and the console-json sink also prints each one as one JSON line, for the log shipper the app already uses. If the team has its own endpoint for them, the webhook sink sends batched POSTs there instead: import { webhook } from "@genclass/runtime/sinks/webhook"; sinks: [webhook({ url: "" })], requests: { ignore: [""] } (so GenClass does not watch its own POSTs; data-sink="webhook:" on the script tag does both). Ask me for that URL rather than inventing one.'] as [string],
]
: []),
- ...(own
- ? [
- [`Serve the model from the app itself, so its pages download no model from a CDN: npx ${n.pkg} fetch-model public/genclass-model (the folder the project serves as-is: public/ for Vite, Next.js and Astro, static/ for SvelteKit), before init if you use init. It downloads the model and onnxruntime-web's files, checks the model files against the sizes and SHA-256 hashes its model card lists, and records onnxruntime-web's hashes in ort/ort.json; the model option above points at it. On a host with a 25 MiB per-file limit (Cloudflare), run fetch-model public/genclass-model --variant q8 --ort wasm instead and add device: "wasm" to the model option (data-device="wasm" on the script tag; init --model-url adds it when it finds only the WASM build). With a bundler nothing else loads from a CDN. Without one, the runtime's script and what it loads on demand (its model worker, onnxruntime-web's JavaScript, sinks, visual checks, the overlay, the agent link) still come from jsDelivr unless you serve the package's dist/ folder from the app and point the script tag and the agent link's import at it (data-base if they are in different folders).`] as [string],
- ]
- : []),
[`Run the dev server and load a page to check that the app builds and runs without errors. Until the MCP server runs (your next conversation), the page logs a failed request to 127.0.0.1:47357: that is the agent link finding no server, and expected. In your next conversation, reload a dev page and genclass_status lists it. Then check a page for visual bugs with genclass_scan on its local URL, or from a terminal: npx ${n.pkg} scan http://localhost:5173/ --local (keep --local). It runs headless Chromium on this machine and needs Playwright: if the scan says it is missing, ask me before adding playwright as a dev dependency and downloading Chromium (about 600 MB): npm i -D playwright && npx playwright install chromium; or skip the scan and say so. Do not use hosted: true: it sends the page URL to GenClass's hosted page check, which is not open source.`],
...(c.deploy
? [["Deploy it, as chosen, with the command this project already uses (a deploy script in package.json, wrangler deploy for a Cloudflare Worker, vercel deploy --prod, and so on), then check that the deployed site serves the change."] as [string]]
@@ -462,11 +439,6 @@ function choiceOpt(k: string, label: string, note: string, sub = false): string
return `${label} ${note} `;
}
-/** The commands' agent link, before its development check (which is the bundler's: init writes the same one). */
-const AGENT_LINK_HEAD = `// in the app's entry, after the lines init added
-import { GenClass } from "@genclass/runtime";
-import { connectAgent } from "@genclass/runtime/agent";`;
-
/** The prompt block's styles on genclass.dev's palette (the dashboard's .copts and .cprompt, DASH_CSS, re-tokened). */
const OSS_CSS = `
.copts{display:grid;gap:6px;max-width:72ch}
@@ -517,7 +489,7 @@ export function openSourcePage(nonce: string): string {
Copy the prompt for your coding agent
-
Paste it into Claude Code, Cursor or Codex: it adds GenClass to your app and the MCP server to the agent, with nothing to sign up for.
+
Paste it into Claude Code, Cursor or Codex: two commands add GenClass to your app and the MCP server and the genclass skill to the agent, with nothing to sign up for.
@@ -533,12 +505,10 @@ export function openSourcePage(nonce: string): string {
Or run the commands yourself
- ${cmd("Add the runtime to your app", `npx ${RUNTIME_PKG} init --no-telemetry`)}
- ${cmd("Connect the dev pages to the MCP server: Vite", `${AGENT_LINK_HEAD}\nif (import.meta.env.DEV && GenClass.runtime) connectAgent(GenClass.runtime);`)}
- ${cmd("The same for Next.js and webpack", `${AGENT_LINK_HEAD.replace("the app's entry", "the app's entry (Next.js: instrumentation-client.ts)")}\nif (process.env.NODE_ENV === "development" && GenClass.runtime) connectAgent(GenClass.runtime);`)}
- ${cmd("Add the MCP server for Claude Code", `npx -y ${MCP_PKG} init`)}
+ ${cmd("Add the runtime to your app, with the dev-only agent link", `npx ${RUNTIME_PKG} init --no-telemetry --agent`)}
+ ${cmd("Add the MCP server and the genclass skill for Claude Code", `npx -y ${MCP_PKG} init`)}
${cmd("Check a page for visual bugs", `npx ${RUNTIME_PKG} scan http://localhost:5173/ --local`)}
- init shows the diff and asks before it writes; add --mode guard for guard. Other agents: npx -y ${MCP_PKG} config <client> prints the block for Cursor, VS Code, Codex, Gemini CLI and others; keep GENCLASS_DASHBOARD and GENCLASS_REPORT out of it. The scan needs Playwright (npm i -D playwright && npx playwright install chromium).
+ init shows the diff and asks before it writes; add --mode guard for guard. Until the MCP server runs, a dev page logs one failed request to 127.0.0.1:47357 (the agent link finding no server). Other agents: npx -y ${MCP_PKG} config <client> prints the block for Cursor, VS Code, Codex, Gemini CLI and others; keep GENCLASS_DASHBOARD and GENCLASS_REPORT out of it. The scan needs Playwright (npm i -D playwright && npx playwright install chromium).
Want a dashboard without sending data to us? The collector is open source too:
run it on your own Cloudflare account .
diff --git a/telemetry-worker/test/bundle.test.ts b/telemetry-worker/test/bundle.test.ts
index e6e51c59..c86959cf 100644
--- a/telemetry-worker/test/bundle.test.ts
+++ b/telemetry-worker/test/bundle.test.ts
@@ -57,7 +57,7 @@ describe("page scripts survive Wrangler's bundling (keepNames)", () => {
new Function("window", "document", "location", "navigator", script)(win, win.document, win.location, win.navigator);
(win.document.querySelector('#choices [data-choice="guard"]') as unknown as HTMLInputElement).click();
expect(win.document.getElementById("cp")!.getAttribute("data-copy")).toBe(mod.openSourcePrompt({ guard: true }));
- expect(win.document.getElementById("cp")!.getAttribute("data-copy")).toContain('mode: "guard"');
+ expect(win.document.getElementById("cp")!.getAttribute("data-copy")).toContain("--mode guard");
await win.happyDOM.close();
});
});
diff --git a/telemetry-worker/test/pages.test.ts b/telemetry-worker/test/pages.test.ts
index 9030dcef..f17f86c6 100644
--- a/telemetry-worker/test/pages.test.ts
+++ b/telemetry-worker/test/pages.test.ts
@@ -1284,28 +1284,26 @@ describe("/start/open-source: the open-source parts with no account, no token an
return { html, win, doc, urls, copied, box, copy, close: () => win.happyDOM.close() };
}
- it("the default prompt: no token, telemetry off, observe, the agent link and the MCP server without a dashboard, the local scan", () => {
+ it("the default prompt: two commands (init --no-telemetry --agent, @genclass/mcp init), no token, observe, the skill, the local scan", () => {
const p = openSourcePrompt();
- expect(p).toContain("No GenClass account and no token: nothing is sent to genclass.dev.");
- expect(p).toContain(`npm install ${RUNTIME_PKG}`);
- expect(p).toContain("const rt = GenClass.init({ telemetry: false, autoState: true });");
- // GenClass.init finds React, Redux and Zustand state only with the discover import first and autoState: true
- expect(p).toContain('import "@genclass/runtime/discover"; // first');
- expect(p.indexOf('import "@genclass/runtime/discover"')).toBeLessThan(p.indexOf('import { GenClass } from "@genclass/runtime"'));
+ expect(p).toContain("No GenClass account and no token: nothing is sent to genclass.dev. Two commands do it; run them yourself.");
+ expect(p).toContain(`\n1. In the project's root run: npx ${RUNTIME_PKG} init --no-telemetry --agent --yes It finds the framework`);
+ expect(p).toContain("the dev-only devtools overlay and the dev-only agent link (which records what happens on local pages for the GenClass MCP server, talks only to 127.0.0.1 and is never part of a production build)");
+ expect(p).toContain('writes telemetry: false into a marked option file next to the entry (data-telemetry="off" on the tag)');
// no data is sent, but the public files still come from jsDelivr unless the app serves them; the prompt says so
- expect(p).toContain("so it sends no data anywhere; the browser still downloads its model and onnxruntime-web, public files, from cdn.jsdelivr.net");
+ expect(p).toContain("so GenClass's anonymous diagnostics are off and it sends no data anywhere; the browser still downloads its model and onnxruntime-web, public files, from cdn.jsdelivr.net");
+ expect(p).toContain("(about 13 MB, 18 MB on WebGPU devices, then cached)");
expect(p).not.toContain("sends nothing anywhere");
- expect(p).toContain(``);
- expect(p).toContain(`npx ${RUNTIME_PKG} init --no-telemetry --yes does steps 1 and 2`);
- expect(p).toContain("and adds step 3's dev-only overlay; the handle is then GenClass.runtime.)");
- expect(p).toContain("Keep the default mode, observe");
- expect(p).toContain('rt.atom("search", { query: "", results: [] })');
- expect(p).toContain('import { connectAgent } from "@genclass/runtime/agent"; if (import.meta.env.DEV) connectAgent(rt);');
- expect(p).toContain(`import("${CDN_SCRIPT}/dist/agent.js")`);
- expect(p).toContain(`npx -y ${MCP_PKG} init writes .mcp.json`);
+ expect(p).toContain("The mode stays observe: GenClass reports and never changes what the app does.");
+ // discovery covers React state, Redux through its DevTools hooks and Zustand with devtools; registering is on request only
+ expect(p).toContain("Zustand stores made with the devtools middleware are found automatically");
+ expect(p).toContain('GenClass.runtime.atom("name", initial)');
+ expect(p).toContain("do that only if I ask.");
+ expect(p).toContain(`\n2. Run: npx -y ${MCP_PKG} init. It writes the GenClass MCP server into .mcp.json for Claude Code`);
+ expect(p).toContain("and the genclass skill, the procedure you follow for timing bugs, to .claude/skills/genclass/SKILL.md");
expect(p).toContain("leave GENCLASS_DASHBOARD and GENCLASS_REPORT unset");
- // the MCP server's init prints its own setup lines (a bare GenClass.init()): the prompt keeps its own
- expect(p).toContain("keep the setup from steps 2 and 5 instead");
+ // the MCP server's init prints its own app-side lines: init --agent already did them
+ expect(p).toContain("The app-side lines it prints are already done by the init command above.");
expect(p).toContain(`npx ${RUNTIME_PKG} scan http://localhost:5173/ --local`);
expect(p).toContain("Do not use hosted: true: it sends the page URL to GenClass's hosted page check, which is not open source.");
// the scan needs Playwright: the agent asks before adding the dev dependency and downloading Chromium
@@ -1313,44 +1311,45 @@ describe("/start/open-source: the open-source parts with no account, no token an
// the agent link's failed request before the MCP server runs is expected
expect(p).toContain("the page logs a failed request to 127.0.0.1:47357");
expect(p).toContain("In your next conversation, reload a dev page and genclass_status lists it.");
- // discovery covers React state, Redux through its DevTools hooks and Zustand with devtools; the prompt says so
- expect(p).toContain("Zustand stores made with the devtools middleware are found automatically");
- expect(p).toContain("(about 13 MB, 18 MB on WebGPU devices, then cached)");
+ // nothing hand-written: no import lines, no GenClass.init call, no script tag, no connectAgent
+ expect(p).not.toContain('import "');
+ expect(p).not.toContain("import {");
+ expect(p).not.toContain("GenClass.init(");
+ expect(p).not.toContain("');
- expect(p).toContain(``);
- expect(p).toContain(`npx ${RUNTIME_PKG} init --no-telemetry --mode guard --sink console-json --model-url /genclass-model/ --yes`);
+ expect(p).toContain(`\n1. Serve the model from the app itself, so its pages download no model from a CDN: npx ${RUNTIME_PKG} fetch-model public/genclass-model`);
+ expect(p).toContain('run fetch-model public/genclass-model --variant q8 --ort wasm instead (init --model-url adds device: "wasm" when it finds only the WASM build)');
+ expect(p).toContain(`\n2. In the project's root run: npx ${RUNTIME_PKG} init --no-telemetry --agent --mode guard --sink console-json --model-url /genclass-model/ --yes `);
// init writes no visual or aggressiveness option: the prompt says where they go
- expect(p).toContain('add aggressiveness: "eager" and visual: { on: true, fix: true } to the option file it writes (data-visual="fix" on the tag it writes, and the GENCLASS_CONFIG line above; Astro gets a line instead: add visual=fix to its content, and the aggressiveness in a window.GENCLASS_CONFIG script before it); run the fetch-model command below before it.)');
- expect(openSourcePrompt({ guard: true })).toContain('; add visual: { on: true, fix: true } to the option file it writes (data-visual="fix" on the tag it writes; Astro gets a line instead: add visual=fix to its content).)');
- expect(p).toContain("Mode guard: when GenClass is sure");
- expect(p).toContain("the webhook sink sends batched POSTs there instead");
- expect(p).toContain('sinks: [webhook({ url: "" })], requests: { ignore: [""] }');
- expect(p).toContain(`npx ${RUNTIME_PKG} fetch-model public/genclass-model`);
- expect(p).toContain('run fetch-model public/genclass-model --variant q8 --ort wasm instead and add device: "wasm" to the model option (data-device="wasm" on the script tag');
+ expect(p).toContain('Mode guard: when GenClass is sure, it acts with minimal, reversible steps (it drops a stale response or fixes a CSS bug on the page) and never changes a response; aggressiveness "eager" lets it act on smaller signals. Then add aggressiveness: "eager" and visual: { on: true, fix: true } to the option file it writes (data-visual="fix" on the tag it writes, and a line before it; Astro gets a line instead: add visual=fix to its content, and the aggressiveness in a window.GENCLASS_CONFIG script before it).');
+ expect(openSourcePrompt({ guard: true })).toContain('Then add visual: { on: true, fix: true } to the option file it writes (data-visual="fix" on the tag it writes; Astro gets a line instead: add visual=fix to its content).');
+ expect(openSourcePrompt({ guard: true })).not.toContain("eager");
// the model served by the app: no jsDelivr download for it to mention
expect(p).not.toContain("still downloads");
+ expect(p).toContain("the webhook sink sends batched POSTs there instead");
+ expect(p).toContain('sinks: [webhook({ url: "" })], requests: { ignore: [""] }');
expect(p).toContain("Deploy it, as chosen");
- expect(p).toMatch(/\n11\. Tell me what you changed and where it is deployed/);
+ const nums = [...p.matchAll(/^(\d+)\. /gm)].map((m) => Number(m[1]));
+ expect(nums).toEqual([1, 2, 3, 4, 5, 6, 7]);
+ expect(p).toMatch(/\n7\. Tell me what you changed and where it is deployed/);
// eager only with guard
expect(openSourcePrompt({ eager: true })).toBe(openSourcePrompt());
});
@@ -1377,16 +1376,10 @@ describe("/start/open-source: the open-source parts with no account, no token an
expect(r.copied).toEqual([openSourcePrompt({ logs: true, selfHost: true, deploy: true })]);
// the commands copy too
const cmds = [...r.doc.querySelectorAll(".cmds [data-copy]")].map((b) => b.getAttribute("data-copy"));
- expect(cmds).toEqual([
- `npx ${RUNTIME_PKG} init --no-telemetry`,
- `// in the app's entry, after the lines init added\nimport { GenClass } from "@genclass/runtime";\nimport { connectAgent } from "@genclass/runtime/agent";\nif (import.meta.env.DEV && GenClass.runtime) connectAgent(GenClass.runtime);`,
- `// in the app's entry (Next.js: instrumentation-client.ts), after the lines init added\nimport { GenClass } from "@genclass/runtime";\nimport { connectAgent } from "@genclass/runtime/agent";\nif (process.env.NODE_ENV === "development" && GenClass.runtime) connectAgent(GenClass.runtime);`,
- `npx -y ${MCP_PKG} init`,
- `npx ${RUNTIME_PKG} scan http://localhost:5173/ --local`,
- ]);
+ expect(cmds).toEqual([`npx ${RUNTIME_PKG} init --no-telemetry --agent`, `npx -y ${MCP_PKG} init`, `npx ${RUNTIME_PKG} scan http://localhost:5173/ --local`]);
// the choices are a fieldset with a visible legend; the commands' titles are h3 under the section's h2
expect(r.doc.querySelector("fieldset#choices > legend")!.textContent).toContain("What the prompt sets up");
- expect(r.doc.querySelectorAll(".cmds h3").length).toBe(5);
+ expect(r.doc.querySelectorAll(".cmds h3").length).toBe(3);
expect(r.doc.querySelectorAll(".cmds h2").length).toBe(1);
expect(r.urls).toEqual([]);
await r.close();
From b3c36e7b656d9d9267826f7457f98f14cae645e0 Mon Sep 17 00:00:00 2001
From: Claude
Date: Mon, 2 Nov 2026 17:52:21 +0000
Subject: [PATCH 02/11] Onboarding docs from the fresh-eyes review: INSTALL.md
on the current line, the script-tag agent link in AGENT.md, what you will see
on /start/open-source, the skill's listings
- INSTALL.md names 0.3.0-beta.5 and 0.2.3, pins its script tags to beta.5 (SINKS.md too; beta.0 is inside the
mode-raise advisory's range), gains the --sync and --no-network rows its help already prints, and says to reload a
dev page once the MCP server runs.
- AGENT.md no longer says the script-tag build has no agent entry: init --agent writes the module script.
- README.md names @genclass/mcp 0.2.1; the worker's MCP_PKG follows.
- /start/open-source says what the developer will see (the Model ready line, the overlay, genclass_status).
- docs/adoption/listings/skills.md: where the genclass skill gets listed (skills.sh by installs, gh skill,
cursor.directory, the curated lists) and what each needs; mcp.md points at it.
Co-Authored-By: Claude Fable 5.1
Claude-Session: https://claude.ai/code/session_01Fqwfq3CizvxvgyXp6wY8WR
---
README.md | 4 +-
docs/adoption/listings/mcp.md | 3 +
docs/adoption/listings/skills.md | 248 +++++++++++++++++++++++++++++++
docs/runtime/AGENT.md | 4 +-
docs/runtime/INSTALL.md | 15 +-
docs/runtime/SINKS.md | 2 +-
telemetry-worker/src/pages.ts | 10 +-
7 files changed, 275 insertions(+), 11 deletions(-)
create mode 100644 docs/adoption/listings/skills.md
diff --git a/README.md b/README.md
index 16b122a3..ea0a4120 100644
--- a/README.md
+++ b/README.md
@@ -152,7 +152,7 @@ The full tables, with every false-intervention rate next to its recall, are unde
## New: your coding agent can see the race, replay it, and prove the fix
-`@genclass/mcp` (`0.2.0`, on npm since 2026-10-25) is an MCP server for Claude Code and other coding agents. Your
+`@genclass/mcp` (`0.2.1`, on npm since 2026-10-28) is an MCP server for Claude Code and other coding agents. Your
app's development build (`@genclass/runtime` `0.3.0-beta.1` or later) connects to it with one line, and the agent
gets every click, request, the order the responses arrived and what they wrote, uncaught errors with the click and
request behind them, and the on-device model's detections. It can run your steps again with the network answering in
@@ -447,7 +447,7 @@ a new tag and regenerated data (`training/curriculum/rt.py` mirrors the renderer
|---|---|
| [`packages/runtime`](packages/runtime) | `@genclass/runtime`, the library: observers, causality, stores and adapters, learned baselines, relations and profiles, facts, triage, policy gate, actions, model host (Web Worker, ONNX Runtime Web on WebGPU or WASM), measured visual checks, devtools overlay. [README](packages/runtime/README.md) · [CHANGELOG](packages/runtime/CHANGELOG.md) |
| [`packages/runtime-model`](packages/runtime-model) | `@genclass/runtime-model`, the default model package (data only; `files/` is gitignored and filled at release time) and its [model card](packages/runtime-model/MODEL_CARD.md) |
-| [`packages/mcp`](packages/mcp) | `@genclass/mcp` (`0.2.0` on npm), the MCP server for coding agents: pages connect through `@genclass/runtime/agent`; the agent gets findings in causal order, replays, explore verdicts, generated regression tests and, with `genclass_scan`, the page audit ([AGENT.md](docs/runtime/AGENT.md)). [README](packages/mcp/README.md) · [CHANGELOG](packages/mcp/CHANGELOG.md) |
+| [`packages/mcp`](packages/mcp) | `@genclass/mcp` (`0.2.1` on npm), the MCP server for coding agents: pages connect through `@genclass/runtime/agent`; the agent gets findings in causal order, replays, explore verdicts, generated regression tests and, with `genclass_scan`, the page audit ([AGENT.md](docs/runtime/AGENT.md)). [README](packages/mcp/README.md) · [CHANGELOG](packages/mcp/CHANGELOG.md) |
| [`packages/playwright`](packages/playwright) | `@genclass/playwright` (unreleased), GenClass for Playwright: a fixture that puts the runtime on every page under test (observe mode, seeded network chaos with `page.route`, the model skipped by default) and writes one race file per test, and a reporter that turns those files into one markdown report for the pull request, with the evidence line and what reproduced across seeds. [README](packages/playwright/README.md) |
| [`packages/nuxt`](packages/nuxt), [`packages/astro`](packages/astro) | `@genclass/nuxt` and `@genclass/astro` (unreleased): the runtime as a Nuxt module and as an Astro integration, one line in the framework's config, with options for the mode, the token, telemetry and the devtools overlay; browser only. [Nuxt README](packages/nuxt/README.md) · [Astro README](packages/astro/README.md) |
| [`packages/sv`](packages/sv) | `@genclass/sv` (unreleased), a community add-on for the Svelte CLI: `npx sv add @genclass` sets up GenClass in a SvelteKit app (the dependency, its import first in `src/hooks.client`, the devtools overlay in development). [README](packages/sv/README.md) |
diff --git a/docs/adoption/listings/mcp.md b/docs/adoption/listings/mcp.md
index 0d2bfa18..497483d5 100644
--- a/docs/adoption/listings/mcp.md
+++ b/docs/adoption/listings/mcp.md
@@ -371,6 +371,9 @@ Source: mxschmitt/awesome-playwright `README.md` (section "AI & Agents", alphabe
## Skill and plugin directories (2026-10-28)
+The skill's own listings (skills.sh, `gh skill`, cursor.directory, the curated lists, what the skill file needs where)
+are in [skills.md](skills.md) (2026-11-02); this section keeps the plugin and MCP-server directories.
+
The skill is `skills/genclass/SKILL.md`, at the root of both repositories; the plugin is the root of genclass-plugin.
Verified on this machine on 2026-10-28 from the pushed repository: `claude plugin marketplace add`, `codex plugin
marketplace add` and `codex plugin add genclass@genclass`, `gemini extensions install`, `gh skill install` (gh 2.103)
diff --git a/docs/adoption/listings/skills.md b/docs/adoption/listings/skills.md
new file mode 100644
index 00000000..6405a22a
--- /dev/null
+++ b/docs/adoption/listings/skills.md
@@ -0,0 +1,248 @@
+# Listing the `genclass` skill: every skill directory, ready to send
+
+Where a SKILL.md-based skill (the Agent Skills format, agentskills.io) gets listed, what each place reads, and what
+is left to do for `skills/genclass/SKILL.md`. Checked on 2026-11-02; each section names its source. Nothing here has
+been submitted. This file takes over the skill items of the last section of `mcp.md` ("Skill and plugin
+directories", 2026-10-28); the plugin and MCP-server directories stay there.
+
+Not readable from the session that wrote this (facts from those sites come from search excerpts, the tool's own
+repository or the 2026-10-28 notes in `mcp.md`, and are marked "not verified"): skills.sh, vercel.com, agentskills.io,
+docs.github.com, cli.github.com, github.blog, the `gh` manual mirrors, cursor.com, smithery.ai, developers.openai.com,
+docs.tessl.io, claude-plugins.dev, skillsmp.com, agenticskills.io, awesomeskill.ai.
+
+## What is true today (keep every entry to this)
+
+- **The skill.** `skills/genclass/SKILL.md` at the root of `genclass-dev/GenClass` (the repository was renamed from
+ `GenClass-lib` on 2026-11-02; the old name still resolves, see below) and at the root of `genclass-dev/genclass-plugin`,
+ byte-identical to `packages/mcp/plugin/skills/genclass/SKILL.md` (`packages/mcp/test/manifests.test.ts` keeps it so
+ and `npm run sync -w @genclass/mcp` refreshes it). 80 lines; frontmatter `name: genclass`, `license: Apache-2.0`,
+ `description` of 509 characters; no scripts, references or assets. It is the procedure; the triggers are its
+ description and the server's instructions (`docs/runtime/AGENT.md` section 4.2).
+- **It is valid.** Against the Agent Skills specification (agentskills/agentskills `docs/specification.mdx`): `name` at
+ most 64 characters, lowercase letters, digits and hyphens, equal to the directory name; `description` non-empty, at
+ most 1,024 characters; `license`, `compatibility` (at most 500 characters), `metadata` (string map) and
+ `allowed-tools` (experimental) optional; body under 500 lines. `claude plugin validate` (Claude Code 2.1.316) passes
+ on `packages/mcp/plugin` ("These checks found nothing to report") and on `skills/`. The spec's own validator,
+ `skills-ref validate`, could not be installed in the session (the install was refused), so run it once by hand.
+- **What it needs to be useful.** The GenClass MCP server (`@genclass/mcp`, npm) on the developer's machine and a page of
+ their dev server connected through `@genclass/runtime/agent`. Installed alone, the skill's last section tells the
+ agent how to add the server; it does nothing by itself. Every entry says "with the GenClass MCP server".
+- **Install lines, run on 2026-11-02** with the skills CLI 1.7.4 (npm `skills`, Vercel Labs, published 2026-10-19),
+ telemetry off, `--list` only: `npx skills add genclass-dev/genclass-plugin`, `npx skills add genclass-dev/GenClass` and
+ the old `npx skills add genclass-dev/GenClass-lib` each clone the repository and find exactly one skill, `genclass`,
+ with the description above. The GenClass clone is the whole 109 MB repository, so the install lines keep naming
+ `genclass-plugin`. `gh skill install genclass-dev/genclass-plugin genclass` was verified on 2026-10-28 with gh 2.103
+ (`mcp.md`); the session's gh is 2.89, which has no `skill` command, so it was not re-run.
+- **Releases and stars.** `GenClass`'s latest GitHub release is v0.2.1 (2026-10-11), before the skill existed, and
+ `genclass-plugin` has no release; the tools that read the latest release before the default branch (`gh skill`,
+ Gemini CLI, per `mcp.md`) therefore work from `genclass-plugin` only. Stars: `GenClass` 7, `genclass-plugin` 0. Lists
+ with a star or usage threshold (sections 7.2 and 7.3) are closed to it for now.
+- **Measured claims.** Only what `mcp.md` states: one page, the race found in 5 of 6 reordered runs, 0 of 6 differing
+ on the fixed page. No rate beyond that in any entry.
+- **GitHub topics.** `genclass-plugin`: `agent-skills`, `claude-code-plugin`, `claude-plugin`, `codex-plugin`,
+ `gemini-cli-extension`, `mcp`, `mcp-server`, `debugging`, `frontend`, `playwright`, `race-condition`. `GenClass` carries
+ `claude-code-plugin`, `gemini-cli-extension` and `mcp-server` but not `agent-skills` (41,066 public repositories carry
+ that topic). Adding it is a repository setting, done by hand.
+
+### Texts to reuse
+
+- Ten words or fewer (section 7.2): `Find and prove fixes for timing bugs in web apps.`
+- One sentence: `A skill for coding agents with the GenClass MCP server: record what happens inside a web app's pages in causal order, re-run a page with responses delivered in different orders to find race conditions, replay one exact order, and prove the fix with a generated Playwright test.`
+- The skill's own description (509 characters) is what the skills CLI, skills.sh and Claude Code show; reuse it where a
+ form asks for the description and allows it.
+
+## Order
+
+1. Nothing to submit: skills.sh lists installs by itself (section 1); the plugin bundle already submitted to Anthropic's
+ directory is the only route there (section 3); Codex and Gemini CLI read the plugin repository (sections 4, 5). In
+ this repository: the skills.sh badge, the `--path` install line for Gemini CLI, and the `agent-skills` topic on
+ `GenClass` (by hand).
+2. cursor.directory (web form, detects `skills/*/SKILL.md`; section 6), then github/awesome-copilot (a pull request that
+ copies the skill into that repository under MIT; section 2.2, needs the owner's decision on the licence).
+3. Later, once installs and stars exist: VoltAgent/awesome-agent-skills, travisvn/awesome-claude-skills,
+ ComposioHQ/awesome-claude-skills (section 7). The crawlers in section 8 need nothing and were not reachable.
+
+---
+
+## 1. skills.sh (Vercel Labs) and the `skills` CLI
+
+Source: npm `skills` 1.7.4 (`README.md`, `docs/creating-skills.md`, `docs/commands.md`, `docs/agents.md`,
+`docs/troubleshooting.md`, and `dist/cli.mjs` for the telemetry); the runs above. skills.sh/about: not verified
+(search excerpts only).
+
+- **What it is.** The CLI installs skills from any public git repository into the skill folders of 79 agents (Claude
+ Code `.claude/skills/`, Codex, Cursor, Copilot, Gemini CLI, OpenCode, Antigravity and others `.agents/skills/`,
+ Windsurf `.windsurf/skills/`; `-g` for the user scope, `-a` to pick agents, `--skill` to pick skills, `--copy` instead
+ of symlinks, `-y`, `--list`). skills.sh is the directory built from its telemetry.
+- **How `npx skills add genclass-dev/GenClass` works.** It clones the repository (GitHub shorthand, URL, GitLab, Azure,
+ any git URL, a local path, or a direct `SKILL.md` or archive URL), then looks for `SKILL.md` in the root, `skills/`
+ (and its `.curated/`, `.experimental/`, `.system/`), `.agents/skills/`, `.claude/skills/`, `.windsurf/skills/` and
+ about 50 other agent folders, each walked three levels deep (a shallower `SKILL.md` shadows deeper ones;
+ `--full-depth` searches outside them), plus skills declared in `.claude-plugin/marketplace.json` or `plugin.json`
+ (`skills.sh.json` at the root can add folders; nothing found means a recursive search). Then it asks which skills and
+ agents (non-interactive inside an agent), links one canonical copy into each agent's folder, records the source for
+ `update`, `check` and `remove`, and sends one install event.
+- **The listing is the telemetry.** After an install from a GitHub repository that GitHub confirms is public, the CLI
+ requests `https://www.skills.sh/tele/t` with `event=install`, `source` (owner/repo), `skills`, `agents`, `global`, the
+ skill file URLs, the CLI version, `ci=1` in CI and the detected agent; `find` sends the query; `DISABLE_TELEMETRY=1` or
+ `DO_NOT_TRACK=1` turns it off ("anonymous usage data", "No personal information"). Before an install it asks
+ `https://www.skills.sh/tele/audit` for the partner security audits of those skills. Not verified (About page
+ excerpts): the site "indexes public skills shipped through the open skills CLI and ranks them by anonymous install
+ telemetry", each page shows the source repository, install count, the agents it is most used on and the audit
+ results, one skill under several repository names is merged at query time, inflated counts are hidden. No
+ submission, form or claim step was found.
+- **Status.** Listed since the owner's installs on 2026-10-28 at `skills.sh/genclass-dev/genclass-lib/genclass`
+ (`mcp.md`); `genclass-plugin` and the renamed `genclass-dev/genclass` get pages the same way (whether the site merges
+ the three: not verified). Nothing to do; `metadata.internal` must stay absent (it hides a skill from the CLI).
+- **In this repository.** The badge the CLI's own README uses, for `packages/mcp/README.md` and the plugin README:
+ `[](https://skills.sh/genclass-dev/genclass-plugin)`
+ (format from vercel-labs/skills; whether the badge renders for this repository is not verified).
+
+## 2. GitHub CLI `gh skill` and GitHub Copilot
+
+### 2.1 `gh skill`
+
+Source: `mcp.md` (install verified 2026-10-28); npm `skills` `docs/agents.md` for Copilot's folders. The GitHub
+changelog ("Manage agent skills with GitHub CLI", 2026-04-16), docs.github.com and the `gh skill` manual pages were not
+reachable: the command details below are from search excerpts of those pages and are not verified.
+
+- **What it is.** In GitHub CLI 2.90.0 and later, a public preview: `gh skill search`, `preview`, `install`, `update`,
+ `publish` (`list` in later builds). `install OWNER/REPO [SKILL]` installs from a repository; `@tag` or `@sha` and
+ `--pin` fix a version; the default agent is Copilot and the default scope the project; `--agent claude-code`,
+ `cursor`, `codex`, `gemini-cli`, `antigravity` or `--dir` choose where; hidden folders such as `.claude/skills/` need
+ `--allow-hidden-dirs`. The latest release is read before the default branch (`mcp.md`), hence `genclass-plugin`.
+ Where Copilot reads project skills (`.github/skills/` per third-party pages) is not verified.
+- **No directory to submit to.** `gh skill search` searches GitHub; what it indexes (SKILL.md files, the `agent-skills`
+ topic, an index of its own) is not verified. `gh skill publish` validates a skill against the specification and
+ publishes it as a tag or release in its own repository (`--fix` for metadata); it is not a registry and is not used
+ here: `genclass-plugin` is assembled by `packages/mcp/scripts/plugin-repo.mjs`, re-synced daily and never edited or
+ tagged by hand (AGENTS.md), and the skill already carries the `license` field `publish` recommends (CHANGELOG 0.2.2).
+- **By hand.** Add the `agent-skills` topic to `genclass-dev/GenClass` (repository settings). Nothing else.
+
+### 2.2 github/awesome-copilot (community collection)
+
+Source: github/awesome-copilot `README.md`, `CONTRIBUTING.md`, `docs/README.skills.md` (2026-11-02).
+
+- **How.** A pull request that copies the skill into their repository: `npm run skill:create -- --name genclass
+ --description "..."` makes `skills/genclass/SKILL.md`, paste the body, `npm run skill:validate`, then `npm run build`
+ (the README tables are generated; CI fails if they are stale). Branch from and target `main`, not `staged`. Each PR
+ gets a state label and a risk tier from the `submission-gate` check; bundled scripts or MCP configuration are "High"
+ risk (this skill has neither; it names tools of a server the user installs). Reviewers are assigned by hand. An
+ agent opening the PR adds `🤖🤖🤖` to the title; a person does not. Rejected: skills that "mainly restate what
+ frontier models already do well"; paid services follow their separate guidance.
+- **Licence.** "By contributing to this repository, you agree that your contributions will be licensed under the MIT
+ License." The copy there would be MIT while ours is Apache-2.0: the owner decides; keep `license: Apache-2.0` out of
+ the copied frontmatter if they agree, or do not submit.
+- **The entry.** Generated from the frontmatter: name `genclass`, the description, "Bundled Assets: None", and the
+ install line `gh skill install github/awesome-copilot genclass`. The PR description: the one-sentence text above, that
+ it needs the GenClass MCP server (`npx -y @genclass/mcp@0.2.1`) and a dev server on the same machine, and the measured
+ result.
+
+## 3. Anthropic's directory and Claude Code marketplaces
+
+Source: claude.com/docs/directory/publish, code.claude.com/docs/en/plugins/publish, code.claude.com/docs/en/skills,
+code.claude.com/docs/en/plugins/create-marketplace (2026-11-02).
+
+- **Skills are not a listing.** "Skills aren't a submission type on their own. Put them in a bundle." A listing is a
+ plugin bundle (a GitHub repository, public before it goes live, paid claude.ai plan) or an MCP connector (a remote
+ server). The plugin bundle `genclass-dev/genclass-plugin`, submitted 2026-10-28 and waiting for a reviewer (`mcp.md`
+ section 3), carries this skill; once published, its Usage tab reports "how often each skill and MCP server runs".
+ `claude-plugins-official` takes no submissions through the portal. Nothing to do.
+- **Claude Code.** Reads `.claude/skills//SKILL.md` (project, personal, nested, `--add-dir`), a plugin's
+ `skills//`, managed settings and skills synced from claude.ai, not `.agents/skills/` (so the skills CLI links
+ into `.claude/skills/` for it). All frontmatter is optional there; the listing shows `description` plus `when_to_use`
+ cut at 1,536 characters; `license`, `compatibility` and `metadata` are accepted and ignored; claude.ai uploads and the
+ Skills API reject any key beyond the six spec fields, so the file's three keys are right. Both `GenClass` (root
+ marketplace, `source: ./packages/mcp/plugin`) and `genclass-plugin` are marketplaces; `/plugin install genclass
+ --marketplace genclass-dev/genclass-plugin` does both steps (Claude Code 2.1.275 or later).
+- **claude-plugins.dev** (indexes public plugin repositories by topic, `mcp.md`): not reachable, not verified.
+
+## 4. Codex
+
+Source: github.com/openai/skills and github.com/openai/plugins READMEs (2026-11-02); developers.openai.com not reachable.
+
+- openai/skills, the catalog (`skills/.system`, `.curated`, `.experimental`, `$skill-installer`), "is deprecated" and
+ points to the plugins guide; openai/plugins is "a curated collection of Codex plugin examples" (`.codex-plugin/plugin.json`,
+ `skills/`, `.mcp.json`, `.agents/plugins/marketplace.json`) with no text on submissions; OpenAI's directory takes
+ local servers from approved partners only (`mcp.md`, not re-verified). The route stays `codex plugin marketplace add
+ genclass-dev/genclass-plugin` then `codex plugin add genclass@genclass` (verified 2026-10-28), or the skills CLI. Nothing to submit.
+
+## 5. Gemini CLI
+
+Source: google-gemini/gemini-cli `docs/cli/skills.md` (2026-11-02).
+
+- Skills are discovered in `~/.gemini/skills/` or `~/.agents/skills/` (user) and `.gemini/skills/` or `.agents/skills/`
+ (workspace), plus "skills bundled within installed extensions"; `gemini skills install
+ --consent`, with `--path` for "a subdirectory of a Git repo containing the skill" and `--scope user|workspace`. No
+ skills gallery: geminicli.com/extensions crawls the `gemini-cli-extension` topic (`mcp.md`), and `genclass-plugin`
+ is an extension with the skill inside.
+- **In this repository**, one more install line for the READMEs (from the doc page; no Gemini CLI in the session, not
+ run): `gemini skills install https://github.com/genclass-dev/genclass-plugin.git --path skills/genclass --consent`.
+
+## 6. Cursor
+
+Source: cursor/community-plugins `README.md` (the source of cursor.directory, 2026-11-02); `mcp.md` section 10 for the
+Cursor Marketplace. Cursor's own skills documentation (cursor.com, docs.cursor.com) was not reachable.
+
+- **cursor.directory.** "All content is submitted through the website - no pull requests needed for data":
+ cursor.directory/plugins/new, sign in with GitHub or Google, paste the repository URL, Submit. It detects, under the
+ Open Plugins standard, `skills/*/SKILL.md`, `.mcp.json`, `hooks/hooks.json`, `rules/*.mdc`, `agents/*.md`,
+ `.lsp.json`; every submission is reviewed by a Cursor SDK agent (`composer-2`) and stored as safe, suspicious or
+ malicious. Submit `https://github.com/genclass-dev/genclass-plugin` (the skill, `.mcp.json` and the hook are at its
+ root). Whether a skill without a plugin manifest is listed is not documented. By hand.
+- **Cursor Marketplace** (cursor.com/marketplace/publish, manual review): as in `mcp.md` section 10. By hand.
+
+## 7. Curated lists (pull requests by a person)
+
+### 7.1 VoltAgent/awesome-agent-skills
+
+Source: its `CONTRIBUTING.md` (2026-11-02). Links only; "Skill must have real community usage"; "Brand new skills that
+were just created are not accepted"; description "10 words or fewer"; "Author/org prefix included in the name"; PR
+title `Add skill: author/skill-name`; at the end of Community Skills, Development and Testing. Later. Draft line:
+
+```
+- **[genclass-dev/genclass](https://github.com/genclass-dev/genclass-plugin/tree/main/skills/genclass)** - Find and prove fixes for timing bugs in web apps.
+```
+
+### 7.2 travisvn/awesome-claude-skills
+
+Source: its `CONTRIBUTING.md` (2026-11-02). One row, `- **[Name](link)** - description`; "if your skill hasn't acquired
+a basic 10 stars, it will be closed automatically"; a skill "based around a SaaS" is closed; no PR "generated or
+submitted with AI assistance"; more than one file is "a strong guideline". Later, by a person, from `GenClass` (7 stars).
+
+### 7.3 ComposioHQ/awesome-claude-skills
+
+Source: its `CONTRIBUTING.md` (2026-11-02). Copies the skill folder into their repository on their template ("When to
+Use This Skill", "How to Use", "Example"), one README line in alphabetical order, PR title `Add genclass skill`, an
+"Inspired by" or "Credit" line, tested on Claude.ai, Claude Code and/or the API; no licence stated. Later, as 2.2.
+
+### 7.4 Not routes
+
+anthropics/skills has no contribution statement (its README highlights partner skills Anthropic chooses);
+hesreallyhim/awesome-claude-code takes the plugin (`mcp.md` section 13); block/agent-skills was archived on 2026-09-25.
+
+## 8. Crawlers and aggregators (nothing to do, not verified)
+
+Sites that index public GitHub repositories with a `SKILL.md` or mirror the skills CLI's index, none reachable from the
+session: SkillsMP (search results say it crawls GitHub, some with a 2-star floor), Smithery skills ("mirrors the skills
+CLI's index", `mcp.md`), agenticskills.io (a submit form, a "verified org" badge), awesomeskill.ai, skills-hub.ai
+(badges with install counts), skillselion.com, vibeindex.ai, skills.cat, Tessl (`tessl skill publish --public` after
+approval, `mcp.md`). Check in a month whether they list `genclass-dev/genclass-plugin`; submit nothing.
+
+## 9. The skill file against each place
+
+| field or file | spec | the file | needed anywhere? |
+|---|---|---|---|
+| `name` | required, at most 64, lowercase, equals the folder | `genclass` | everywhere; done |
+| `description` | required, at most 1,024 | 509 characters, the triggers first | everywhere; done (Claude Code shows up to 1,536) |
+| `license` | optional, short | `Apache-2.0` | no directory requires it; `gh skill publish` recommends it; it travels with the copies in 2.2 and 7.3 |
+| `compatibility` | optional, at most 500 | absent | nowhere. Optional, in this repository: `Needs the GenClass MCP server (npm @genclass/mcp) and the app's dev server on the same machine; Node 20 or later.` Claude Code ignores it; `manifests.test.ts` checks the frontmatter, so run it after |
+| `metadata` | optional string map | absent | nowhere; `metadata.internal: true` would hide it from the skills CLI |
+| `allowed-tools` | experimental | absent | nowhere; leave out |
+| Claude-only keys (`argument-hint`, `paths`, ...) | not in the spec | none | keep none: claude.ai and the Skills API reject them |
+| `scripts/`, `references/`, `assets/` | optional | none | none required; travisvn prefers more than one file |
+| layout `skills/genclass/SKILL.md` at the root | | both repositories | the skills CLI, `gh skill`, cursor.directory, Claude Code and Codex plugins, Gemini `--path`: all read it |
+| a `LICENSE` next to `SKILL.md` | not required | the repository's `LICENSE` | none asks |
+| `skills.sh.json` | optional | absent | not needed: `skills/` is a default folder |
+| README badge and install lines | | `npx skills add`, `gh skill install` present | add the skills.sh badge (1) and the Gemini line (5) in this repository |
+| GitHub topic `agent-skills` | | `genclass-plugin` yes, `GenClass` no | add on `GenClass`, by hand |
diff --git a/docs/runtime/AGENT.md b/docs/runtime/AGENT.md
index ffef4fbc..294203db 100644
--- a/docs/runtime/AGENT.md
+++ b/docs/runtime/AGENT.md
@@ -439,7 +439,9 @@ This is one page and one bug class, a proof of the mechanism, not a recall figur
findings each witness makes stay as they were, so on an app whose cache writes its own bookkeeping (Redux Toolkit
Query's statuses, subscriptions) `genclass_findings` still lists those (RESULTS.md section 22 counts them).
- WebSocket and EventSource messages are recorded, not reordered; failure responses are not held. Both are next.
-- The script-tag build has no agent entry yet (ESM only).
+- The script-tag build has no agent attribute; a page without a bundler loads the ESM entry next to it, which
+ `init --agent` writes: a module script after the tag that, on `localhost`, imports `dist/agent.js` from the script
+ URL's directory and calls `connectAgent(GenClass.runtime)` (module scripts run after deferred ones, in order).
- Production: today the agent reads production through the dashboard (counts by diagnosis and page) and reproduces
locally with `focus` on the flagged signature, and with `GENCLASS_REPORT` the dashboard shows what it reproduced
and fixed (section 4.5). Sending production witnesses (the recorded order of a real user's
diff --git a/docs/runtime/INSTALL.md b/docs/runtime/INSTALL.md
index 5febcb77..04a15f73 100644
--- a/docs/runtime/INSTALL.md
+++ b/docs/runtime/INSTALL.md
@@ -2,18 +2,18 @@
How to add `@genclass/runtime` to a web app and take it out again: the `init` and `remove` commands with every
flag, the app token and dashboard that `init` creates, the zero-code options, the import, the script tag and its
-attributes, `GenClass.init()`, and the projects `init` was tested on. For `@genclass/runtime` 0.3.0 (`0.3.0-beta.0` on the npm
+attributes, `GenClass.init()`, and the projects `init` was tested on. For `@genclass/runtime` 0.3.0 (`0.3.0-beta.5` on the npm
`beta` dist-tag). The short version is in the [package README](../../packages/runtime/README.md#install).
## Which version should I install?
While `0.3.0` is in beta, every npm and npx command here names the `@beta` dist-tag. Without it you get the stable
-`0.2.x` (`0.2.2` was npm `latest` on 2026-10-22; `npm view @genclass/runtime dist-tags` shows them now), whose
+`0.2.x` (`0.2.3`, npm's `latest` since 2026-10-28; `npm view @genclass/runtime dist-tags` shows them now), whose
runtime ignores a token and whose CLI has no `login`, `connect`, `whoami`, `logout`, `dashboard`, `--token` or `--sink`. Both
lines load model `@genclass/runtime-model@0.2.0` by default.
-Pin the script tag's version (`https://cdn.jsdelivr.net/npm/@genclass/runtime@0.3.0-beta.0`): the unversioned URL
-serves the `latest` dist-tag (`0.2.2` on 2026-10-22) until 0.3.0 is released.
+Pin the script tag's version (`https://cdn.jsdelivr.net/npm/@genclass/runtime@0.3.0-beta.5`): the unversioned URL
+serves the `latest` dist-tag (`0.2.3` on 2026-11-02) until 0.3.0 is released.
**Older versions.** `0.1.0-beta.3` has these problems, fixed in `0.2.0`: app builds carried 41 MB of unused ONNX
Runtime wasm, a CSP-blocked model failed silently, `init` could not turn telemetry off, and `status.scope.mode` read
@@ -65,6 +65,8 @@ Content-Security-Policy (`next.config` headers, a proxy or middleware, a ` ` | init | install `@genclass/runtime` from this spec (a version, tag or tarball path) |
| `--cdn ` | init | plain HTML: the script URL (default: jsDelivr, this version, with an SRI hash; this version's unpkg URL gets one too; other URLs get no hash) |
| `--no-sri` | init | plain HTML: no integrity attribute |
+| `--sync` | init | plain HTML: a blocking script tag (the default is `defer`: the page never waits for the CDN; GenClass then starts after classic scripts that have neither `defer` nor `async`) |
+| `--no-network` | init | do not ask npm for newer releases (`--dry-run`, `--no-token` and `--no-telemetry` do not ask either) |
| `--strategy instrumentation\|layout\|pages` | init | Next.js only: where the import goes. By default `instrumentation-client` on Next.js 15.3 and later, else `layout` (App Router) or `pages` (Pages Router) |
| `--keep-package` | remove | leave `@genclass/runtime` installed (by default `remove` uninstalls it if nothing else imports it) |
@@ -158,7 +160,8 @@ The second writes the server into `.mcp.json` and the `genclass` skill (the proc
bugs) to `.claude/skills/genclass/SKILL.md`; it runs on your machine and needs no account
([`@genclass/mcp`](../../packages/mcp/README.md); other agents: `npx -y @genclass/mcp@0.2.1 config `). Run the dev
server: until the MCP server runs, the page logs one failed request to `127.0.0.1:47357`, the agent link finding no
-server. `npx @genclass/runtime@beta remove` takes the first command's changes out; delete `.mcp.json`'s entry and
+server: reload the page once it runs (the link tries once per page load). `npx @genclass/runtime@beta remove` takes the
+first command's changes out; delete `.mcp.json`'s entry and
`.claude/skills/genclass/` for the second.
## How do I install it by hand?
@@ -187,7 +190,7 @@ During SSR or in Node, `/auto` installs nothing and returns an inert runtime.
**One script tag** (no build step), first in ``:
```html
-
+
```
It exposes `window.GenClass` (since `0.3.0` also `window.GenClass.protect`), discovers the app's state like the
diff --git a/docs/runtime/SINKS.md b/docs/runtime/SINKS.md
index a0bcae6f..8500cbf0 100644
--- a/docs/runtime/SINKS.md
+++ b/docs/runtime/SINKS.md
@@ -32,7 +32,7 @@ npx @genclass/runtime@beta init --sink webhook:/genclass # or console-json; re
```html
-
+
```
diff --git a/telemetry-worker/src/pages.ts b/telemetry-worker/src/pages.ts
index 9ac16baf..504a9c58 100644
--- a/telemetry-worker/src/pages.ts
+++ b/telemetry-worker/src/pages.ts
@@ -62,7 +62,7 @@ export const LOGO =
' GenClass ';
/** The MCP server for coding agents, pinned as its own install blocks pin it (packages/mcp/src/clients.ts). */
-export const MCP_PKG = "@genclass/mcp@0.2.0";
+export const MCP_PKG = "@genclass/mcp@0.2.1";
/** The package names and URLs installPrompt names; passed in, so the page script runs the same function. */
export interface PromptNames {
@@ -503,6 +503,14 @@ export function openSourcePage(nonce: string): string {
The runtime, the MCP server, the model's training code and the collector behind genclass.dev are on GitHub under the Apache-2.0 license; the model's weights are on npm as @genclass/runtime-model (Apache-2.0).
+
+ What you will see
+
+ In the browser console, once the model has loaded: [GenClass] Model ready (…). Mode: observe., then one [GenClass] … line per detection, with its evidence.
+ On localhost, the devtools overlay (bottom-right, Alt+Shift+G): what GenClass sees on the page, its checks and detections.
+ In your agent, once the MCP server runs: genclass_status lists the dev page (reload it after starting the server), genclass_findings what GenClass saw, genclass_explore the race, genclass_replay the proof.
+
+
Or run the commands yourself
${cmd("Add the runtime to your app, with the dev-only agent link", `npx ${RUNTIME_PKG} init --no-telemetry --agent`)}
From 46ebe9dd14464cee869ac5e3f1b5a8577d2193c2 Mon Sep 17 00:00:00 2001
From: Claude
Date: Mon, 2 Nov 2026 18:10:54 +0000
Subject: [PATCH 03/11] init --agent: no module script for a --cdn copy under
another file name; the CLI's MCP launcher is pinned; two wording fixes
From the adversarial review of the diff:
- agentUrl returns null when the script URL does not end in genclass.global(.min).js, so init --agent with such a
--cdn writes no module script (it imported the runtime itself as a module, and connectAgent was undefined) and
says so in a note; test in cli.test.ts.
- The runtime CLI's help and Next line name the MCP server's launcher pinned (bin/lib/version.mjs MCP_PKG, in the
manifests sync), as every other copied command does; the CHANGELOG entry too.
- The READMEs say what the telemetry opt-out is for plain HTML and Astro; skills.md cites the MCP CHANGELOG's
Unreleased entry for the licence field.
Co-Authored-By: Claude Fable 5.1
Claude-Session: https://claude.ai/code/session_01Fqwfq3CizvxvgyXp6wY8WR
---
README.md | 3 ++-
docs/adoption/listings/skills.md | 2 +-
packages/mcp/test/manifests.test.ts | 2 ++
packages/runtime/CHANGELOG.md | 2 +-
packages/runtime/README.md | 3 ++-
packages/runtime/bin/lib/init.mjs | 8 ++++----
packages/runtime/bin/lib/plan.mjs | 14 +++++++++++---
packages/runtime/bin/lib/version.mjs | 2 ++
packages/runtime/test/install/cli.test.ts | 11 ++++++++++-
9 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/README.md b/README.md
index ea0a4120..556e46fc 100644
--- a/README.md
+++ b/README.md
@@ -44,7 +44,8 @@ npx @genclass/runtime@beta init --no-telemetry --agent # the runtime (observe)
npx -y @genclass/mcp@0.2.1 init # the GenClass MCP server and the `genclass` skill for Claude Code
```
-The first adds one marked import (or script tag) plus an option file with `telemetry: false`; the second writes
+The first adds one marked import plus an option file with `telemetry: false` (plain HTML: the script tag with
+`data-telemetry="off"`; Astro: a ` ` line); the second writes
`.mcp.json` and `.claude/skills/genclass/SKILL.md` (other agents: `npx -y @genclass/mcp@0.2.1 config `). Nothing
else is needed; `npx @genclass/runtime@beta remove` undoes the first
([the open-source setup](docs/runtime/INSTALL.md#how-do-i-set-up-the-open-source-parts-only)).
diff --git a/docs/adoption/listings/skills.md b/docs/adoption/listings/skills.md
index 6405a22a..5c247144 100644
--- a/docs/adoption/listings/skills.md
+++ b/docs/adoption/listings/skills.md
@@ -116,7 +116,7 @@ reachable: the command details below are from search excerpts of those pages and
topic, an index of its own) is not verified. `gh skill publish` validates a skill against the specification and
publishes it as a tag or release in its own repository (`--fix` for metadata); it is not a registry and is not used
here: `genclass-plugin` is assembled by `packages/mcp/scripts/plugin-repo.mjs`, re-synced daily and never edited or
- tagged by hand (AGENTS.md), and the skill already carries the `license` field `publish` recommends (CHANGELOG 0.2.2).
+ tagged by hand (AGENTS.md), and the skill already carries the `license` field `publish` recommends (packages/mcp/CHANGELOG.md, Unreleased).
- **By hand.** Add the `agent-skills` topic to `genclass-dev/GenClass` (repository settings). Nothing else.
### 2.2 github/awesome-copilot (community collection)
diff --git a/packages/mcp/test/manifests.test.ts b/packages/mcp/test/manifests.test.ts
index 787b3ab9..ee0bb7c5 100644
--- a/packages/mcp/test/manifests.test.ts
+++ b/packages/mcp/test/manifests.test.ts
@@ -78,6 +78,8 @@ const PINS: Pin[] = [
{ file: "packages/runtime/README.md", text: (s) => s.replace(PINNED, pinned(V)) },
{ file: "docs/runtime/INSTALL.md", text: (s) => s.replace(PINNED, pinned(V)) },
{ file: "FAQ.md", text: (s) => s.replace(PINNED, pinned(V)) },
+ // the runtime CLI's own text (init --help, the Next line after init --agent) names the server's launcher
+ { file: "packages/runtime/bin/lib/version.mjs", text: (s) => s.replace(PINNED, pinned(V)) },
];
function read(file: string): string {
diff --git a/packages/runtime/CHANGELOG.md b/packages/runtime/CHANGELOG.md
index 42d2bf81..d0e36625 100644
--- a/packages/runtime/CHANGELOG.md
+++ b/packages/runtime/CHANGELOG.md
@@ -8,7 +8,7 @@
in the files it creates for Next.js; plain HTML gets a module script after the tag, which loads `dist/agent.js` from
the script URL's directory on `localhost` and connects `GenClass.runtime`; module scripts run after deferred ones,
in order). `remove` takes it out, wrapped by a formatter or not, and refuses an edited one. So
- `npx @genclass/runtime@beta init --no-telemetry --agent` and `npx -y @genclass/mcp init` set up every open-source
+ `npx @genclass/runtime@beta init --no-telemetry --agent` and `npx -y @genclass/mcp@0.2.1 init` set up every open-source
part with no account and nothing sent, and the READMEs, INSTALL.md ("How do I set up the open-source parts only?"),
FAQ, AGENT.md, the MCP server's setup text and genclass.dev/start/open-source say so with those two commands instead
of a nine-step hand edit. No runtime code, no model-visible text, no change to what is sent. Tests:
diff --git a/packages/runtime/README.md b/packages/runtime/README.md
index 965a30e7..aa191400 100644
--- a/packages/runtime/README.md
+++ b/packages/runtime/README.md
@@ -42,7 +42,8 @@ npx @genclass/runtime@beta init --no-telemetry --agent # the runtime (observe)
npx -y @genclass/mcp@0.2.1 init # the GenClass MCP server and the `genclass` skill for Claude Code
```
-The first adds one marked import (or script tag) plus an option file with `telemetry: false`; the second writes
+The first adds one marked import plus an option file with `telemetry: false` (plain HTML: the script tag with
+`data-telemetry="off"`; Astro: a ` ` line); the second writes
`.mcp.json` and `.claude/skills/genclass/SKILL.md` (other agents: `npx -y @genclass/mcp@0.2.1 config `). Nothing
else is needed; `npx @genclass/runtime@beta remove` undoes the first
([the open-source setup](https://github.com/genclass-dev/GenClass-lib/blob/main/docs/runtime/INSTALL.md#how-do-i-set-up-the-open-source-parts-only)).
diff --git a/packages/runtime/bin/lib/init.mjs b/packages/runtime/bin/lib/init.mjs
index 4d1f4382..4378290f 100644
--- a/packages/runtime/bin/lib/init.mjs
+++ b/packages/runtime/bin/lib/init.mjs
@@ -20,7 +20,7 @@ import { createAccountProject, readCredentials } from "./account.mjs";
import { hostConfig, hostUrl } from "./host.mjs";
import { LOCAL_FILE, PENDING_TOKEN, START_URL, TOKEN_RE, createProject, readLocal, saveLocal, tokenInFiles } from "./token.mjs";
import { banner, c, confirm, err, interactive, out, printChange, row, sym } from "./ui.mjs";
-import { CMD, PKG, PKG_DIR, VERSION, compareVersions, distTags, installedVersion, versionInSpec, versionStatus } from "./version.mjs";
+import { CMD, PKG, PKG_DIR, VERSION, compareVersions, distTags, installedVersion, versionInSpec, versionStatus, MCP_PKG } from "./version.mjs";
const MODES = ["observe", "guard", "heal"];
@@ -81,9 +81,9 @@ remove takes out exactly what init added (the lines and blocks marked "${MARK}
--no-install do not run the package manager
--agent also connect development builds to your coding agent: a dev-only line that loads
@genclass/runtime/agent and calls connectAgent (plain HTML: a module script after the
- tag), so the GenClass MCP server (npx -y @genclass/mcp init) sees the page. Production
+ tag), so the GenClass MCP server (npx -y ${MCP_PKG} init) sees the page. Production
builds drop it; off loopback hosts it is inert. The open-source setup, no account:
- init --no-telemetry --agent, then npx -y @genclass/mcp init
+ init --no-telemetry --agent, then npx -y ${MCP_PKG} init
--no-devtools do not add the dev-only devtools overlay
--no-network do not ask npm for newer releases (--dry-run, --no-token and --no-telemetry do not
ask either)
@@ -995,7 +995,7 @@ export async function init(o, ctx = {}) {
if (cfg.sinks?.length) out(` ${sym.dot} They also reach ${c.cyan(cfg.sinks.join(", "))}: ${cfg.sinks.map((s) => SINK_WHAT[sinkBase(s)] ?? s).join("; ")}.`);
if (devtools && changes.some((ch) => /devtools/.test(ch.after))) out(` ${sym.dot} In development an overlay shows what GenClass sees (bottom-right, ${c.bold("Alt+Shift+G")}).`);
if (agent && changes.some((ch) => /runtime\/agent|\/agent\.js/.test(ch.after)))
- out(` ${sym.dot} In development the page connects to the GenClass MCP server: ${c.cyan("npx -y @genclass/mcp init")} adds it to Claude Code (other agents: ${c.cyan("npx -y @genclass/mcp config ")}); until it runs, the page logs one failed request to 127.0.0.1:47357.`);
+ out(` ${sym.dot} In development the page connects to the GenClass MCP server: ${c.cyan(`npx -y ${MCP_PKG} init`)} adds it to Claude Code (other agents: ${c.cyan(`npx -y ${MCP_PKG} config `)}); until it runs, the page logs one failed request to 127.0.0.1:47357.`);
out(` ${sym.dot} Rule it out while debugging: add ${c.cyan("?genclass=off")} to the URL.`);
out();
diff --git a/packages/runtime/bin/lib/plan.mjs b/packages/runtime/bin/lib/plan.mjs
index 365f5665..dad789ad 100644
--- a/packages/runtime/bin/lib/plan.mjs
+++ b/packages/runtime/bin/lib/plan.mjs
@@ -278,8 +278,14 @@ function planAstro(p, o) {
}
export const cdnUrl = (version, min = true) => `https://cdn.jsdelivr.net/npm/@genclass/runtime@${version}/dist/genclass.global${min ? ".min" : ""}.js`;
-/** The agent entry next to the script URL: the same directory's agent.js (jsDelivr, unpkg or a self-hosted dist/). */
-export const agentUrl = (scriptUrl) => scriptUrl.replace(/\/genclass\.global(?:\.min)?\.js(?:[?#].*)?$/, "/agent.js");
+/**
+ * The agent entry next to the script URL: the same directory's agent.js (jsDelivr, unpkg or a self-hosted dist/), or
+ * null when the URL does not end in the runtime's file name (a renamed copy: the CLI cannot know where agent.js is).
+ */
+export function agentUrl(scriptUrl) {
+ const u = scriptUrl.replace(/\/genclass\.global(?:\.min)?\.js(?:[?#].*)?$/, "/agent.js");
+ return u === scriptUrl ? null : u;
+}
/**
* With --agent, plain HTML gets this after the runtime's tag: a module script (which runs after the deferred tag, in
* order) that on a page served from this machine loads the agent entry and connects the page to the local MCP bridge.
@@ -287,7 +293,7 @@ export const agentUrl = (scriptUrl) => scriptUrl.replace(/\/genclass\.global(?:\
*/
export function agentTag(o, version) {
const url = agentUrl(o.cdn || cdnUrl(version));
- return ``;
+ return url ? `` : null;
}
const unpkgUrl = (version, min) => `https://unpkg.com/@genclass/runtime@${version}/dist/genclass.global${min ? ".min" : ""}.js`;
@@ -350,6 +356,8 @@ function planHtml(p, o, ctx) {
changes.push({ file: f, kind: "modify", before, after });
}
const notes = [];
+ if (o.agent && !agent)
+ notes.push(`The agent link was not added: --cdn ${o.cdn} does not end in genclass.global.js or genclass.global.min.js, so the CLI cannot know where that copy's agent.js is. Add the module script by hand (docs/runtime/AGENT.md).`);
if (o.sri !== false && !/ integrity="/.test(tag)) {
notes.push(
o.cdn
diff --git a/packages/runtime/bin/lib/version.mjs b/packages/runtime/bin/lib/version.mjs
index a5e178b3..1384d1bb 100644
--- a/packages/runtime/bin/lib/version.mjs
+++ b/packages/runtime/bin/lib/version.mjs
@@ -12,6 +12,8 @@ import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
export const PKG = "@genclass/runtime";
+/** The MCP server's launcher, pinned to its release (packages/mcp/test/manifests.test.ts keeps it current; `npm run sync -w @genclass/mcp`). */
+export const MCP_PKG = "@genclass/mcp@0.2.1";
export const PKG_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
/** This package's version ("latest" if package.json cannot be read). */
diff --git a/packages/runtime/test/install/cli.test.ts b/packages/runtime/test/install/cli.test.ts
index 63c0f5ec..d6d6ef07 100644
--- a/packages/runtime/test/install/cli.test.ts
+++ b/packages/runtime/test/install/cli.test.ts
@@ -1242,7 +1242,7 @@ describe("init --agent: the dev-only agent link next to the overlay (the open-so
const dir = project(VITE_TS);
const r = cli(dir, "init", "--yes", "--no-install", "--agent");
expect(r.code, r.out).toBe(0);
- expect(r.out).toContain("npx -y @genclass/mcp init");
+ expect(r.out).toContain("npx -y @genclass/mcp@0.2.1 init");
expect(r.out).toContain("127.0.0.1:47357");
const main = readFileSync(join(dir, "src/main.tsx"), "utf8");
const lines = main.trimEnd().split("\n");
@@ -1293,6 +1293,15 @@ describe("init --agent: the dev-only agent link next to the overlay (the open-so
expect(after["about.html"]).toContain(`>${agent}`);
const dflt = roundTrip(project({ "index.html": `x \n` }), "--agent")["index.html"];
expect(dflt).toContain(`import("https://cdn.jsdelivr.net/npm/@genclass/runtime@${VERSION}/dist/agent.js")`);
+ // a --cdn copy under another file name: the CLI cannot know where its agent.js is, so no module script and a note
+ const odd = project({ "index.html": `x \n` });
+ const r = cli(odd, "init", "--yes", "--no-install", "--agent", "--no-sri", "--cdn", "https://example.test/gc.js");
+ expect(r.code, r.out).toBe(0);
+ expect(r.out).toContain("The agent link was not added: --cdn https://example.test/gc.js does not end in genclass.global.js");
+ const html = readFileSync(join(odd, "index.html"), "utf8");
+ expect(html).toContain('');
+ expect(html).not.toContain("connectAgent");
+ expect(cli(odd, "remove", "--yes").code).toBe(0);
});
it("remove takes out a Prettier-wrapped agent line whole, and refuses one that was edited", () => {
From 4eb75d773edc304538d8fc22ba434757dd04e4d3 Mon Sep 17 00:00:00 2001
From: Claude
Date: Mon, 2 Nov 2026 18:19:28 +0000
Subject: [PATCH 04/11] init --agent: remove needs one of init's calls inside a
block; the agent entry for the READMEs' bare package URL; the prompt's
webhook sink by name
From the adversarial review:
- A block form in remove's recogniser could match an empty if (...) {} window, so after a developer edited the
agent line, a user's line below it could be taken out with it; a block now needs one of init's two calls.
- --cdn https://cdn.jsdelivr.net/npm/@genclass/runtime@ (the READMEs' script URL, with no file name)
gets its dist/agent.js next to it; other file names still get a note instead of a module script.
- /start/open-source: the logs choice says --sink webhook: (which init and the runtime handle, the endpoint
kept out of what GenClass watches) instead of a hand-written sink; step 1 says what the plain-HTML and Astro
forms are.
Co-Authored-By: Claude Fable 5.1
Claude-Session: https://claude.ai/code/session_01Fqwfq3CizvxvgyXp6wY8WR
---
packages/runtime/bin/lib/edit.mjs | 2 +-
packages/runtime/bin/lib/plan.mjs | 5 ++++-
packages/runtime/test/install/cli.test.ts | 21 +++++++++++++++++++++
telemetry-worker/src/pages.ts | 4 ++--
telemetry-worker/test/pages.test.ts | 10 ++++++----
5 files changed, 34 insertions(+), 8 deletions(-)
diff --git a/packages/runtime/bin/lib/edit.mjs b/packages/runtime/bin/lib/edit.mjs
index 90ed7542..f45301c6 100644
--- a/packages/runtime/bin/lib/edit.mjs
+++ b/packages/runtime/bin/lib/edit.mjs
@@ -130,7 +130,7 @@ const META_CONFIG = String.raw``;
const DEV_LINE = String.raw`if\(${COND}\)${DEVTOOLS_CALL};?`;
const AGENT_LINE = String.raw`if\(${COND}\)${AGENT_CALL};?`;
// the same with braces (ESLint's `curly` fix), and the one block Next.js's created files hold both calls in
-const DEV_BLOCK = String.raw`if\(${COND}\)\{(?:${DEVTOOLS_CALL};?)?(?:${AGENT_CALL};?)?\}`;
+const DEV_BLOCK = String.raw`if\(${COND}\)\{(?:${DEVTOOLS_CALL};?(?:${AGENT_CALL};?)?|${AGENT_CALL};?)\}`;
const AGENT_BLOCK = String.raw`if\(${COND}\)\{${AGENT_CALL};?\}`;
// plain HTML with --agent: a module script after the runtime's tag (module scripts run after deferred ones, in order)
const AGENT_SCRIPT = String.raw`if\(\["localhost","127\.0\.0\.1"\]\.includes\(location\.hostname\)\)import\("[^"]*"\)\.then\(a=>a\.connectAgent\(GenClass\.runtime\)\);?`;
diff --git a/packages/runtime/bin/lib/plan.mjs b/packages/runtime/bin/lib/plan.mjs
index dad789ad..46b83680 100644
--- a/packages/runtime/bin/lib/plan.mjs
+++ b/packages/runtime/bin/lib/plan.mjs
@@ -284,7 +284,10 @@ export const cdnUrl = (version, min = true) => `https://cdn.jsdelivr.net/npm/@ge
*/
export function agentUrl(scriptUrl) {
const u = scriptUrl.replace(/\/genclass\.global(?:\.min)?\.js(?:[?#].*)?$/, "/agent.js");
- return u === scriptUrl ? null : u;
+ if (u !== scriptUrl) return u;
+ // the bare package URL the READMEs' script tag uses (jsDelivr and unpkg serve the package's own file there)
+ const m = /^(https:\/\/(?:cdn\.jsdelivr\.net\/npm|unpkg\.com)\/@genclass\/runtime@[^/?#]+)\/?(?:[?#].*)?$/.exec(scriptUrl);
+ return m ? `${m[1]}/dist/agent.js` : null;
}
/**
* With --agent, plain HTML gets this after the runtime's tag: a module script (which runs after the deferred tag, in
diff --git a/packages/runtime/test/install/cli.test.ts b/packages/runtime/test/install/cli.test.ts
index d6d6ef07..1ca950a3 100644
--- a/packages/runtime/test/install/cli.test.ts
+++ b/packages/runtime/test/install/cli.test.ts
@@ -1302,6 +1302,27 @@ describe("init --agent: the dev-only agent link next to the overlay (the open-so
expect(html).toContain('');
expect(html).not.toContain("connectAgent");
expect(cli(odd, "remove", "--yes").code).toBe(0);
+ // the READMEs' bare package URL: the agent entry is dist/agent.js next to it
+ const bare = roundTrip(project({ "index.html": `x \n` }), "--agent", "--no-sri", "--cdn", `https://cdn.jsdelivr.net/npm/@genclass/runtime@${VERSION}`)["index.html"];
+ expect(bare).toContain(`import("https://cdn.jsdelivr.net/npm/@genclass/runtime@${VERSION}/dist/agent.js")`);
+ });
+
+ it("remove never swallows a user's line below an edited dev-only line (a block needs one of init's calls inside)", () => {
+ const dir = viteVue();
+ const before = snapshot(dir);
+ expect(cli(dir, "init", "--yes", "--no-install", "--agent").code).toBe(0);
+ const f = join(dir, "src/main.js");
+ const added = readFileSync(f, "utf8");
+ const line = `if (import.meta.env.DEV) import("@genclass/runtime/agent").then((a) => a.connectAgent(genclass)); // genclass:init`;
+ expect(added).toContain(line);
+ // the developer passes options to the link and adds a function right after it: the marked line is no longer init's
+ const edited = added.replace(line, `const opts = { anyHost: true };\n${line.replace("a.connectAgent(genclass)", "a.connectAgent(genclass, opts)")}\nfunction reportRaces(races) {}`);
+ writeFileSync(f, edited);
+ const r = cli(dir, "remove", "--yes");
+ expect(r.code).not.toBe(0);
+ expect(r.out).toContain("not a statement init writes");
+ expect(readFileSync(f, "utf8")).toBe(edited);
+ expect(snapshot(dir)).not.toEqual(before);
});
it("remove takes out a Prettier-wrapped agent line whole, and refuses one that was edited", () => {
diff --git a/telemetry-worker/src/pages.ts b/telemetry-worker/src/pages.ts
index 504a9c58..91945975 100644
--- a/telemetry-worker/src/pages.ts
+++ b/telemetry-worker/src/pages.ts
@@ -399,7 +399,7 @@ export function openSourcePrompt(c: OpenSourceChoices = {}, n: PromptNames = PRO
: []),
[
`In the project's root run: npx ${n.pkg} init ${flags.join(" ")} ` +
- "It finds the framework and package manager, installs the runtime, adds one marked import first in the browser entry (plain HTML pages, no bundler: the script tag, pinned with an integrity hash, in every page's ), the dev-only devtools overlay and the dev-only agent link (which records what happens on local pages for the GenClass MCP server, talks only to 127.0.0.1 and is never part of a production build), and writes telemetry: false into a marked option file next to the entry (data-telemetry=\"off\" on the tag), so GenClass's anonymous diagnostics are off and it sends no data anywhere" +
+ "It finds the framework and package manager, installs the runtime, adds one marked import first in the browser entry (plain HTML pages, no bundler: the script tag, pinned with an integrity hash, in every page's ), the dev-only devtools overlay and the dev-only agent link (which records what happens on local pages for the GenClass MCP server, talks only to 127.0.0.1 and is never part of a production build; on plain HTML pages it stays in the page and runs only on localhost), and writes telemetry: false into a marked option file next to the entry (data-telemetry=\"off\" on the tag; Astro: a line), so GenClass's anonymous diagnostics are off and it sends no data anywhere" +
(own ? "" : "; the browser still downloads its model and onnxruntime-web, public files, from cdn.jsdelivr.net (about 13 MB, 18 MB on WebGPU devices, then cached) unless the app serves them") +
". It shows the diff; --yes applies it. " +
(guard
@@ -412,7 +412,7 @@ export function openSourcePrompt(c: OpenSourceChoices = {}, n: PromptNames = PRO
],
...(logs
? [
- ['Findings print as [GenClass] lines in the browser console, and the console-json sink also prints each one as one JSON line, for the log shipper the app already uses. If the team has its own endpoint for them, the webhook sink sends batched POSTs there instead: import { webhook } from "@genclass/runtime/sinks/webhook"; sinks: [webhook({ url: "" })], requests: { ignore: [""] } (so GenClass does not watch its own POSTs; data-sink="webhook:" on the script tag does both). Ask me for that URL rather than inventing one.'] as [string],
+ ['Findings print as [GenClass] lines in the browser console, and the console-json sink also prints each one as one JSON line, for the log shipper the app already uses. If the team has its own endpoint for them, use the webhook sink instead: --sink webhook: on the init command (data-sink="webhook:" on a script tag) sends batched POSTs there and keeps GenClass from watching its own POSTs. Ask me for that URL rather than inventing one.'] as [string],
]
: []),
[`Run the dev server and load a page to check that the app builds and runs without errors. Until the MCP server runs (your next conversation), the page logs a failed request to 127.0.0.1:47357: that is the agent link finding no server, and expected. In your next conversation, reload a dev page and genclass_status lists it. Then check a page for visual bugs with genclass_scan on its local URL, or from a terminal: npx ${n.pkg} scan http://localhost:5173/ --local (keep --local). It runs headless Chromium on this machine and needs Playwright: if the scan says it is missing, ask me before adding playwright as a dev dependency and downloading Chromium (about 600 MB): npm i -D playwright && npx playwright install chromium; or skip the scan and say so. Do not use hosted: true: it sends the page URL to GenClass's hosted page check, which is not open source.`],
diff --git a/telemetry-worker/test/pages.test.ts b/telemetry-worker/test/pages.test.ts
index f17f86c6..442f2f99 100644
--- a/telemetry-worker/test/pages.test.ts
+++ b/telemetry-worker/test/pages.test.ts
@@ -1288,8 +1288,9 @@ describe("/start/open-source: the open-source parts with no account, no token an
const p = openSourcePrompt();
expect(p).toContain("No GenClass account and no token: nothing is sent to genclass.dev. Two commands do it; run them yourself.");
expect(p).toContain(`\n1. In the project's root run: npx ${RUNTIME_PKG} init --no-telemetry --agent --yes It finds the framework`);
- expect(p).toContain("the dev-only devtools overlay and the dev-only agent link (which records what happens on local pages for the GenClass MCP server, talks only to 127.0.0.1 and is never part of a production build)");
- expect(p).toContain('writes telemetry: false into a marked option file next to the entry (data-telemetry="off" on the tag)');
+ expect(p).toContain("the dev-only devtools overlay and the dev-only agent link (which records what happens on local pages for the GenClass MCP server, talks only to 127.0.0.1 and is never part of a production build; on plain HTML pages it stays in the page and runs only on localhost)");
+ expect(p).toContain('writes telemetry: false into a marked option file next to the entry (data-telemetry="off" on the tag; Astro: a line)');
+ expect(p).toContain("on plain HTML pages it stays in the page and runs only on localhost");
// no data is sent, but the public files still come from jsDelivr unless the app serves them; the prompt says so
expect(p).toContain("so GenClass's anonymous diagnostics are off and it sends no data anywhere; the browser still downloads its model and onnxruntime-web, public files, from cdn.jsdelivr.net");
expect(p).toContain("(about 13 MB, 18 MB on WebGPU devices, then cached)");
@@ -1344,8 +1345,9 @@ describe("/start/open-source: the open-source parts with no account, no token an
expect(openSourcePrompt({ guard: true })).not.toContain("eager");
// the model served by the app: no jsDelivr download for it to mention
expect(p).not.toContain("still downloads");
- expect(p).toContain("the webhook sink sends batched POSTs there instead");
- expect(p).toContain('sinks: [webhook({ url: "" })], requests: { ignore: [""] }');
+ // the webhook sink by name: init --sink does it, and the runtime keeps its own POSTs out of what it watches
+ expect(p).toContain("use the webhook sink instead: --sink webhook: on the init command");
+ expect(p).not.toContain("import {");
expect(p).toContain("Deploy it, as chosen");
const nums = [...p.matchAll(/^(\d+)\. /gm)].map((m) => Number(m[1]));
expect(nums).toEqual([1, 2, 3, 4, 5, 6, 7]);
From 044ff2399f2834d6e2114d421387b044d6e27b6d Mon Sep 17 00:00:00 2001
From: Claude
Date: Mon, 2 Nov 2026 18:24:20 +0000
Subject: [PATCH 05/11] init --agent: the install test takes the MCP pin from
version.mjs; module headers name the agent line and the fourth inline form;
skills.md cross-references
Co-Authored-By: Claude Fable 5.1
Claude-Session: https://claude.ai/code/session_01Fqwfq3CizvxvgyXp6wY8WR
---
docs/adoption/listings/skills.md | 4 ++--
packages/runtime/bin/lib/edit.mjs | 7 ++++---
packages/runtime/bin/lib/init.mjs | 3 ++-
packages/runtime/test/install/cli.test.ts | 4 ++--
4 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/docs/adoption/listings/skills.md b/docs/adoption/listings/skills.md
index 5c247144..11fafaec 100644
--- a/docs/adoption/listings/skills.md
+++ b/docs/adoption/listings/skills.md
@@ -36,7 +36,7 @@ docs.tessl.io, claude-plugins.dev, skillsmp.com, agenticskills.io, awesomeskill.
- **Releases and stars.** `GenClass`'s latest GitHub release is v0.2.1 (2026-10-11), before the skill existed, and
`genclass-plugin` has no release; the tools that read the latest release before the default branch (`gh skill`,
Gemini CLI, per `mcp.md`) therefore work from `genclass-plugin` only. Stars: `GenClass` 7, `genclass-plugin` 0. Lists
- with a star or usage threshold (sections 7.2 and 7.3) are closed to it for now.
+ with a star or usage threshold (sections 7.1 and 7.2) are closed to it for now.
- **Measured claims.** Only what `mcp.md` states: one page, the race found in 5 of 6 reordered runs, 0 of 6 differing
on the fixed page. No rate beyond that in any entry.
- **GitHub topics.** `genclass-plugin`: `agent-skills`, `claude-code-plugin`, `claude-plugin`, `codex-plugin`,
@@ -46,7 +46,7 @@ docs.tessl.io, claude-plugins.dev, skillsmp.com, agenticskills.io, awesomeskill.
### Texts to reuse
-- Ten words or fewer (section 7.2): `Find and prove fixes for timing bugs in web apps.`
+- Ten words or fewer (section 7.1): `Find and prove fixes for timing bugs in web apps.`
- One sentence: `A skill for coding agents with the GenClass MCP server: record what happens inside a web app's pages in causal order, re-run a page with responses delivered in different orders to find race conditions, replay one exact order, and prove the fix with a generated Playwright test.`
- The skill's own description (509 characters) is what the skills CLI, skills.sh and Claude Code show; reuse it where a
form asks for the description and allows it.
diff --git a/packages/runtime/bin/lib/edit.mjs b/packages/runtime/bin/lib/edit.mjs
index f45301c6..ba2a24a6 100644
--- a/packages/runtime/bin/lib/edit.mjs
+++ b/packages/runtime/bin/lib/edit.mjs
@@ -1,9 +1,10 @@
// Text edits for `genclass-runtime init|remove`. Everything init adds carries a marker:
// - single lines: `import genclass from "@genclass/runtime/auto"; // genclass:init`
// - blocks (files init creates): from a line containing `genclass:init start` to one containing `genclass:init end`
-// - three inline forms, used only when the place to insert shares its line with other code (a one-line or
-// ): ` {/* genclass:inline */}`, `` (Astro) and
-// `` (HTML)
+// - four inline forms, used only when the place to insert shares its line with other code (a one-line or
+// ): ` {/* genclass:inline */}`, `` (Astro),
+// `` (HTML) and ``
+// (HTML with --agent: the agent link's module script)
// `planRemoval` deletes exactly those (a marked statement together with its line break), so a file init only added
// to comes back byte for byte, and refuses (reports a problem, deletes nothing there) when a marked line or block is
// not what init wrote. `switchMode` re-points the same marked code at another mode.
diff --git a/packages/runtime/bin/lib/init.mjs b/packages/runtime/bin/lib/init.mjs
index 4378290f..d808ab9b 100644
--- a/packages/runtime/bin/lib/init.mjs
+++ b/packages/runtime/bin/lib/init.mjs
@@ -1,7 +1,8 @@
// `genclass-runtime init` and `genclass-runtime remove` (also `npx @genclass/runtime init|remove`).
//
// init: detects the project, installs @genclass/runtime, adds the auto import as the first statement of the entry
-// file (plus a dev-only devtools line), shows the diff and asks before writing. Every added line or created file
+// file (plus a dev-only devtools line and, with --agent, the dev-only agent line), shows the diff and asks before
+// writing. Every added line or created file
// carries the marker `genclass:init`, so `remove` can take out exactly that and nothing else (and refuses when a
// marked line or block was edited). Running init twice changes nothing; running it again with another --mode
// switches the marked import (or the script tag's data-mode) to that mode in place.
diff --git a/packages/runtime/test/install/cli.test.ts b/packages/runtime/test/install/cli.test.ts
index 1ca950a3..9bb78ac8 100644
--- a/packages/runtime/test/install/cli.test.ts
+++ b/packages/runtime/test/install/cli.test.ts
@@ -13,7 +13,7 @@ import { appendEnd, bodyTagEnd, codeStyle, insertTop, planRemoval, removeMarked,
import { integrityFor, nodeOnlyImport, scriptTag } from "../../bin/lib/plan.mjs";
// @ts-expect-error plain ESM module without types
import { libraryEvidence } from "../../bin/lib/detect.mjs";
-import { CMD, VERSION, channelOf, cmdFor, compareVersions, versionInSpec, versionStatus } from "../../bin/lib/version.mjs";
+import { CMD, MCP_PKG, VERSION, channelOf, cmdFor, compareVersions, versionInSpec, versionStatus } from "../../bin/lib/version.mjs";
import { assetBase } from "../../src/cdn/global.js";
import { GenClass } from "../../src/index.js";
import { DEFAULT_MODEL_BASE_URL } from "../../src/model/host.js";
@@ -1242,7 +1242,7 @@ describe("init --agent: the dev-only agent link next to the overlay (the open-so
const dir = project(VITE_TS);
const r = cli(dir, "init", "--yes", "--no-install", "--agent");
expect(r.code, r.out).toBe(0);
- expect(r.out).toContain("npx -y @genclass/mcp@0.2.1 init");
+ expect(r.out).toContain(`npx -y ${MCP_PKG} init`);
expect(r.out).toContain("127.0.0.1:47357");
const main = readFileSync(join(dir, "src/main.tsx"), "utf8");
const lines = main.trimEnd().split("\n");
From bfb233ece58e8be4c5b6cb6088c5e8d4a7c35666 Mon Sep 17 00:00:00 2001
From: Claude
Date: Mon, 2 Nov 2026 18:38:24 +0000
Subject: [PATCH 06/11] Docs: the two-command blocks say --agent is new in
0.3.0-beta.6
The adversarial review's last confirmed item: every command block named --agent as the setup that works today, while
npm's beta tag (0.3.0-beta.4, then beta.5) rejects the flag; the blocks now carry the version, and the merge is
tied to the 0.3.0-beta.6 release.
Co-Authored-By: Claude Fable 5.1
Claude-Session: https://claude.ai/code/session_01Fqwfq3CizvxvgyXp6wY8WR
---
FAQ.md | 2 +-
README.md | 3 ++-
docs/runtime/INSTALL.md | 2 +-
packages/mcp/README.md | 2 +-
packages/mcp/src/tools.ts | 2 +-
packages/runtime/README.md | 3 ++-
6 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/FAQ.md b/FAQ.md
index 3696f3dc..fa6804c7 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -175,7 +175,7 @@ Details: [genclass.dev/pricing](https://genclass.dev/pricing),
Yes. Two commands set up every open-source part with nothing sent to genclass.dev:
`npx @genclass/runtime@beta init --no-telemetry --agent` (the runtime in observe mode, the dev-only overlay and agent
-link, no token) and `npx -y @genclass/mcp@0.2.1 init` (the MCP server and the `genclass` skill for Claude Code). Details:
+link, no token; `--agent` is new in `0.3.0-beta.6`) and `npx -y @genclass/mcp@0.2.1 init` (the MCP server and the `genclass` skill for Claude Code). Details:
[INSTALL.md](https://github.com/genclass-dev/GenClass-lib/blob/main/docs/runtime/INSTALL.md#how-do-i-set-up-the-open-source-parts-only).
## How is it different from Sentry, Datadog or my tests?
diff --git a/README.md b/README.md
index 556e46fc..6fe82ca8 100644
--- a/README.md
+++ b/README.md
@@ -37,7 +37,8 @@ Once you approve, `init` installs the package, adds one import first in your ent
devtools overlay in development only) and creates your app's dashboard token (`--no-token` skips it; every flag:
[INSTALL.md](docs/runtime/INSTALL.md)).
-**Open source only, no account.** Two commands set up every open-source part, with nothing sent to genclass.dev:
+**Open source only, no account.** Two commands set up every open-source part, with nothing sent to genclass.dev
+(`--agent` is new in `0.3.0-beta.6`):
```bash
npx @genclass/runtime@beta init --no-telemetry --agent # the runtime (observe), the dev-only overlay and agent link; no token
diff --git a/docs/runtime/INSTALL.md b/docs/runtime/INSTALL.md
index 04a15f73..a3f9f550 100644
--- a/docs/runtime/INSTALL.md
+++ b/docs/runtime/INSTALL.md
@@ -141,7 +141,7 @@ installs nothing.
## How do I set up the open-source parts only?
-Two commands, no account, no token, nothing sent to genclass.dev:
+Two commands, no account, no token, nothing sent to genclass.dev (`--agent` is new in `0.3.0-beta.6`):
```bash
npx @genclass/runtime@beta init --no-telemetry --agent # the runtime in observe, the dev-only overlay and agent link
diff --git a/packages/mcp/README.md b/packages/mcp/README.md
index 5823f316..b454dc04 100644
--- a/packages/mcp/README.md
+++ b/packages/mcp/README.md
@@ -307,7 +307,7 @@ read a report, what to say when done, what to do when the tools are missing) is
To remove it: delete `.claude/skills/genclass/` (or the directory the skill tool wrote to); with the plugin,
`/plugin uninstall genclass@genclass`.
-Then connect the app's development build (once): `npx @genclass/runtime@beta init --agent` adds a dev-only line next to
+Then connect the app's development build (once): `npx @genclass/runtime@beta init --agent` (0.3.0-beta.6 or later) adds a dev-only line next to
the import it writes (plain HTML: a module script after the tag), installing the runtime first if needed. By hand, the
agent link needs the newest runtime line, `@genclass/runtime` 0.3.0-beta.1 or later: `npm install @genclass/runtime@beta`
(a bare `npm install @genclass/runtime` gets npm's `latest`, the older 0.2.x, which has no agent entry):
diff --git a/packages/mcp/src/tools.ts b/packages/mcp/src/tools.ts
index 380e8390..6b92b136 100644
--- a/packages/mcp/src/tools.ts
+++ b/packages/mcp/src/tools.ts
@@ -559,7 +559,7 @@ export function setupText(cwd: string, client?: string | null): string {
const guard = next ? `process.env.NODE_ENV === "development"` : vite ? "import.meta.env.DEV" : `process.env.NODE_ENV !== "production"`;
const where = next ? "a client component loaded once from the root layout (\"use client\")" : vite ? "the app's entry (src/main.tsx or src/main.ts), before the app renders" : "the app's browser entry, before the app starts";
const lines = [
- "One command does the app side: npx @genclass/runtime@beta init --agent (it installs the runtime if needed and adds a dev-only agent line next to the import it writes; --no-telemetry too for no diagnostics). By hand:",
+ "One command does the app side: npx @genclass/runtime@beta init --agent (@genclass/runtime 0.3.0-beta.6 or later; it installs the runtime if needed and adds a dev-only agent line next to the import it writes; --no-telemetry too for no diagnostics). By hand:",
installed
? "@genclass/runtime is installed."
: `1. Install the newest runtime, 0.3.0-beta.1 or later (the agent entry and analytics; 0.2.x has neither${has("@genclass/runtime") ? `; this project has ${JSON.stringify(range)}${have !== range ? `, installed ${have}` : ""}` : ""}): npm install @genclass/runtime@beta`,
diff --git a/packages/runtime/README.md b/packages/runtime/README.md
index aa191400..2db2dc4d 100644
--- a/packages/runtime/README.md
+++ b/packages/runtime/README.md
@@ -35,7 +35,8 @@ Once you approve the diff, `init` also creates your app's free dashboard at genc
`package.json` `name`; `--no-token`, `--token`, `--no-telemetry` and `--dry-run` create no dashboard and never contact
genclass.dev ([Your dashboard](#your-dashboard)).
-**Open source only, no account.** Two commands set up every open-source part, with nothing sent to genclass.dev:
+**Open source only, no account.** Two commands set up every open-source part, with nothing sent to genclass.dev
+(`--agent` is new in `0.3.0-beta.6`):
```bash
npx @genclass/runtime@beta init --no-telemetry --agent # the runtime (observe), the dev-only overlay and agent link; no token
From 248f8498eedb5c6da031ce0fe1f9e9fc8bb3733d Mon Sep 17 00:00:00 2001
From: Karan
Date: Mon, 2 Nov 2026 16:13:04 -0500
Subject: [PATCH 07/11] Two-command setup: diagnostics on (init --agent), the
opt-out stays a documented flag
Owner decision 2026-11-02: the two commands are `npx @genclass/runtime@beta init --agent` and
`npx -y @genclass/mcp@0.2.1 init`, with the runtime's anonymous diagnostics on and the app's free dashboard link,
as with every init; `init --no-telemetry --agent` is the documented way to send nothing. Every surface that showed
`init --no-telemetry --agent` now shows `init --agent` and says what is sent: both READMEs, INSTALL.md, the FAQ,
the CLI's --agent help, the CHANGELOG, and the worker's /start/open-source (its prompt, lead, "What leaves your
network" and commands), with its tests. The MCP-side mentions (AGENT.md, the MCP README, tools.ts) already showed
the bare `init --agent` and are unchanged.
Co-Authored-By: Claude Fable 5.1
---
FAQ.md | 8 +++++---
README.md | 14 +++++++------
docs/runtime/INSTALL.md | 15 ++++++++------
packages/runtime/CHANGELOG.md | 5 +++--
packages/runtime/README.md | 14 +++++++------
packages/runtime/bin/lib/init.mjs | 4 ++--
telemetry-worker/src/pages.ts | 31 +++++++++++++++--------------
telemetry-worker/test/pages.test.ts | 23 +++++++++++----------
8 files changed, 64 insertions(+), 50 deletions(-)
diff --git a/FAQ.md b/FAQ.md
index fa6804c7..17c625fd 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -173,9 +173,11 @@ Details: [genclass.dev/pricing](https://genclass.dev/pricing),
## Can I use it without an account?
-Yes. Two commands set up every open-source part with nothing sent to genclass.dev:
-`npx @genclass/runtime@beta init --no-telemetry --agent` (the runtime in observe mode, the dev-only overlay and agent
-link, no token; `--agent` is new in `0.3.0-beta.6`) and `npx -y @genclass/mcp@0.2.1 init` (the MCP server and the `genclass` skill for Claude Code). Details:
+Yes. Two commands set up every open-source part, and nothing asks you to sign in:
+`npx @genclass/runtime@beta init --agent` (the runtime in observe mode, the dev-only overlay and agent link, and the
+app's free dashboard link; `--agent` is new in `0.3.0-beta.6`) and `npx -y @genclass/mcp@0.2.1 init` (the MCP server and the `genclass` skill for Claude Code).
+Anonymous diagnostics stay on, as with every `init` (never page text, never from local hosts);
+`init --no-telemetry --agent` turns them off and creates no dashboard link. Details:
[INSTALL.md](https://github.com/genclass-dev/GenClass-lib/blob/main/docs/runtime/INSTALL.md#how-do-i-set-up-the-open-source-parts-only).
## How is it different from Sentry, Datadog or my tests?
diff --git a/README.md b/README.md
index 6fe82ca8..8b3b1d62 100644
--- a/README.md
+++ b/README.md
@@ -37,16 +37,18 @@ Once you approve, `init` installs the package, adds one import first in your ent
devtools overlay in development only) and creates your app's dashboard token (`--no-token` skips it; every flag:
[INSTALL.md](docs/runtime/INSTALL.md)).
-**Open source only, no account.** Two commands set up every open-source part, with nothing sent to genclass.dev
-(`--agent` is new in `0.3.0-beta.6`):
+**Two commands, no account.** They set up every open-source part, and nothing asks you to sign in (`--agent` is new
+in `0.3.0-beta.6`):
```bash
-npx @genclass/runtime@beta init --no-telemetry --agent # the runtime (observe), the dev-only overlay and agent link; no token
-npx -y @genclass/mcp@0.2.1 init # the GenClass MCP server and the `genclass` skill for Claude Code
+npx @genclass/runtime@beta init --agent # the runtime (observe), the dev-only overlay and agent link, your free dashboard link
+npx -y @genclass/mcp@0.2.1 init # the GenClass MCP server and the `genclass` skill for Claude Code
```
-The first adds one marked import plus an option file with `telemetry: false` (plain HTML: the script tag with
-`data-telemetry="off"`; Astro: a ` ` line); the second writes
+The first adds one marked import plus an option file with the app's token (plain HTML: the script tag with
+`data-token`; Astro: a ` ` line), creates the app's free dashboard link at genclass.dev (it sends
+the package name, nothing else) and keeps anonymous diagnostics on, as every `init` does (never page text, never from
+local hosts; `init --no-telemetry --agent` turns them off and creates no link); the second writes
`.mcp.json` and `.claude/skills/genclass/SKILL.md` (other agents: `npx -y @genclass/mcp@0.2.1 config `). Nothing
else is needed; `npx @genclass/runtime@beta remove` undoes the first
([the open-source setup](docs/runtime/INSTALL.md#how-do-i-set-up-the-open-source-parts-only)).
diff --git a/docs/runtime/INSTALL.md b/docs/runtime/INSTALL.md
index a3f9f550..78843e41 100644
--- a/docs/runtime/INSTALL.md
+++ b/docs/runtime/INSTALL.md
@@ -141,17 +141,20 @@ installs nothing.
## How do I set up the open-source parts only?
-Two commands, no account, no token, nothing sent to genclass.dev (`--agent` is new in `0.3.0-beta.6`):
+Two commands, no account, nothing to sign in to (`--agent` is new in `0.3.0-beta.6`):
```bash
-npx @genclass/runtime@beta init --no-telemetry --agent # the runtime in observe, the dev-only overlay and agent link
-npx -y @genclass/mcp@0.2.1 init # the GenClass MCP server and the `genclass` skill for Claude Code
+npx @genclass/runtime@beta init --agent # the runtime in observe, the dev-only overlay and agent link, your free dashboard link
+npx -y @genclass/mcp@0.2.1 init # the GenClass MCP server and the `genclass` skill for Claude Code
```
The first finds your framework, installs `@genclass/runtime`, adds one marked import (plain HTML: the script tag,
-pinned with an integrity hash) with the dev-only devtools and agent lines, and writes `telemetry: false` into a
-marked `genclass.config.ts` (or `.js`) next to your entry (`data-telemetry="off"` on a script tag), so GenClass's
-anonymous diagnostics are off; `--no-telemetry` implies `--no-token`. Browsers still download the model and
+pinned with an integrity hash) with the dev-only devtools and agent lines, and, once you approve the diff, creates the
+app's free dashboard link at genclass.dev (it sends the package name, nothing else) and writes the token into a marked
+`genclass.config.ts` (or `.js`) next to your entry (`data-token` on a script tag). GenClass's anonymous diagnostics
+stay on, as with every `init` (never page text, never from local hosts;
+[TELEMETRY.md](../../packages/runtime/TELEMETRY.md)): `init --no-telemetry --agent` turns them off and implies
+`--no-token`; `--no-token` alone skips the link. Browsers still download the model and
onnxruntime-web, public files, from jsDelivr unless you serve them (`--model-url`,
[Content-Security-Policy and self-hosting](../../packages/runtime/README.md#content-security-policy-and-self-hosting)).
Add `--mode guard` to let GenClass act, `--sink console-json` for findings in your own logs.
diff --git a/packages/runtime/CHANGELOG.md b/packages/runtime/CHANGELOG.md
index d0e36625..34f702f8 100644
--- a/packages/runtime/CHANGELOG.md
+++ b/packages/runtime/CHANGELOG.md
@@ -8,8 +8,9 @@
in the files it creates for Next.js; plain HTML gets a module script after the tag, which loads `dist/agent.js` from
the script URL's directory on `localhost` and connects `GenClass.runtime`; module scripts run after deferred ones,
in order). `remove` takes it out, wrapped by a formatter or not, and refuses an edited one. So
- `npx @genclass/runtime@beta init --no-telemetry --agent` and `npx -y @genclass/mcp@0.2.1 init` set up every open-source
- part with no account and nothing sent, and the READMEs, INSTALL.md ("How do I set up the open-source parts only?"),
+ `npx @genclass/runtime@beta init --agent` and `npx -y @genclass/mcp@0.2.1 init` set up every open-source part with no
+ account (anonymous diagnostics on and a free dashboard link, as with every `init`; `--no-telemetry` for neither;
+ owner decision 2026-11-02), and the READMEs, INSTALL.md ("How do I set up the open-source parts only?"),
FAQ, AGENT.md, the MCP server's setup text and genclass.dev/start/open-source say so with those two commands instead
of a nine-step hand edit. No runtime code, no model-visible text, no change to what is sent. Tests:
`test/install/cli.test.ts` ("init --agent").
diff --git a/packages/runtime/README.md b/packages/runtime/README.md
index 2db2dc4d..689a7687 100644
--- a/packages/runtime/README.md
+++ b/packages/runtime/README.md
@@ -35,16 +35,18 @@ Once you approve the diff, `init` also creates your app's free dashboard at genc
`package.json` `name`; `--no-token`, `--token`, `--no-telemetry` and `--dry-run` create no dashboard and never contact
genclass.dev ([Your dashboard](#your-dashboard)).
-**Open source only, no account.** Two commands set up every open-source part, with nothing sent to genclass.dev
-(`--agent` is new in `0.3.0-beta.6`):
+**Two commands, no account.** They set up every open-source part, and nothing asks you to sign in (`--agent` is new
+in `0.3.0-beta.6`):
```bash
-npx @genclass/runtime@beta init --no-telemetry --agent # the runtime (observe), the dev-only overlay and agent link; no token
-npx -y @genclass/mcp@0.2.1 init # the GenClass MCP server and the `genclass` skill for Claude Code
+npx @genclass/runtime@beta init --agent # the runtime (observe), the dev-only overlay and agent link, your free dashboard link
+npx -y @genclass/mcp@0.2.1 init # the GenClass MCP server and the `genclass` skill for Claude Code
```
-The first adds one marked import plus an option file with `telemetry: false` (plain HTML: the script tag with
-`data-telemetry="off"`; Astro: a ` ` line); the second writes
+The first adds one marked import plus an option file with the app's token (plain HTML: the script tag with
+`data-token`; Astro: a ` ` line), creates the app's free dashboard link at genclass.dev (it sends
+the package name, nothing else) and keeps anonymous diagnostics on, as every `init` does (never page text, never from
+local hosts; `init --no-telemetry --agent` turns them off and creates no link); the second writes
`.mcp.json` and `.claude/skills/genclass/SKILL.md` (other agents: `npx -y @genclass/mcp@0.2.1 config `). Nothing
else is needed; `npx @genclass/runtime@beta remove` undoes the first
([the open-source setup](https://github.com/genclass-dev/GenClass-lib/blob/main/docs/runtime/INSTALL.md#how-do-i-set-up-the-open-source-parts-only)).
diff --git a/packages/runtime/bin/lib/init.mjs b/packages/runtime/bin/lib/init.mjs
index d808ab9b..9a35330e 100644
--- a/packages/runtime/bin/lib/init.mjs
+++ b/packages/runtime/bin/lib/init.mjs
@@ -83,8 +83,8 @@ remove takes out exactly what init added (the lines and blocks marked "${MARK}
--agent also connect development builds to your coding agent: a dev-only line that loads
@genclass/runtime/agent and calls connectAgent (plain HTML: a module script after the
tag), so the GenClass MCP server (npx -y ${MCP_PKG} init) sees the page. Production
- builds drop it; off loopback hosts it is inert. The open-source setup, no account:
- init --no-telemetry --agent, then npx -y ${MCP_PKG} init
+ builds drop it; off loopback hosts it is inert. The two-command setup, no account:
+ init --agent, then npx -y ${MCP_PKG} init (--no-telemetry too sends nothing)
--no-devtools do not add the dev-only devtools overlay
--no-network do not ask npm for newer releases (--dry-run, --no-token and --no-telemetry do not
ask either)
diff --git a/telemetry-worker/src/pages.ts b/telemetry-worker/src/pages.ts
index 91945975..d36e7afb 100644
--- a/telemetry-worker/src/pages.ts
+++ b/telemetry-worker/src/pages.ts
@@ -350,9 +350,9 @@ See
// ------------------------------------------------------------------------------------- /start/open-source
// GenClass's open-source parts with no account: the runtime in the app's pages, the agent link, the MCP server and the
-// page check, all Apache-2.0, with no token and the runtime's anonymous diagnostics off, so nothing reaches
-// genclass.dev. For teams that cannot sign up for or send data to a hosted dashboard (enterprises). The page sends
-// nothing either: its choices rewrite the prompt in the browser, with the server's own openSourcePrompt.
+// page check, all Apache-2.0, with no account: init creates the app's free dashboard link and keeps the runtime's
+// anonymous diagnostics on, as every init does (`--no-telemetry` for neither; owner decision 2026-11-02). For teams
+// that cannot sign up for a hosted dashboard. The page sends nothing either: its choices rewrite the prompt in the browser, with the server's own openSourcePrompt.
/** What /start/open-source's choices add to openSourcePrompt; all off is observe, the overlay in development only. */
export interface OpenSourceChoices {
@@ -369,10 +369,10 @@ export interface OpenSourceChoices {
}
/**
- * The prompt /start/open-source copies: the two commands (`init --no-telemetry --agent` for the app, `@genclass/mcp
- * init` for the agent), with `telemetry: false` (the runtime sends no data anywhere; it still downloads public files
- * from jsDelivr unless the app serves them), no token, the MCP server on the developer's machine and the page check
- * run locally; the choices are init flags. Pure and self-contained, like installPrompt: the page script runs this
+ * The prompt /start/open-source copies: the two commands (`init --agent` for the app, `@genclass/mcp init` for the
+ * agent), with the app's free dashboard link and anonymous diagnostics on (never page text, never from local hosts;
+ * the browser downloads public files from jsDelivr unless the app serves them), no account, the MCP server on the
+ * developer's machine and the page check run locally; the choices are init flags. Pure and self-contained, like installPrompt: the page script runs this
* same function.
*/
export function openSourcePrompt(c: OpenSourceChoices = {}, n: PromptNames = PROMPT_NAMES): string {
@@ -382,7 +382,7 @@ export function openSourcePrompt(c: OpenSourceChoices = {}, n: PromptNames = PRO
const own = !!c.selfHost;
const dir = "/genclass-model/";
// every choice is an init flag, except the visual fixes and the aggressiveness, which init does not write
- const flags = ["--no-telemetry", "--agent", ...(guard ? ["--mode guard"] : []), ...(logs ? ["--sink console-json"] : []), ...(own ? [`--model-url ${dir}`] : []), "--yes"];
+ const flags = ["--agent", ...(guard ? ["--mode guard"] : []), ...(logs ? ["--sink console-json"] : []), ...(own ? [`--model-url ${dir}`] : []), "--yes"];
const initAdds = guard
? `add ${eager ? 'aggressiveness: "eager" and ' : ""}visual: { on: true, fix: true } to the option file it writes (data-visual="fix" on the tag it writes${eager ? ', and a line before it' : ""}; Astro gets a line instead: add visual=fix to its content${eager ? ", and the aggressiveness in a window.GENCLASS_CONFIG script before it" : ""})`
: "";
@@ -390,7 +390,7 @@ export function openSourcePrompt(c: OpenSourceChoices = {}, n: PromptNames = PRO
// function: Wrangler's bundler (keepNames) would wrap it in a __name() helper that the page script, which runs this
// function's source, lacks.
const out: (string | [string])[] = [
- "Add GenClass's open-source parts to this web app (Apache-2.0, https://github.com/genclass-dev/GenClass): the @genclass/runtime library in its pages, which reports the bugs that never throw (double submits, stale responses that overwrite newer data, write races, visual bugs), and the @genclass/mcp server on this machine, so you, the coding agent, can see what happens on the dev pages, replay it and prove fixes. No GenClass account and no token: nothing is sent to genclass.dev. Two commands do it; run them yourself.",
+ "Add GenClass's open-source parts to this web app (Apache-2.0, https://github.com/genclass-dev/GenClass): the @genclass/runtime library in its pages, which reports the bugs that never throw (double submits, stale responses that overwrite newer data, write races, visual bugs), and the @genclass/mcp server on this machine, so you, the coding agent, can see what happens on the dev pages, replay it and prove fixes. No GenClass account and nothing to sign in to: init creates the app's free dashboard link. Two commands do it; run them yourself.",
"",
...(own
? [
@@ -399,7 +399,7 @@ export function openSourcePrompt(c: OpenSourceChoices = {}, n: PromptNames = PRO
: []),
[
`In the project's root run: npx ${n.pkg} init ${flags.join(" ")} ` +
- "It finds the framework and package manager, installs the runtime, adds one marked import first in the browser entry (plain HTML pages, no bundler: the script tag, pinned with an integrity hash, in every page's ), the dev-only devtools overlay and the dev-only agent link (which records what happens on local pages for the GenClass MCP server, talks only to 127.0.0.1 and is never part of a production build; on plain HTML pages it stays in the page and runs only on localhost), and writes telemetry: false into a marked option file next to the entry (data-telemetry=\"off\" on the tag; Astro: a line), so GenClass's anonymous diagnostics are off and it sends no data anywhere" +
+ "It finds the framework and package manager, installs the runtime, adds one marked import first in the browser entry (plain HTML pages, no bundler: the script tag, pinned with an integrity hash, in every page's ), the dev-only devtools overlay and the dev-only agent link (which records what happens on local pages for the GenClass MCP server, talks only to 127.0.0.1 and is never part of a production build; on plain HTML pages it stays in the page and runs only on localhost), and, once applied, creates the app's free dashboard link at genclass.dev (it sends the package name, nothing else) and writes the token into a marked option file next to the entry (data-token on the tag; Astro: a line). GenClass's anonymous diagnostics stay on: its decisions and counts, never text from the page, and never from localhost or private hosts" +
(own ? "" : "; the browser still downloads its model and onnxruntime-web, public files, from cdn.jsdelivr.net (about 13 MB, 18 MB on WebGPU devices, then cached) unless the app serves them") +
". It shows the diff; --yes applies it. " +
(guard
@@ -419,7 +419,7 @@ export function openSourcePrompt(c: OpenSourceChoices = {}, n: PromptNames = PRO
...(c.deploy
? [["Deploy it, as chosen, with the command this project already uses (a deploy script in package.json, wrangler deploy for a Cloudflare Worker, vercel deploy --prod, and so on), then check that the deployed site serves the change."] as [string]]
: []),
- [`Tell me what you changed${c.deploy ? " and where it is deployed" : ""}, that the app sets no GenClass token and has telemetry off, what it downloads from outside this network, and that a new conversation with you has the GenClass tools.`],
+ [`Tell me what you changed${c.deploy ? " and where it is deployed" : ""}, the dashboard link init printed if it created one (it is saved in .genclass.local, which init adds to .gitignore; keep it private), what it downloads from outside this network, and that a new conversation with you has the GenClass tools.`],
];
let k = 0;
return out.map((l) => (typeof l === "string" ? l : `${++k}. ${l[0]}`)).join("\n");
@@ -476,7 +476,8 @@ export function openSourcePage(nonce: string): string {
GenClass without an account
The open-source parts only, Apache-2.0: the runtime in your app's pages, and the MCP server and the
- page check on your machine. No sign-in, no token, and nothing is sent to genclass.dev.
+ page check on your machine. No sign-in: init creates the app's free dashboard link, and anonymous diagnostics stay on
+ unless you turn them off.
@@ -496,7 +497,7 @@ export function openSourcePage(nonce: string): string {
What leaves your network
- Nothing goes to genclass.dev: there is no token, and the runtime's anonymous diagnostics are off (telemetry: false).
+ To genclass.dev: the app's package name, once, when init creates its free dashboard link (--no-token skips it); then, from public hosts only, the runtime's anonymous diagnostics: its decisions and counts, never text from the page (every field ). init --no-telemetry --agent turns them off and creates no link, so nothing goes to genclass.dev at all.
Browsers download public files from jsDelivr (cdn.jsdelivr.net), once, then cached: the model and onnxruntime-web (about 13 MB on WASM, 18 MB on WebGPU) unless you serve them yourself, and on sites without a bundler the runtime's own files unless you serve its dist/ folder. No app data goes with those requests.
The MCP server runs on your machine and its bridge listens on 127.0.0.1 only; with GENCLASS_DASHBOARD and GENCLASS_REPORT unset it sends nothing off the machine, and it keeps what it records in .genclass/agent in the project, which git ignores. genclass_scan and scan --local check pages in headless Chromium on your machine. A page URL leaves it only with hosted: true (or scan without --local when Playwright or its Chromium is missing): it then goes to GenClass's hosted page check (genclass-scan.mehar-144.workers.dev), which is not open source.
On developer machines, npm install and npx fetch packages from the npm registry (or your mirror), and the page check's Chromium comes from Playwright's download servers; fetch-model (to serve the model yourself) downloads the model and onnxruntime-web from jsDelivr, or from a mirror you name with --from and --ort-from.
@@ -513,10 +514,10 @@ export function openSourcePage(nonce: string): string {
Or run the commands yourself
- ${cmd("Add the runtime to your app, with the dev-only agent link", `npx ${RUNTIME_PKG} init --no-telemetry --agent`)}
+ ${cmd("Add the runtime to your app, with the dev-only agent link", `npx ${RUNTIME_PKG} init --agent`)}
${cmd("Add the MCP server and the genclass skill for Claude Code", `npx -y ${MCP_PKG} init`)}
${cmd("Check a page for visual bugs", `npx ${RUNTIME_PKG} scan http://localhost:5173/ --local`)}
- init shows the diff and asks before it writes; add --mode guard for guard. Until the MCP server runs, a dev page logs one failed request to 127.0.0.1:47357 (the agent link finding no server). Other agents: npx -y ${MCP_PKG} config <client> prints the block for Cursor, VS Code, Codex, Gemini CLI and others; keep GENCLASS_DASHBOARD and GENCLASS_REPORT out of it. The scan needs Playwright (npm i -D playwright && npx playwright install chromium).
+ init shows the diff and asks before it writes; add --mode guard for guard, --no-telemetry to send nothing to genclass.dev. Until the MCP server runs, a dev page logs one failed request to 127.0.0.1:47357 (the agent link finding no server). Other agents: npx -y ${MCP_PKG} config <client> prints the block for Cursor, VS Code, Codex, Gemini CLI and others; keep GENCLASS_DASHBOARD and GENCLASS_REPORT out of it. The scan needs Playwright (npm i -D playwright && npx playwright install chromium).
Want a dashboard without sending data to us? The collector is open source too:
run it on your own Cloudflare account .
diff --git a/telemetry-worker/test/pages.test.ts b/telemetry-worker/test/pages.test.ts
index 442f2f99..3efd0053 100644
--- a/telemetry-worker/test/pages.test.ts
+++ b/telemetry-worker/test/pages.test.ts
@@ -1284,15 +1284,18 @@ describe("/start/open-source: the open-source parts with no account, no token an
return { html, win, doc, urls, copied, box, copy, close: () => win.happyDOM.close() };
}
- it("the default prompt: two commands (init --no-telemetry --agent, @genclass/mcp init), no token, observe, the skill, the local scan", () => {
+ it("the default prompt: two commands (init --agent, @genclass/mcp init), no account, diagnostics on, observe, the skill, the local scan", () => {
const p = openSourcePrompt();
- expect(p).toContain("No GenClass account and no token: nothing is sent to genclass.dev. Two commands do it; run them yourself.");
- expect(p).toContain(`\n1. In the project's root run: npx ${RUNTIME_PKG} init --no-telemetry --agent --yes It finds the framework`);
+ expect(p).toContain("No GenClass account and nothing to sign in to: init creates the app's free dashboard link. Two commands do it; run them yourself.");
+ expect(p).toContain(`\n1. In the project's root run: npx ${RUNTIME_PKG} init --agent --yes It finds the framework`);
+ // diagnostics on and the free dashboard link (owner decision 2026-11-02); the opt-out is a documented flag, not the default
+ expect(p).not.toContain("--no-telemetry");
expect(p).toContain("the dev-only devtools overlay and the dev-only agent link (which records what happens on local pages for the GenClass MCP server, talks only to 127.0.0.1 and is never part of a production build; on plain HTML pages it stays in the page and runs only on localhost)");
- expect(p).toContain('writes telemetry: false into a marked option file next to the entry (data-telemetry="off" on the tag; Astro: a line)');
+ expect(p).toContain('creates the app\'s free dashboard link at genclass.dev (it sends the package name, nothing else) and writes the token into a marked option file next to the entry (data-token on the tag; Astro: a line)');
expect(p).toContain("on plain HTML pages it stays in the page and runs only on localhost");
- // no data is sent, but the public files still come from jsDelivr unless the app serves them; the prompt says so
- expect(p).toContain("so GenClass's anonymous diagnostics are off and it sends no data anywhere; the browser still downloads its model and onnxruntime-web, public files, from cdn.jsdelivr.net");
+ // what is sent is named, and the public files still come from jsDelivr unless the app serves them; the prompt says so
+ expect(p).toContain("GenClass's anonymous diagnostics stay on: its decisions and counts, never text from the page, and never from localhost or private hosts; the browser still downloads its model and onnxruntime-web, public files, from cdn.jsdelivr.net");
+ expect(p).not.toContain("telemetry: false");
expect(p).toContain("(about 13 MB, 18 MB on WebGPU devices, then cached)");
expect(p).not.toContain("sends nothing anywhere");
expect(p).toContain("The mode stays observe: GenClass reports and never changes what the app does.");
@@ -1319,7 +1322,7 @@ describe("/start/open-source: the open-source parts with no account, no token an
expect(p).not.toContain(" line before it; Astro gets a line instead: add visual=fix to its content, and the aggressiveness in a window.GENCLASS_CONFIG script before it).');
expect(openSourcePrompt({ guard: true })).toContain('Then add visual: { on: true, fix: true } to the option file it writes (data-visual="fix" on the tag it writes; Astro gets a line instead: add visual=fix to its content).');
@@ -1378,7 +1381,7 @@ describe("/start/open-source: the open-source parts with no account, no token an
expect(r.copied).toEqual([openSourcePrompt({ logs: true, selfHost: true, deploy: true })]);
// the commands copy too
const cmds = [...r.doc.querySelectorAll(".cmds [data-copy]")].map((b) => b.getAttribute("data-copy"));
- expect(cmds).toEqual([`npx ${RUNTIME_PKG} init --no-telemetry --agent`, `npx -y ${MCP_PKG} init`, `npx ${RUNTIME_PKG} scan http://localhost:5173/ --local`]);
+ expect(cmds).toEqual([`npx ${RUNTIME_PKG} init --agent`, `npx -y ${MCP_PKG} init`, `npx ${RUNTIME_PKG} scan http://localhost:5173/ --local`]);
// the choices are a fieldset with a visible legend; the commands' titles are h3 under the section's h2
expect(r.doc.querySelector("fieldset#choices > legend")!.textContent).toContain("What the prompt sets up");
expect(r.doc.querySelectorAll(".cmds h3").length).toBe(3);
From 20c2d24931930f6803146f63559ff44e179d1488 Mon Sep 17 00:00:00 2001
From: Karan
Date: Tue, 3 Nov 2026 00:46:07 -0500
Subject: [PATCH 08/11] 0.3.0-beta.6: the version in package.json, version.ts
and the lockfile; the CHANGELOG heading names the release
The two-command setup (`init --agent`) ships in 0.3.0-beta.6, so the package version moves from 0.3.0-beta.5 to
0.3.0-beta.6 in `packages/runtime/package.json`, in `RUNTIME_VERSION` (`src/version.ts`; the release workflow checks
that the tag, package.json and this string agree, and `test/telemetry.test.ts` keeps the two equal) and in the root
`package-lock.json`'s `packages/runtime` workspace entry, edited by hand so the committed lockfile stays in sync
(`ONNXRUNTIME_NODE_INSTALL=skip npm ci --no-audit --no-fund` succeeds against it). The CHANGELOG heading
"Unreleased (0.3.0-beta.6)" becomes "0.3.0-beta.6 (2026-11-03)", the tag date assumed for the release; nothing in the
entry changes. No runtime code, no model-visible text.
Co-Authored-By: Claude Fable 5.1
---
package-lock.json | 2 +-
packages/runtime/CHANGELOG.md | 2 +-
packages/runtime/package.json | 2 +-
packages/runtime/src/version.ts | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 3018f76f..494f6f23 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16964,7 +16964,7 @@
},
"packages/runtime": {
"name": "@genclass/runtime",
- "version": "0.3.0-beta.5",
+ "version": "0.3.0-beta.6",
"license": "Apache-2.0",
"dependencies": {
"onnxruntime-web": "1.30.0"
diff --git a/packages/runtime/CHANGELOG.md b/packages/runtime/CHANGELOG.md
index 34f702f8..58e10ce3 100644
--- a/packages/runtime/CHANGELOG.md
+++ b/packages/runtime/CHANGELOG.md
@@ -1,6 +1,6 @@
# Changelog
-## Unreleased (0.3.0-beta.6)
+## 0.3.0-beta.6 (2026-11-03)
- **The open-source setup is two commands** (`bin/lib/`, owner request 2026-11-02). `init --agent` adds the dev-only
agent link next to the import it writes, the same way it adds the devtools line: `if ()
diff --git a/packages/runtime/package.json b/packages/runtime/package.json
index 7767a005..7f0e35c7 100644
--- a/packages/runtime/package.json
+++ b/packages/runtime/package.json
@@ -1,6 +1,6 @@
{
"name": "@genclass/runtime",
- "version": "0.3.0-beta.5",
+ "version": "0.3.0-beta.6",
"description": "Browser library that reports race conditions in web apps while they happen (stale responses, double submits, inconsistent state, failure storms) using a small on-device model. Report-only by default; an opt-in guard mode can prevent a few of them.",
"type": "module",
"license": "Apache-2.0",
diff --git a/packages/runtime/src/version.ts b/packages/runtime/src/version.ts
index f9ed7c94..c6e14e88 100644
--- a/packages/runtime/src/version.ts
+++ b/packages/runtime/src/version.ts
@@ -2,4 +2,4 @@
// test/telemetry.test.ts ("RUNTIME_VERSION matches package.json"); bump both together: .github/workflows/release.yml
// checks that the v tag equals package.json and that this file holds the same string.
-export const RUNTIME_VERSION = "0.3.0-beta.5";
+export const RUNTIME_VERSION = "0.3.0-beta.6";
From 391554758408645f6296bf48d1748ef9aae9e981 Mon Sep 17 00:00:00 2001
From: Karan
Date: Tue, 3 Nov 2026 00:46:07 -0500
Subject: [PATCH 09/11] 0.3.0-beta.6 docs: the newest line, the install
sentences and the script-tag pins move from beta.5 to beta.6
The same pass commit b740e43 made for 0.3.0-beta.5, one release on. The shipped README, TELEMETRY.md and
INTERCEPTION.md describe and pin the version they ship with (a published tarball cannot be republished), so every
"newest line" and "installs" mention and every jsDelivr script-tag pin names 0.3.0-beta.6, with the beta line's
publish dates as 2026-10-22 to 2026-11-03 (0.3.0-beta.5 published 2026-11-03, beta.6 tagged the same day, both
assumed); the repository README and docs/runtime (API, ARCHITECTURE, OPTIONS-SPEC, README, INSTALL, SINKS,
ANALYTICS) follow. The package README's `init` version-check example moves one step (its own version beta.5, the newer
one beta.6) and its "installs its own version" range reads `^0.3.0-beta.6`. The pins carry no integrity hash, as
before. Historical mentions stay: "since 0.2.3 and 0.3.0-beta.5" in OPTIONS-SPEC and THREAT-MODEL, the measured visual
checks' "from 0.3.0-beta.5" in the READMEs, TELEMETRY.md, PRIVACY.md and VISUAL.md, the CHANGELOG's beta.5 section,
RESULTS.md's limit rows, SECURITY.md and docs/security, and the test comments. No runtime code, no model-visible text.
Co-Authored-By: Claude Fable 5.1
---
README.md | 12 ++++++------
docs/runtime/ANALYTICS.md | 2 +-
docs/runtime/API.md | 2 +-
docs/runtime/ARCHITECTURE.md | 4 ++--
docs/runtime/INSTALL.md | 8 ++++----
docs/runtime/OPTIONS-SPEC.md | 2 +-
docs/runtime/README.md | 4 ++--
docs/runtime/SINKS.md | 2 +-
packages/runtime/INTERCEPTION.md | 6 +++---
packages/runtime/README.md | 12 ++++++------
packages/runtime/TELEMETRY.md | 8 ++++----
11 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/README.md b/README.md
index 8b3b1d62..2058af31 100644
--- a/README.md
+++ b/README.md
@@ -18,10 +18,10 @@ Angular, Solid and plain-HTML apps (measured in Chromium with an unpublished 0.1
2026-10-10, not re-run on 0.2.2 or 0.3.0:
[compatibility matrix](https://github.com/genclass-dev/GenClass-lib/blob/main/compat/RESULTS.md)).
-**Status: `@genclass/runtime@0.3.0-beta.5`, the newest line (npm `beta` dist-tag: `npm install @genclass/runtime@beta`;
-the stable line is `0.2.x`), with model `@genclass/runtime-model@0.2.0`.** npm dist-tags on 2026-11-02: `latest` is
-`0.2.3` and `beta` is `0.3.0-beta.5` (`0.3.0-beta.1` to `0.3.0-beta.5` were released between 2026-10-22 and
-2026-11-02). This README describes the `0.3.0` line; `0.2.x`, npm's `latest`, is the exception for an app that cannot
+**Status: `@genclass/runtime@0.3.0-beta.6`, the newest line (npm `beta` dist-tag: `npm install @genclass/runtime@beta`;
+the stable line is `0.2.x`), with model `@genclass/runtime-model@0.2.0`.** npm dist-tags on 2026-11-03: `latest` is
+`0.2.3` and `beta` is `0.3.0-beta.6` (`0.3.0-beta.1` to `0.3.0-beta.6` were released between 2026-10-22 and
+2026-11-03). This README describes the `0.3.0` line; `0.2.x`, npm's `latest`, is the exception for an app that cannot
take a prerelease. Both lines load the same model. AI coding agents working on this repository: start at
[AGENTS.md](AGENTS.md).
@@ -63,7 +63,7 @@ import "@genclass/runtime/auto";
Or with no build step, first in ``:
```html
-
+
```
- **That covers network, user actions, errors and timing in the whole app, and its state where it can be found.**
@@ -288,7 +288,7 @@ but the gate fired anyway. Source and history:
10.2 MB q8, about 180 to 600 ms per model pass at 500 to 1,170 tokens on one WASM thread (estimated from runs in Node,
not in a browser), loaded from jsDelivr at idle and cached. The model and the
situation text it reads (`situation-v2.3`) are the same in `0.2.2` and in every `0.3.0` release so far
-(`0.3.0-beta.0` to `0.3.0-beta.5`; each CHANGELOG entry says no model-visible text changed). On held-out data (§1):
+(`0.3.0-beta.0` to `0.3.0-beta.6`; each CHANGELOG entry says no model-visible text changed). On held-out data (§1):
| profile | guard FIR | guard recall (clear / real) | heal FIR | heal recall (clear / real) | report threshold |
|---|---|---|---|---|---|
diff --git a/docs/runtime/ANALYTICS.md b/docs/runtime/ANALYTICS.md
index 07e26eb2..19365362 100644
--- a/docs/runtime/ANALYTICS.md
+++ b/docs/runtime/ANALYTICS.md
@@ -6,7 +6,7 @@ app's token (or a custom telemetry endpoint), are turned off by every telemetry
never record element text, and never reach the model or a decision. Status: merged into `main` on 2026-10-18 and
shipped in `@genclass/runtime` 0.3.0-beta.1 (2026-10-22, npm's `beta` dist-tag); visits, funnels, navigation paths
and the version check (sections 1.2, 3.1, 11 and 4.1) followed in 0.3.0-beta.2 (2026-10-25); the newest release is
-0.3.0-beta.5 (2026-11-02). npm's `latest`, 0.2.3, has no analytics (section 4.1).
+0.3.0-beta.6 (2026-11-03). npm's `latest`, 0.2.3, has no analytics (section 4.1).
Design written 2026-10-17 and **approved by the owner the same day** with every recommendation in
[section 9](#9-decisions-for-the-owner) (AGENTS.md rule 8: widening what telemetry sends needs that OK). **Built**
diff --git a/docs/runtime/API.md b/docs/runtime/API.md
index 0ccc968b..e96633c8 100644
--- a/docs/runtime/API.md
+++ b/docs/runtime/API.md
@@ -1,7 +1,7 @@
# GenClass Runtime API reference (@genclass/runtime)
This page describes every export, option, event, action and type of `@genclass/runtime` on `main`.
-`npm i @genclass/runtime` installs 0.2.3 (`latest`); `npm i @genclass/runtime@beta` installs 0.3.0-beta.5. Items
+`npm i @genclass/runtime` installs 0.2.3 (`latest`); `npm i @genclass/runtime@beta` installs 0.3.0-beta.6. Items
marked 0.3.0 are not in 0.2.x; items marked 0.3.0-beta.1 (interaction analytics, the devtools redesign) and later
are on npm's `beta` dist-tag since 2026-10-22.
diff --git a/docs/runtime/ARCHITECTURE.md b/docs/runtime/ARCHITECTURE.md
index d37956ca..99ea0d0e 100644
--- a/docs/runtime/ARCHITECTURE.md
+++ b/docs/runtime/ARCHITECTURE.md
@@ -3,8 +3,8 @@
GenClass Runtime (`@genclass/runtime`) is a browser library. It watches what a web app does (requests, pushed
messages, user actions, timers, state writes, errors) and, for the few situations that look risky, asks a small
on-device model whether something is going wrong and what to do. This page explains how the parts fit together and
-why they are built this way, for `@genclass/runtime` on `main` (version string 0.3.0-beta.5; npm `latest` is 0.2.3, `beta` is
-0.3.0-beta.5) with model
+why they are built this way, for `@genclass/runtime` on `main` (version string 0.3.0-beta.6; npm `latest` is 0.2.3, `beta` is
+0.3.0-beta.6) with model
`@genclass/runtime-model` 0.2.0. Items marked 0.3.0 are in the 0.3.0 line (0.3.0-beta.0 and later) and not in
0.2.x. How to use it: [API.md](API.md). Binding rules: [CONTRACT.md](CONTRACT.md). Every measured number:
[RESULTS.md](RESULTS.md). Terms: the [glossary](README.md#glossary).
diff --git a/docs/runtime/INSTALL.md b/docs/runtime/INSTALL.md
index 78843e41..33ca296b 100644
--- a/docs/runtime/INSTALL.md
+++ b/docs/runtime/INSTALL.md
@@ -2,7 +2,7 @@
How to add `@genclass/runtime` to a web app and take it out again: the `init` and `remove` commands with every
flag, the app token and dashboard that `init` creates, the zero-code options, the import, the script tag and its
-attributes, `GenClass.init()`, and the projects `init` was tested on. For `@genclass/runtime` 0.3.0 (`0.3.0-beta.5` on the npm
+attributes, `GenClass.init()`, and the projects `init` was tested on. For `@genclass/runtime` 0.3.0 (`0.3.0-beta.6` on the npm
`beta` dist-tag). The short version is in the [package README](../../packages/runtime/README.md#install).
## Which version should I install?
@@ -12,8 +12,8 @@ While `0.3.0` is in beta, every npm and npx command here names the `@beta` dist-
runtime ignores a token and whose CLI has no `login`, `connect`, `whoami`, `logout`, `dashboard`, `--token` or `--sink`. Both
lines load model `@genclass/runtime-model@0.2.0` by default.
-Pin the script tag's version (`https://cdn.jsdelivr.net/npm/@genclass/runtime@0.3.0-beta.5`): the unversioned URL
-serves the `latest` dist-tag (`0.2.3` on 2026-11-02) until 0.3.0 is released.
+Pin the script tag's version (`https://cdn.jsdelivr.net/npm/@genclass/runtime@0.3.0-beta.6`): the unversioned URL
+serves the `latest` dist-tag (`0.2.3` on 2026-11-03) until 0.3.0 is released.
**Older versions.** `0.1.0-beta.3` has these problems, fixed in `0.2.0`: app builds carried 41 MB of unused ONNX
Runtime wasm, a CSP-blocked model failed silently, `init` could not turn telemetry off, and `status.scope.mode` read
@@ -193,7 +193,7 @@ During SSR or in Node, `/auto` installs nothing and returns an inert runtime.
**One script tag** (no build step), first in ``:
```html
-
+
```
It exposes `window.GenClass` (since `0.3.0` also `window.GenClass.protect`), discovers the app's state like the
diff --git a/docs/runtime/OPTIONS-SPEC.md b/docs/runtime/OPTIONS-SPEC.md
index df3c0a13..0277f360 100644
--- a/docs/runtime/OPTIONS-SPEC.md
+++ b/docs/runtime/OPTIONS-SPEC.md
@@ -3,7 +3,7 @@
This page is the design spec for the configuration options of `@genclass/runtime`: why each option exists and how
the options combine. The reference for each option is [API.md](API.md) and the JSDoc in
`packages/runtime/src/types.ts`; where they differ from this spec, they describe the code. `npm i @genclass/runtime@beta`
-installs 0.3.0-beta.5 (npm's `beta` dist-tag, 2026-11-02); plain `npm i @genclass/runtime` installs the stable line,
+installs 0.3.0-beta.6 (npm's `beta` dist-tag, 2026-11-03); plain `npm i @genclass/runtime` installs the stable line,
0.2.3 (`latest`). Items marked 0.3.0 are not in 0.2.x.
Status: built. Most options here shipped in 0.1.0-beta.1 (the CHANGELOG's "Batch 12, 19 options") and are in every
diff --git a/docs/runtime/README.md b/docs/runtime/README.md
index dd247f26..85c8e2ef 100644
--- a/docs/runtime/README.md
+++ b/docs/runtime/README.md
@@ -1,8 +1,8 @@
# GenClass documentation
This is the index of the GenClass Runtime documentation: which document answers which question, how current each one
-is, and where genclass.dev shows it. It covers `@genclass/runtime` on `main` (version string 0.3.0-beta.5;
-`npm i @genclass/runtime@beta` installs 0.3.0-beta.5, `npm i @genclass/runtime` installs 0.2.3) and the model
+is, and where genclass.dev shows it. It covers `@genclass/runtime` on `main` (version string 0.3.0-beta.6;
+`npm i @genclass/runtime@beta` installs 0.3.0-beta.6, `npm i @genclass/runtime` installs 0.2.3) and the model
`@genclass/runtime-model` 0.2.0. Items marked 0.3.0 are in
the 0.3.0 line (0.3.0-beta.0 and later) and not in 0.2.x. The [glossary](#glossary) at the end defines the terms the
other documents use.
diff --git a/docs/runtime/SINKS.md b/docs/runtime/SINKS.md
index 8500cbf0..2d793b93 100644
--- a/docs/runtime/SINKS.md
+++ b/docs/runtime/SINKS.md
@@ -32,7 +32,7 @@ npx @genclass/runtime@beta init --sink webhook:/genclass # or console-json; re
```html
-
+
```
diff --git a/packages/runtime/INTERCEPTION.md b/packages/runtime/INTERCEPTION.md
index 85e37f29..654470de 100644
--- a/packages/runtime/INTERCEPTION.md
+++ b/packages/runtime/INTERCEPTION.md
@@ -7,9 +7,9 @@ browser global, compares what changed with the inventory at the end of this page
and counts the patch sites in `src/` (a new `addEventListener`, `defineProperty` or global assignment fails the test
until this page is updated).
-> **Version.** Written for `@genclass/runtime` 0.3.0-beta.5 as it is on GitHub `main` (released 2026-11-02). The
-> copy in an npm package describes that package's version. As of 2026-11-02, `npm i @genclass/runtime@beta` installs
-> 0.3.0-beta.5 (the 0.3.0 line: 0.3.0-beta.1 to 0.3.0-beta.5, released 2026-10-22 to 2026-11-02), and
+> **Version.** Written for `@genclass/runtime` 0.3.0-beta.6 as it is on GitHub `main` (released 2026-11-03). The
+> copy in an npm package describes that package's version. As of 2026-11-03, `npm i @genclass/runtime@beta` installs
+> 0.3.0-beta.6 (the 0.3.0 line: 0.3.0-beta.1 to 0.3.0-beta.6, released 2026-10-22 to 2026-11-03), and
> `npm i @genclass/runtime` installs 0.2.3 (`latest`, 2026-10-28), which has no measured visual checks, no `protect()`,
> no webhook sink and no interaction analytics. Items marked 0.3.0 are not in 0.2.x; the interaction analytics rows
> (`src/analytics/`) and the devtools overlay's `theme: "dark"` default are 0.3.0-beta.1, the `genclass.analytics.`
diff --git a/packages/runtime/README.md b/packages/runtime/README.md
index 689a7687..40fb79f3 100644
--- a/packages/runtime/README.md
+++ b/packages/runtime/README.md
@@ -66,7 +66,7 @@ import "@genclass/runtime/auto"; // first line of your entry file (Next.js 15.3+
Or with no build step, first in ``:
```html
-
+
```
That is the whole setup. Network traffic, user actions, errors and timing are observed, and so is your app's state:
@@ -75,7 +75,7 @@ React component state, Redux and Redux Toolkit stores, and Zustand stores with `
are not: there, stale responses are reported only for stores you register (double submits need no state).
**Versions:** this README describes `0.3.0` with model `@genclass/runtime-model@0.2.0`. The newest line is
-`0.3.0-beta.5`, npm's `beta` dist-tag (`0.3.0-beta.1` to `beta.5` were released between 2026-10-22 and 2026-11-02);
+`0.3.0-beta.6`, npm's `beta` dist-tag (`0.3.0-beta.1` to `beta.6` were released between 2026-10-22 and 2026-11-03);
npm's `latest` is still the older `0.2.3` (`npm view @genclass/runtime dist-tags` shows them now). Every npm and npx
command here names `@beta`: without it npm installs `0.2.x`, which has no token, dashboard, interaction analytics,
visual checks or agent link and ignores those options without a word (a TypeScript app gets a type error for
@@ -494,11 +494,11 @@ dist-tag it came from, asks npm's dist-tags once (`npm view @genclass/runtime di
on npm, with the command that runs it:
```
- ✔ Version @genclass/runtime 0.3.0-beta.4 (npm dist-tag beta)
- ▲ Newer @genclass/runtime 0.3.0-beta.5 is on npm (dist-tag beta): run npx @genclass/runtime@beta init instead
+ ✔ Version @genclass/runtime 0.3.0-beta.5 (npm dist-tag beta)
+ ▲ Newer @genclass/runtime 0.3.0-beta.6 is on npm (dist-tag beta): run npx @genclass/runtime@beta init instead
```
-It installs its own version (`@genclass/runtime@^0.3.0-beta.5` today), and a project that already has an older one
+It installs its own version (`@genclass/runtime@^0.3.0-beta.6` today), and a project that already has an older one
(a `0.2.x` from `npx @genclass/runtime init` without `@beta`) is upgraded, after the same diff and question. Every
command it prints names `@beta` while it is a prerelease.
@@ -527,7 +527,7 @@ Options go in `window.GENCLASS_CONFIG = { ... }` (any `InitOptions`, set before
**3. One script tag** (no build step), first in ``:
```html
-
+
```
It exposes `window.GenClass` and loads the model worker and the overlay on demand from the same version; `data-mode`,
diff --git a/packages/runtime/TELEMETRY.md b/packages/runtime/TELEMETRY.md
index 5769accc..45a75ebe 100644
--- a/packages/runtime/TELEMETRY.md
+++ b/packages/runtime/TELEMETRY.md
@@ -4,10 +4,10 @@ GenClass Runtime (`@genclass/runtime`), an open-source browser library that repo
sends anonymous diagnostics about its own decisions to its maintainers, by default on public websites; this page lists
every event and field it sends, where they are stored and for how long, and every way to turn it off.
-> **Version.** Written for `@genclass/runtime` 0.3.0-beta.5 (2026-11-02), the version on GitHub `main`, in
+> **Version.** Written for `@genclass/runtime` 0.3.0-beta.6 (2026-11-03), the version on GitHub `main`, in
> `package.json` and in the `runtime` field of every batch. The copy in an npm package describes that package's version.
-> As of 2026-11-02, `npm i @genclass/runtime@beta` installs 0.3.0-beta.5 (the newest line; 0.3.0-beta.1 to beta.5 were
-> released 2026-10-22 to 2026-11-02) and `npm i @genclass/runtime` installs the stable line, 0.2.3 (`latest`,
+> As of 2026-11-03, `npm i @genclass/runtime@beta` installs 0.3.0-beta.6 (the newest line; 0.3.0-beta.1 to beta.6 were
+> released 2026-10-22 to 2026-11-03) and `npm i @genclass/runtime` installs the stable line, 0.2.3 (`latest`,
> 2026-10-28). Items
> marked 0.3.0 are not in 0.2.x; interaction analytics are marked 0.3.0-beta.1, visits and navigation paths
> 0.3.0-beta.2.
@@ -106,7 +106,7 @@ segment holding an `@`, such as an e-mail address, is `:id` too).
"token": "gc_…", // only when the app configured a valid token (InitOptions.token); see "App tokens"
"sid": "3f9c…", // 24 hex chars from crypto.getRandomValues, new on every page load, never stored
"sent": 12034, // ms since this page's GenClass started (no wall-clock time is sent)
- "runtime": "0.3.0-beta.5", // @genclass/runtime version
+ "runtime": "0.3.0-beta.6", // @genclass/runtime version
"model": "2.0.0-rc4t", // model card version, or null without a model
"events": [ /* ≤ 100 events, ≤ 60 KB per request */ ]
}
From a380e1902f7177615e5ec3c4efd16d730036ab08 Mon Sep 17 00:00:00 2001
From: Karan
Date: Tue, 3 Nov 2026 00:47:37 -0500
Subject: [PATCH 10/11] adoption: the swarm brief (one cloud session per
target, prepare-never-send, the hand-back format and the review loop)
Co-Authored-By: Claude Fable 5.1
---
docs/adoption/swarm.md | 211 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 211 insertions(+)
create mode 100644 docs/adoption/swarm.md
diff --git a/docs/adoption/swarm.md b/docs/adoption/swarm.md
new file mode 100644
index 00000000..f55b7251
--- /dev/null
+++ b/docs/adoption/swarm.md
@@ -0,0 +1,211 @@
+# The adoption swarm: one session per target
+
+Written 2026-11-03. Fifty cloud sessions each prepare one contribution that brings GenClass into an open-source project
+or ecosystem, all at the same time. No session sends anything to a third-party repository or site: each one opens a
+pull request against this repository with everything a person needs to send its contribution, and the owner (or the
+session that launched the swarm, with the owner's go-ahead) sends it from a personal account, a few a day, and
+answers the maintainers personally. This file is the brief every session reads first (sections 2 to 5), the roster
+(section 6) and the loop that turns the sessions' pull requests into contributions (section 7).
+
+## 1. Where GenClass can be added (the map)
+
+What "adding GenClass" is in each kind of place, and why that place:
+
+- **AI coding agents and their ecosystems** (`@genclass/mcp`, the plugin, the skill): registry entries, extension
+ packages and plugins reachable by pull request (Zed's extensions repository, Goose's directory, OpenCode's plugins
+ and lists, the Roo and Kilo marketplaces, Docker's MCP registry, the Copilot and Codex lists). The agents' users meet
+ GenClass where they already install tools, and `genclass_explore` is something no other MCP server does.
+- **Open-source web apps, by race hunt**: a real race found with explore, reproduced without GenClass, fixed with a
+ regression test in the project's own style, with one disclosed sentence on how it was found. The strongest form:
+ the maintainers and every reader of the issue see the tool do something. Seven hunts are drafted in
+ [hunts/](hunts/), none sent.
+- **Curated lists and directories**: one line each, by pull request where the list allows it (the form-only ones are
+ in [listings/](listings/) for the owner).
+- **Framework and dev-tooling integration points** (example apps, templates, devtools tabs) that take pull requests
+ today. The ones that need `@genclass/nuxt`, `@genclass/astro`, `@genclass/sv` or `@genclass/playwright` wait for
+ those releases: none of the four is on npm (checked 2026-11-03).
+- **Contributor setups**: apps that already commit agent configuration (`.mcp.json`, `opencode.json`,
+ `.cursor/mcp.json`, an `AGENTS.md` MCP section) get GenClass's server entry the same way.
+- **Upstream evidence**: open race-condition issues in data-fetching and state libraries where a measured timeline
+ from explore and replay settles the thread, as [hunts/rtk-5139.md](hunts/rtk-5139.md) prepares for Redux Toolkit.
+
+## 2. Rules for every session
+
+1. **Prepare, never send.** Do not open, comment on, react to, star, fork, push to or edit anything on any repository,
+ site, forum, chat or tracker other than this repository (`genclass-dev/GenClass`). No `npm publish`, no release,
+ no tag. The contribution is handed back as files and a pull request here (section 5); a person sends it.
+2. **Claims discipline.** Any number in any text is one you measured in this session (say how, with the commands)
+ or one in [../runtime/RESULTS.md](../runtime/RESULTS.md) or a hunt report. Never "detects all races", "zero false
+ positives" or a rate beyond what was measured. GenClass's role in an upstream text is one sentence, at the end,
+ never a pitch; what the maintainers get is a bug, a fix and a test they can run without GenClass.
+3. **Disclosure.** Every draft that a person will send carries an "AI assistance" paragraph in the project's wording
+ if it has one, otherwise this one: "I used Claude (Claude Code) to investigate this, write the fix and the tests,
+ and draft this description; I reviewed the change and ran the tests and the manual check myself. The race was
+ found with GenClass, a tool I work on, which replays the same steps with the server's responses delivered in
+ different orders." The sender must be able to make every sentence true before sending; say in the report what
+ they must do themselves (reproduce by hand, run the tests, read the diff).
+4. **The target's rules come first.** Read its `CONTRIBUTING.md`, `.github/` templates, code of conduct, DCO or CLA
+ requirement and any AI or LLM policy before writing a line. A project that bans AI-assisted contributions gets no
+ pull request draft: write the report, mark the status "not worth sending" with the policy quoted, and stop. A
+ project that wants an issue before a pull request gets both drafts, in that order. Use its issue and pull request
+ templates verbatim, its commit style, its test framework, its formatter.
+5. **This repository's rules** ([../../AGENTS.md](../../AGENTS.md)) hold: never change `packages/runtime/src`,
+ `packages/mcp/src`, any test, any model-visible text or any file outside `docs/adoption/` unless your target brief
+ says so (an ecosystem target may add one small package where the brief names the folder, with tests, never
+ published). Never add a dependency to a workspace package. Fix GenClass problems you hit by writing them down
+ (section 5, "Problems with GenClass itself"), not by patching GenClass.
+6. **Local only.** Run the target on this machine with seeded local accounts. Never drive a public or hosted
+ instance (no `demo.example.com`, no `try.*`), never sign up anywhere, never use a real credential.
+7. **Nothing large in git.** Clone the target outside this checkout (`~/targets/`). Commit no `node_modules`,
+ builds, clones, databases, screenshots over 200 KB or raw result files over 200 KB: summarise results into a small
+ JSON or a table in the report and keep the harness that regenerates them.
+8. **Negative results are results.** No race found, an app that will not run here, a list closed to GenClass: still
+ open the pull request with the report, the status and what was tried ([hunts/ghost.md](hunts/ghost.md) is the
+ model for "no race found"). Guesswork is not: every claim in the report names the command, file or URL behind it.
+9. **Time.** One session. If the target is not running after about two hours of setup, stop setting up and report
+ "blocked" with the exact failure. A hunt that has a confirmed race keeps going until the fix, the test and the
+ drafts are done; one with none stops after the planned scenarios and writes the negative report.
+10. **Determinism and honesty in numbers.** Report "found in N of M reordered runs" with M, the latencies, the seeds and
+ the baselines; report every scenario, the negatives included; report the run without GenClass next to the run with
+ it.
+
+## 3. The environment and the common setup
+
+The cloud container (as the 2026-10-24 hunts found it): Ubuntu 24.04, 4 vCPUs, 15 GB RAM, root, Node 22, outbound
+network, Chromium preinstalled for Playwright (`npx playwright install` is not allowed and not needed), a Docker client
+but no daemon (no `docker compose`; run services natively: `apt-get install postgresql` or `mysql-server` or `redis`,
+then start them with `service ... start`), Go, Python 3 and `pip` available, `dotnet` and `bun` installable.
+
+Build GenClass once, from this checkout:
+
+```bash
+ONNXRUNTIME_NODE_INSTALL=skip npm ci --no-audit --no-fund
+npm run build -w @genclass/runtime # packages/runtime/dist: genclass.global.js (script tag), agent.js, index.js
+npm run build -w @genclass/mcp # packages/mcp/dist: index.js exports serve(), cli.js is the server
+```
+
+Read before writing a harness (each header says what it does and how to run it):
+
+- [hunts/gitea-explore.mjs](hunts/gitea-explore.mjs): injection from outside with a Playwright route that rewrites
+ each HTML page to load `packages/runtime/dist/genclass.global.js` from a virtual same-origin path, model off,
+ telemetry off, the agent link (`dist/agent.js`) connected to an MCP bridge started in-process with `serve()` from
+ `packages/mcp/dist/index.js`; the local-network-access permission each browser context needs; `rt.atom()` mirrors
+ of page regions for apps without a discoverable store; one explore session per latency (2 baselines plus 6 seeded
+ loads at 300, 600 and 900 ms).
+- [hunts/vendure-hunt.mjs](hunts/vendure-hunt.mjs): a duplicate-submit hunt with raw CDP input events, three
+ independent counts (wire, database, GenClass witnesses) and the control run without GenClass (`GENCLASS=0`).
+- [hunts/umami/throttle.mjs](hunts/umami/throttle.mjs): a reproduction without GenClass through Chromium's network
+ throttling.
+- [../../packages/mcp/test/e2e/race.e2e.mjs](../../packages/mcp/test/e2e/race.e2e.mjs): the whole loop on one page:
+ explore, replay (reproduced), the generated regression test (fails), the fix, replay (not reproduced), the test
+ (passes), explore (no race).
+- [../runtime/AGENT.md](../runtime/AGENT.md): the agent link, the bridge, explore's verdict (section 5.1), replays,
+ the generated tests, what is measured (section 7) and the limits (section 8).
+
+`npx @genclass/runtime@beta init --agent` is in the unreleased `0.3.0-beta.6`; use the built `dist/` from this
+checkout, never an npm install of the runtime, for anything measured.
+
+## 4. Procedures by contribution type
+
+### 4.1 `hunt`: a race hunt on an open-source web app
+
+1. **Run the app natively** as its own developer docs say (the brief has the commands). Seed what the surfaces need
+ (an admin, a few hundred rows for lists and search). Record versions and the commit.
+2. **Attach GenClass from outside** (the Gitea harness pattern): the target's source stays unmodified for the hunt.
+ Where the app's state is not discovered (Vue, Svelte, Angular, plain DOM), mirror the regions under test with
+ `rt.atom()` from a `MutationObserver`; say in the report which state the verdict compared.
+3. **Scenarios.** The brief's surfaces, usually: search-as-you-type (type a prefix, then the full word), autosave or
+ blur-save (edit two fields in a row), list filters and pagination (switch twice fast), create and update with a
+ double-click, optimistic updates under a refetch or poll, anything the brief's existing issues name. For each: 2
+ request-order baselines plus 6 seeded reordered loads, at 300, 600 and 900 ms, the same steps each load, and an
+ oracle of your own next to GenClass's verdict (read the DOM or the API after `whenSettled()`).
+4. **Reproduce without GenClass** every RACE line that is a real difference in the app's data or display: plain
+ Playwright with a delayed route or Chromium throttling, N of N runs. A RACE line that is a timing-dependent request
+ count, a relative time, a store present in one run and not another, or a witness on your own mirror atom is not a
+ bug: classify it as the Ghost report does (section 6 there).
+5. **Fix** the cause in the project's style (keep only the latest response, abort the superseded request, a request
+ counter, disable the control while in flight, an idempotency key), smallest diff, no reformatting. **Regression
+ test** in the project's own framework (its Playwright, Cypress, Vitest or Jest suite, in its folder, with its
+ helpers), failing on the unfixed code and passing on the fixed, run three times each way. Run the project's
+ related suite and its lint. Then explore again on the fixed build (expect 0 of N) and the plain reproduction
+ (expect 0 of N).
+6. **Write** `hunts/.md` with the sections of [hunts/strapi.md](hunts/strapi.md): setup (versions, commit,
+ exact commands), how the app was driven, scenarios and verdicts (a table, negatives included), the finding with
+ its evidence in causal order (quoted from `genclass_explain` or the recorded timeline), root cause (file and
+ lines), the fix, test results, the fixed variant, problems with GenClass itself, time spent, reproducing. Then
+ `hunts/.patch` (`git format-patch` or `git diff` against the named upstream commit, fix and test together),
+ `hunts/-issue.md` (the issue in the project's template, then the pull request description in its template,
+ each with the disclosure paragraph, and a "before sending" checklist for the sender: search the tracker for
+ duplicates since the hunt date, reproduce by hand, run the test, read the diff), and `hunts//` with the
+ harness and small summaries. Add the row to [hunts/README.md](hunts/README.md).
+
+### 4.2 `hunt-refresh`: a drafted hunt brought up to date and made ready to send
+
+For Strapi, Payload, Gitea, Mealie, Umami, Vikunja, Vendure and the Redux Toolkit comment. The drafts in `hunts/` are
+from 2026-10-24 and 2026-10-25. Today: run the target at its current main, apply the patch (rebase it if it no longer
+applies), run the regression test on the unfixed and the fixed code, re-run the hunt's reproduction without GenClass,
+check the upstream tracker and pull requests for anything filed on the same bug since the hunt (the search API, with
+the words the draft's "before sending" notes name), read the project's current contribution and AI policy, complete
+every item of the draft's own "before filing" or "before sending" list that a session can do, and rewrite the drafts
+where facts changed (versions, line numbers, the issue's related links). Add a dated "Refresh" section at the end of
+the report with what changed, what was re-measured and the status. Status "ready to send" means the sender has
+nothing left but the by-hand items the draft names.
+
+### 4.3 `ecosystem`, `framework`, `listing`, `contributor-setup`: a pull request to another repository, prepared here
+
+1. Read the target repository's contribution rules and the format of three recent accepted entries or changes of the
+ same kind. Clone it to `~/targets/` at its default branch and record the commit.
+2. Make the change there exactly as it would be submitted (the entry, the file, the manifest, the example app), run
+ whatever check the repository runs on such changes (its validator, build, lint, link check, generated README).
+3. Hand back `contributions//upstream.patch` (against the recorded commit) or, for a new package or extension
+ that lives in its own repository, `contributions//repo/` (the complete repository contents, with a README,
+ licence and tests, validated with the tool the ecosystem uses), plus `contributions//PR.md` (title and body
+ in the target's template, disclosure paragraph included), `ISSUE.md` where the target wants an issue first, and
+ `contributions//README.md`: the report (what the entry does, every rule checked with its URL, the check you
+ ran and its output, what the sender must do by hand such as a logo upload or a form, risks).
+4. For an entry that needs a published artifact GenClass does not have (a release, a badge, a score, a package on
+ npm), stop at the report, mark "needs owner decision", and say exactly what is missing.
+
+### 4.4 `upstream-evidence`: a comment with a reproduction on an open issue
+
+Build a standalone reproduction that imports nothing from GenClass (the pattern in [hunts/rtk-5139/](hunts/rtk-5139/)),
+record the timeline with the agent link in a harness, state what the maintainers asked for and answer exactly that,
+and draft the comment in `contributions//COMMENT.md` (short, the reproduction's URL in this repository, the
+timeline, the two test cases, the disclosure line). The report in `README.md` says why the comment helps the thread
+and when it should not be posted (a maintainer already answered, the issue closed).
+
+## 5. What to hand back
+
+- **Branch** `adopt/` from this repository's `main`, one or more commits whose messages end with
+ `Co-Authored-By: Claude Fable 5.1 ` (or the model's own line), pushed to this repository.
+- **Pull request** against `main`, title `adopt(): : ` where status is one of
+ `ready to send`, `needs owner decision`, `not worth sending`, `blocked`. The body starts with the status line and
+ gives: what was found or prepared (three sentences), the exact files, the "to send" steps for a person (fork, push,
+ open, which account, which text, what to say when asked), the measured numbers with their M and latencies, the
+ problems hit with GenClass itself, and the time spent. If `gh pr create` is not available in the session, push the
+ branch and put the title and body in `contributions//PR-to-genclass.md` (or `hunts/-pr-to-genclass.md`)
+ and in the session's final message.
+- **Problems with GenClass itself**: every false RACE line and why, every tool error, every missing feature, every
+ place the docs were wrong, in the report's own section. This is product feedback the launcher triages; file no
+ issue for it.
+
+## 6. Roster
+
+Filled by the launching session once the targets are verified (the workflow's verdicts). One row per session.
+
+
+
+
+## 7. The review and shipping loop (the launching session, with the owner)
+
+1. A session's pull request arrives. Read the report; run the harness or the test where it is cheap; check the
+ claims discipline, the disclosure paragraph and the target's policy; merge the pull request into `main` when it
+ holds (the report is the record even when nothing is sent), or send it back with questions.
+2. "Ready to send" contributions go out from the owner's or the user's personal GitHub account only after the owner
+ says so, in batches of a few a day (never dozens in one hour: GitHub's spam heuristics and maintainers' patience
+ both count), each followed personally: the sender reproduces by hand first, answers questions, and never argues
+ with a maintainer who declines. The sent URL and the date are added to the report.
+3. "Needs owner decision" items (a licence, a logo, a form, a release that must happen first) are listed to the owner
+ in one message with the decision each needs.
+4. "Not worth sending" and "blocked" reports are merged as records; their GenClass problems feed the runtime's and
+ the MCP server's backlog.
From 83f3d04310d0e4a5c7dd96362bbe83438d98d2db Mon Sep 17 00:00:00 2001
From: Karan
Date: Tue, 3 Nov 2026 13:02:52 -0500
Subject: [PATCH 11/11] Rename cleanup: the two new INSTALL.md links say
genclass-dev/GenClass
The rename on main left these out because the sections they sit in are this branch's.
Co-Authored-By: Claude Opus 5.5
---
FAQ.md | 2 +-
packages/runtime/README.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/FAQ.md b/FAQ.md
index ef321ace..6fbb3ed3 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -178,7 +178,7 @@ Yes. Two commands set up every open-source part, and nothing asks you to sign in
app's free dashboard link; `--agent` is new in `0.3.0-beta.6`) and `npx -y @genclass/mcp@0.2.1 init` (the MCP server and the `genclass` skill for Claude Code).
Anonymous diagnostics stay on, as with every `init` (never page text, never from local hosts);
`init --no-telemetry --agent` turns them off and creates no dashboard link. Details:
-[INSTALL.md](https://github.com/genclass-dev/GenClass-lib/blob/main/docs/runtime/INSTALL.md#how-do-i-set-up-the-open-source-parts-only).
+[INSTALL.md](https://github.com/genclass-dev/GenClass/blob/main/docs/runtime/INSTALL.md#how-do-i-set-up-the-open-source-parts-only).
## How is it different from Sentry, Datadog or my tests?
diff --git a/packages/runtime/README.md b/packages/runtime/README.md
index 8d524b82..c9ea7d0e 100644
--- a/packages/runtime/README.md
+++ b/packages/runtime/README.md
@@ -49,7 +49,7 @@ the package name, nothing else) and keeps anonymous diagnostics on, as every `in
local hosts; `init --no-telemetry --agent` turns them off and creates no link); the second writes
`.mcp.json` and `.claude/skills/genclass/SKILL.md` (other agents: `npx -y @genclass/mcp@0.2.1 config `). Nothing
else is needed; `npx @genclass/runtime@beta remove` undoes the first
-([the open-source setup](https://github.com/genclass-dev/GenClass-lib/blob/main/docs/runtime/INSTALL.md#how-do-i-set-up-the-open-source-parts-only)).
+([the open-source setup](https://github.com/genclass-dev/GenClass/blob/main/docs/runtime/INSTALL.md#how-do-i-set-up-the-open-source-parts-only)).
Or by hand: