Create Hana plugin scaffolds and guide users through beginner or developer plugin planning, capability checks, manifest setup, runtime tools, WebView/iframe UI, Session/Agent APIs, model/media APIs, SDK templates, and install-ready plugin directories. Use when HanaAgent/Codex needs to explain what Hana plugins can do, help a user describe a plugin idea, check whether the SDK supports it, or generate/update a Hana plugin with @hana/plugin-runtime, @hana/plugin-sdk, and @hana/plugin-components.
71
88%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Use this skill for Hana application plugins, not Codex .codex-plugin bundles.
On first use, give a map, not an encyclopedia. Explain what Hana plugins can add, ask what the user wants to build, and invite follow-up questions. Expand details only after the user asks or after the chosen scaffold needs them.
Choose the user mode this way:
你想我用哪种方式帮你创建插件?A. 边讲边做 B. 开发者模式Beginner mode tone: encouraging, concrete, and guided. Say that the user can describe the feature in plain language, HanaAgent will help turn it into a plugin plan and scaffold, and HanaAgent can answer questions at any step. Ask:
Developer mode tone: concise and collaborative. Lead with the capability surface, then ask for the target contribution and integration boundary.
After delivering a plugin, encourage with grounded product value. Name the real situation where the plugin helps, such as reducing repeated steps, making an external service available inside Hana, turning a manual workflow into an Agent-callable tool, or giving a recurring task a stable UI. Use natural wording such as 这个想法挺实用,适合把每周重复整理的步骤固定下来 or 这个方向比较适合做成工具型插件,因为 Agent 可以在对话里直接调用. Avoid inflated praise like 你的设想太棒了.
Hana plugins can provide:
chat.surface cards for showing plugin-owned private session transcripts in the main chat stream.@hana/plugin-runtime: create/list/update/send/abort/history sessions, subscribe to session events, create/read/update plugin-owned agents, and hide plugin-private resources from the main Hana UI.sendSessionMessage(..., { context }) or session:send.context, suitable for plugin-owned RAG, world lore, mood, character state, or routing hints. This affects only the current provider request and does not rewrite visible user text.sampleText() for plugin-side summarization, RAG query rewriting, routing, and classification.ctx.network.fetch() with manifest-declared hosts, methods, timeout, cache, and response-size boundaries.ctx.resources, with ResourceRef inputs for local files, mounts, SessionFiles, durable resources, read-only URLs, and backend watch subscriptions.listMediaProviders(), resolveMediaModel(), and generateImage(), with generated files delivered as SessionFile resources.extensions/*.js where the plugin must observe or transform the LLM request pipeline.Hana provides install/enable/reload, per-agent skill toggles, manifest capability checks, iframe host messaging, theme tokens, toast/clipboard/external host APIs, EventBus, data directories, and SDK packages.
Current boundaries: WebView/iframe UI is the stable escape hatch for existing web apps, remote sites, and standalone HTML. chat.surface is a thin native transcript surface for plugin-owned plugin_private / private sessions created through the runtime session API. Rich native card composition is not part of the public SDK contract yet. Native renderer components and code sandboxing are not the default path yet. Ordinary manifest capabilities are declaration metadata and can be used directly through the SDK/EventBus; sensitiveCapabilities records future user-granted permission intent. If a request depends on native renderer hooks, code sandboxing, or fine-grained permission prompts, explain the gap and propose the closest supported shape.
Run the bundled Node preflight before invoking the Python scaffold script:
node skills2set/hana-plugin-creator/scripts/check_env.mjs --capability scaffoldBehavior:
HANA_PLUGIN_CREATOR_PYTHON, python3, python, or Windows py -3.ok: false, stop and show the user the message or installGuidance. Do not auto-install dependencies.python3.PLUGIN_SDK.md, PLUGINS.md, and packages/plugin-runtime.PLUGIN_SDK.md and the relevant sections of PLUGINS.md before changing plugin code. For React UI, also read packages/plugin-sdk/README.md and packages/plugin-components/README.md.direct: no npm install, no build step, best for a beginner's first runnable plugin.guided-react: React/Vite/SDK starter with shared Hana components and a gentler README.professional-react: React/Vite/SDK starter for developers who expect package scripts and typed UI code.tool: restricted plugin with tools/*.js.ui: full-access WebView/iframe page/widget.full: tool, lifecycle/EventBus entry, and WebView/iframe UI.provider: full-access provider declaration under providers/*.js.plugins/<plugin-id>.examples/plugins/<plugin-id>./api/plugins/settings or ${HANA_HOME}/plugins.fetch('/api/...') calls to hana.api.fetch(...), move static files under assets/, and use hana.assets.url(...) for browser-side asset references.ctx.network.fetch(...) from that route. Add network.fetch and network.allowedHosts to the manifest instead of calling the third-party API directly from iframe JavaScript.plugin.dev.install;plugin.dev.reload after edits;devRunId and pass it to lifecycle controls when available;plugin.dev.enable, plugin.dev.disable, plugin.dev.reset, and plugin.dev.uninstall;plugin.dev.diagnostics;plugin.dev.invokeTool;plugin.dev.listSurfaces;manifest.dev.scenarios with plugin.dev.runScenario.Beginner starter:
python3 skills2set/hana-plugin-creator/scripts/create_hana_plugin.py "My Plugin" --path examples/plugins --audience beginner --template directDeveloper React starter:
python3 skills2set/hana-plugin-creator/scripts/create_hana_plugin.py "My Plugin" --path examples/plugins --audience developer --template professional-react --sdk-mode workspaceUseful options:
--kind tool: restricted plugin with a static tools/create-note.js.--kind ui: full-access plugin with page and widget WebView/iframe UI.--kind full: tool, lifecycle/EventBus entry, and WebView/iframe UI.--kind provider: full-access provider contribution with a media-capability provider declaration.--sdk-mode workspace: use repo-local SDK packages.--sdk-mode bundled: copy SDK tarballs from this skill into the generated plugin.--dev-scenario: add a first-phase manifest.dev.scenarios smoke test.--force: replace an existing generated directory only when the user explicitly wants overwrite.Provider contribution starter:
python3 skills2set/hana-plugin-creator/scripts/create_hana_plugin.py "Jimeng Provider" --path examples/plugins --kind provider --audience developertools/*.js must export name, description, parameters, and execute.sessionPermission. Use readOnly: true for pure reads, kind: "plugin_output" for bounded plugin-data writes that return SessionFile media, and kind: "external_side_effect" for network/provider/platform actions that Auto mode should send to the reviewer. Tools that modify user workspace files should stay reviewer-bound unless the user has explicitly granted a narrower workflow.@hana/plugin-runtime, @hana/plugin-sdk, and @hana/plugin-components.assets/ and should be referenced with hana.assets.url(path) from browser code or the official /api/plugins/{pluginId}/assets/... path from the route shell. This includes CSS, JS, images, fonts, JSON, wasm, and browser-playable videos such as MP4/WebM/MOV. Do not inline large assets as a workaround./api/video, /api/file, or /assets/*, in new Agent-generated code. Existing plugins with static-file compatibility handlers may continue to run; if editing them, prefer adding the official assets/ references without removing the existing handler unless the user explicitly asks for cleanup.${HANA_HOME}/plugins-dev/, and Agent dev tools are hidden until the user enables the dev tools setting.capabilities, such as session, agent, model.sample, and media.generate. Put future high-risk needs in sensitiveCapabilities."network.fetch" in capabilities and add a top-level network object with allowedHosts, methods, defaultTimeoutMs, and maxResponseBytes. Use ctx.network.fetch(url, { cacheTtlMs }) from Node-side tools, routes, or lifecycle code.hana.api.fetch(...); the route reads config/secrets server-side and calls ctx.network.fetch(...).fetch() remain compatible, but new or refactored Agent-generated code should use ctx.network.fetch() so diagnostics can explain missing capabilities, hosts, methods, and response-size limits.ctx.resources. Declare resource.read for stat/read/list, resource.search for search, resource.write for write/writeExpectedVersion/edit/mkdir/delete/copy/rename/move/trash, resource.materialize for concrete local paths, and resource.watch for backend watch subscriptions through ctx.resources.watch() / ctx.resources.subscribe(). URL resources are read-only. Do not use local path writes for user resources.watch.unsubscribe to register(), and short-lived tools should release in finally. Listen for resource.changed, resource.deleted, and resource.renamed on ctx.bus, then filter by the handle's resourceKeys.{ kind: "local-file", path }, { kind: "mount", mountId, path }, { kind: "session-file", fileId }, { kind: "resource", resourceId }, or { kind: "url", url }. Avoid designing new tool parameters that require host-local absolute paths unless the feature is explicitly local-execution-only.ctx.resources is for user resources; toolCtx.stageFile() is for plugin-generated files that need to become SessionFile media; ctx.dataDir and packaged assets/ are plugin-owned storage. Raw fs examples are only acceptable for plugin-owned storage, not workspace, mount, URL, or SessionFile inputs.ctx.resources.materialize(ref) only when a parser, CLI, or host library needs a concrete local path. Treat the returned path as an execution boundary and write back through ResourceIO explicitly if the source resource must change.hana.resources.open(), hana.resources.pick(), or hana.resources.requestAccess() as host-mediated requests only. It must not read or write filesystem content directly; server-side plugin routes and tools should use ctx.resources for actual resource operations.hana.resources.open(), hana.resources.pick(), or hana.resources.requestAccess(), declare the matching resource.open, resource.pick, or resource.requestAccess entry under ui.hostCapabilities. Do not request resource host grants in templates that do not use those calls.ctx.config; never place secrets in assets/, iframe JavaScript, route shell HTML, or checked-in examples.createSession, getSession, listSessions, updateSession, sendSessionMessage, subscribeSessionEvents, createAgent, updateAgent, sampleText, ctx.resources.watch, ctx.resources.subscribe, listMediaProviders, resolveMediaModel, generateImage, generateMedia, generateVideo, and transcribeAudio.createSession() creates a detached Hana session and does not switch the main UI focus. Use visibility: "plugin_private" and ownerPluginId for plugin-only sessions or Tavern-style parallel chat surfaces.createChatSurfaceCard(ctx, session.sessionRef ?? session, options) when a plugin wants to display its own private session in chat. Do not hand-build path-only chat.surface payloads; the helper requires sessionId / sessionRef and Hana verifies plugin ownership before rendering.createAgent() / updateAgent() can create plugin-owned hidden agents. Keep plugin-only characters and resources marked visibility: "plugin_private" unless the user expects them in the main Agent list.sendSessionMessage() with context.system, context.beforeUser, or context.afterUser for per-turn RAG/world-lore/mood injection. Do not write JSONL history directly and do not mutate the visible user message to smuggle hidden context.sampleText() for plugin-side reasoning tasks that do not need a full chat turn, such as query rewriting, summaries, classifiers, or routing.generateImage() / generateMedia() for host media generation instead of calling provider internals directly. The media task pipeline owns progress, cancellation, delivery, and SessionFile registration. Image references should use { kind: "session_file", fileId } instead of raw local paths. Provider models must declare reference-image support on each mode with modes[].inputLimits.referenceImages, such as { min: 0, max: 0 } for text-only generation or { min: 1, max: 1 } for a single-reference mode. Use transcribeAudio() for ASR over registered SessionFile audio.media-gen:* events from newly generated plugins. They remain only for old adapter compatibility. New provider plugins must declare providers/*.js with capabilities.media.*, then use stable media helpers or the formal Adapter Plugin API once available.toolCtx.stageFile({ sessionId, sessionRef, filePath, label }), then media details. sessionPath is legacy locator metadata only, not identity. Do not hand-build local MEDIA: or file:// output."trust": "full-access" and route-backed WebView/iframe UI. WebView/iframe cards remain valid for plugin web UI; native chat.surface cards are only for plugin-owned private session transcripts. Rich native card APIs are not part of the public SDK contract yet.hana.api.fetch('route/path', init) or hana.api.url('route/path'). Do not hard-code /api/plugins/{pluginId}/... in browser code, do not reuse pluginIframeTicket for XHR/fetch, and do not ask authors to manually pass pluginSurfaceSession unless documenting the low-level protocol.pluginIframeTicket is only for iframe document loading. Do not append it to CSS, JS, image, font, video, or XHR URLs.extensions/*.js require "trust": "full-access". They are for provider request rewriting, context filtering, and tool-call observation; use ordinary tools/*.js for Agent-callable actions.HANA_BUS_SKIP for payloads that do not belong to them.desktop/src/react.providers/*.js and require "trust": "full-access".capabilities.chat separate from capabilities.media.*. Media-only providers must set chat.projection = "none" so they never appear in chat model selectors.runtime.kind = "local-cli" or "browser-cli" with structured arg bindings and output contracts. Do not build shell command strings.OH-Plugins repository, not inside project-hana.OH-Plugins/official-plugins/<plugin-id>/ with a matching plugins/<plugin-id>.yaml.readme, readmePath, or readmeUrl. Use readmePath only for local file marketplaces; use inline readme or HTTPS readmeUrl for URL marketplaces.versions[] once a plugin has more than one release line. Each version item declares version, compatibility.minAppVersion, and its own distribution.version, compatibility, and distribution remain valid; Hana normalizes them into a single version entry.allowDowngrade: true.distribution.kind = "source" entries because paths resolve on disk.sha256.OH-Plugins, complete the release safety review and wait for explicit user confirmation.HanaThemeProvider mode="inherit" so it follows the host theme.mode="hana" for a named Hana theme, and mode="custom" only for explicit token overrides.hana-theme and hana-css query params, include the theme CSS link when present, and escape values inserted into HTML attributes.hana.api.fetch() for plugin route calls; preserve that helper when simplifying generated browser code.assets/. Keep HTML structure in the shell, compiled or copied JS/CSS/media in assets/, and business APIs in routes/*.js.assets/; do not base64-inline them and do not stream them through custom plugin routes.ctx.network.fetch(). The browser page calls hana.api.fetch('api/...'), receives sanitized JSON, and renders it locally.hana.api.fetch(...); the backend route may use sampleText() or other runtime helpers.pluginIframeTicket in asset/API URLs, hard-coded /api/plugins/{pluginId} in browser code, direct third-party fetch() from iframe assets, custom static-file routes in new code, missing assets/ files, and page-load LLM calls.${HANA_HOME}/plugins-dev/, reload after edits, run diagnostics and scenarios, then package or install into the normal plugin directory only after the dev copy works. Existing installed plugins may include compatibility handlers; treat them as cleanup candidates, not broken plugins.5f08a4f
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.