[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CHTS7H72S8FAZ58GVPF32G":3,"skill-same:01M6CHTS7H72S8FAZ58GVPF32G":150},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":33,"linkOnly":34,"markdownContent":35,"markdownBody":36,"frontMatter":37,"refName":38,"commitSha":39,"skillDirectory":40,"forksCount":41,"repositoryHtmlUrl":42,"repositoryHomepageUrl":43,"ownerHtmlUrl":44,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":45,"install":46,"resources":59},"01M6CHTS7H72S8FAZ58GVPF32G","sero-plugin",null,"Use when creating or converting a Sero plugin, or changing its manifest,\nhost integration, state contract, or contributed UI.","sero-labs\u002Fsero","sero-labs","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F278893820?v=4","01M6CHSF0GA1ZZSBGVB5ESH37Q","01M6CHSF4WD1EGGY0RNFHQ5R4N",28,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[23,24,25,26,27,28,29,30,31,32],"plugin","sero plugin","state","ui","integration","manifest","use","contract","host","when","2026-11-10 10:12:30",false,"---\nname: sero-plugin\ndescription: |\n  Use when creating or converting a Sero plugin, or changing its manifest,\n  host integration, state contract, or contributed UI.\n---\n\n# Building Sero Plugins\n\nA Sero plugin can expose up to three coordinated surfaces, all backed by a\nsingle JSON state file:\n\n- **Pi extension** (`extension\u002F`) — standard Pi. Pi-CLI-safe, no Sero imports. Registers tools and commands.\n- **Web UI** (`ui\u002F`) — optional React UI loaded via Module Federation. Sero-only.\n- **Background runtime** (`runtime\u002F`) — optional. Sero-only. Long-lived workspace orchestration.\n\n```\n                    state.json (source of truth)\n            ┌──────────────┼──────────────┐\n       Pi extension     Web UI     Background runtime\n       (Pi-CLI safe)   (Sero only)    (Sero only)\n```\n\nSero auto-discovers `plugins\u002Fsero-*-plugin\u002F` directories with a `sero.app`\nmanifest in `package.json`. No manual registry edits.\n\n## When to read reference files\n\n| Reference | When to read |\n|-----------|--------------|\n| `example\u002Fsero-notes-plugin\u002F` | For a new plugin, copy and rename this minimal example. It covers the extension, CLI bridge, runtime, UI hooks, widgets, and MF config. See `example\u002FREADME.md` for the file map. |\n| `references\u002Ftemplates.md` | Creating any file (package.json, extension, runtime, UI, Vite, styles). Also contains the Quick do\u002Fdon't guide and mini examples. |\n| `references\u002Fapi-and-widgets.md` | Using app-runtime hooks, background runtimes, dashboard widgets, manifest fields |\n| `references\u002Fconversion-guide.md` | Converting an existing Pi extension into a plugin |\n\n## Core rules\n\n### UI → plugin behavior\nIf the UI must trigger plugin-owned logic (sign in, refresh, mutate state,\ncall an API), register a normal plugin tool and invoke it from React:\n\n```ts\nconst { run } = useAppTools();\nawait run('myapp_auth', { action: 'login' });\n```\n\nNever add a plugin-specific host bridge (`window.sero.myPlugin.*`, custom\npreload\u002FIPC channels). Declare the host seams you actually use in\n`sero.plugin.requiredHostCapabilities`:\n\n| Capability | Declare when |\n|------------|--------------|\n| `appAgent.invokeTool` | UI uses `useAppTools()` or `window.sero.appAgent.invokeTool(...)` |\n| `tool.cli` | Plugin uses `bridgeTools`, custom `cli` metadata, or `cli.overrideBuiltin` |\n| `appRuntime.background` | Plugin declares `sero.app.runtime` |\n\n### Tool bridging (AD-020)\nApp tools are bridged into the single `sero-cli` tool — always use `pi.registerTool()`.\n\n- Plugins bridge all tools to `sero \u003Ctool> ...` by default\n- `sero.plugin.bridgeTools`: omit\u002F`true` = bridge all, `false` = none, `string[]` = selected tool names\n- `sero.plugin.uiOnlyTools`: `string[]` of tools only your UI calls through `appAgent.invokeTool`. Leave a UI-only tool out of `bridgeTools` and register it with `exposure: 'hidden'`; the host enforces the same for every declared name. Its actions count as the user's, so a model that could call it would be able to raise a limit the user set\n- Custom CLI help \u002F summary \u002F raw-args parsing goes on the tool's `cli` field\n- `cli.overrideBuiltin: true` only when intentionally replacing a builtin command\n- Never register app tools as `customTools` in `createAgentSession()`\n- Bridged tools run against the current session's extension — don't capture registration-scoped `pi` state in tool logic\n- If a tool exposes CLI subcommands, keep them self-explanatory and consistent with any structured tool actions; support aliases when needed and return explicit errors for unknown subcommands rather than silently falling back to another action\n\n### Prompt templates, skills, and slash-command naming\n- Plugin-owned prompt templates and skills are **manifest-driven**. Declaring `prompts\u002F` or `skills\u002F` folders is not enough by itself.\n- Add prompt templates to `pi.prompts` in `package.json` (for example `\".\u002Fprompts\u002Fmyapp.md\"`).\n- Add plugin skills to `pi.skills` in `package.json` (for example `\".\u002Fskills\"`).\n- If a bridged tool should also have a same-name slash shortcut (for example `\u002Fmcp` for the bridged `mcp` tool), prefer a prompt template declared in `pi.prompts`.\n- Keep `pi.registerCommand(...)` names **distinct** from bridged tool names unless you intentionally want to shadow\u002Freplace that CLI entry point.\n- After adding or changing `pi.prompts` \u002F `pi.skills`, reload resources (`\u002Freload`) or restart the session before testing the slash menu.\n\n### Background runtime\nUse `runtime\u002F` **only** for long-lived workspace-scoped behavior: startup\nrecovery\u002Freconcile, watchers beyond simple UI sync, subagent orchestration,\nworktree\u002FPR\u002Fcleanup flows, managed dev-server coordination.\n\nDo **not** use it for simple CRUD, one-shot UI actions, or Pi-CLI-safe logic.\n\nBoundaries:\n- `extension\u002F` stays Pi-safe\n- `runtime\u002F` is Sero-only; type against `@sero-ai\u002Fcommon`, never desktop internals\n- Plugin-specific orchestration stays in the plugin, not the host\n\n### Host ownership\n- Plugin-specific business logic lives in the plugin, not desktop preload\u002FIPC\n- External plugins consume `packages\u002F*` via published package names — do **not** import `..\u002F..\u002Fpackages\u002F*` source paths\n- Keep plugin-specific types in `shared\u002F`; only promote neutral cross-plugin contracts to `@sero-ai\u002Fcommon`\n- Never copy desktop host aliases (`@electron`, `@plugins`, `@packages`, `@\u002F`) into plugin TS config\n\n### State\n- **Never use `localStorage`** — all UI state through `useAppState` (file-backed)\n- Keep state JSON-serialisable (no Date\u002FMap\u002FSet\u002Ffunctions)\n- Always use atomic writes (temp file → `fs.rename`)\n- Resolve global paths from `SERO_HOME` \u002F `PI_CODING_AGENT_DIR`; fall back to `~\u002F.pi` only when env vars are unset (Pi CLI mode)\n\n## Step-by-step workflow\n\nUse this workflow for a new plugin. For an existing plugin, apply only the\nrelevant rules, references, and steps. Select checks for the changed behavior\nand install dependencies only when needed.\n\n### 1. Plan\nDecide up front:\n- **Plugin name** (e.g. `myapp`) — directory, app ID, state path\n- **Display name**, **Lucide icon**, **scope** (`workspace` default, or `global`)\n- **State shape** shared across surfaces\n- **Tools** to register\n- **Runtime?** Only for long-lived orchestration\n- **Dev port** — unique 5174+; check existing:\n  ```bash\n  grep -r '\"devPort\"' plugins\u002Fsero-*-plugin\u002Fpackage.json\n  ```\n\n### 2. Create the directory\n\n```\nplugins\u002Fsero-\u003Cname>-plugin\u002F\n├── package.json\n├── vite.config.ts            # UI only, at package root\n├── prompts\u002F                  # optional prompt templates (declare in pi.prompts)\n├── skills\u002F                   # optional plugin skills (declare in pi.skills)\n├── shared\u002Ftypes.ts\n├── extension\u002F\n│   ├── index.ts\n│   └── tsconfig.json\n├── runtime\u002F                  # optional\n│   ├── index.ts\n│   └── tsconfig.json\n└── ui\u002F                       # optional\n    ├── \u003CName>App.tsx\n    ├── styles.css\n    ├── tsconfig.json\n    ├── vite-env.d.ts\n    └── index.html\n```\n\nExtension-only plugins omit `vite.config.ts`, `ui\u002F`, and the\n`sero.app.ui`\u002F`component`\u002F`devPort` fields.\n\n### 3. Write `package.json`\n\nTriple-duty: Pi manifest + Sero app manifest + Sero plugin manifest.\nSee `references\u002Ftemplates.md` for the full template.\n\nCritical:\n- `\"keywords\": [\"pi-package\"]`\n- Pi SDK packages in `peerDependencies`\n- `@sero-ai\u002Fapp-runtime` and `@sero-ai\u002Fui` in `devDependencies`\n- `stateFile` is required even for global apps (Pi-CLI fallback)\n- `ui`, `component`, `devPort` only when the plugin ships a UI\n- Put extra federated components and host-rendered controls under\n  `sero.app.contributes`. Never generate legacy `widgets`, `search`,\n  `explorerView`, `titlebar`, or `workspaceCreation` fields for a new plugin.\n- `runtime` only when the plugin ships a runtime; add `runtime\u002Ftsconfig.json` to the `typecheck` script\n- Declare prompt templates in `pi.prompts` and plugin skills in `pi.skills`; folders alone are not auto-loaded\n- If you need a same-name slash shortcut for a bridged tool, use a prompt template in `pi.prompts` rather than `pi.registerCommand` with the same name\n- Declare `requiredHostCapabilities` only for seams you use\n- For extension-only plugins, drop the Vite `dev`\u002F`build` scripts\n- For built-in plugins with non-trivial extension deps, set `sero.plugin.bundleExtensions: true`; list native, large, or runtime-loaded extension packages in `sero.plugin.extensionExternals`\n\n### 4. Define `shared\u002Ftypes.ts`\n\nSingle source of truth imported by extension, UI, and runtime.\n- JSON-serialisable only\n- Export a `DEFAULT_STATE` constant\n- Auto-incrementing IDs for lists\n\n### 5. Mount the plugin into your workspace (dev only)\n\nExpose the plugin source inside Sero as a multi-root workspace:\n\n```bash\nsero workspace mount-plugin \u002Fabsolute\u002Fpath\u002Fto\u002Fplugins\u002Fsero-\u003Cname>-plugin\n```\n\n### 6. Build the Pi extension\n\n`extension\u002Findex.ts` is standard Pi. Template in `references\u002Ftemplates.md`.\n\nKey patterns:\n- Use `StringEnum` from `@earendil-works\u002Fpi-ai` for action enums (not `Type.Union`)\n- Resolve `statePath` from `ctx.cwd` inside `execute` handlers; use `session_start` only as a warm fallback\n- Atomic writes only (temp → rename)\n- Keep tool output concise\n- Do not depend on `session_switch` unless your target SDK guarantees it\n\n### 7. Optional: background runtime\n\n`runtime\u002Findex.ts` must export `createAppRuntime(ctx)` and default-export `{ createAppRuntime }`.\n\nRequired wiring:\n- `sero.app.runtime: \".\u002Fruntime\u002Findex.ts\"` in `package.json`\n- `runtime\u002Ftsconfig.json` included in the `typecheck` script\n- `requiredHostCapabilities: [\"appRuntime.background\"]`\n- If the runtime imports native\u002Fnon-bundle-safe packages, list them in `sero.app.runtimeExternals`\n- If the extension imports native\u002Fnon-bundle-safe packages and uses bundled release packaging, list them in `sero.plugin.extensionExternals`\n\nContext provides: `appId`, `workspaceId`, `workspacePath`, `stateFilePath`,\nand `host.{appState, subagents, workspace, verification, git, devServers}`.\n\n### 8. Optional: build the UI\n\nReact component in `ui\u002F\u003CName>App.tsx`. Template in `references\u002Ftemplates.md`.\n\nRequired:\n- **Both** exports: `export function MyApp()` AND `export default MyApp`\n- Import UI components from `@sero-ai\u002Fui`\n- Import `.\u002Fstyles.css` from **every** exposed MF entry (main app, widgets, etc.)\n- Tailwind semantic colors (`bg-background`, `text-foreground`, etc.)\n- `ui\u002Fstyles.css` should import `@sero-ai\u002Fui\u002Fstyles\u002Fplugin.css` and scan plugin-local files with `@source \".\u002F**\u002F*.{ts,tsx}\"`. The base stylesheet scans only shared primitives and dashboard components; add `styles\u002Fai-elements.css`, `styles\u002Fmodel-selection.css`, or `styles\u002Fcontext-editor.css` when the UI uses those families.\n- UI plugins must set `sero.app.styleIsolation` to `\"scope\"` and add `seroPluginCssScope({ pluginId: '\u003Capp-id>' })` after Tailwind in `vite.config.ts`.\n- Do not alias `@sero-ai\u002Fapp-runtime`\n- Scope keyboard listeners to the container (`tabIndex={0}`), never `window`\n- Use `ResizeObserver` for dynamic sizing\n\nAlso create: `vite.config.ts` (at package root), `ui\u002Fstyles.css`,\n`ui\u002Ftsconfig.json`, `ui\u002Fvite-env.d.ts`, `ui\u002Findex.html`.\n\n### 9. Verify\n\n```bash\npnpm install                                  # only when dependencies need installation\npnpm --filter @sero-ai\u002Fplugin-\u003Cname> build       # UI only\npnpm --filter @sero-ai\u002Fplugin-\u003Cname> typecheck\nbash scripts\u002Fbuild-plugin.sh plugins\u002Fsero-\u003Cname>-plugin   # installable bundle \u002F release packaging\n```\n\nFor a new plugin, all applicable checks must pass before it is ready. For\nmaintenance, run the checks needed for the changed behavior.\n\n### 10. Test end-to-end\n\n```bash\ncd apps\u002Fdesktop\nSERO_DEV_PLUGINS=\u003Cname> bash scripts\u002Fdev.sh\n```\n\nVerify:\n1. Plugin appears in the sidebar\n2. UI mutations → `state.json` → UI re-renders\n3. Agent tool call → `state.json` → file watcher → UI updates\n4. If the plugin ships `pi.prompts` \u002F `pi.skills`, reload resources (`\u002Freload`) and confirm the slash menu shows them\n5. If tools are CLI-bridged, confirm no command name shadows the bridged entry point (`help \u003Ctool>` \u002F `sero \u003Ctool> ...` still hit the real tool)\n6. If `runtime\u002F`: starts on workspace open, reacts to state, cleans up on close\n\n## Module Federation\n\n- `react` \u002F `react-dom` are shared singletons\n- `@sero-ai\u002Fapp-runtime` is **not** shared via MF — uses `globalThis` singleton; add to `optimizeDeps.exclude`\n- Production `vite.config.ts` must use `base: '.\u002F'`\n- MF remote name convention: `sero_\u003Cid>` (valid JS identifier)\n- Exposed module: `.\u002F\u003CComponent>`\n- Every exposed entry must import the plugin stylesheet so external remotes ship their own CSS\n\n## Development workflow\n\n- UI changes (`ui\u002F`) are handled by the remote Vite dev server. Sero also sends a lightweight cache-busted UI refresh for active local dev sessions; this should remount only the plugin surface, not refresh shell resources or restart agent\u002Fruntime state.\n- Changes to `extension\u002F`, `runtime\u002F`, `shared\u002Ftypes.ts`, `prompts\u002F`, `skills\u002F`, or `package.json` refresh the local plugin development session and may reload plugin resources\n- `devPort` in `package.json` must match `server.port` in `vite.config.ts`\n- Logs: `\u002Ftmp\u002Fsero-vite.log`, `\u002Ftmp\u002Fsero-remote-\u003Cname>.log`, `\u002Ftmp\u002Fsero-electron.log`\n- If Local Plugin Development fails before Vite starts with an `esbuild` host\u002Fbinary version mismatch or a missing Rollup native package, suspect stale platform-specific optional dependencies in the plugin's own `node_modules`. Sero attempts a one-time host-side `pnpm install --force` repair for these failures. If repair still fails, delete `node_modules` and reinstall from inside that plugin directory on the **macOS host** before changing source code. Do not run the reinstall from a Sero workspace\u002Fcontainer terminal, because that can install Linux native packages into a path that the macOS host dev server later executes.\n\n## Conventions\n\n- Plugin directory: `plugins\u002Fsero-\u003Cname>-plugin\u002F`\n- npm package: `@sero-ai\u002Fplugin-\u003Cname>`\n- State file: `.sero\u002Fapps\u002F\u003Cid>\u002Fstate.json` (workspace) or under `SERO_HOME` (global)\n- No source file over 500 LOC — split into sub-components, utils, or types files\n- Always top-level imports; no dynamic `await import(...)` for source modules\n\n## Reference implementations\n\n| Plugin | Best for |\n|--------|----------|\n| `example\u002Fsero-notes-plugin\u002F` (in this skill) | **Canonical minimal plugin.** Every surface (tool + CLI bridge, command, runtime, UI hooks, static + dynamic widgets) in the smallest possible footprint. |\n| `plugins\u002Fsero-git-plugin\u002F` | Focused plugin with single tool + substantial UI |\n| `plugins\u002Fsero-admin-plugin\u002F` | Multiple panels, settings, dashboard surfaces |\n| `plugins\u002Fsero-web-plugin\u002F` | Converting an existing Pi extension |\n| `plugins\u002Fsero-cron-plugin\u002F` | Background jobs, command-oriented plugins |\n| `..\u002Fplugins\u002Fsero-signal-desk-plugin\u002F` | External plugin with background runtime + tool-driven UI + bridged CLI tool |\n\n## Related skills\n\n- **`sero-dashboard-ui`** (`..\u002Fsero-dashboard-ui\u002FSKILL.md`) — building or\n  redesigning dashboard widgets and compact plugin views with the shared\n  `@sero-ai\u002Fui` dashboard components. Read it when the task changes a widget\n  or compact plugin view.\n\n## Related docs\n\n- `apps\u002Fdocs-site\u002Fdocs\u002Freference\u002Fplugin-quickstart.md` - plugin setup\n- `apps\u002Fdocs-site\u002Fdocs\u002Freference\u002Fplugins.md` - packaging and compatibility\n- `apps\u002Fdocs-site\u002Fdocs\u002Freference\u002Fplugin-extension-points.md` - host contributions\n- `ARCHITECTURE.md` - host boundaries and shared services\n\n## Troubleshooting\n\n| Problem | Fix |\n|---------|-----|\n| Build fails: `Could not resolve entry module \"node_modules\u002F__mf__virtual\u002F...hostAutoInit...\"` | Keep Vite root at the package root; use `build.rollupOptions.input: 'ui\u002Findex.html'` instead of `root: 'ui'` |\n| Local Plugin Development fails: `Cannot start service: Host version \"...\" does not match binary version \"...\"` from `esbuild` | The plugin has stale\u002Fmismatched native optional dependencies. Sero should try one host-side auto-repair. If it still fails, from the plugin directory on the **macOS host** (not inside the Sero container), run `rm -rf node_modules && pnpm install --force`, then retry `pnpm exec vite --host 127.0.0.1` or Local Plugin Development. Do not patch Vite config\u002Fpackage versions first. |\n| Local Plugin Development fails: `Cannot find module @rollup\u002Frollup-darwin-arm64` or another `@rollup\u002Frollup-*` native package | Same root cause: platform-specific optional dependencies were not installed for the current machine. Sero should try one host-side auto-repair. If it still fails, from the plugin directory on the macOS host, run `rm -rf node_modules && pnpm install --force`. |\n| App not in sidebar | Check `sero.app.id`\u002F`name` in package.json, run `pnpm install` |\n| Agent missing tool | Restart dev server, check `pi.extensions` field |\n| UI changes not showing | Check remote Vite running; extension changes need full restart |\n| External plugin missing styles | Import `.\u002Fstyles.css` from every exposed MF entry; verify `@source` paths in `ui\u002Fstyles.css` |\n| Packaged plugin missing an extension dependency | If it must stay in `node_modules`, add the package name to `sero.plugin.extensionExternals`; otherwise keep it in `dependencies` and let `bundleExtensions` include it in the JS entrypoint |\n| `Cannot find module '.\u002Fstyles.css'` | Add `ui\u002Fvite-env.d.ts` with `\u002F\u002F\u002F \u003Creference types=\"vite\u002Fclient\" \u002F>` |\n| Runtime never starts | Declare `sero.app.runtime` + `requiredHostCapabilities: [\"appRuntime.background\"]`; check `\u002Ftmp\u002Fsero-electron.log` |\n| Build fails because no HTML entry exists | Add `ui\u002Findex.html` |\n| \"No UI module registered\" | Set `sero.app.component` and `devPort` |\n| Contributed surface does not appear | Use a host-defined `extensionPoint` under `sero.app.contributes`, expose the named component, and check `minSeroVersion` |\n| \"No workspace selected\" | Pick one, or set `scope: \"global\"` |\n| State not syncing | Verify same `stateFile` path, use atomic writes |\n| Keyboard stealing input | Scope listeners to container, not `window` |\n| `lazy: Expected dynamic import` | Add `export default MyApp` to component file |\n| MF errors | `devPort` in package.json must match `server.port` in vite.config.ts |\n","# Building Sero Plugins\n\nA Sero plugin can expose up to three coordinated surfaces, all backed by a\nsingle JSON state file:\n\n- **Pi extension** (`extension\u002F`) — standard Pi. Pi-CLI-safe, no Sero imports. Registers tools and commands.\n- **Web UI** (`ui\u002F`) — optional React UI loaded via Module Federation. Sero-only.\n- **Background runtime** (`runtime\u002F`) — optional. Sero-only. Long-lived workspace orchestration.\n\n```\n                    state.json (source of truth)\n            ┌──────────────┼──────────────┐\n       Pi extension     Web UI     Background runtime\n       (Pi-CLI safe)   (Sero only)    (Sero only)\n```\n\nSero auto-discovers `plugins\u002Fsero-*-plugin\u002F` directories with a `sero.app`\nmanifest in `package.json`. No manual registry edits.\n\n## When to read reference files\n\n| Reference | When to read |\n|-----------|--------------|\n| `example\u002Fsero-notes-plugin\u002F` | For a new plugin, copy and rename this minimal example. It covers the extension, CLI bridge, runtime, UI hooks, widgets, and MF config. See `example\u002FREADME.md` for the file map. |\n| `references\u002Ftemplates.md` | Creating any file (package.json, extension, runtime, UI, Vite, styles). Also contains the Quick do\u002Fdon't guide and mini examples. |\n| `references\u002Fapi-and-widgets.md` | Using app-runtime hooks, background runtimes, dashboard widgets, manifest fields |\n| `references\u002Fconversion-guide.md` | Converting an existing Pi extension into a plugin |\n\n## Core rules\n\n### UI → plugin behavior\nIf the UI must trigger plugin-owned logic (sign in, refresh, mutate state,\ncall an API), register a normal plugin tool and invoke it from React:\n\n```ts\nconst { run } = useAppTools();\nawait run('myapp_auth', { action: 'login' });\n```\n\nNever add a plugin-specific host bridge (`window.sero.myPlugin.*`, custom\npreload\u002FIPC channels). Declare the host seams you actually use in\n`sero.plugin.requiredHostCapabilities`:\n\n| Capability | Declare when |\n|------------|--------------|\n| `appAgent.invokeTool` | UI uses `useAppTools()` or `window.sero.appAgent.invokeTool(...)` |\n| `tool.cli` | Plugin uses `bridgeTools`, custom `cli` metadata, or `cli.overrideBuiltin` |\n| `appRuntime.background` | Plugin declares `sero.app.runtime` |\n\n### Tool bridging (AD-020)\nApp tools are bridged into the single `sero-cli` tool — always use `pi.registerTool()`.\n\n- Plugins bridge all tools to `sero \u003Ctool> ...` by default\n- `sero.plugin.bridgeTools`: omit\u002F`true` = bridge all, `false` = none, `string[]` = selected tool names\n- `sero.plugin.uiOnlyTools`: `string[]` of tools only your UI calls through `appAgent.invokeTool`. Leave a UI-only tool out of `bridgeTools` and register it with `exposure: 'hidden'`; the host enforces the same for every declared name. Its actions count as the user's, so a model that could call it would be able to raise a limit the user set\n- Custom CLI help \u002F summary \u002F raw-args parsing goes on the tool's `cli` field\n- `cli.overrideBuiltin: true` only when intentionally replacing a builtin command\n- Never register app tools as `customTools` in `createAgentSession()`\n- Bridged tools run against the current session's extension — don't capture registration-scoped `pi` state in tool logic\n- If a tool exposes CLI subcommands, keep them self-explanatory and consistent with any structured tool actions; support aliases when needed and return explicit errors for unknown subcommands rather than silently falling back to another action\n\n### Prompt templates, skills, and slash-command naming\n- Plugin-owned prompt templates and skills are **manifest-driven**. Declaring `prompts\u002F` or `skills\u002F` folders is not enough by itself.\n- Add prompt templates to `pi.prompts` in `package.json` (for example `\".\u002Fprompts\u002Fmyapp.md\"`).\n- Add plugin skills to `pi.skills` in `package.json` (for example `\".\u002Fskills\"`).\n- If a bridged tool should also have a same-name slash shortcut (for example `\u002Fmcp` for the bridged `mcp` tool), prefer a prompt template declared in `pi.prompts`.\n- Keep `pi.registerCommand(...)` names **distinct** from bridged tool names unless you intentionally want to shadow\u002Freplace that CLI entry point.\n- After adding or changing `pi.prompts` \u002F `pi.skills`, reload resources (`\u002Freload`) or restart the session before testing the slash menu.\n\n### Background runtime\nUse `runtime\u002F` **only** for long-lived workspace-scoped behavior: startup\nrecovery\u002Freconcile, watchers beyond simple UI sync, subagent orchestration,\nworktree\u002FPR\u002Fcleanup flows, managed dev-server coordination.\n\nDo **not** use it for simple CRUD, one-shot UI actions, or Pi-CLI-safe logic.\n\nBoundaries:\n- `extension\u002F` stays Pi-safe\n- `runtime\u002F` is Sero-only; type against `@sero-ai\u002Fcommon`, never desktop internals\n- Plugin-specific orchestration stays in the plugin, not the host\n\n### Host ownership\n- Plugin-specific business logic lives in the plugin, not desktop preload\u002FIPC\n- External plugins consume `packages\u002F*` via published package names — do **not** import `..\u002F..\u002Fpackages\u002F*` source paths\n- Keep plugin-specific types in `shared\u002F`; only promote neutral cross-plugin contracts to `@sero-ai\u002Fcommon`\n- Never copy desktop host aliases (`@electron`, `@plugins`, `@packages`, `@\u002F`) into plugin TS config\n\n### State\n- **Never use `localStorage`** — all UI state through `useAppState` (file-backed)\n- Keep state JSON-serialisable (no Date\u002FMap\u002FSet\u002Ffunctions)\n- Always use atomic writes (temp file → `fs.rename`)\n- Resolve global paths from `SERO_HOME` \u002F `PI_CODING_AGENT_DIR`; fall back to `~\u002F.pi` only when env vars are unset (Pi CLI mode)\n\n## Step-by-step workflow\n\nUse this workflow for a new plugin. For an existing plugin, apply only the\nrelevant rules, references, and steps. Select checks for the changed behavior\nand install dependencies only when needed.\n\n### 1. Plan\nDecide up front:\n- **Plugin name** (e.g. `myapp`) — directory, app ID, state path\n- **Display name**, **Lucide icon**, **scope** (`workspace` default, or `global`)\n- **State shape** shared across surfaces\n- **Tools** to register\n- **Runtime?** Only for long-lived orchestration\n- **Dev port** — unique 5174+; check existing:\n  ```bash\n  grep -r '\"devPort\"' plugins\u002Fsero-*-plugin\u002Fpackage.json\n  ```\n\n### 2. Create the directory\n\n```\nplugins\u002Fsero-\u003Cname>-plugin\u002F\n├── package.json\n├── vite.config.ts            # UI only, at package root\n├── prompts\u002F                  # optional prompt templates (declare in pi.prompts)\n├── skills\u002F                   # optional plugin skills (declare in pi.skills)\n├── shared\u002Ftypes.ts\n├── extension\u002F\n│   ├── index.ts\n│   └── tsconfig.json\n├── runtime\u002F                  # optional\n│   ├── index.ts\n│   └── tsconfig.json\n└── ui\u002F                       # optional\n    ├── \u003CName>App.tsx\n    ├── styles.css\n    ├── tsconfig.json\n    ├── vite-env.d.ts\n    └── index.html\n```\n\nExtension-only plugins omit `vite.config.ts`, `ui\u002F`, and the\n`sero.app.ui`\u002F`component`\u002F`devPort` fields.\n\n### 3. Write `package.json`\n\nTriple-duty: Pi manifest + Sero app manifest + Sero plugin manifest.\nSee `references\u002Ftemplates.md` for the full template.\n\nCritical:\n- `\"keywords\": [\"pi-package\"]`\n- Pi SDK packages in `peerDependencies`\n- `@sero-ai\u002Fapp-runtime` and `@sero-ai\u002Fui` in `devDependencies`\n- `stateFile` is required even for global apps (Pi-CLI fallback)\n- `ui`, `component`, `devPort` only when the plugin ships a UI\n- Put extra federated components and host-rendered controls under\n  `sero.app.contributes`. Never generate legacy `widgets`, `search`,\n  `explorerView`, `titlebar`, or `workspaceCreation` fields for a new plugin.\n- `runtime` only when the plugin ships a runtime; add `runtime\u002Ftsconfig.json` to the `typecheck` script\n- Declare prompt templates in `pi.prompts` and plugin skills in `pi.skills`; folders alone are not auto-loaded\n- If you need a same-name slash shortcut for a bridged tool, use a prompt template in `pi.prompts` rather than `pi.registerCommand` with the same name\n- Declare `requiredHostCapabilities` only for seams you use\n- For extension-only plugins, drop the Vite `dev`\u002F`build` scripts\n- For built-in plugins with non-trivial extension deps, set `sero.plugin.bundleExtensions: true`; list native, large, or runtime-loaded extension packages in `sero.plugin.extensionExternals`\n\n### 4. Define `shared\u002Ftypes.ts`\n\nSingle source of truth imported by extension, UI, and runtime.\n- JSON-serialisable only\n- Export a `DEFAULT_STATE` constant\n- Auto-incrementing IDs for lists\n\n### 5. Mount the plugin into your workspace (dev only)\n\nExpose the plugin source inside Sero as a multi-root workspace:\n\n```bash\nsero workspace mount-plugin \u002Fabsolute\u002Fpath\u002Fto\u002Fplugins\u002Fsero-\u003Cname>-plugin\n```\n\n### 6. Build the Pi extension\n\n`extension\u002Findex.ts` is standard Pi. Template in `references\u002Ftemplates.md`.\n\nKey patterns:\n- Use `StringEnum` from `@earendil-works\u002Fpi-ai` for action enums (not `Type.Union`)\n- Resolve `statePath` from `ctx.cwd` inside `execute` handlers; use `session_start` only as a warm fallback\n- Atomic writes only (temp → rename)\n- Keep tool output concise\n- Do not depend on `session_switch` unless your target SDK guarantees it\n\n### 7. Optional: background runtime\n\n`runtime\u002Findex.ts` must export `createAppRuntime(ctx)` and default-export `{ createAppRuntime }`.\n\nRequired wiring:\n- `sero.app.runtime: \".\u002Fruntime\u002Findex.ts\"` in `package.json`\n- `runtime\u002Ftsconfig.json` included in the `typecheck` script\n- `requiredHostCapabilities: [\"appRuntime.background\"]`\n- If the runtime imports native\u002Fnon-bundle-safe packages, list them in `sero.app.runtimeExternals`\n- If the extension imports native\u002Fnon-bundle-safe packages and uses bundled release packaging, list them in `sero.plugin.extensionExternals`\n\nContext provides: `appId`, `workspaceId`, `workspacePath`, `stateFilePath`,\nand `host.{appState, subagents, workspace, verification, git, devServers}`.\n\n### 8. Optional: build the UI\n\nReact component in `ui\u002F\u003CName>App.tsx`. Template in `references\u002Ftemplates.md`.\n\nRequired:\n- **Both** exports: `export function MyApp()` AND `export default MyApp`\n- Import UI components from `@sero-ai\u002Fui`\n- Import `.\u002Fstyles.css` from **every** exposed MF entry (main app, widgets, etc.)\n- Tailwind semantic colors (`bg-background`, `text-foreground`, etc.)\n- `ui\u002Fstyles.css` should import `@sero-ai\u002Fui\u002Fstyles\u002Fplugin.css` and scan plugin-local files with `@source \".\u002F**\u002F*.{ts,tsx}\"`. The base stylesheet scans only shared primitives and dashboard components; add `styles\u002Fai-elements.css`, `styles\u002Fmodel-selection.css`, or `styles\u002Fcontext-editor.css` when the UI uses those families.\n- UI plugins must set `sero.app.styleIsolation` to `\"scope\"` and add `seroPluginCssScope({ pluginId: '\u003Capp-id>' })` after Tailwind in `vite.config.ts`.\n- Do not alias `@sero-ai\u002Fapp-runtime`\n- Scope keyboard listeners to the container (`tabIndex={0}`), never `window`\n- Use `ResizeObserver` for dynamic sizing\n\nAlso create: `vite.config.ts` (at package root), `ui\u002Fstyles.css`,\n`ui\u002Ftsconfig.json`, `ui\u002Fvite-env.d.ts`, `ui\u002Findex.html`.\n\n### 9. Verify\n\n```bash\npnpm install                                  # only when dependencies need installation\npnpm --filter @sero-ai\u002Fplugin-\u003Cname> build       # UI only\npnpm --filter @sero-ai\u002Fplugin-\u003Cname> typecheck\nbash scripts\u002Fbuild-plugin.sh plugins\u002Fsero-\u003Cname>-plugin   # installable bundle \u002F release packaging\n```\n\nFor a new plugin, all applicable checks must pass before it is ready. For\nmaintenance, run the checks needed for the changed behavior.\n\n### 10. Test end-to-end\n\n```bash\ncd apps\u002Fdesktop\nSERO_DEV_PLUGINS=\u003Cname> bash scripts\u002Fdev.sh\n```\n\nVerify:\n1. Plugin appears in the sidebar\n2. UI mutations → `state.json` → UI re-renders\n3. Agent tool call → `state.json` → file watcher → UI updates\n4. If the plugin ships `pi.prompts` \u002F `pi.skills`, reload resources (`\u002Freload`) and confirm the slash menu shows them\n5. If tools are CLI-bridged, confirm no command name shadows the bridged entry point (`help \u003Ctool>` \u002F `sero \u003Ctool> ...` still hit the real tool)\n6. If `runtime\u002F`: starts on workspace open, reacts to state, cleans up on close\n\n## Module Federation\n\n- `react` \u002F `react-dom` are shared singletons\n- `@sero-ai\u002Fapp-runtime` is **not** shared via MF — uses `globalThis` singleton; add to `optimizeDeps.exclude`\n- Production `vite.config.ts` must use `base: '.\u002F'`\n- MF remote name convention: `sero_\u003Cid>` (valid JS identifier)\n- Exposed module: `.\u002F\u003CComponent>`\n- Every exposed entry must import the plugin stylesheet so external remotes ship their own CSS\n\n## Development workflow\n\n- UI changes (`ui\u002F`) are handled by the remote Vite dev server. Sero also sends a lightweight cache-busted UI refresh for active local dev sessions; this should remount only the plugin surface, not refresh shell resources or restart agent\u002Fruntime state.\n- Changes to `extension\u002F`, `runtime\u002F`, `shared\u002Ftypes.ts`, `prompts\u002F`, `skills\u002F`, or `package.json` refresh the local plugin development session and may reload plugin resources\n- `devPort` in `package.json` must match `server.port` in `vite.config.ts`\n- Logs: `\u002Ftmp\u002Fsero-vite.log`, `\u002Ftmp\u002Fsero-remote-\u003Cname>.log`, `\u002Ftmp\u002Fsero-electron.log`\n- If Local Plugin Development fails before Vite starts with an `esbuild` host\u002Fbinary version mismatch or a missing Rollup native package, suspect stale platform-specific optional dependencies in the plugin's own `node_modules`. Sero attempts a one-time host-side `pnpm install --force` repair for these failures. If repair still fails, delete `node_modules` and reinstall from inside that plugin directory on the **macOS host** before changing source code. Do not run the reinstall from a Sero workspace\u002Fcontainer terminal, because that can install Linux native packages into a path that the macOS host dev server later executes.\n\n## Conventions\n\n- Plugin directory: `plugins\u002Fsero-\u003Cname>-plugin\u002F`\n- npm package: `@sero-ai\u002Fplugin-\u003Cname>`\n- State file: `.sero\u002Fapps\u002F\u003Cid>\u002Fstate.json` (workspace) or under `SERO_HOME` (global)\n- No source file over 500 LOC — split into sub-components, utils, or types files\n- Always top-level imports; no dynamic `await import(...)` for source modules\n\n## Reference implementations\n\n| Plugin | Best for |\n|--------|----------|\n| `example\u002Fsero-notes-plugin\u002F` (in this skill) | **Canonical minimal plugin.** Every surface (tool + CLI bridge, command, runtime, UI hooks, static + dynamic widgets) in the smallest possible footprint. |\n| `plugins\u002Fsero-git-plugin\u002F` | Focused plugin with single tool + substantial UI |\n| `plugins\u002Fsero-admin-plugin\u002F` | Multiple panels, settings, dashboard surfaces |\n| `plugins\u002Fsero-web-plugin\u002F` | Converting an existing Pi extension |\n| `plugins\u002Fsero-cron-plugin\u002F` | Background jobs, command-oriented plugins |\n| `..\u002Fplugins\u002Fsero-signal-desk-plugin\u002F` | External plugin with background runtime + tool-driven UI + bridged CLI tool |\n\n## Related skills\n\n- **`sero-dashboard-ui`** (`..\u002Fsero-dashboard-ui\u002FSKILL.md`) — building or\n  redesigning dashboard widgets and compact plugin views with the shared\n  `@sero-ai\u002Fui` dashboard components. Read it when the task changes a widget\n  or compact plugin view.\n\n## Related docs\n\n- `apps\u002Fdocs-site\u002Fdocs\u002Freference\u002Fplugin-quickstart.md` - plugin setup\n- `apps\u002Fdocs-site\u002Fdocs\u002Freference\u002Fplugins.md` - packaging and compatibility\n- `apps\u002Fdocs-site\u002Fdocs\u002Freference\u002Fplugin-extension-points.md` - host contributions\n- `ARCHITECTURE.md` - host boundaries and shared services\n\n## Troubleshooting\n\n| Problem | Fix |\n|---------|-----|\n| Build fails: `Could not resolve entry module \"node_modules\u002F__mf__virtual\u002F...hostAutoInit...\"` | Keep Vite root at the package root; use `build.rollupOptions.input: 'ui\u002Findex.html'` instead of `root: 'ui'` |\n| Local Plugin Development fails: `Cannot start service: Host version \"...\" does not match binary version \"...\"` from `esbuild` | The plugin has stale\u002Fmismatched native optional dependencies. Sero should try one host-side auto-repair. If it still fails, from the plugin directory on the **macOS host** (not inside the Sero container), run `rm -rf node_modules && pnpm install --force`, then retry `pnpm exec vite --host 127.0.0.1` or Local Plugin Development. Do not patch Vite config\u002Fpackage versions first. |\n| Local Plugin Development fails: `Cannot find module @rollup\u002Frollup-darwin-arm64` or another `@rollup\u002Frollup-*` native package | Same root cause: platform-specific optional dependencies were not installed for the current machine. Sero should try one host-side auto-repair. If it still fails, from the plugin directory on the macOS host, run `rm -rf node_modules && pnpm install --force`. |\n| App not in sidebar | Check `sero.app.id`\u002F`name` in package.json, run `pnpm install` |\n| Agent missing tool | Restart dev server, check `pi.extensions` field |\n| UI changes not showing | Check remote Vite running; extension changes need full restart |\n| External plugin missing styles | Import `.\u002Fstyles.css` from every exposed MF entry; verify `@source` paths in `ui\u002Fstyles.css` |\n| Packaged plugin missing an extension dependency | If it must stay in `node_modules`, add the package name to `sero.plugin.extensionExternals`; otherwise keep it in `dependencies` and let `bundleExtensions` include it in the JS entrypoint |\n| `Cannot find module '.\u002Fstyles.css'` | Add `ui\u002Fvite-env.d.ts` with `\u002F\u002F\u002F \u003Creference types=\"vite\u002Fclient\" \u002F>` |\n| Runtime never starts | Declare `sero.app.runtime` + `requiredHostCapabilities: [\"appRuntime.background\"]`; check `\u002Ftmp\u002Fsero-electron.log` |\n| Build fails because no HTML entry exists | Add `ui\u002Findex.html` |\n| \"No UI module registered\" | Set `sero.app.component` and `devPort` |\n| Contributed surface does not appear | Use a host-defined `extensionPoint` under `sero.app.contributes`, expose the named component, and check `minSeroVersion` |\n| \"No workspace selected\" | Pick one, or set `scope: \"global\"` |\n| State not syncing | Verify same `stateFile` path, use atomic writes |\n| Keyboard stealing input | Scope listeners to container, not `window` |\n| `lazy: Expected dynamic import` | Add `export default MyApp` to component file |\n| MF errors | `devPort` in package.json must match `server.port` in vite.config.ts |\n",{"name":5,"description":7},"main","e91c3c773b84e88a929cae3c36977e892ca4871a",".agents\u002Fskills\u002Fsero-plugin",4,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero","https:\u002F\u002Fsero-ai.dev\u002F","https:\u002F\u002Fgithub.com\u002Fsero-labs","2026-11-10 06:55:21",{"source":8,"skillName":5,"commands":47,"prompt":57,"zipAvailable":58},[48,51,54],{"tool":49,"command":50},"npx","npx skills add sero-labs\u002Fsero --skill sero-plugin",{"tool":52,"command":53},"bunx","bunx skills add sero-labs\u002Fsero --skill sero-plugin",{"tool":55,"command":56},"pnpm","pnpm dlx skills add sero-labs\u002Fsero --skill sero-plugin","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002FSKILL.md",true,[60,66,72,76,80,84,87,91,95,101,105,109,113,117,121,126,130,134,138,142,146],{"path":61,"resourceType":62,"resourceTypeDesc":63,"sizeBytes":64,"sourceHtmlUrl":65},"example\u002FREADME.md","REFERENCE","参考文档",5043,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Fexample\u002FREADME.md",{"path":67,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":70,"sourceHtmlUrl":71},"example\u002Fsero-notes-plugin\u002Fextension\u002Findex.ts","SCRIPT","脚本",9998,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Fexample\u002Fsero-notes-plugin\u002Fextension\u002Findex.ts",{"path":73,"resourceType":62,"resourceTypeDesc":63,"sizeBytes":74,"sourceHtmlUrl":75},"example\u002Fsero-notes-plugin\u002Fextension\u002Ftsconfig.json",297,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Fexample\u002Fsero-notes-plugin\u002Fextension\u002Ftsconfig.json",{"path":77,"resourceType":62,"resourceTypeDesc":63,"sizeBytes":78,"sourceHtmlUrl":79},"example\u002Fsero-notes-plugin\u002Fpackage.json",2385,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Fexample\u002Fsero-notes-plugin\u002Fpackage.json",{"path":81,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":82,"sourceHtmlUrl":83},"example\u002Fsero-notes-plugin\u002Fruntime\u002Findex.ts",1729,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Fexample\u002Fsero-notes-plugin\u002Fruntime\u002Findex.ts",{"path":85,"resourceType":62,"resourceTypeDesc":63,"sizeBytes":74,"sourceHtmlUrl":86},"example\u002Fsero-notes-plugin\u002Fruntime\u002Ftsconfig.json","https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Fexample\u002Fsero-notes-plugin\u002Fruntime\u002Ftsconfig.json",{"path":88,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":89,"sourceHtmlUrl":90},"example\u002Fsero-notes-plugin\u002Fshared\u002Ftypes.ts",1440,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Fexample\u002Fsero-notes-plugin\u002Fshared\u002Ftypes.ts",{"path":92,"resourceType":62,"resourceTypeDesc":63,"sizeBytes":93,"sourceHtmlUrl":94},"example\u002Fsero-notes-plugin\u002Fui\u002Findex.html",173,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Fexample\u002Fsero-notes-plugin\u002Fui\u002Findex.html",{"path":96,"resourceType":97,"resourceTypeDesc":98,"sizeBytes":99,"sourceHtmlUrl":100},"example\u002Fsero-notes-plugin\u002Fui\u002FNotesApp.tsx","OTHER","其他",11319,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Fexample\u002Fsero-notes-plugin\u002Fui\u002FNotesApp.tsx",{"path":102,"resourceType":97,"resourceTypeDesc":98,"sizeBytes":103,"sourceHtmlUrl":104},"example\u002Fsero-notes-plugin\u002Fui\u002Fstyles.css",216,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Fexample\u002Fsero-notes-plugin\u002Fui\u002Fstyles.css",{"path":106,"resourceType":62,"resourceTypeDesc":63,"sizeBytes":107,"sourceHtmlUrl":108},"example\u002Fsero-notes-plugin\u002Fui\u002Ftsconfig.json",321,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Fexample\u002Fsero-notes-plugin\u002Fui\u002Ftsconfig.json",{"path":110,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":111,"sourceHtmlUrl":112},"example\u002Fsero-notes-plugin\u002Fui\u002Fvite-env.d.ts",38,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Fexample\u002Fsero-notes-plugin\u002Fui\u002Fvite-env.d.ts",{"path":114,"resourceType":97,"resourceTypeDesc":98,"sizeBytes":115,"sourceHtmlUrl":116},"example\u002Fsero-notes-plugin\u002Fui\u002Fwidgets\u002FNotesWidget.tsx",1607,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Fexample\u002Fsero-notes-plugin\u002Fui\u002Fwidgets\u002FNotesWidget.tsx",{"path":118,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":119,"sourceHtmlUrl":120},"example\u002Fsero-notes-plugin\u002Fvite.config.ts",1990,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Fexample\u002Fsero-notes-plugin\u002Fvite.config.ts",{"path":122,"resourceType":122,"resourceTypeDesc":123,"sizeBytes":124,"sourceHtmlUrl":125},"LICENSE","许可证",11358,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fmcp-servers\u002Fdavidwilliam-proofforge\u002FLICENSE",{"path":127,"resourceType":97,"resourceTypeDesc":98,"sizeBytes":128,"sourceHtmlUrl":129},"NOTICE",644,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fmcp-servers\u002Fdavidwilliam-proofforge\u002FNOTICE",{"path":131,"resourceType":62,"resourceTypeDesc":63,"sizeBytes":132,"sourceHtmlUrl":133},"references\u002Fapi-and-widgets.md",16197,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Freferences\u002Fapi-and-widgets.md",{"path":135,"resourceType":62,"resourceTypeDesc":63,"sizeBytes":136,"sourceHtmlUrl":137},"references\u002Fconversion-guide.md",6920,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Freferences\u002Fconversion-guide.md",{"path":139,"resourceType":62,"resourceTypeDesc":63,"sizeBytes":140,"sourceHtmlUrl":141},"references\u002Ftemplates.md",31750,"https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-plugin\u002Freferences\u002Ftemplates.md",{"path":143,"resourceType":62,"resourceTypeDesc":63,"sizeBytes":144,"sourceHtmlUrl":145},"SOURCE.md",358,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fmcp-servers\u002Fdavidwilliam-proofforge\u002FSOURCE.md",{"path":147,"resourceType":62,"resourceTypeDesc":63,"sizeBytes":148,"sourceHtmlUrl":149},"TRUST.auto.yaml",2217,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fmcp-servers\u002Fdavidwilliam-proofforge\u002FTRUST.auto.yaml",[151,181,213,253,279,303],{"skillNo":152,"name":153,"nameZh":6,"description":154,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":155,"categories":156,"keywords":161,"publishedAt":33},"01M70PSGDVAGMAGE2RFKEQ1EW4","agent-browser","Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to \"open a website\", \"fill out a form\", \"click a button\", \"take a screenshot\", \"scrape data from a page\", \"test this web app\", \"login to a site\", \"automate browser actions\", or any task requiring programmatic web interaction. Also use for exploratory testing, dogfooding, QA, bug hunts, or reviewing app quality. Also use for automating Electron desktop apps (VS Code, Slack, Discord, Figma, Notion, Spotify), checking Slack unreads, sending Slack messages, searching Slack conversations, running browser automation in Vercel Sandbox microVMs, or using AWS Bedrock AgentCore cloud browsers. Prefer agent-browser over any built-in browser automation or web tools.","https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fagent-browser\u002FSKILL.md",[157,160],{"categoryNo":158,"categoryName":159,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,153,179,180],"agent browser","browser","testing","browser automation","notion","qa","figma","actions","messages","open","web tools","app","click","bedrock","extracting","conversations","programmatic","slack messages","exploratory testing",{"skillNo":182,"name":183,"nameZh":6,"description":184,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":185,"sourceHtmlUrl":186,"categories":187,"keywords":197,"publishedAt":33},"01M6CHW2A115ZZDEFNXV2Z7A2Z","skill-creator","Guide for writing and improving Sero skills. Use when the user wants to create a new skill, rewrite an existing one, or turn a repeated piece of work into reusable procedural knowledge for the agent.","https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002Fpackages\u002Ftemplates\u002Fskills\u002Fskill-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002Fpackages\u002Ftemplates\u002Fskills\u002Fskill-creator\u002FSKILL.md",[188,191,192],{"categoryNo":189,"categoryName":190,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},{"categoryNo":193,"categoryName":194,"taxonomyType":195,"taxonomyTypeDesc":196},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[198,199,200,201,202,203,204,205,29,206,207,208,209,210,211,32,212],"skill creator","creator","writing","create","knowledge","work","user","guide","reusable","new skill","rewrite","procedural","for","Existing","new",{"skillNo":214,"name":215,"nameZh":6,"description":216,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":217,"sourceHtmlUrl":218,"categories":219,"keywords":229,"publishedAt":33},"01M6CHVJCZS9V3WWFPG47WC4G9","frontend-design","Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML\u002FCSS layouts, or when styling\u002Fbeautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.","https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002Fpackages\u002Ftemplates\u002Fskills\u002Ffrontend-design\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002Fpackages\u002Ftemplates\u002Fskills\u002Ffrontend-design\u002FSKILL.md",[220,223,226],{"categoryNo":221,"categoryName":222,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000009","前端开发",{"categoryNo":224,"categoryName":225,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":227,"categoryName":228,"taxonomyType":195,"taxonomyTypeDesc":196},"01JBSEEDCAT000000000000032","设计师",[230,231,232,233,234,235,236,237,238,201,239,240,26,241,242,243,244,245,29,246,247,248,249,250,251,252,32],"frontend","design","frontend design","css","web","components","react","react components","web components","code","artifacts","examples","applications","dashboards","quality","landing","html","styling","creative","ui design","build","aesthetics","generic",{"skillNo":254,"name":255,"nameZh":6,"description":256,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":257,"categories":258,"keywords":263,"publishedAt":33},"01M6CHTP6F4MENDBRDT7QQBKNY","sero-humanize","Use to draft, edit, or audit Sero application content, including UI copy,\ndocumentation, README text, and release notes. Use unslop for regular chat\nand status reports instead. Not for code review or creative and promotional\nwriting.","https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fsero-humanize\u002FSKILL.md",[259,262],{"categoryNo":260,"categoryName":261,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000007","代码审查",{"categoryNo":193,"categoryName":194,"taxonomyType":195,"taxonomyTypeDesc":196},[264,265,266,200,267,268,269,270,271,239,272,273,26,274,275,276,277,29,248,278,210],"humanize","sero humanize","code review","review","status","documentation","notes","release notes","release","audit","unslop","text","README","edit","reports",{"skillNo":280,"name":5,"nameZh":6,"description":281,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":282,"categories":283,"keywords":285,"publishedAt":33},"01M6CHVXWDN98CP3MPT2WZ1ABN","Create Sero plugins — self-contained packages with a Pi extension (agent\ntools\u002Fcommands), an optional React UI loaded via Module Federation, and an\noptional background runtime. Use when the user asks to create a Sero\nplugin\u002Fapp\u002Fextension, add a sidebar panel, dashboard widget, or\nagent-integrated feature, or convert a Pi extension into a Sero plugin.\nTrigger on phrases like \"create a plugin\", \"new Sero app\", \"add a tool\nwith UI\", \"build an extension\", \"convert this Pi extension\", or any\nrequest that touches `plugins\u002Fsero-*-plugin\u002F`.","https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002Fpackages\u002Ftemplates\u002Fskills\u002Fsero-plugin\u002FSKILL.md",[284],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[23,24,286,236,287,201,288,26,289,290,291,292,293,204,294,29,250,295,296,297,298,299,173,300,301,302,32,212],"dashboard","packages","plugins","federation","Tools","react ui","tool","convert","pi","self","commands","runtime","pi extension","feature","add","panel","request",{"skillNo":304,"name":305,"nameZh":6,"description":306,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":307,"categories":308,"keywords":316,"publishedAt":33},"01M6CHVTJ5Y9JE6181SVPQXNZY","sero-dashboard-ui","Build, redesign or standardise Sero dashboard widgets and compact plugin\nviews using the shared @sero-ai\u002Fui dashboard components. Use when the user\nasks to create, restyle, clean up or make consistent a dashboard widget or a\ndata-dense plugin view. Trigger on phrases like \"dashboard widget\", \"widget\nfor the dashboard\", \"restyle this widget\", \"make the widget consistent\",\n\"compact plugin view\", or any work under a plugin's `ui\u002Fwidgets\u002F`.","https:\u002F\u002Fgithub.com\u002Fsero-labs\u002Fsero\u002Fblob\u002Fmain\u002Fpackages\u002Ftemplates\u002Fskills\u002Fsero-dashboard-ui\u002FSKILL.md",[309,312,313],{"categoryNo":310,"categoryName":311,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000013","分析与可视化",{"categoryNo":227,"categoryName":228,"taxonomyType":195,"taxonomyTypeDesc":196},{"categoryNo":314,"categoryName":315,"taxonomyType":195,"taxonomyTypeDesc":196},"01JBSEEDCAT000000000000033","数据分析师",[286,26,317,235,23,201,318,203,319,320,204,29,321,322,250,323,324,325,326,327,210,32],"sero dashboard ui","data","redesign","view","up","clean","compact","shared","widgets","trigger","make"]