Agent skill

MoviePilot Plugin Developer

by jxxghp in jxxghp/MoviePilot

Builds, fixes and validates MoviePilot local plugins for V3 and V2 hosts: metadata files, source layout, Vue and Vuetify pages, commands, services and local reload.

GPL-3.0Auto-check passedDevelopment

Install MoviePilot Plugin Developer

skills CLI
$ npx skills add jxxghp/MoviePilot --skill create-moviepilot-plugin -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install jxxghp/MoviePilot create-moviepilot-plugin --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/jxxghp/MoviePilot.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/create-moviepilot-plugin .claude/skills/create-moviepilot-plugin && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
create-moviepilot-plugin
GitHub stars
12k
Token cost
~6.4k tokens
SKILL.md length
2,525 words
Files
1
Skills in repo
16
Repo updated
First seen
Licence
GPL-3.0

At a glance

Builds, fixes and validates MoviePilot local plugins for V3 and V2 hosts: metadata files, source layout, Vue and Vuetify pages, commands, services and local reload.

  • Works in 5 steps: Understand the user request: plugin… → Run the UI Mode Selection Gate before… → Inspect existing plugins before creating… → …
  • Scaffolding a new MoviePilot plugin in a local plugin repository
  • SKILL.md covers Ground Truth, Task Scope, Code Tool Workflow and Pre-Flight, plus 10 more sections
  • Needs API_TOKEN

What it does

The skill guides the agent through creating or revising a MoviePilot plugin from a local plugin source and installing it into a running MoviePilot instance. It starts by identifying the host generation, because V3 uses plugins.v3 with package.v3.json, V2 uses plugins.v2 with package.v2.json and legacy V1 uses plugins with package.json, and V2 paths must not be produced for a V3 host. Host files such as _PluginBase, the plugin manager and the plugin endpoints serve as the ground truth.

Covered areas include plugin APIs, Vuetify JSON forms, pages and dashboards, Vue module federation remote components, sidebar pages, commands, services, workflow actions and agent tools. Scope rules are explicit: a request to create or fix a plugin allows local source edits and validation, but installing, reloading, restarting, publishing or changing host configuration needs your request or approval, and watched live sources are checked for auto-reload before editing. Requests written in Chinese are handled as well.

When your agent uses it

  • Scaffolding a new MoviePilot plugin in a local plugin repository
  • Fixing or debugging an existing V2 or V3 plugin
  • Adding a Vue page, sidebar entry or dashboard to a plugin
  • Validating plugin metadata files such as package.v3.json

Example prompts

  • “Create a MoviePilot V3 plugin that sends a notification when a download completes.”
  • “My V2 plugin does not appear in the local plugin source, so check package.v2.json for mistakes.”
  • “Add a sidebar page built with a Vue remote component to my plugin.”
  • “Add a command and a scheduled service to my existing plugin.”

Requirements

  • A running MoviePilot instance or its source checkout
  • A local plugin source configured through PLUGIN_LOCAL_REPO_PATHS
  • Pre-approved tools (allowed-tools): read_file, write_file, edit_file, apply_patch, execute_command, search_web, browse_webpage, moviepilot_api

Workflow steps

5 steps, taken from the first numbered list in SKILL.md.

  1. Understand the user request: plugin purpose, trigger mode, configuration,
  2. Run the UI Mode Selection Gate before writing any UI code.
  3. Inspect existing plugins before creating a new one
  4. Determine the target source path
  5. Choose the plugin ID

What it can do on your machine

Read from SKILL.md and the folder at commit 6034dcc. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves these tools, so the agent can use them without asking each time:

    • read_file
    • write_file
    • edit_file
    • apply_patch
    • execute_command
    • search_web
    • browse_webpage
    • moviepilot_api

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are python, json and javascript).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • API_TOKEN

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

MoviePilot Plugin Developer loads about 6.4k tokens when it runs. Until then it costs about 175 tokens; SKILL.md has 2,525 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~175
When it runs · the whole SKILL.md, loaded when a task matches
~6.4k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from jxxghp/MoviePilot at commit 6034dcc, republished under its GPL-3.0 licence (© jxxghp). 2,525 words, ~6,408 tokens.

Download SKILL.mdSave it as .claude/skills/create-moviepilot-plugin/SKILL.md (or your agent's skills folder).
name
create-moviepilot-plugin
description
Use this skill when the user asks to create, modify, debug, validate, or scaffold a MoviePilot local plugin. Covers version-aware V3/V2 plugin development, _PluginBase implementations, package.v3.json/package.v2.json/package.json metadata, plugins.v3/plugins.v2/plugins source layout, PLUGIN_LOCAL_REPO_PATHS local plugin sources, plugin APIs, Vuetify JSON forms/pages/dashboards, Vue module federation remote components, get_render_mode, get_sidebar_nav, plugin sidebar pages, commands, services, workflow actions, agent tools, and local install/reload flows. Also use for Chinese requests mentioning 编写插件、本地插件源, 插件开发, V3插件, V2插件, 插件市场, 本地安装插件, 插件热加载, 前端联邦, 侧栏入口, Vue插件页面.
allowed-tools
read_file, write_file, edit_file, apply_patch, execute_command, search_web, browse_webpage, moviepilot_api
version
6
allowed-api-operations
config.system.get config.system.update plugin.market plugin.installed plugin.install plugin.reload

Create MoviePilot Plugin

Use this skill to build or revise MoviePilot plugins that can be developed from a local plugin source and installed into the running MoviePilot instance.

Ground Truth

  • Host plugin contract: app/plugins/__init__.py, especially _PluginBase.
  • Host plugin discovery, local source sync, install, reload: app/runtime/extensions/plugin_manager.py and app/adapters/external/market.py.
  • Host plugin endpoints, API auth, static files, remotes, and sidebar nav: app/api/endpoints/plugin.py.
  • Local development note: docs/development-setup.md.
  • First identify the actual host generation from its source/version and the target plugin repository. MoviePilot V3 uses plugins.v3/ with package.v3.json; V2 uses plugins.v2/ with package.v2.json; legacy V1 uses plugins/ with package.json. Do not generate V2 paths for a V3 host.
  • When working in or from MoviePilot-Plugins, read its README.md, docs/Repository_Guide.md, and the guide for the target generation: docs/Plugin_Development.md for V3, docs/V2_Plugin_Development.md for V2. For scenario-specific extensions, read the matching docs/faq/*.md.
  • For V3, prefer the public app.sdk.* entry points documented by the current host and guide; do not copy old internal imports from a V2 example. Verify extension signatures against the installed host before using a template.

Task Scope

A request to create or fix a plugin authorizes relevant local source edits and validation. Reuse that authorization; it does not by itself authorize changing host configuration, installing/reloading the plugin, restarting, or publishing. Perform those steps when the user requested them or already approved their scope, honoring host confirmation requirements. Inspect auto-reload settings before editing a live watched plugin source; such edits can affect the runtime immediately and require that runtime effect to be within the authorized scope.

Code Tool Workflow

  • Use execute_command(action="run") with rg and narrow globs or paths to locate plugin classes, extension points, tests, package entries, and directory contents.
  • Read the relevant implementation and adjacent example before editing.
  • If read_file reports truncation, continue with smaller start_line and end_line ranges until all relevant sections have been inspected.
  • Before using a Python or Node.js dependency API, determine the exact installed or locked version from requirements, package manifests, lockfiles, local package source, and .pyi/.d.ts declarations. If those are insufficient, use search_web with the official documentation domain and browse_webpage to read the matching version. Do not guess API signatures from memory or mix examples from different major versions. Search the relevant package directory, .venv, or node_modules directly with rg instead of scanning the entire project without bounds.
  • Pick the editing tool by scope. Use apply_patch when one logical change spans multiple files, adds new files, or deletes files: submit a single patch wrapped in *** Begin Patch / *** End Patch with *** Add File:, *** Update File:, and *** Delete File: sections; every context and removed line must match the current content exactly.
  • Use edit_file for a single localized change in one file. Its old_text must identify one exact location by default; add surrounding context instead of enabling replace_all unless every match intentionally changes.
  • Use write_file for one standalone new file. Existing files require overwrite=true for a full rewrite; first call read_file(include_metadata=true) and pass its sha256 as expected_sha256 when replacing previously read content.
  • Use execute_command(action="run") for short validation, Git, and diagnostic commands. Use action="start" only for interactive or long-running commands, then continue through the returned session ID.
  • Read the structured command result: only execution_outcome="succeeded" with exit_code=0 means a completed command passed. Inspect output on failure and output_file for a truncated log. A timeout or unknown result does not undo side effects and must not trigger a blind retry of a write.
  • For background commands, resume using both output_until_seq and output_until_offset as since_seq and since_offset. Start with offset 0 for partial-chunk paging; last_seq is not a consumed position. Wait for new output in bounded intervals, and drain the remaining pages until output_complete=true for a complete log. Report any output_lost gap. An output_error after start/write/kill requires another read with a suitable byte limit, not another execution of the action.
  • Do not use shell redirection or inline scripts to perform source edits or to bypass a file-tool permission error.
  • When the plugin uses Vue federation, also read MoviePilot-Frontend/docs/module-federation-guide.md, MoviePilot-Frontend/docs/federation-troubleshooting.md, MoviePilot-Frontend/src/utils/federationLoader.ts, and MoviePilot-Frontend/src/pages/plugin-app.vue.
  • Repository boundaries: MoviePilot owns runtime loading, API registration, events, services, data, and permissions; MoviePilot-Frontend owns plugin UI rendering, federation loading, and sidebar pages; MoviePilot-Plugins owns plugin source, icons, package indexes, and release metadata.

Pre-Flight

  1. Understand the user request: plugin purpose, trigger mode, configuration, output UI, whether it needs a scheduler, API, command, workflow action, or agent tool.
  2. Run the UI Mode Selection Gate before writing any UI code.
    • If the user already explicitly chose JSON config/Vuetify JSON or Vue federation, follow that choice.
    • If the plugin has any UI surface and the user has not chosen a mode, ask them to choose between the two modes below and wait for the answer before implementing UI files or schemas.
    • Do not silently default to either mode just because one seems easier.
  3. Inspect existing plugins before creating a new one:
    • Local runtime examples: app/plugins/<plugin>/__init__.py
    • Market/local source candidates: call moviepilot_api with operation_id=plugin.market when the running instance is available.
    • Installed plugin candidates: use operation_id=plugin.installed; its summaries include repo_url when the source can be matched from a local plugin repository or plugin market metadata.
    • For Vue federation examples, use a current plugin from the matching generation and MoviePilot-Frontend/examples/plugin-component/.
  4. Determine the target source path:
    • Query PLUGIN_LOCAL_REPO_PATHS with operation_id=config.system.get when possible.
    • If exactly one local plugin repository is configured, prefer that path.
    • If several are configured, choose the one the user named; otherwise ask which repository to use.
    • If none is configured, prepare the source in an appropriate local directory. When local installation/configuration is authorized, register it with operation_id=config.system.update with setting_key="PLUGIN_LOCAL_REPO_PATHS", the chosen source path as value, and operation="replace". A relative path such as local-plugins resolves against the MoviePilot root. Write the plugin under the chosen source; do not write directly into app/plugins/ unless the user explicitly asks for a runtime-only experiment.
  5. Choose the plugin ID:
    • Class name is the plugin ID, for example MyNotifier.
    • Directory name is the class name lowercased, for example mynotifier.
    • Avoid collisions with installed or market plugins unless the user is explicitly modifying that plugin.
    • Do not hardcode the original plugin ID for data/config namespaces when the plugin may support clones; use self.__class__.__name__.

UI Mode Selection Gate

MoviePilot plugin UI has exactly two implementation modes. Make the user choose one whenever the request includes configuration, detail pages, dashboards, sidebar pages, or any other plugin UI and the mode is not already explicit.

Ask a concise question like:

text
这个插件 UI 用哪种方式实现?
1. JSON 配置:后端返回 Vuetify JSON,适合普通配置表单、简单详情页和轻量仪表板。
2. 联邦 UI:独立 Vue 远程组件,适合复杂交互、自定义布局、侧栏全页或多页面。

Selection rules:

  • JSON config / Vuetify JSON: implement get_form(), get_page(), and get_dashboard() with JSON component schemas. No frontend build or dist/assets/remoteEntry.js is needed.
  • Federation UI / Vue remote component: implement get_render_mode(), expose Vue components through Vite federation, build frontend assets into the plugin directory, and use get_sidebar_nav() only when a sidebar page is requested.
  • If the plugin truly has no user-facing UI, state that no UI mode is needed and implement only the backend extension points the request requires.
  • Backend-only work may proceed while waiting only if it cannot constrain or preclude either UI mode.

Local Source Layout

For a verified V3 host, use this layout for new local plugins. For V2, use package.v2.json and plugins.v2/ instead and follow its dependency contract.

text
<local-plugin-repo>/
├── package.v3.json
└── plugins.v3/
    └── <plugin_id_lower>/
        ├── __init__.py
        ├── pyproject.toml          # only when extra runtime dependencies are necessary
        └── ...                     # helper modules, schemas, static assets

For a Vue federation plugin, the runtime requirement is the built remote assets under the plugin directory:

text
plugins.v3/<plugin_id_lower>/
├── __init__.py
├── dist/
│   └── assets/
│       ├── remoteEntry.js
│       └── ...                     # JS/CSS/assets referenced by remoteEntry
├── package.json                    # optional frontend build project metadata
├── vite.config.js                  # optional frontend build config
└── src/                            # optional source, not required at runtime

Do not rely on frontend source files at runtime. If the source is kept in the plugin repository for maintainability, still build and ship the dist/assets files required by remoteEntry.js.

Only use the legacy layout when the user explicitly needs it:

text
<local-plugin-repo>/
├── package.json
└── plugins/
    └── <plugin_id_lower>/
        └── __init__.py

For legacy package.json entries that should work on V2, include "v2": true. For current V3 work, use package.v3.json and plugins.v3/.

Package Metadata

Add or update the package entry for the plugin ID. Keep the package version and the class plugin_version synchronized.

json
{
  "MyNotifier": {
    "name": "通知示例",
    "description": "根据用户配置发送示例通知。",
    "labels": "消息通知",
    "version": "1.0.0",
    "icon": "mynotifier.png",
    "author": "local",
    "level": 1,
    "system_version": ">=3.0.0",
    "history": {
      "v1.0.0": "初始版本"
    }
  }
}

Rules:

  • The package object key must match the plugin class name.
  • version must match plugin_version.
  • name, description, icon, author, labels, and level should match the plugin class attributes when those attributes exist (plugin_name, plugin_desc, plugin_icon, plugin_author, plugin_label, auth_level).
  • history should record user-readable changes for each published version.
  • Use system_version when the plugin depends on a host capability introduced in a specific MoviePilot version, including new backend APIs, helpers, events, Vue federation behavior, sidebar nav, dashboard behavior, or agent tools.
  • Use "release": true only when the plugin is intentionally distributed by a GitHub Release archive.
  • New plugin entries should usually be appended to the package index so they appear as newer marketplace items.
  • Set system_version to the actual minimum version providing the APIs used; the example is not proof that every host capability exists in 3.0.0.
  • Do not add dependencies unless required. Use the host generation's manifest contract (pyproject.toml for current V3). Dependency changes require the host installation flow; hot reload alone does not install them.
  • Plugin dependencies are installed into the shared MoviePilot Python environment. Do not pin or downgrade packages already provided by MoviePilot unless the user has explicitly accepted the compatibility risk.

Implementation Skeleton

Implement all abstract methods from _PluginBase. All new functions and methods need Chinese docstrings; public classes, public methods, and public functions are a hard review gate.

python
from typing import Any, Dict, List, Optional, Tuple

from app.plugins import _PluginBase


class MyNotifier(_PluginBase):
    """通知示例插件。"""

    plugin_name = "通知示例"
    plugin_desc = "根据用户配置发送示例通知。"
    plugin_icon = "mynotifier.png"
    plugin_version = "1.0.0"
    plugin_label = "消息通知"
    plugin_author = "local"
    plugin_config_prefix = "mynotifier_"
    plugin_order = 100
    auth_level = 1

    _enabled = False
    _message = ""

    def init_plugin(self, config: dict = None) -> None:
        """根据插件配置初始化运行状态。"""
        self.stop_service()
        self._enabled = False
        self._message = ""
        if not config:
            return
        self._enabled = bool(config.get("enabled"))
        self._message = str(config.get("message") or "")

    def get_state(self) -> bool:
        """获取插件启用状态。"""
        return self._enabled

    @staticmethod
    def get_command() -> List[Dict[str, Any]]:
        """返回插件远程命令列表。"""
        return []

    def get_api(self) -> List[Dict[str, Any]]:
        """返回插件 API 列表。"""
        return []

    def get_form(self) -> Tuple[Optional[List[dict]], Dict[str, Any]]:
        """返回插件配置表单与默认配置。"""
        return [
            {
                "component": "VForm",
                "content": [
                    {
                        "component": "VSwitch",
                        "props": {
                            "model": "enabled",
                            "label": "启用插件"
                        }
                    },
                    {
                        "component": "VTextField",
                        "props": {
                            "model": "message",
                            "label": "通知内容"
                        }
                    }
                ]
            }
        ], {
            "enabled": False,
            "message": ""
        }

    def get_page(self) -> Optional[List[dict]]:
        """返回插件详情页面。"""
        if not self._enabled:
            return None
        return [
            {
                "component": "VAlert",
                "props": {
                    "type": "info",
                    "text": self._message or "插件已启用"
                }
            }
        ]

    def stop_service(self) -> None:
        """停止插件后台服务并释放资源。"""
        return None
Show full SKILL.md (1,030 more words)Show less

Extension Points

Use only the extension points the requested plugin actually needs:

  • Configuration: get_form() returns Vuetify form schema and default data; init_plugin() reads config; update_config() persists internal changes.
  • Data: use save_data(), get_data(), del_data(), and get_data_path().
  • Notification: use post_message() instead of directly calling message modules.
  • APIs: return route definitions from get_api(); default auth is apikey when auth is omitted. Vue component APIs should normally use auth: "bear" and be called through the api prop passed by the frontend.
  • Commands: return slash-command definitions from get_command() and dispatch through MoviePilot events.
  • Services: return scheduler services from get_service() and always clean them up in stop_service().
  • One-shot or delayed jobs (for example "run once now" or "run N seconds after an event"): call app.sdk.scheduler.add_plugin_once_job(plugin_id, job_id, self.method, name, delay_seconds=..., func_kwargs=...) instead of creating a private BackgroundScheduler. It does not reset the plugin's periodic services, replaces a pending job with the same ID, and is cleared when the plugin is reloaded or uninstalled. Pass a bound method of the plugin instance, and cancel pending jobs with remove_plugin_once_job() in stop_service() when they must not run after the plugin stops.
  • Dashboards: use get_dashboard_meta() and get_dashboard() for homepage widgets.
  • Workflow actions: use get_actions(); action functions receive ActionContent first and return (success, action_content).
  • Agent tools: use get_agent_tools(); each tool class must inherit app.agent.tools.base.MoviePilotTool.
  • Custom Vue UI: implement get_render_mode() when Vue is the selected UI mode. Return ("vue", "<compiled-assets-path>") and include built frontend assets in the plugin directory.

Vue Federation UI

Use Vue federation when selected in the Pre-Flight UI decision. A Vue plugin must align backend methods, built files, and federation exposes.

Backend requirements:

python
from typing import Any, Dict, List, Tuple


@staticmethod
def get_render_mode() -> Tuple[str, str]:
    """声明插件使用 Vue 联邦组件渲染。"""
    return "vue", "dist/assets"


def get_form(self) -> Tuple[List[dict], Dict[str, Any]]:
    """Vue 模式下返回默认配置模型。"""
    return [], self._current_config()


def get_page(self) -> List[dict]:
    """Vue 模式下详情页由远程 Page 组件渲染。"""
    return []

When the plugin needs a main-layout sidebar page, also implement:

python
def get_sidebar_nav(self) -> List[Dict[str, Any]]:
    """声明插件在主界面左侧导航栏中的全页入口。"""
    if not self.get_state():
        return []
    return [
        {
            "nav_key": "main",
            "title": "我的插件",
            "icon": "mdi-puzzle",
            "section": "system",
            "permission": "manage",
            "order": 10,
        }
    ]

Sidebar rules:

  • Sidebar entries are only aggregated for enabled plugins whose get_render_mode() returns "vue".
  • section must be one of start, discovery, subscribe, organize, system; invalid values fall back to system.
  • permission may be subscribe, discovery, search, manage, or admin; invalid values are ignored.
  • nav_key defaults to main and must not contain /, ?, #, or spaces.
  • Multiple sidebar entries are allowed; each entry needs a stable nav_key.

Frontend federation requirements:

js
federation({
  name: 'MyPlugin',
  filename: 'remoteEntry.js',
  exposes: {
    './Page': './src/components/Page.vue',
    './Config': './src/components/Config.vue',
    './Dashboard': './src/components/Dashboard.vue',
    './AppPage': './src/components/AppPage.vue',
    './AppPageSettings': './src/components/AppPageSettings.vue',
  },
  shared: {
    vue: { requiredVersion: false, generate: false },
    vuetify: { requiredVersion: false, generate: false, singleton: true },
    'vuetify/styles': { requiredVersion: false, generate: false, singleton: true },
  },
  format: 'esm',
})

Build requirements:

  • Set Vite build.target to esnext because federation uses top-level await.
  • Use cssCodeSplit: true and scoped/component-local styles where possible.
  • Build with the frontend project's documented command, then keep remoteEntry.js and every JS/CSS/asset file it references under dist/assets.
  • Do not add frontend runtime dependencies to the plugin Python requirements.txt; keep frontend dependencies in the frontend build project.

Component contracts:

  • Page renders the plugin detail dialog and may emit action, switch, and close.
  • Config renders plugin settings, receives initialConfig and api, and emits save, close, and switch.
  • Dashboard receives config and allowRefresh.
  • AppPage renders the main-layout sidebar page and receives api, pluginId, and navKey.
  • For sidebar nav_key=main, the frontend loads ./AppPage then ./Page.
  • For any other nav_key, the frontend loads ./AppPage{PascalCase(nav_key)}, then ./AppPage, then ./Page. Examples: settings -> AppPageSettings, my_tool -> AppPageMyTool.
  • A single AppPage may branch on navKey, or separate AppPage{PascalCase} files may be exposed for specific entries.

Vue API calls:

  • Define frontend-facing plugin APIs with auth: "bear".
  • Call them with the injected API object, for example props.api.get(\plugin/${props.pluginId}/history`)`.
  • Do not pass settings.API_TOKEN into Vue components for browser-side calls.

Local Install And Reload

Run this phase only within the authorized installation/runtime scope.

  1. After writing files in a configured local plugin repository, call moviepilot_api with operation_id=plugin.market and query fields query="<PluginID>", force_refresh=true to confirm the local source is visible.
  2. Install or reinstall with operation_id=plugin.install, path parameter plugin_id="<PluginID>", and query.force=true. The install flow copies the source into app/plugins/<plugin_id_lower>/.
  3. If PLUGIN_AUTO_RELOAD or development mode is enabled, Python source changes in an installed local plugin can auto-sync and reload. If it is not enabled, call operation_id=plugin.reload with path parameter plugin_id after editing runtime files.
  4. When the dependency manifest changes, reinstall with force=True; reloading alone does not install new dependencies.

Validation

  • Re-read the changed files and confirm class name, directory name, package ID, and package version are consistent.
  • Confirm every public class, public method, and public function has a Chinese docstring.
  • Confirm every newly written function or method has a Chinese docstring, even when it is private helper code.
  • For Vue federation plugins, confirm get_render_mode() returns ("vue", "dist/assets") or the actual built asset path, and that dist/assets/remoteEntry.js exists.
  • For sidebar plugins, confirm the plugin is enabled, get_state() returns True, get_sidebar_nav() returns valid items, and matching AppPage exposes exist for all non-main nav_key values or a generic AppPage handles them.
  • Confirm frontend-facing API routes use auth: "bear" and browser code calls them through the provided api prop.
  • Keep external HTTP calls behind MoviePilot utilities and avoid real network calls in tests.
  • If the plugin has non-trivial logic, add or update pytest-native tests using the repository's bootstrap for the target generation. Inspect its current test configuration instead of copying a V2 backend or namespace into V3.
  • Run the narrowest allowed validation for the touched area. In this repository, follow docs/rules/03-commands.md; for plugin-only repositories, follow their own documented validation commands.
  • For plugin repository Python changes, use the host Python environment when possible and run at least syntax compilation for touched plugin files.
  • For Vue federation changes, run the frontend project's documented typecheck and build commands when available, then verify the built assets were copied to the plugin directory.

Vue Federation Troubleshooting

  • GET /api/v1/plugin/remotes?token=moviepilot should include the plugin with a URL ending in /plugin/file/<plugin_id_lower>/<dist_path>/remoteEntry.js.
  • GET /api/v1/plugin/sidebar_nav should include sidebar entries for enabled Vue plugins with valid nav_key, section, and permission.
  • If the console says Module name 'vue' does not resolve to a valid URL, check the federation shared config and use requiredVersion: false.
  • If the console says top-level await is unavailable, set build.target to esnext.
  • If dynamic import fails, check the remote file request status, the computed remoteEntry.js path, and whether the installed runtime plugin directory actually contains the built assets.
  • If a sidebar page is blank, check the expose name resolution for the current nav_key and fallbacks (AppPage{PascalCase} -> AppPage -> Page).

Final Report

Report:

  • Plugin ID, source path, and runtime path if installed.
  • Host/plugin generation and package file changed (package.v3.json, package.v2.json, or legacy package.json).
  • UI mode used (vuetify JSON or vue federation), and for Vue plugins the exposed components and built asset path.
  • Whether the plugin was installed or reloaded.
  • Validation commands run, or why validation was not run.

© jxxghp, GPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in skills/create-moviepilot-plugin of jxxghp/MoviePilot.

Open the folder on GitHubat commit 6034dcc

Compare with similar skills

MoviePilot Plugin Developer next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

MoviePilot Plugin Developer compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
MoviePilot Plugin Developer this skilljxxghp/MoviePilot12k—~6.4kAutomated safety check: PassGPL-3.0
Plugin Forges0912758806p/agentic-sop-to-work209—~242Automated safety check: PassMIT
LangBot Plugin Developmentlangbot-app/LangBot18k—~3.9kAutomated safety check: PassApache-2.0
Mirage VFS Adapter Authoringstrukto-ai/mirage3.7k—~2.5kAutomated safety check: PassApache-2.0
CLI-Anything for CodexHKUDS/CLI-Anything52k—~1.5kAutomated safety check: PassApache-2.0
CLI-Anything for ReasonixHKUDS/CLI-Anything52k—~1.8kAutomated safety check: PassApache-2.0

Similar skills

  • Plugin Forge

    s0912758806p/agentic-sop-to-work

    A skill your agent uses when creating, scaffolding, or linting a Claude Code plugin — generate a grammar-conformant plugin skeleton, or validate a plugin / whole marketplace against house invariants…

    209 GitHub stars~242 tokensUpdated 1 mo ago
    DevelopmentAuto-check passed
  • LangBot Plugin Development

    langbot-app/LangBot

    Guides building, debugging and testing LangBot plugins: components, SDK calls, README and locale rules, SDK pitfalls and WebSocket-based testing.

    18k GitHub stars~3.9k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Builds or extends a custom Mirage virtual filesystem adapter for an API, database, object store or app data, with a working mount configuration and filesystem tests.

    3.7k GitHub stars~2.5k tokensUpdated today
    DevelopmentAuto-check passed
  • CLI-Anything for Codex

    HKUDS/CLI-Anything

    Lets Codex build, refine, test, validate and list CLI-Anything harnesses for GUI applications or source repositories, following the project's full methodology.

    52k GitHub stars~1.5k tokensUpdated 18 days ago
    DevelopmentAuto-check passed
  • CLI-Anything for Reasonix

    HKUDS/CLI-Anything

    Adapts the CLI-Anything methodology so Reasonix can build, refine, test and validate a command-line harness for an existing GUI application or source repository.

    52k GitHub stars~1.8k tokensUpdated 18 days ago
    DevelopmentAuto-check passed
  • Jeecg Codegen New

    jeecgboot/skills

    A skill your agent uses when user asks to generate JeecgBoot CRUD code, create a new module, add/modify fields on existing module, or says "代码生成", "生成代码", "创建模块", "新增功能", "建表", "加字段", "加一个字段"…

    239 GitHub stars~2.4k tokensUpdated 22 days ago
    DevelopmentAuto-check passed

More from jxxghp/MoviePilot

All 16 skills in this repo
  • Inspects, diagnoses and directly controls qBittorrent, Transmission or rTorrent downloaders configured in MoviePilot through a bundled Python helper.

    12k GitHub stars~4.4k tokensUpdated yesterday
    Auto-check passed
  • Turns a confirmed MoviePilot bug or feature request into a structured upstream GitHub issue, but only after local diagnosis and an explicit request to file.

    12k GitHub stars~2.9k tokensUpdated yesterday
    Auto-check passed
  • Inspects and operates Emby, Jellyfin, Plex and other media servers configured in MoviePilot through one helper script, without exposing stored credentials.

    12k GitHub stars~3.4k tokensUpdated yesterday
    Auto-check passed
  • Publish MoviePilot Plugin

    jxxghp/MoviePilot

    Publishes and syncs a local MoviePilot plugin to a GitHub repository, merging only that plugin's package entry and previewing differences before writing.

    12k GitHub stars~1.9k tokensUpdated yesterday
    Auto-check: notes
  • Submits code changes as a GitHub pull request through an isolated Git clone, reusing or creating your fork and pushing only after you confirm the real diff.

    12k GitHub stars~1.1k tokensUpdated yesterday
    Auto-check: notes
  • AnySearch

    jxxghp/MoviePilot

    Gives your agent a real-time search service for web queries, domain-specific lookups, parallel batch searches and full-page URL extraction.

    12k GitHub starsUsed in 1 repo~2.7k tokens
    Auto-check: notes

Works with

Categories

Questions about MoviePilot Plugin Developer

What does MoviePilot Plugin Developer do?

Builds, fixes and validates MoviePilot local plugins for V3 and V2 hosts: metadata files, source layout, Vue and Vuetify pages, commands, services and local reload. The skill guides the agent through creating or revising a MoviePilot plugin from a local plugin source and installing it into a running MoviePilot instance.json, and V2 paths must not be produced for a V3 host.

When should I use MoviePilot Plugin Developer?

MoviePilot Plugin Developer fits situations like: scaffolding a new MoviePilot plugin in a local plugin repository; fixing or debugging an existing V2 or V3 plugin; adding a Vue page, sidebar entry or dashboard to a plugin; validating plugin metadata files such as package.v3.json.

How do I install MoviePilot Plugin Developer in Claude Code?

Run `npx skills add jxxghp/MoviePilot --skill create-moviepilot-plugin -a claude-code`. Or copy the skill folder (skills/create-moviepilot-plugin in jxxghp/MoviePilot) into .claude/skills/create-moviepilot-plugin in your project. Claude Code loads it when a task matches its description.

How do I install MoviePilot Plugin Developer in Codex?

Run `npx skills add jxxghp/MoviePilot --skill create-moviepilot-plugin -a codex`. Or copy the skill folder (skills/create-moviepilot-plugin in jxxghp/MoviePilot) into .agents/skills/create-moviepilot-plugin in your project. Codex loads it when a task matches its description.

Can I use MoviePilot Plugin Developer in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add jxxghp/MoviePilot --skill create-moviepilot-plugin -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/create-moviepilot-plugin, .gemini/skills/create-moviepilot-plugin, .github/skills/create-moviepilot-plugin and .opencode/skills/create-moviepilot-plugin in your project.

What does MoviePilot Plugin Developer need to run?

Going by SKILL.md and its folder, MoviePilot Plugin Developer needs credentials named API_TOKEN. Our summary lists: A running MoviePilot instance or its source checkout; A local plugin source configured through PLUGIN_LOCAL_REPO_PATHS. Its frontmatter pre-approves these tools: read_file, write_file, edit_file, apply_patch, execute_command, search_web, browse_webpage, moviepilot_api.

Does MoviePilot Plugin Developer access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is MoviePilot Plugin Developer safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does MoviePilot Plugin Developer use?

MoviePilot Plugin Developer is published under the GPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does MoviePilot Plugin Developer use?

About 6.4k tokens (SKILL.md is roughly 26k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to MoviePilot Plugin Developer?

Skills that share tags, products or a category with MoviePilot Plugin Developer: Plugin Forge (s0912758806p/agentic-sop-to-work, 209 stars), LangBot Plugin Development (langbot-app/LangBot, 18k stars), Mirage VFS Adapter Authoring (strukto-ai/mirage, 3.7k stars) and CLI-Anything for Codex (HKUDS/CLI-Anything, 52k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains MoviePilot Plugin Developer?

jxxghp (a GitHub user) maintains it in jxxghp/MoviePilot, which has 11,853 GitHub stars. The repository holds 16 skills in this directory. The repository was last updated on October 9, 2026.

Source: jxxghp/MoviePilot on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.