Guidance for developing, testing, securely installing or refreshing, versioning, and submitting Xpert plugins. Use for general, model, skill-only, integration, or middleware plugins; large or revisioned Agent data mutations; local deployment; plugin-managed MCP tools and Apps; Workspace Files; Managed Queue; Sandbox Jobs; Runtime Providers; Artifacts; and Collaboration.
Guidance for developing, testing, securely installing or refreshing, versioning, and submitting Xpert plugins. Use for general, model, skill-only, integration, or middleware plugins; large or revisioned Agent data mutations; local deployment; plugin-managed MCP tools and Apps; Workspace Files; Managed Queue; Sandbox Jobs; Runtime Providers; Artifacts; and Collaboration.
Xpert Plugin Development
Use this skill when the task involves plugin work in the Xpert plugin repository:
creating a new plugin
updating an existing plugin
installing a local plugin into the platform
validating plugin config, runtime behavior, or packaging
developing plugin-managed MCP tools or MCP Apps
preparing commits, version updates, or PRs
Repository:
Official upstream: https://github.com/xpert-ai/xpert-plugins.git
Local plugin repository root: discover from the current workspace instead of assuming a fixed absolute path
Local platform backend root: discover from the current workspace instead of assuming a fixed absolute path
Golden Principle: Review Files Over 1,000 Lines
Treat 1,000 lines as an architecture-review threshold for maintained source files. When a code file exceeds 1,000 lines, pause before adding more behavior and assess whether it combines multiple responsibilities. Split coherent responsibilities into focused files when clear boundaries exist, while preserving explicit ownership, stable public contracts, and test coverage. Do not mechanically fragment a cohesive file merely to satisfy the line count.
Workflow
Identify the plugin type first: general tool plugin, model plugin, integration plugin, middleware plugin, skill-only plugin, plugin-managed MCP server, or MCP App plugin.
Discover the actual local paths for the plugin repository, the target plugin directory, and the platform backend before running commands.
Read references/general.md for repository layout, install flow, test flow, versioning, and PR rules.
When initializing a new plugin, create its default Mintlify documentation package by running mint new docs from the plugin root. Keep future project documentation under docs/; if that directory already exists, preserve and validate it instead of overwriting it. Follow the initialization and packaging rules in references/general.md.
If the task creates, changes, or reviews model-visible/plugin-callable Middleware or MCP tools, read references/tool-contract-design.md for strict Zod inputs, DTO outputs, progressive disclosure, pagination, scope, ChatKit title and Tool/Middleware icon contracts, draft revision/conflict handling, and test rules.
If a model iteratively creates or updates many records, read references/large-data-mutation-workflows.md for item granularity, idempotency, revision checks, transaction boundaries, lifecycle-call compression, bulk manifest limits, and retry behavior; also read references/tool-contract-design.md.
If the task is about model providers, yaml, assets, or packaging, also read references/model-plugins.md.
If the task is about callbacks, bindings, notifications, or third-party platform connectivity, also read references/integration-middleware.md.
If the task is about plugin background jobs, BullMQ, delayed/retry jobs, Redis queue state, or multi-tenant queue isolation, also read references/managed-queue.md.
If a queued Agent workflow must keep the current conversation turn alive until completion because durable proactive delivery is unavailable, read references/agent-long-running-tasks.md; also read references/managed-queue.md and references/tool-contract-design.md.
If the task is about plugin file inputs, workspace files, sandbox /workspace paths, file upload/download/send flows, platform file references, or queued file retries, also read references/workspace-files.md.
If the task is about isolated browser rendering, Chromium, PDF/PPTX export, document conversion, Sandbox Action Bundles, Browser Runtime, Runtime Definition/Binding/Provider health, Runtime Provider or workspace mapper development, ephemeral Job sandboxes, or the sandbox-browser execution pool, read references/sandbox-jobs.md; also read references/managed-queue.md and references/workspace-files.md.
If the task is about creating, versioning, previewing, sharing, revoking, archiving, or deleting platform-managed Artifacts, read references/artifacts.md; also read references/workspace-files.md when Artifact content is written or deleted.
If the task is about Yjs/CRDT state, collaborative editing, WebSocket sessions, presence, remote cursors, user/Agent co-editing, state-vector synchronization, or plugin business-state materialization, read references/collaboration.md.
If the task is about .xpertai-plugin/plugin.json, plugin-managed MCP servers, MCP tool metadata, ui:// resources, MCP Apps, or ChatKit inline app rendering, also read references/mcp-tools-and-apps.md.
If the task is about Xpert skill-only plugins, Codex-to-Xpert skill conversion, skill marketplace cards, skill resource installation, skill document dialogs, or ClawXpert skill trial flows, also read references/skill-only-plugins.md.
Prefer the platform's plugin:deploy:local command for local development. It builds, tests, refreshes an existing source=code plugin or installs it on first use, and verifies the loaded descriptor. Use the manual source=code + sourceConfig.workspacePath flow only when that command is unavailable. Treat a staged descriptor as registration evidence only; restart when required and verify runtime loading separately.
Prefer configured Xpert username/password credentials for local deployment. The platform CLI logs in for a fresh JWT, uses it only for the current process, and may infer the tenant from the login response. Treat an explicit --token as an intentional override; keep XPERT_TOKEN and the legacy token Keychain item only as compatibility fallbacks. Follow the credential setup procedure in references/general.md; never extract browser credentials or ask the user to paste a password or token into chat.
When the plugin contributes an Assistant template, deploy and verify the plugin first, then provision a new Assistant or update the existing one from the template as a separate lifecycle. Plugin deployment never proves Assistant initialization or publication.
Before finishing, verify build output, installation, runtime behavior, and submit only relevant files.
Plugin Levels and System-Level Artifact Isolation
Choose meta.level from the plugin's runtime class and allowed installation scope:
Use system for a system-level plugin that may be installed only at tenant scope in the Default tenant.
Use tenant for a system-level plugin that may be installed at tenant scope in other tenants.
Use organization for a non-system-level plugin that may be installed at organization scope.
Treat a plugin that registers or exposes host server capabilities such as TypeORM entities, controllers, server modules, routes, or equivalent process-global infrastructure as system-level. Choose system or tenant according to its tenant eligibility; never use organization for this kind of plugin. Both system-level values require a stable meta.artifactNamespace; do not rely on the package-name compatibility fallback.
Use the same artifactNamespace as the source of every plugin-owned artifact name. Build database table names, controller route prefixes, provider/view/registry keys, queue identifiers, and other process-global or persisted unique strings through a shared namespace constant and contract-appropriate helper. Do not scatter copied namespace literals or create unnamespaced identifiers that can drift during later refactors. Keep package or bundle metadata aligned with runtime metadata, and test the namespace plus all derived artifact names. See references/general.md for the required naming and validation pattern.
Deployment State and Assistant Lifecycle
staged successfully, descriptor visibility, or restartRequired: true means the plugin was registered or copied; it does not prove the module is running. Restart the API when required, then verify bootstrap plus an observable provider, View, route, or tool call.
Plugin deployment and Assistant initialization are separate. Deploy and verify the plugin first; then provision or update, save, publish, and test the Assistant independently without creating a duplicate instance unintentionally.
Rules
Keep package metadata, exported entrypoints, schema, and runtime behavior aligned.
Do not commit secrets, tokens, passwords, temporary callback URLs, or local-only debug values.
Do not expose platform capabilities as tools unless the upstream platform APIs are confirmed to exist and are stable enough for users.
Treat createTools() and runtime tool execution as separate contracts and verify both.
When the platform backend code changes, restart the backend before concluding installation or loading is broken.
Do not hardcode machine-specific absolute paths in docs, scripts, or instructions. Use discovered paths or placeholders such as <plugin-repo-root> and <platform-root>.
For plugin-managed MCP servers, use stable manifest placeholders such as ${PLUGIN_ROOT} and ${PLUGIN_DATA} instead of installed runtime paths.
For MCP Apps, keep tool metadata and resource metadata separate: tool _meta.ui carries resourceUri / visibility; resource _meta.ui carries display metadata (title, description, icon) plus CSP, permissions, domain, and prefersBorder.
Treat plugin-managed stdio MCP servers as platform-controlled runtimes: production must be explicitly enabled, commands must be policy-checked, mutable state belongs in ${PLUGIN_DATA}, and MCP App resource/RPC requests must carry the host-issued appInstanceToken.
Style MCP Apps with host-injected CSS variables using the public --mcp-app-* contract. Do not hardcode ChatKit internals, private theme tokens, or tenant-specific colors in iframe HTML.
Localize MCP App iframe UI from the host ui/initialize language context instead of hardcoding one language in app HTML.
Do not use broad TypeScript escape hatches as normal implementation strategy: avoid as any, as unknown as, : any, : unknown, Record<string, any>, untyped callbacks, and untyped test mocks. First inspect the SDK, platform, React, MCP, or domain-library types; import concrete types, derive callback/event shapes with Parameters<> / ReturnType<>, add narrow type guards, or define small boundary DTOs. If a compatibility assertion is unavoidable, isolate it in a named helper at the boundary and keep downstream code typed.
Output expectations
When using this skill, prefer this order:
identify plugin type and affected directories
make the minimum safe code changes
build and validate locally
install or refresh through plugin:deploy:local
verify runtime behavior
summarize risks, versioning impact, and PR readiness
For new plugin background jobs, use the platform Managed Queue abstraction instead of plugin-owned BullMQ queues or Redis connections.
For Sandbox Jobs, declare a deterministic Action Bundle and call only its registered action + actionVersion with structured payloads and portable file references. Never pass a profile, renderer version, shell command, Docker option, image name, entrypoint, environment map, or host path in a Job request.
Run heavyweight Sandbox actions from the API-owned sandbox-browser Managed Queue pool. Do not block HTTP handlers; keep the pool physically separate and use conservative local concurrency.
Implement Sandbox Runtime Providers only as private or built-in system-level infrastructure. Keep Definition and Job Core provider-neutral, register the Provider in the API Runtime executor, connect to engines lazily, and revalidate Binding health before every execution.
Import Sandbox Jobs, Runtime Provider, workspace mapper, and Managed Queue contracts only from @xpert-ai/contracts or @xpert-ai/plugin-sdk. If an older host SDK requires compatibility code, isolate one temporary boundary instead of copying parallel interfaces through business code.
Reuse the platform Browser Runtime for Chromium-based work. Do not add plugin-owned Browser Dockerfiles or plugin identifiers to platform Runtime Profiles.
Verify Sandbox Action hashes against an extracted, real npm pack tarball. Put Action-owned dependencies in a normal directory such as runtime-modules, never nested node_modules, which npm strips from packed dependencies.
Implement plugin i18n through explicit locale boundaries. Frontend iframe/MCP App UI must resolve host language into a typed supported locale and render all user-visible static text from a shared dictionary or host i18n mechanism. Backend services should return stable codes and structured DTOs by default, localizing only user-facing artifacts, localized metadata, or explicit display messages with a normalized locale.
Treat an unexpectedly multi-gigabyte tsc heap requirement as a type-boundary defect, not a build requirement. When a plugin declares many heterogeneous LangChain tool() calls, prevent the Zod v3/v4/JSON Schema overloads from propagating complete schema generics into the SDK tool array; follow the narrow-boundary pattern in references/general.md and verify the package with the default Node heap.