[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6D2KSRX7DFS4TV852PW2P1K":3,"skill-same:01M6D2KSRX7DFS4TV852PW2P1K":88},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":40,"linkOnly":41,"markdownContent":42,"markdownBody":43,"frontMatter":44,"refName":45,"commitSha":46,"skillDirectory":47,"forksCount":48,"repositoryHtmlUrl":49,"repositoryHomepageUrl":6,"ownerHtmlUrl":50,"ownerBlogUrl":51,"ownerDescription":52,"updatedAt":53,"install":54,"resources":67},"01M6D2KSRX7DFS4TV852PW2P1K","minecraft-plugin-dev",null,"Create, modify, and debug server plugins for current Paper 26.x on Java 25 or legacy Bukkit-derived 1.21.x servers on Java 21. Use for JavaPlugin APIs, events, commands, schedulers, configuration, PDC, and Adventure, not client mods or vanilla datapacks.","Jahrome907\u002Fminecraft-agent-skills","Jahrome907","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F222458345?v=4","01M6D2JFFY1EQCC572G6G3X1R2","Joe ","01M6D2JFS2EE87QN8QCFVFY6M8",201,"MIT","https:\u002F\u002Fgithub.com\u002FJahrome907\u002Fminecraft-agent-skills\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fminecraft-plugin-dev\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000021","资料检索与研究","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],"plugin","dev","minecraft","plugin dev","minecraft plugin","minecraft plugin dev","debug","create","java","plugins","server","use","Legacy","configuration","commands","paper","2026-11-10 10:12:30",false,"---\nname: minecraft-plugin-dev\ndescription: \"Create, modify, and debug server plugins for current Paper 26.x on Java 25 or legacy Bukkit-derived 1.21.x servers on Java 21. Use for JavaPlugin APIs, events, commands, schedulers, configuration, PDC, and Adventure, not client mods or vanilla datapacks.\"\n---\n\n# Minecraft Plugin Development Skill\n\n## Platform Overview\n\n| Platform | Base API | Notes |\n|----------|----------|-------|\n| **Paper** | Bukkit\u002FSpigot + Paper extensions | Recommended; async chunk loading, Adventure native |\n| **Spigot** | Bukkit + Spigot extensions | Legacy; fewer APIs, slower |\n| **Bukkit** | Base API only | Avoid for new plugins |\n| **Folia** | Paper fork | Region-threaded; requires special scheduler APIs |\n\n> Paper is the recommended target. Paper includes all Bukkit and Spigot APIs plus\n> significant performance improvements and additional APIs.\n\n### Routing Boundaries\n- `Use when`: the target is server-side Paper\u002FBukkit\u002FSpigot plugin behavior with JavaPlugin APIs.\n- `Do not use when`: the task requires client-side installable mods or loader APIs (`minecraft-modding` \u002F `minecraft-multiloader`).\n- `Do not use when`: the task is pure vanilla datapack\u002Fcommand content (`minecraft-datapack` \u002F `minecraft-commands-scripting`).\n\n## Bundled References\n\n- Read `references\u002Fruntime-patterns.md` when the task touches scheduling, Folia support, PDC, Adventure\u002FMiniMessage, YAML config, Vault, or Paper-specific APIs.\n- Read `references\u002Fpaper-plugin-commands.md` for a Paper-only `paper-plugin.yml` project or Brigadier command registration.\n\n---\n\n## Project Setup\n\nThe examples below target current Paper 26.3 and Java 25. For an existing\n1.21.x plugin, preserve its `1.21.x-R0.1-SNAPSHOT` dependency, Java 21\ntoolchain, and matching `api-version` until the project is intentionally ported.\n\n### `settings.gradle.kts`\n```kotlin\nrootProject.name = \"my-plugin\"\n```\n\n### `build.gradle.kts`\n```kotlin\nplugins {\n    java\n}\n\ngroup = \"com.example\"\nversion = \"1.0.0-SNAPSHOT\"\n\nrepositories {\n    mavenCentral()\n    maven(\"https:\u002F\u002Frepo.papermc.io\u002Frepository\u002Fmaven-public\u002F\")\n}\n\ndependencies {\n    compileOnly(\"io.papermc.paper:paper-api:26.3.build.+\")\n}\n\njava {\n    toolchain.languageVersion.set(JavaLanguageVersion.of(25))\n}\n\ntasks {\n    processResources {\n        \u002F\u002F Substitutes ${version} in plugin.yml with the Gradle project version\n        filesMatching(listOf(\"plugin.yml\", \"paper-plugin.yml\")) {\n            expand(\"version\" to project.version)\n        }\n    }\n}\n```\n\nAdd Shadow only when the plugin has runtime libraries that must be bundled and\nrelocated. Paper and optional plugin APIs such as Vault remain `compileOnly` and\nmust not be shaded into the plugin JAR.\n\n### `gradle\u002Fwrapper\u002Fgradle-wrapper.properties`\n```properties\ndistributionUrl=https\\:\u002F\u002Fservices.gradle.org\u002Fdistributions\u002Fgradle-9.1.0-bin.zip\n```\n\nGradle 8.8 cannot run on Java 25. Use Gradle 9.1 or newer for a current Java 25\nproject. Preserve the existing wrapper and Java 21 toolchain for a legacy 1.21.x\nproject unless its build is intentionally upgraded and verified.\n\n---\n\n## Project Layout\n```\nmy-plugin\u002F\n├── build.gradle.kts\n├── settings.gradle.kts\n├── gradle\u002F\n│   └── wrapper\u002F\n│       └── gradle-wrapper.properties\n└── src\u002Fmain\u002F\n    ├── java\u002Fcom\u002Fexample\u002Fmyplugin\u002F\n    │   ├── MyPlugin.java          ← main class (extends JavaPlugin)\n    │   ├── listeners\u002F\n    │   │   └── PlayerListener.java\n    │   ├── commands\u002F\n    │   │   └── MyCommand.java\n    │   └── managers\u002F\n    │       └── DataManager.java\n    └── resources\u002F\n        ├── plugin.yml            ← Bukkit-compatible descriptor\n        ├── paper-plugin.yml      ← active descriptor for a Paper plugin\n        └── config.yml\n```\n\n---\n\n## Core Files\n\n### `plugin.yml` (Bukkit-compatible default)\n```yaml\nname: MyPlugin\nversion: \"${version}\"\nmain: com.example.myplugin.MyPlugin\ndescription: An example Paper plugin\nauthor: YourName\nwebsite: https:\u002F\u002Fgithub.com\u002Fexample\u002Fmy-plugin\napi-version: '26.3'\n\ncommands:\n  myplugin:\n    description: Main plugin command\n    usage: \u002Fmyplugin \u003Csubcommand>\n    permission: myplugin.use\n    aliases: [mp]\n\npermissions:\n  myplugin.use:\n    description: Allows use of \u002Fmyplugin\n    default: true\n  myplugin.admin:\n    description: Admin access\n    default: op\n```\n\n> Match `api-version` to the oldest Paper API the plugin intentionally supports.\n> Current Paper examples use `26.3`; legacy `1.21` and positive `1.21.\u003Cpatch>`\n> values remain valid for older servers. A server older than the declared value\n> refuses to load the plugin.\n\n### `paper-plugin.yml` (experimental Paper-only format)\n\nPrefer `plugin.yml` for Bukkit-compatible plugins. Use `paper-plugin.yml` only\nwhen the JAR is intentionally Paper-only and needs Paper-plugin behavior such\nas bootstrapping, loaders, or classloading isolation. It can be the only\ndescriptor, but is not a drop-in replacement: Paper plugins do not use a\n`commands` field or `getCommand(...)` registration. Read\n[`references\u002Fpaper-plugin-commands.md`](references\u002Fpaper-plugin-commands.md)\nfor the paired descriptor, main class, and Brigadier lifecycle registration.\n\nWhen one JAR ships both descriptors, keep their shared metadata and main class\naligned. Do not combine the Paper-only sample with the Bukkit-compatible\n`MyPlugin` sample below.\n\n### Bukkit-compatible main class\n```java\npackage com.example.myplugin;\n\nimport com.example.myplugin.commands.MyCommand;\nimport com.example.myplugin.listeners.PlayerListener;\nimport org.bukkit.plugin.java.JavaPlugin;\n\npublic final class MyPlugin extends JavaPlugin {\n\n    @Override\n    public void onEnable() {\n        saveDefaultConfig();\n\n        \u002F\u002F Register listeners\n        getServer().getPluginManager().registerEvents(new PlayerListener(), this);\n\n        \u002F\u002F Register commands\n        var cmd = getCommand(\"myplugin\");\n        if (cmd == null) {\n            throw new IllegalStateException(\"myplugin command is missing from plugin.yml\");\n        }\n        var handler = new MyCommand(this);\n        cmd.setExecutor(handler);\n        cmd.setTabCompleter(handler);\n\n        getLogger().info(\"MyPlugin enabled!\");\n    }\n\n    @Override\n    public void onDisable() {\n        getLogger().info(\"MyPlugin disabled.\");\n    }\n\n}\n```\n\n---\n\n## Event Listeners\n\n```java\npackage com.example.myplugin.listeners;\n\nimport net.kyori.adventure.text.Component;\nimport net.kyori.adventure.text.format.NamedTextColor;\nimport org.bukkit.event.EventHandler;\nimport org.bukkit.event.EventPriority;\nimport org.bukkit.event.Listener;\nimport org.bukkit.event.entity.PlayerDeathEvent;\nimport org.bukkit.event.player.PlayerJoinEvent;\nimport org.bukkit.event.player.PlayerQuitEvent;\n\npublic class PlayerListener implements Listener {\n\n    @EventHandler(priority = EventPriority.NORMAL)\n    public void onPlayerJoin(PlayerJoinEvent event) {\n        event.joinMessage(\n            Component.text(event.getPlayer().getName() + \" joined!\", NamedTextColor.GREEN)\n        );\n    }\n\n    @EventHandler\n    public void onPlayerQuit(PlayerQuitEvent event) {\n        event.quitMessage(\n            Component.text(event.getPlayer().getName() + \" left.\", NamedTextColor.YELLOW)\n        );\n    }\n\n    @EventHandler\n    public void onPlayerDeath(PlayerDeathEvent event) {\n        \u002F\u002F Modify death message using Adventure components\n        event.deathMessage(\n            Component.text(\"☠ \", NamedTextColor.RED)\n                .append(Component.text(event.getPlayer().getName(), NamedTextColor.WHITE))\n                .append(Component.text(\" died!\", NamedTextColor.RED))\n        );\n    }\n}\n```\n\n### EventPriority order\n`LOWEST → LOW → NORMAL → HIGH → HIGHEST → MONITOR`  \nUse `MONITOR` for logging only (never modify outcome). On events that implement\n`Cancellable`, use `ignoreCancelled = true` unless you need cancelled events.\n\n### Cancellable events\n```java\n@EventHandler\npublic void onBlockBreak(BlockBreakEvent event) {\n    if (event.getPlayer().hasPermission(\"myplugin.break.deny\")) {\n        event.setCancelled(true);\n        event.getPlayer().sendMessage(Component.text(\"You cannot break blocks!\", NamedTextColor.RED));\n    }\n}\n```\n\n---\n\n## Commands\n\nThis section is for the `plugin.yml` path above. Its declared command enables\n`getCommand(\"myplugin\")`. For a Paper-only descriptor, use the Brigadier\nlifecycle example in [`references\u002Fpaper-plugin-commands.md`](references\u002Fpaper-plugin-commands.md).\n\n```java\npackage com.example.myplugin.commands;\n\nimport com.example.myplugin.MyPlugin;\nimport net.kyori.adventure.text.Component;\nimport net.kyori.adventure.text.format.NamedTextColor;\nimport org.bukkit.command.Command;\nimport org.bukkit.command.CommandExecutor;\nimport org.bukkit.command.CommandSender;\nimport org.bukkit.command.TabCompleter;\nimport org.bukkit.entity.Player;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.util.List;\nimport java.util.Locale;\n\npublic class MyCommand implements CommandExecutor, TabCompleter {\n\n    private final MyPlugin plugin;\n\n    public MyCommand(MyPlugin plugin) {\n        this.plugin = plugin;\n    }\n\n    @Override\n    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command,\n                             @NotNull String label, @NotNull String[] args) {\n        if (!(sender instanceof Player player)) {\n            sender.sendMessage(Component.text(\"Only players can use this command.\", NamedTextColor.RED));\n            return true;\n        }\n\n        if (!player.hasPermission(\"myplugin.use\")) {\n            player.sendMessage(Component.text(\"No permission.\", NamedTextColor.RED));\n            return true;\n        }\n\n        if (args.length == 0) {\n            player.sendMessage(Component.text(\"Usage: \u002Fmyplugin \u003Creload|info>\", NamedTextColor.YELLOW));\n            return true;\n        }\n\n        return switch (args[0].toLowerCase(Locale.ROOT)) {\n            case \"reload\" -> {\n                if (!player.hasPermission(\"myplugin.admin\")) {\n                    player.sendMessage(Component.text(\"No permission.\", NamedTextColor.RED));\n                    yield true;\n                }\n                plugin.reloadConfig();\n                player.sendMessage(Component.text(\"Config reloaded.\", NamedTextColor.GREEN));\n                yield true;\n            }\n            case \"info\" -> {\n                player.sendMessage(Component.text(\"Version: \" + plugin.getDescription().getVersion(), NamedTextColor.AQUA));\n                yield true;\n            }\n            default -> {\n                player.sendMessage(Component.text(\"Unknown subcommand.\", NamedTextColor.RED));\n                yield true;\n            }\n        };\n    }\n\n    @Override\n    public @Nullable List\u003CString> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,\n                                                @NotNull String label, @NotNull String[] args) {\n        if (!sender.hasPermission(\"myplugin.use\")) return List.of();\n        if (args.length == 1) {\n            var subcommands = sender.hasPermission(\"myplugin.admin\")\n                ? List.of(\"reload\", \"info\") : List.of(\"info\");\n            return subcommands.stream()\n                .filter(s -> s.startsWith(args[0].toLowerCase(Locale.ROOT)))\n                .toList();\n        }\n        return List.of();\n    }\n}\n```\n\n---\n\n## Schedulers\n\nFor classic Paper plugins, `BukkitScheduler` is still fine. If you claim Folia support,\nroute player, entity, region, global, and async work through the matching Folia-aware\nscheduler. Keep scheduling behind a small project-local interface when one plugin must\nsupport both Paper and Folia.\n\nSee `references\u002Fruntime-patterns.md` for copy-ready sync, async, cancelable, and\nFolia-safe scheduler examples.\n\n---\n\n## Persistent Data Container (PDC)\n\nPDC stores arbitrary data on any `PersistentDataHolder` (players, entities, items, chunks).\nData is saved with the world and persists across restarts.\n\nCreate `NamespacedKey` instances once, keep data types stable after release, and use\nPDC for small metadata rather than large datasets. Prefer config files or a database\nfor large or query-heavy plugin state.\n\nSee `references\u002Fruntime-patterns.md` for player, item, chunk, and world PDC examples.\n\n---\n\n## Adventure Text Components\n\nPaper uses [Adventure](https:\u002F\u002Fdocs.advntr.dev\u002F) natively for all text. No legacy chat colors.\nUse `Component` builders for code-owned messages and MiniMessage for config-driven\nmessages. Avoid legacy `ChatColor` unless the target project already depends on it\nfor compatibility.\n\nSee `references\u002Fruntime-patterns.md` for simple messages, hover\u002Fclick events,\nMiniMessage parsing, titles, and action bars.\n\n---\n\n## Configuration (YAML)\n\n### `src\u002Fmain\u002Fresources\u002Fconfig.yml`\n```yaml\n# Default config\nsettings:\n  max-players: 20\n  welcome-message: \"\u003Cgreen>Welcome to the server!\"\n  cooldown-seconds: 30\n\ndatabase:\n  host: localhost\n  port: 3306\n  name: myplugin_db\n```\n\n### Accessing config values\nCall `saveDefaultConfig()` in `onEnable()`, provide explicit defaults when reading\nvalues, and validate config shape before starting long-running tasks.\n\n### Custom config file\nUse custom YAML files only when separating user config from mutable plugin data is\nworth the extra file handling. Keep blocking disk writes off hot event paths.\n\nSee `references\u002Fruntime-patterns.md` for config read\u002Fwrite and custom YAML examples.\n\n---\n\n## Vault Integration (Economy \u002F Permissions)\n\nDeclare Vault as `compileOnly`, soft-depend on it in plugin metadata, and disable\neconomy features cleanly when the service provider is unavailable. Never assume a\nVault-compatible economy plugin is installed just because Vault itself is present.\n\nWhen Vault support is required, add the JitPack repository and\n`compileOnly(\"com.github.MilkBowl:VaultAPI:1.7\")` to the Gradle build.\n\nSee `references\u002Fruntime-patterns.md` for a minimal economy setup and charge example.\n\n---\n\n## Paper-Specific APIs\n\nUse Paper APIs when they remove main-thread blocking or simplify Adventure-native\nbehavior. Keep optional plugin integrations behind presence checks and metadata\nsoft-dependencies.\n\nSee `references\u002Fruntime-patterns.md` for async chunk loading, custom item meta,\nprofile lookup, and protection-plugin integration examples.\n\n---\n\n## Common Tasks Checklist\n\n### Creating a new event listener\n- [ ] Create class implementing `Listener`\n- [ ] Annotate methods with `@EventHandler`\n- [ ] Call `getServer().getPluginManager().registerEvents(listener, plugin)` in `onEnable()`\n- [ ] On cancellable events, add `ignoreCancelled = true` unless you need cancelled events\n\n### Adding a new command\n- [ ] For a Bukkit-compatible plugin, define the command in `plugin.yml`, create a `CommandExecutor`, and register it with `getCommand(\"name\")`\n- [ ] For a Paper-only plugin, register the command through `LifecycleEvents.COMMANDS`; do not add a `commands` field\n\n### Saving plugin data\n- [ ] For simple values: use `config.yml` via `getConfig()` \u002F `saveConfig()`\n- [ ] For per-entity data: use PDC with a `NamespacedKey`\n- [ ] For large datasets: use async scheduler + file I\u002FO or a database\n\n### Scheduling a repeating task\n- [ ] Determine if task needs main thread (use `runTaskTimer`) or is I\u002FO (use `runTaskTimerAsynchronously`)\n- [ ] Store the `BukkitTask` reference so you can cancel in `onDisable()`\n- [ ] Cancel all tasks in `onDisable()` or use `getServer().getScheduler().cancelTasks(plugin)`\n\n---\n\n## Build, Validate, and Run\n\n1. Build the plugin JAR:\n   ```bash\n   .\u002Fgradlew build\n   # Output: build\u002Flibs\u002Fmy-plugin-1.0.0-SNAPSHOT.jar\n   ```\n2. Run the bundled validator to catch config and layout errors:\n   ```bash\n   .\u002Fscripts\u002Fvalidate-plugin-layout.sh --root \u002Fpath\u002Fto\u002Fplugin-project\n   # Strict mode treats warnings as failures:\n   .\u002Fscripts\u002Fvalidate-plugin-layout.sh --root \u002Fpath\u002Fto\u002Fplugin-project --strict\n   ```\n   The validator requires Node and includes its own YAML parser for descriptor checks.\n3. Fix any reported errors and re-run until clean.\n4. Deploy: copy the built JAR to `server\u002Fplugins\u002F` and restart the Paper server.\n   If the real project already applies a Paper dev-server plugin such as `xyz.jpenilla.run-paper`,\n   use that project's documented dev task instead of assuming `.\u002Fgradlew runServer` exists.\n\nThe validator checks:\n- active `plugin.yml` or `paper-plugin.yml` required keys (`name`, `version`, `main`, `api-version`) and repo-supported current `26.\u003Crelease>` or legacy `1.21` \u002F positive `1.21.\u003Cpatch>` values, with warnings for versions newer than the documented examples\n- cross-descriptor metadata consistency when both descriptors are present; `paper-plugin.yml` is selected as active\n- Active main class path exists and extends `JavaPlugin`\n- actual server `\u002Freload` anti-patterns such as `Bukkit.reload()` or dispatching the server reload command\n\n---\n\n## References\n\n- Paper API Javadoc: https:\u002F\u002Fjd.papermc.io\u002Fpaper\u002F\n- Paper plugin descriptor: https:\u002F\u002Fdocs.papermc.io\u002Fpaper\u002Fdev\u002Fplugin-yml\u002F\n- Paper plugins: https:\u002F\u002Fdocs.papermc.io\u002Fpaper\u002Fdev\u002Fgetting-started\u002Fpaper-plugins\u002F\n- Paper Brigadier registration: https:\u002F\u002Fdocs.papermc.io\u002Fpaper\u002Fdev\u002Fcommand-api\u002Fbasics\u002Fregistration\u002F\n- Gradle Java compatibility: https:\u002F\u002Fdocs.gradle.org\u002Fcurrent\u002Fuserguide\u002Fcompatibility.html\n- Adventure (text API): https:\u002F\u002Fdocs.advntr.dev\u002F\n- MiniMessage format: https:\u002F\u002Fdocs.advntr.dev\u002Fminimessage\u002Fformat.html\n- Vault API: https:\u002F\u002Fgithub.com\u002FMilkBowl\u002FVaultAPI\n- Bukkit API Javadoc: https:\u002F\u002Fjavadoc.io\u002Fdoc\u002Forg.bukkit\u002Fbukkit\u002F\n- run-task Gradle plugin: https:\u002F\u002Fgithub.com\u002Fjpenilla\u002Frun-task\n","# Minecraft Plugin Development Skill\n\n## Platform Overview\n\n| Platform | Base API | Notes |\n|----------|----------|-------|\n| **Paper** | Bukkit\u002FSpigot + Paper extensions | Recommended; async chunk loading, Adventure native |\n| **Spigot** | Bukkit + Spigot extensions | Legacy; fewer APIs, slower |\n| **Bukkit** | Base API only | Avoid for new plugins |\n| **Folia** | Paper fork | Region-threaded; requires special scheduler APIs |\n\n> Paper is the recommended target. Paper includes all Bukkit and Spigot APIs plus\n> significant performance improvements and additional APIs.\n\n### Routing Boundaries\n- `Use when`: the target is server-side Paper\u002FBukkit\u002FSpigot plugin behavior with JavaPlugin APIs.\n- `Do not use when`: the task requires client-side installable mods or loader APIs (`minecraft-modding` \u002F `minecraft-multiloader`).\n- `Do not use when`: the task is pure vanilla datapack\u002Fcommand content (`minecraft-datapack` \u002F `minecraft-commands-scripting`).\n\n## Bundled References\n\n- Read `references\u002Fruntime-patterns.md` when the task touches scheduling, Folia support, PDC, Adventure\u002FMiniMessage, YAML config, Vault, or Paper-specific APIs.\n- Read `references\u002Fpaper-plugin-commands.md` for a Paper-only `paper-plugin.yml` project or Brigadier command registration.\n\n---\n\n## Project Setup\n\nThe examples below target current Paper 26.3 and Java 25. For an existing\n1.21.x plugin, preserve its `1.21.x-R0.1-SNAPSHOT` dependency, Java 21\ntoolchain, and matching `api-version` until the project is intentionally ported.\n\n### `settings.gradle.kts`\n```kotlin\nrootProject.name = \"my-plugin\"\n```\n\n### `build.gradle.kts`\n```kotlin\nplugins {\n    java\n}\n\ngroup = \"com.example\"\nversion = \"1.0.0-SNAPSHOT\"\n\nrepositories {\n    mavenCentral()\n    maven(\"https:\u002F\u002Frepo.papermc.io\u002Frepository\u002Fmaven-public\u002F\")\n}\n\ndependencies {\n    compileOnly(\"io.papermc.paper:paper-api:26.3.build.+\")\n}\n\njava {\n    toolchain.languageVersion.set(JavaLanguageVersion.of(25))\n}\n\ntasks {\n    processResources {\n        \u002F\u002F Substitutes ${version} in plugin.yml with the Gradle project version\n        filesMatching(listOf(\"plugin.yml\", \"paper-plugin.yml\")) {\n            expand(\"version\" to project.version)\n        }\n    }\n}\n```\n\nAdd Shadow only when the plugin has runtime libraries that must be bundled and\nrelocated. Paper and optional plugin APIs such as Vault remain `compileOnly` and\nmust not be shaded into the plugin JAR.\n\n### `gradle\u002Fwrapper\u002Fgradle-wrapper.properties`\n```properties\ndistributionUrl=https\\:\u002F\u002Fservices.gradle.org\u002Fdistributions\u002Fgradle-9.1.0-bin.zip\n```\n\nGradle 8.8 cannot run on Java 25. Use Gradle 9.1 or newer for a current Java 25\nproject. Preserve the existing wrapper and Java 21 toolchain for a legacy 1.21.x\nproject unless its build is intentionally upgraded and verified.\n\n---\n\n## Project Layout\n```\nmy-plugin\u002F\n├── build.gradle.kts\n├── settings.gradle.kts\n├── gradle\u002F\n│   └── wrapper\u002F\n│       └── gradle-wrapper.properties\n└── src\u002Fmain\u002F\n    ├── java\u002Fcom\u002Fexample\u002Fmyplugin\u002F\n    │   ├── MyPlugin.java          ← main class (extends JavaPlugin)\n    │   ├── listeners\u002F\n    │   │   └── PlayerListener.java\n    │   ├── commands\u002F\n    │   │   └── MyCommand.java\n    │   └── managers\u002F\n    │       └── DataManager.java\n    └── resources\u002F\n        ├── plugin.yml            ← Bukkit-compatible descriptor\n        ├── paper-plugin.yml      ← active descriptor for a Paper plugin\n        └── config.yml\n```\n\n---\n\n## Core Files\n\n### `plugin.yml` (Bukkit-compatible default)\n```yaml\nname: MyPlugin\nversion: \"${version}\"\nmain: com.example.myplugin.MyPlugin\ndescription: An example Paper plugin\nauthor: YourName\nwebsite: https:\u002F\u002Fgithub.com\u002Fexample\u002Fmy-plugin\napi-version: '26.3'\n\ncommands:\n  myplugin:\n    description: Main plugin command\n    usage: \u002Fmyplugin \u003Csubcommand>\n    permission: myplugin.use\n    aliases: [mp]\n\npermissions:\n  myplugin.use:\n    description: Allows use of \u002Fmyplugin\n    default: true\n  myplugin.admin:\n    description: Admin access\n    default: op\n```\n\n> Match `api-version` to the oldest Paper API the plugin intentionally supports.\n> Current Paper examples use `26.3`; legacy `1.21` and positive `1.21.\u003Cpatch>`\n> values remain valid for older servers. A server older than the declared value\n> refuses to load the plugin.\n\n### `paper-plugin.yml` (experimental Paper-only format)\n\nPrefer `plugin.yml` for Bukkit-compatible plugins. Use `paper-plugin.yml` only\nwhen the JAR is intentionally Paper-only and needs Paper-plugin behavior such\nas bootstrapping, loaders, or classloading isolation. It can be the only\ndescriptor, but is not a drop-in replacement: Paper plugins do not use a\n`commands` field or `getCommand(...)` registration. Read\n[`references\u002Fpaper-plugin-commands.md`](references\u002Fpaper-plugin-commands.md)\nfor the paired descriptor, main class, and Brigadier lifecycle registration.\n\nWhen one JAR ships both descriptors, keep their shared metadata and main class\naligned. Do not combine the Paper-only sample with the Bukkit-compatible\n`MyPlugin` sample below.\n\n### Bukkit-compatible main class\n```java\npackage com.example.myplugin;\n\nimport com.example.myplugin.commands.MyCommand;\nimport com.example.myplugin.listeners.PlayerListener;\nimport org.bukkit.plugin.java.JavaPlugin;\n\npublic final class MyPlugin extends JavaPlugin {\n\n    @Override\n    public void onEnable() {\n        saveDefaultConfig();\n\n        \u002F\u002F Register listeners\n        getServer().getPluginManager().registerEvents(new PlayerListener(), this);\n\n        \u002F\u002F Register commands\n        var cmd = getCommand(\"myplugin\");\n        if (cmd == null) {\n            throw new IllegalStateException(\"myplugin command is missing from plugin.yml\");\n        }\n        var handler = new MyCommand(this);\n        cmd.setExecutor(handler);\n        cmd.setTabCompleter(handler);\n\n        getLogger().info(\"MyPlugin enabled!\");\n    }\n\n    @Override\n    public void onDisable() {\n        getLogger().info(\"MyPlugin disabled.\");\n    }\n\n}\n```\n\n---\n\n## Event Listeners\n\n```java\npackage com.example.myplugin.listeners;\n\nimport net.kyori.adventure.text.Component;\nimport net.kyori.adventure.text.format.NamedTextColor;\nimport org.bukkit.event.EventHandler;\nimport org.bukkit.event.EventPriority;\nimport org.bukkit.event.Listener;\nimport org.bukkit.event.entity.PlayerDeathEvent;\nimport org.bukkit.event.player.PlayerJoinEvent;\nimport org.bukkit.event.player.PlayerQuitEvent;\n\npublic class PlayerListener implements Listener {\n\n    @EventHandler(priority = EventPriority.NORMAL)\n    public void onPlayerJoin(PlayerJoinEvent event) {\n        event.joinMessage(\n            Component.text(event.getPlayer().getName() + \" joined!\", NamedTextColor.GREEN)\n        );\n    }\n\n    @EventHandler\n    public void onPlayerQuit(PlayerQuitEvent event) {\n        event.quitMessage(\n            Component.text(event.getPlayer().getName() + \" left.\", NamedTextColor.YELLOW)\n        );\n    }\n\n    @EventHandler\n    public void onPlayerDeath(PlayerDeathEvent event) {\n        \u002F\u002F Modify death message using Adventure components\n        event.deathMessage(\n            Component.text(\"☠ \", NamedTextColor.RED)\n                .append(Component.text(event.getPlayer().getName(), NamedTextColor.WHITE))\n                .append(Component.text(\" died!\", NamedTextColor.RED))\n        );\n    }\n}\n```\n\n### EventPriority order\n`LOWEST → LOW → NORMAL → HIGH → HIGHEST → MONITOR`  \nUse `MONITOR` for logging only (never modify outcome). On events that implement\n`Cancellable`, use `ignoreCancelled = true` unless you need cancelled events.\n\n### Cancellable events\n```java\n@EventHandler\npublic void onBlockBreak(BlockBreakEvent event) {\n    if (event.getPlayer().hasPermission(\"myplugin.break.deny\")) {\n        event.setCancelled(true);\n        event.getPlayer().sendMessage(Component.text(\"You cannot break blocks!\", NamedTextColor.RED));\n    }\n}\n```\n\n---\n\n## Commands\n\nThis section is for the `plugin.yml` path above. Its declared command enables\n`getCommand(\"myplugin\")`. For a Paper-only descriptor, use the Brigadier\nlifecycle example in [`references\u002Fpaper-plugin-commands.md`](references\u002Fpaper-plugin-commands.md).\n\n```java\npackage com.example.myplugin.commands;\n\nimport com.example.myplugin.MyPlugin;\nimport net.kyori.adventure.text.Component;\nimport net.kyori.adventure.text.format.NamedTextColor;\nimport org.bukkit.command.Command;\nimport org.bukkit.command.CommandExecutor;\nimport org.bukkit.command.CommandSender;\nimport org.bukkit.command.TabCompleter;\nimport org.bukkit.entity.Player;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.util.List;\nimport java.util.Locale;\n\npublic class MyCommand implements CommandExecutor, TabCompleter {\n\n    private final MyPlugin plugin;\n\n    public MyCommand(MyPlugin plugin) {\n        this.plugin = plugin;\n    }\n\n    @Override\n    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command,\n                             @NotNull String label, @NotNull String[] args) {\n        if (!(sender instanceof Player player)) {\n            sender.sendMessage(Component.text(\"Only players can use this command.\", NamedTextColor.RED));\n            return true;\n        }\n\n        if (!player.hasPermission(\"myplugin.use\")) {\n            player.sendMessage(Component.text(\"No permission.\", NamedTextColor.RED));\n            return true;\n        }\n\n        if (args.length == 0) {\n            player.sendMessage(Component.text(\"Usage: \u002Fmyplugin \u003Creload|info>\", NamedTextColor.YELLOW));\n            return true;\n        }\n\n        return switch (args[0].toLowerCase(Locale.ROOT)) {\n            case \"reload\" -> {\n                if (!player.hasPermission(\"myplugin.admin\")) {\n                    player.sendMessage(Component.text(\"No permission.\", NamedTextColor.RED));\n                    yield true;\n                }\n                plugin.reloadConfig();\n                player.sendMessage(Component.text(\"Config reloaded.\", NamedTextColor.GREEN));\n                yield true;\n            }\n            case \"info\" -> {\n                player.sendMessage(Component.text(\"Version: \" + plugin.getDescription().getVersion(), NamedTextColor.AQUA));\n                yield true;\n            }\n            default -> {\n                player.sendMessage(Component.text(\"Unknown subcommand.\", NamedTextColor.RED));\n                yield true;\n            }\n        };\n    }\n\n    @Override\n    public @Nullable List\u003CString> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,\n                                                @NotNull String label, @NotNull String[] args) {\n        if (!sender.hasPermission(\"myplugin.use\")) return List.of();\n        if (args.length == 1) {\n            var subcommands = sender.hasPermission(\"myplugin.admin\")\n                ? List.of(\"reload\", \"info\") : List.of(\"info\");\n            return subcommands.stream()\n                .filter(s -> s.startsWith(args[0].toLowerCase(Locale.ROOT)))\n                .toList();\n        }\n        return List.of();\n    }\n}\n```\n\n---\n\n## Schedulers\n\nFor classic Paper plugins, `BukkitScheduler` is still fine. If you claim Folia support,\nroute player, entity, region, global, and async work through the matching Folia-aware\nscheduler. Keep scheduling behind a small project-local interface when one plugin must\nsupport both Paper and Folia.\n\nSee `references\u002Fruntime-patterns.md` for copy-ready sync, async, cancelable, and\nFolia-safe scheduler examples.\n\n---\n\n## Persistent Data Container (PDC)\n\nPDC stores arbitrary data on any `PersistentDataHolder` (players, entities, items, chunks).\nData is saved with the world and persists across restarts.\n\nCreate `NamespacedKey` instances once, keep data types stable after release, and use\nPDC for small metadata rather than large datasets. Prefer config files or a database\nfor large or query-heavy plugin state.\n\nSee `references\u002Fruntime-patterns.md` for player, item, chunk, and world PDC examples.\n\n---\n\n## Adventure Text Components\n\nPaper uses [Adventure](https:\u002F\u002Fdocs.advntr.dev\u002F) natively for all text. No legacy chat colors.\nUse `Component` builders for code-owned messages and MiniMessage for config-driven\nmessages. Avoid legacy `ChatColor` unless the target project already depends on it\nfor compatibility.\n\nSee `references\u002Fruntime-patterns.md` for simple messages, hover\u002Fclick events,\nMiniMessage parsing, titles, and action bars.\n\n---\n\n## Configuration (YAML)\n\n### `src\u002Fmain\u002Fresources\u002Fconfig.yml`\n```yaml\n# Default config\nsettings:\n  max-players: 20\n  welcome-message: \"\u003Cgreen>Welcome to the server!\"\n  cooldown-seconds: 30\n\ndatabase:\n  host: localhost\n  port: 3306\n  name: myplugin_db\n```\n\n### Accessing config values\nCall `saveDefaultConfig()` in `onEnable()`, provide explicit defaults when reading\nvalues, and validate config shape before starting long-running tasks.\n\n### Custom config file\nUse custom YAML files only when separating user config from mutable plugin data is\nworth the extra file handling. Keep blocking disk writes off hot event paths.\n\nSee `references\u002Fruntime-patterns.md` for config read\u002Fwrite and custom YAML examples.\n\n---\n\n## Vault Integration (Economy \u002F Permissions)\n\nDeclare Vault as `compileOnly`, soft-depend on it in plugin metadata, and disable\neconomy features cleanly when the service provider is unavailable. Never assume a\nVault-compatible economy plugin is installed just because Vault itself is present.\n\nWhen Vault support is required, add the JitPack repository and\n`compileOnly(\"com.github.MilkBowl:VaultAPI:1.7\")` to the Gradle build.\n\nSee `references\u002Fruntime-patterns.md` for a minimal economy setup and charge example.\n\n---\n\n## Paper-Specific APIs\n\nUse Paper APIs when they remove main-thread blocking or simplify Adventure-native\nbehavior. Keep optional plugin integrations behind presence checks and metadata\nsoft-dependencies.\n\nSee `references\u002Fruntime-patterns.md` for async chunk loading, custom item meta,\nprofile lookup, and protection-plugin integration examples.\n\n---\n\n## Common Tasks Checklist\n\n### Creating a new event listener\n- [ ] Create class implementing `Listener`\n- [ ] Annotate methods with `@EventHandler`\n- [ ] Call `getServer().getPluginManager().registerEvents(listener, plugin)` in `onEnable()`\n- [ ] On cancellable events, add `ignoreCancelled = true` unless you need cancelled events\n\n### Adding a new command\n- [ ] For a Bukkit-compatible plugin, define the command in `plugin.yml`, create a `CommandExecutor`, and register it with `getCommand(\"name\")`\n- [ ] For a Paper-only plugin, register the command through `LifecycleEvents.COMMANDS`; do not add a `commands` field\n\n### Saving plugin data\n- [ ] For simple values: use `config.yml` via `getConfig()` \u002F `saveConfig()`\n- [ ] For per-entity data: use PDC with a `NamespacedKey`\n- [ ] For large datasets: use async scheduler + file I\u002FO or a database\n\n### Scheduling a repeating task\n- [ ] Determine if task needs main thread (use `runTaskTimer`) or is I\u002FO (use `runTaskTimerAsynchronously`)\n- [ ] Store the `BukkitTask` reference so you can cancel in `onDisable()`\n- [ ] Cancel all tasks in `onDisable()` or use `getServer().getScheduler().cancelTasks(plugin)`\n\n---\n\n## Build, Validate, and Run\n\n1. Build the plugin JAR:\n   ```bash\n   .\u002Fgradlew build\n   # Output: build\u002Flibs\u002Fmy-plugin-1.0.0-SNAPSHOT.jar\n   ```\n2. Run the bundled validator to catch config and layout errors:\n   ```bash\n   .\u002Fscripts\u002Fvalidate-plugin-layout.sh --root \u002Fpath\u002Fto\u002Fplugin-project\n   # Strict mode treats warnings as failures:\n   .\u002Fscripts\u002Fvalidate-plugin-layout.sh --root \u002Fpath\u002Fto\u002Fplugin-project --strict\n   ```\n   The validator requires Node and includes its own YAML parser for descriptor checks.\n3. Fix any reported errors and re-run until clean.\n4. Deploy: copy the built JAR to `server\u002Fplugins\u002F` and restart the Paper server.\n   If the real project already applies a Paper dev-server plugin such as `xyz.jpenilla.run-paper`,\n   use that project's documented dev task instead of assuming `.\u002Fgradlew runServer` exists.\n\nThe validator checks:\n- active `plugin.yml` or `paper-plugin.yml` required keys (`name`, `version`, `main`, `api-version`) and repo-supported current `26.\u003Crelease>` or legacy `1.21` \u002F positive `1.21.\u003Cpatch>` values, with warnings for versions newer than the documented examples\n- cross-descriptor metadata consistency when both descriptors are present; `paper-plugin.yml` is selected as active\n- Active main class path exists and extends `JavaPlugin`\n- actual server `\u002Freload` anti-patterns such as `Bukkit.reload()` or dispatching the server reload command\n\n---\n\n## References\n\n- Paper API Javadoc: https:\u002F\u002Fjd.papermc.io\u002Fpaper\u002F\n- Paper plugin descriptor: https:\u002F\u002Fdocs.papermc.io\u002Fpaper\u002Fdev\u002Fplugin-yml\u002F\n- Paper plugins: https:\u002F\u002Fdocs.papermc.io\u002Fpaper\u002Fdev\u002Fgetting-started\u002Fpaper-plugins\u002F\n- Paper Brigadier registration: https:\u002F\u002Fdocs.papermc.io\u002Fpaper\u002Fdev\u002Fcommand-api\u002Fbasics\u002Fregistration\u002F\n- Gradle Java compatibility: https:\u002F\u002Fdocs.gradle.org\u002Fcurrent\u002Fuserguide\u002Fcompatibility.html\n- Adventure (text API): https:\u002F\u002Fdocs.advntr.dev\u002F\n- MiniMessage format: https:\u002F\u002Fdocs.advntr.dev\u002Fminimessage\u002Fformat.html\n- Vault API: https:\u002F\u002Fgithub.com\u002FMilkBowl\u002FVaultAPI\n- Bukkit API Javadoc: https:\u002F\u002Fjavadoc.io\u002Fdoc\u002Forg.bukkit\u002Fbukkit\u002F\n- run-task Gradle plugin: https:\u002F\u002Fgithub.com\u002Fjpenilla\u002Frun-task\n",{"name":5,"description":7},"main","22d61ce6b7a0c5f215008824aa6b94ecc73f2a43",".agents\u002Fskills\u002Fminecraft-plugin-dev",11,"https:\u002F\u002Fgithub.com\u002FJahrome907\u002Fminecraft-agent-skills","https:\u002F\u002Fgithub.com\u002FJahrome907","joe-o.com","Product engineer building field tools, workflow automation, and polished web applications.","2026-10-30 08:19:45",{"source":8,"skillName":5,"commands":55,"prompt":65,"zipAvailable":66},[56,59,62],{"tool":57,"command":58},"npx","npx skills add Jahrome907\u002Fminecraft-agent-skills --skill minecraft-plugin-dev",{"tool":60,"command":61},"bunx","bunx skills add Jahrome907\u002Fminecraft-agent-skills --skill minecraft-plugin-dev",{"tool":63,"command":64},"pnpm","pnpm dlx skills add Jahrome907\u002Fminecraft-agent-skills --skill minecraft-plugin-dev","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FJahrome907\u002Fminecraft-agent-skills\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fminecraft-plugin-dev\u002FSKILL.md",true,[68,74,78,82],{"path":69,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":72,"sourceHtmlUrl":73},"references\u002Fexamples.md","REFERENCE","参考文档",22722,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fskills\u002Fblob\u002Fmain\u002F.github\u002Fplugins\u002Fazure-sdk-java\u002Fskills\u002Fazure-ai-agents-persistent-java\u002Freferences\u002Fexamples.md",{"path":75,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":76,"sourceHtmlUrl":77},"references\u002Fpaper-plugin-commands.md",2655,"https:\u002F\u002Fgithub.com\u002FJahrome907\u002Fminecraft-agent-skills\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fminecraft-plugin-dev\u002Freferences\u002Fpaper-plugin-commands.md",{"path":79,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":80,"sourceHtmlUrl":81},"references\u002Fruntime-patterns.md",7845,"https:\u002F\u002Fgithub.com\u002FJahrome907\u002Fminecraft-agent-skills\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fminecraft-plugin-dev\u002Freferences\u002Fruntime-patterns.md",{"path":83,"resourceType":84,"resourceTypeDesc":85,"sizeBytes":86,"sourceHtmlUrl":87},"scripts\u002Fvalidate-plugin-layout.sh","SCRIPT","脚本",11085,"https:\u002F\u002Fgithub.com\u002FJahrome907\u002Fminecraft-agent-skills\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fminecraft-plugin-dev\u002Fscripts\u002Fvalidate-plugin-layout.sh",[89,105,110,120,128,135],{"skillNo":90,"name":91,"nameZh":6,"description":92,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":93,"categories":94,"keywords":95,"publishedAt":40},"01M6D2TV8CBAMB70CEC19VMVX5","minecraft-ci-release","Fixture with valid workflow YAML and a warning-only glob pattern.","https:\u002F\u002Fgithub.com\u002FJahrome907\u002Fminecraft-agent-skills\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fvalidators\u002Fci-release\u002Fwarn-only\u002FSKILL.md",[],[96,26,97,98,99,100,101,102,103,104],"minecraft ci release","ci","release","fixture","pattern","only","yaml","workflow","valid",{"skillNo":106,"name":104,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":107,"categories":108,"keywords":109,"publishedAt":40},"01M6D2TR1N9TNJPTRB66WDCY8X","https:\u002F\u002Fgithub.com\u002FJahrome907\u002Fminecraft-agent-skills\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fvalidators\u002Fci-release\u002Fvalid\u002FSKILL.md",[],[104],{"skillNo":111,"name":91,"nameZh":6,"description":112,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":113,"categories":114,"keywords":118,"publishedAt":40},"01M6D2TNBM97CCTYFCDKCFQ4AR","Fixture for a secretless workflow that passes strict validation.","https:\u002F\u002Fgithub.com\u002FJahrome907\u002Fminecraft-agent-skills\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fvalidators\u002Fci-release\u002Fsecretless-strict\u002FSKILL.md",[115],{"categoryNo":116,"categoryName":117,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[96,26,97,98,99,119,103],"validation",{"skillNo":121,"name":122,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":123,"categories":124,"keywords":126,"publishedAt":40},"01M6D2TJ9FX4FH1TMGKQPYNZQX","non-workflow-yaml","https:\u002F\u002Fgithub.com\u002FJahrome907\u002Fminecraft-agent-skills\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fvalidators\u002Fci-release\u002Fnon-workflow-yaml\u002FSKILL.md",[125],{"categoryNo":116,"categoryName":117,"taxonomyType":21,"taxonomyTypeDesc":22},[127,102,103],"non workflow yaml",{"skillNo":129,"name":91,"nameZh":6,"description":130,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":131,"categories":132,"keywords":133,"publishedAt":40},"01M6D2TFE807BSXTEREYPWFY3G","Fixture with a mutable remote action reference.","https:\u002F\u002Fgithub.com\u002FJahrome907\u002Fminecraft-agent-skills\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fvalidators\u002Fci-release\u002Fmutable-action\u002FSKILL.md",[],[96,26,97,98,134,99],"reference",{"skillNo":136,"name":91,"nameZh":6,"description":137,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":138,"categories":139,"keywords":140,"publishedAt":40},"01M6D2TBYJ0SM3B79908DH9ECE","Fixture with valid multiline flow collections in workflow YAML.","https:\u002F\u002Fgithub.com\u002FJahrome907\u002Fminecraft-agent-skills\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fvalidators\u002Fci-release\u002Fmultiline-flow\u002FSKILL.md",[],[96,98,26,97,103,102,141,99,142,104],"flow","collections"]