From ed23082cb3d92f0e47fbc7e5f5d7719268c8ac6d Mon Sep 17 00:00:00 2001 From: upalinski Date: Tue, 21 Jul 2026 12:43:17 +0300 Subject: [PATCH 01/10] docs(cef:develop): rewrite widgets.md for the cef dev loop + WidgetRuntime Document real widget development: the cef dev local loop, the widget manifest, typed widget kinds, embedded vs standalone run modes, connectAgent, and querying cubbies via window.WidgetRuntime.query. Bump the cef plugin version to 0.1.1. Co-Authored-By: Claude Opus 4.8 (1M context) --- plugins/cef/.claude-plugin/plugin.json | 2 +- .../cef/skills/develop/references/widgets.md | 255 ++++++++++++++---- 2 files changed, 199 insertions(+), 58 deletions(-) diff --git a/plugins/cef/.claude-plugin/plugin.json b/plugins/cef/.claude-plugin/plugin.json index 0dd976d..0fabf06 100644 --- a/plugins/cef/.claude-plugin/plugin.json +++ b/plugins/cef/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "cef", "description": "Author, test, build, push, and deploy CEF agents", - "version": "0.1.0", + "version": "0.1.1", "author": { "name": "Cere / CEF-AI" }, "homepage": "https://github.com/CEF-AI/cef-plugins" } diff --git a/plugins/cef/skills/develop/references/widgets.md b/plugins/cef/skills/develop/references/widgets.md index b72c7c3..c6a29d9 100644 --- a/plugins/cef/skills/develop/references/widgets.md +++ b/plugins/cef/skills/develop/references/widgets.md @@ -1,106 +1,247 @@ # Widgets -A **widget** is a self-contained static web UI (an entry HTML plus sibling JS/assets) that an agent ships alongside its bundle. You declare it in `cef.config.ts`, build it into a plain directory, and `cef push` uploads the whole directory to DDC as one content-addressed **directory DAG** — next to `bundle.js`. There is no baked gateway URL: consumers resolve the widget at `///`. +A **widget** is a small web UI an agent ships alongside its bundle. At runtime a +widget reads and writes the **viewing user's own vault** — as the connected +agent — through an injected `window.WidgetRuntime`. No secret is baked into the +widget; the user's key material stays in their wallet. The same widget renders +two ways: **embedded** inside a host (the Cere Vault) and **standalone** via a +direct link. Both talk to the SAME agent's cubby for the SAME user. + +You author a widget as source, iterate against your dev vault with `cef dev`, +and ship it with `cef build` + `cef push`. + +> `cef dev` and `cef build`'s widget baking require a recent `@cef-ai/cli`. +> Run `cef --help` to confirm the flags available in your version. + +## The dev loop + +```sh +cef init my-agent # scaffolds an agent with a real, queryable widget +cd my-agent && pnpm install + +cef dev hello # local dev server for the `hello` widget +# - serves the widget on localhost +# - wires the manifest + the widget runtime +# - interactive wallet connect (a Cere wallet popup) — same auth as production standalone +# - watches files → refreshes on save + +# iterate: edit widgets/hello/*, save, the browser refreshes + +cef build --env dev # bakes the manifest + runtime +Candidate List +
Loading…
+ ``` -`app.js`: +`candidates.js`: + ```js -document.getElementById("root").textContent = "hello from widget"; +const root = document.getElementById("root"); + +async function render() { + try { + // "recent" is the query id declared in cef.config.ts; 20 binds to the ? placeholder. + const { columns, rows } = await window.WidgetRuntime.query("recent", [20]); + const name = columns.indexOf("name"); + const stage = columns.indexOf("stage"); + root.innerHTML = rows.length + ? rows.map((r) => `
${r[name]} — ${r[stage]}
`).join("") + : "No candidates yet."; + } catch (err) { + if (err.name === "AgentNotConnectedError") { + renderConnectCta(); // the agent isn't connected for this user yet + } else { + root.textContent = `Error: ${err.message}`; + } + } +} + +function renderConnectCta() { + root.innerHTML = ``; + document.getElementById("connect").onclick = async () => { + await window.WidgetRuntime.connectAgent(); // installs the agent for this user + render(); + }; +} + +render(); ``` -That's a complete, valid widget. Keep the starter widget plain like this — do not pull in the widget runtime until you actually need Vault access. +A `record` widget is the same shape with a query that returns a single row; a +`submit` widget collects form input and calls +`window.WidgetRuntime.publish("candidate_added", { name, stage })`. -> The CLI does NOT bundle or transform your widget. `dir` must already be built by the time you run `cef push`. If your widget needs a build step (bundler, TS), run it as the agent's own `build:widgets` script before `cef build`. +### Connecting the agent (`connectAgent`) -## How `cef build` and `cef push` handle it +`query()` and `publish()` require the agent to be **connected** for the viewing +user. When it isn't, `query()` throws `AgentNotConnectedError` — catch it and +render a CTA wired to `connectAgent()`. `connectAgent()` is the one-time +"install" flow: it connects the agent to the user's vault for the widget's +scope. After it resolves, retry the query. Use `agentStatus()` to check state up +front and `onIdentityChange(cb)` to re-render when the user connects, +disconnects, or the agent's status changes. -- **`cef build`** copies whatever is in each `dir` into `dist//widgets//` (fresh each build — stale files are removed first). It also emits one `ManifestWidget` per declared widget with a **placeholder** `dag: { bucketId: "", cid: "" }`. If `dir` is missing, or the `entry` file isn't found inside it, build prints a WARNING but still emits the manifest entry. -- **`cef push`** reads each staged `dist//widgets//` directory, uploads it to DDC as one content-addressed directory DAG, and stamps the real `{ bucketId, cid }` into that widget's manifest entry. A widget with no staged directory (or an empty one) is skipped with a WARNING. +## Embedded vs standalone -So the flow is: `build:widgets` (your own) → `cef build` (stage into dist) → `cef push` (upload as DAG + stamp ref). +The same widget runs in two modes; you write it once and the runtime handles the +difference. -## Optional: `window.WidgetRuntime` (Vault-native widgets) +- **Embedded** — the widget runs inside a host (the Cere Vault). The host + supplies identity and signing over a bridge; the user is already + authenticated, so `connect()` resolves immediately. +- **Standalone** — the widget is opened via a direct link. The runtime + authenticates the user itself with an interactive Cere wallet connect (a + popup). `cef dev` runs in this mode, so local iteration matches production + standalone. -When a widget is loaded inside the Cere Vault host, an injected runtime (`@cef-ai/widget-runtime`, emerging) exposes `window.WidgetRuntime` for reading/writing the **viewing user's** own Vault as the connected agent — no baked secret, key material stays in the wallet iframe. Core surface: +In both modes the widget queries the **same agent's cubby for the same user** — +the only difference is where the identity comes from. Don't assume a host is +present: rely on `WidgetRuntime` (which works in both) rather than reaching for +host-specific globals. -```ts -window.WidgetRuntime.query(ref, params?) // ref = a named query id (from queries[]) or raw SQL - // → { columns, rows, meta }; params are BOUND, never interpolated -window.WidgetRuntime.publish(type, payload, context?) // → { eventId } -window.WidgetRuntime.connectAgent() // the "install" flow: getAgent + vault.agents.connect() -window.WidgetRuntime.identity() / .connect() / .agentStatus() / .onIdentityChange(cb) -``` +## The manifest + +`cef build` produces a **widget manifest** that the runtime reads at boot. It +carries everything the widget needs to resolve identity, connect the agent, and +run its queries — you don't assemble it by hand: -`query()` throws `AgentNotConnectedError` when the agent isn't connected for this user — catch it to render a "Connect / Install" CTA wired to `connectAgent()`. +- `widgetId`, `name`, `kind`, `config` — from your `WidgetDecl`. +- `agentId`, `scope`, `cubbyAlias` — which agent/cubby the widget binds to. +- `queries[]` — `{ id, label, sql, timeoutMs }` from your declaration. +- `wallet` — `{ appId, env }` used to build the interactive connect in standalone. +- `endpoints` — the resolved `{ vault, gar, marketplace, s3GatewayAuthInfo }` + for the built `--env`. -Gotchas: -- The runtime is injected by the upload/host step, not by `cef push`. Opened directly in a browser (no Vault host) it assigns `window.WidgetRuntime` synchronously but `query()`/`publish()` reject after an ~8s handshake deadline and render "Open this widget inside the Cere Vault." -- Keep starter/hello-world widgets plain and self-contained. Only reach for the runtime once the widget genuinely needs Vault data. +The runtime **reads** a manifest; it never builds one. The CLI owns manifest +construction (from `cef.config.ts` + `--env` + the agent id), which is why the +same widget source works locally under `cef dev` and in production after +`cef build`. ## Gotchas checklist -- `id`, `dir`, and `entry` are all required; `id` must be unique within the agent (build errors on duplicates). -- `dir` must be **built already** — the CLI copies, it does not compile or bundle. -- Reference siblings with `./relative` paths only; absolute/external URLs won't resolve under the directory CID. -- A missing `dir` or `entry` produces a WARNING (not an error) at build; `cef push` then skips that widget — so a "successful" build can still ship no widget. Check push output for `widget : dir DAG ( files)`. -- No gateway URL is baked in; consumers build `///` from the manifest ref. +- **`kind` is required, and non-`custom` kinds need `queries`.** A query-backed + widget with no `queries` (or no `cubbyAlias`) has nothing to render. +- **Query refs are ids or raw SQL, and params are bound.** Pass values in the + `params` array against `?` placeholders; never interpolate into SQL. +- **Handle `AgentNotConnectedError`.** First load for a new user throws it — + render a `connectAgent()` CTA instead of an error. +- **Endpoints are build-time baked from `--env`.** Build for the environment you + intend to run in; there is no runtime environment switch. +- **Don't depend on a host.** Standalone has no host bridge — use + `WidgetRuntime`, not host-only globals, so the widget works in both modes. +- **Reference siblings with `./relative` paths.** The widget is served as one + directory; absolute/external URLs won't resolve. +- **`id` must be unique within the agent** and is what `cef dev [widgetId]` + targets. + + From c775d99000122d1f67b0234fc9d0130f75022463 Mon Sep 17 00:00:00 2001 From: upalinski Date: Tue, 21 Jul 2026 14:44:39 +0300 Subject: [PATCH 02/10] docs(cef): align skills with no-install cef init + add cef dev - deploy/develop quickstarts: add the 'pnpm install' step after 'cef init' (init no longer installs by default). - develop: document 'npx cef dev' (widget dev server) + the 'pnpm dev' script alias. --- plugins/cef/skills/deploy/SKILL.md | 3 ++- plugins/cef/skills/develop/SKILL.md | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/cef/skills/deploy/SKILL.md b/plugins/cef/skills/deploy/SKILL.md index b0e9cbb..2edd026 100644 --- a/plugins/cef/skills/deploy/SKILL.md +++ b/plugins/cef/skills/deploy/SKILL.md @@ -16,7 +16,8 @@ deployed, not because it is published. In a scaffolded project run `cef` via `npx cef …` (it's a local dev-dep). ```bash -npx cef init # scaffold a project (ships a deployments/ folder) +npx cef init my-agent # scaffold (does NOT install deps — fast) +cd my-agent && pnpm install # install project deps (incl. the `cef` dev-dep) npx cef build # local: compile dist//{bundle.js,manifest.json} npx cef push --bucket --as-pubkey # OUTWARD: upload bundle to the DDC registry npx cef deploy --endpoint --as-pubkey # OUTWARD: apply deployments/ — makes the agent live diff --git a/plugins/cef/skills/develop/SKILL.md b/plugins/cef/skills/develop/SKILL.md index ea144c7..9cdeb8d 100644 --- a/plugins/cef/skills/develop/SKILL.md +++ b/plugins/cef/skills/develop/SKILL.md @@ -96,11 +96,13 @@ export default class Echo { ## Dev commands In a scaffolded project `cef` is a local dev-dependency, so run it via `npx cef …` -(bare `cef` is not on `PATH`). A `cef init` project also aliases the common ones -as npm scripts (`pnpm run build`, `pnpm test`). +(bare `cef` is not on `PATH`). `cef init` does not install — run `pnpm install` +once first. The project also aliases the common commands as npm scripts +(`pnpm run build`, `pnpm test`, `pnpm dev`). ```sh npx cef typegen # after editing cef.config.ts: refresh .cef/generated.d.ts + cef.lock.json +npx cef dev [widgetId] # local widget dev server: standalone browser auth + file-watch npx cef build # lint entry + bundle → dist//{bundle.js, manifest.json} npx cef inspect dist/ # verify exposed __handlers match manifest routing npx vitest run # run the @cef-ai/testing simulator tests (or: pnpm test) From b893fc31c839de435f437136b8b095b7b654830b Mon Sep 17 00:00:00 2001 From: upalinski Date: Tue, 21 Jul 2026 15:24:43 +0300 Subject: [PATCH 03/10] docs(cef:develop): add troubleshooting/debugging reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Where logs go, logging that surfaces the real cause (fold error text into the message — the sandbox drops extra console args), guard handlers so a throw can't wedge the Job, local repro with testAgent, and a common-failure table. Linked from SKILL.md; plugin 0.1.1 → 0.1.2. --- plugins/cef/.claude-plugin/plugin.json | 2 +- plugins/cef/skills/develop/SKILL.md | 1 + .../develop/references/troubleshooting.md | 73 +++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 plugins/cef/skills/develop/references/troubleshooting.md diff --git a/plugins/cef/.claude-plugin/plugin.json b/plugins/cef/.claude-plugin/plugin.json index 0fabf06..597ca6a 100644 --- a/plugins/cef/.claude-plugin/plugin.json +++ b/plugins/cef/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "cef", "description": "Author, test, build, push, and deploy CEF agents", - "version": "0.1.1", + "version": "0.1.2", "author": { "name": "Cere / CEF-AI" }, "homepage": "https://github.com/CEF-AI/cef-plugins" } diff --git a/plugins/cef/skills/develop/SKILL.md b/plugins/cef/skills/develop/SKILL.md index 9cdeb8d..ed34e16 100644 --- a/plugins/cef/skills/develop/SKILL.md +++ b/plugins/cef/skills/develop/SKILL.md @@ -44,6 +44,7 @@ to lint + bundle. | Shipping a static UI | [widgets.md](./references/widgets.md) | `WidgetDecl`, self-contained dirs, `cef push` DAG, `window.WidgetRuntime` | | Writing tests | [testing.md](./references/testing.md) | `testAgent`, `testPlatform`, model mocks, `dispatch`/`published`, harness members | | Debugging a build failure or lint error | [constraints.md](./references/constraints.md) | banned imports, string-literal + declared-alias rules, ESLint wiring | +| Debugging a running agent (empty logs, stuck Job, cubby errors) | [troubleshooting.md](./references/troubleshooting.md) | where logs go, logging that surfaces the cause, guard handlers, local repro with `testAgent`, common failure modes | ## The shape at a glance diff --git a/plugins/cef/skills/develop/references/troubleshooting.md b/plugins/cef/skills/develop/references/troubleshooting.md new file mode 100644 index 0000000..63772d1 --- /dev/null +++ b/plugins/cef/skills/develop/references/troubleshooting.md @@ -0,0 +1,73 @@ +# Troubleshooting & debugging a CEF agent + +Agents run server-side per **Job**. You can't attach a debugger, so **logging +and the local simulator are your two windows**. Design for that from the start. + +## Where output goes + +`console.log` / `console.info` / `console.error` from your agent go to the +**sandbox console → the platform/ROC logs**. That is the only runtime signal +from a deployed agent. There is no `ctx.log` — use `console.*`. + +## Logging that is actually debuggable + +- **Fold the error text into the message string.** The sandbox log keeps the + **message string** and may drop extra arguments (or render an `Error` as + `[object Object]`). So this hides the cause: + + ```ts + console.error("failed to persist message", err); // ✗ err is lost + ``` + + and this surfaces it: + + ```ts + const detail = err instanceof Error ? err.message : String(err); + console.error(`[history] failed to persist message: ${detail}`); // ✓ + ``` + +- **Prefix logs** with the subsystem (`[history]`, `[reply]`) so they're + greppable in a busy log. +- **Log enough context** to reproduce (which operation, which keys/ids) — but + never secrets or user PII. + +## Handlers must not throw + +An unhandled error in an `@OnEvent` / `@OnStart` handler can **wedge the Job** +(its queued tasks get stuck). Treat every handler as adversarial-input-facing: + +- **Guard the payload** — it can be missing, empty, or the wrong shape. Validate + before use; reply with a clear message instead of throwing. +- **Wrap side effects** (cubby writes, `publish`, model calls) in `try/catch`, + log the real error, and degrade gracefully. + +## Debug locally FIRST — the simulator + +Before push → deploy → read-logs, reproduce with **`@cef-ai/testing`** +(`testAgent`). It runs your handler in-process and surfaces the **real error + +stack trace immediately** — the fastest loop by far. + +```ts +import { testAgent } from "@cef-ai/testing"; +// drive the exact event that failed; assert the cubby / reply; read the throw +``` + +Run `pnpm test` (or `npx vitest run`) and add a case for the failing event. + +## Common failure modes + +| Symptom (in logs) | Cause | Fix | +|---|---|---| +| `UNIQUE constraint failed: .` | Inserting a non-unique value into a PK/unique column (e.g. `Date.now()` as `id` collides same-ms) | Let SQLite assign `INTEGER PRIMARY KEY` (omit the id), or use a genuinely unique key | +| `NOT NULL constraint failed:
.` | A bound value was `undefined`/`null` | Guard/default the value before the write | +| Widget: `AgentNotConnectedError` | The agent isn't connected for that user | Render a Connect CTA wired to `WidgetRuntime.connectAgent()`, then retry | +| Job stuck / no reply | An unguarded `throw` in a handler | Guard payloads; `try/catch` side effects; always `publish` a reply path | +| Types don't match the model / event | `cef.config.ts` changed but types are stale | Run `cef typegen` | +| `ctx.cubby(...)`: no orchestrator endpoint | Running the handler outside a Job context | Exercise it via `testAgent`, not by calling the class directly | + +## Inspect state + +- **Read the cubby** with a `query` (in a widget or a `testAgent` assertion) to + see what's actually stored. +- **`cef inspect dist/`** verifies the built bundle's handlers match the + manifest routing (catches "event handled but nothing happened"). From 2899af93ae540c8094e4b503b78e1fd2dfdf807c Mon Sep 17 00:00:00 2001 From: upalinski Date: Tue, 21 Jul 2026 15:27:55 +0300 Subject: [PATCH 04/10] =?UTF-8?q?docs(cef:develop):=20precise=20console=20?= =?UTF-8?q?arg=20serialization=20(Error=20=E2=86=92=20{})?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extra console args are JSON-serialized into a separate field; an Error collapses to {} (non-enumerable message/stack). Put the detail in arg 0. --- .../develop/references/troubleshooting.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/plugins/cef/skills/develop/references/troubleshooting.md b/plugins/cef/skills/develop/references/troubleshooting.md index 63772d1..ad234dd 100644 --- a/plugins/cef/skills/develop/references/troubleshooting.md +++ b/plugins/cef/skills/develop/references/troubleshooting.md @@ -11,21 +11,28 @@ from a deployed agent. There is no `ctx.log` — use `console.*`. ## Logging that is actually debuggable -- **Fold the error text into the message string.** The sandbox log keeps the - **message string** and may drop extra arguments (or render an `Error` as - `[object Object]`). So this hides the cause: +- **Fold the error text into the message string.** The sandbox captures the + **first** console arg as the log `message` (via `.String()`) and + **JSON-serializes the rest** into a separate `args` field. The gotcha: + `JSON.stringify(new Error(...))` is `"{}"` — an `Error`'s `message`/`stack` + are non-enumerable — so passing the error as a *second* arg records an empty + `{}` and hides the cause: ```ts - console.error("failed to persist message", err); // ✗ err is lost + console.error("failed to persist message", err); // ✗ args: [{}] — err lost ``` - and this surfaces it: + Put the detail in the first arg, where `.String()` preserves it + (`String(anError)` → `"Error: "`): ```ts const detail = err instanceof Error ? err.message : String(err); console.error(`[history] failed to persist message: ${detail}`); // ✓ ``` + (A *string* or plain object as a later arg serializes fine — it's specifically + `Error` objects that collapse to `{}`.) + - **Prefix logs** with the subsystem (`[history]`, `[reply]`) so they're greppable in a busy log. - **Log enough context** to reproduce (which operation, which keys/ids) — but From 41ac7b153904ec95424f69fa1a1600635db084c5 Mon Sep 17 00:00:00 2001 From: upalinski Date: Tue, 21 Jul 2026 15:53:48 +0300 Subject: [PATCH 05/10] docs(cef:develop): correct Event

shape (timestamp not ts) + fix example Align engagements.md with the vault contract (SDK PR): Event is { type, payload, timestamp, context?, role?, eventId? }; the example handler no longer uses event.ts/event.id (records Date.now()). Plugin 0.1.2 -> 0.1.3. --- plugins/cef/.claude-plugin/plugin.json | 2 +- .../skills/develop/references/engagements.md | 21 ++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/plugins/cef/.claude-plugin/plugin.json b/plugins/cef/.claude-plugin/plugin.json index 597ca6a..01b17d6 100644 --- a/plugins/cef/.claude-plugin/plugin.json +++ b/plugins/cef/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "cef", "description": "Author, test, build, push, and deploy CEF agents", - "version": "0.1.2", + "version": "0.1.3", "author": { "name": "Cere / CEF-AI" }, "homepage": "https://github.com/CEF-AI/cef-plugins" } diff --git a/plugins/cef/skills/develop/references/engagements.md b/plugins/cef/skills/develop/references/engagements.md index 4c864d3..0f93edd 100644 --- a/plugins/cef/skills/develop/references/engagements.md +++ b/plugins/cef/skills/develop/references/engagements.md @@ -31,11 +31,12 @@ export default class Echo { @OnEvent("user_message") async onMessage(event: Event, ctx: Context) { + const now = Date.now(); await ctx.cubby("history").exec( "INSERT INTO messages(id, text, ts) VALUES (?, ?, ?)", - [Date.now(), event.payload.text, event.ts], + [now, event.payload.text, now], ); - await ctx.publish("ack", { for: event.id }); + await ctx.publish("ack", { text: `got: ${event.payload.text}` }); } @OnClose @@ -78,14 +79,20 @@ type per engagement. ```ts interface Event

{ - id: string; // event id - type: string; // event type string - ts: number; // unix-millis timestamp - from: string; // publisher (agent id or external source) - payload: P; // typed body + type: string; // event type string, e.g. "user_message" + payload: P; // typed body + timestamp: string; // ISO-8601, assigned by the vault + context?: string; // stream context (conversation / partition key) + role?: string; // publisher role, e.g. "user" | "agent" + eventId?: string; // server-assigned id (UUID v7); may be absent inbound } ``` +The runtime hands the handler the **published event verbatim**, so read +`event.payload` (typed) and `event.timestamp` (a string — `Date.parse(...)` for +millis). There is no numeric `ts`; don't bind a missing field into a NOT NULL +cubby column — use `Date.now()` for a record time, as above. + Type the payload with your own interface: `Event`, then read `event.payload.text`. From 3a571473c5abbb253efed03514630db8c46a0e90 Mon Sep 17 00:00:00 2001 From: upalinski Date: Tue, 21 Jul 2026 16:01:24 +0300 Subject: [PATCH 06/10] docs(cef:develop): agent browser-iteration loop + live-reload wording MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit widgets.md: cef dev now live-reloads (not manual refresh); add an 'iterating with a coding agent' note — use browser automation for the visual/console loop, but the interactive wallet-connect + live data need a human. Plugin 0.1.3 -> 0.1.4. --- plugins/cef/.claude-plugin/plugin.json | 2 +- .../cef/skills/develop/references/widgets.md | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/plugins/cef/.claude-plugin/plugin.json b/plugins/cef/.claude-plugin/plugin.json index 01b17d6..3aeed48 100644 --- a/plugins/cef/.claude-plugin/plugin.json +++ b/plugins/cef/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "cef", "description": "Author, test, build, push, and deploy CEF agents", - "version": "0.1.3", + "version": "0.1.4", "author": { "name": "Cere / CEF-AI" }, "homepage": "https://github.com/CEF-AI/cef-plugins" } diff --git a/plugins/cef/skills/develop/references/widgets.md b/plugins/cef/skills/develop/references/widgets.md index c6a29d9..1c2a3c0 100644 --- a/plugins/cef/skills/develop/references/widgets.md +++ b/plugins/cef/skills/develop/references/widgets.md @@ -23,9 +23,9 @@ cef dev hello # local dev server for the `hello` widget # - serves the widget on localhost # - wires the manifest + the widget runtime # - interactive wallet connect (a Cere wallet popup) — same auth as production standalone -# - watches files → refreshes on save +# - watches files → live-reloads the browser on save -# iterate: edit widgets/hello/*, save, the browser refreshes +# iterate: edit widgets/hello/*, save → the browser reloads automatically cef build --env dev # bakes the manifest + runtime