Skip to content

Commit d3b53f9

Browse files
author
arch
authored
docs: Revise documentation, move to agents standard (with Claude support) (#385)
* docs: split Claude template guidance ADDED - Fill-template skill with customization checklist CHANGED - Move build and test command guidance into run-plugin skill CHANGED - Keep CLAUDE.md focused on architecture and versioning * docs: add agent workflow guidance * docs: update Claude agent instructions * chore: remove Claude skill shims * docs: simplify fill template skill heading * docs: fix mistaken header * docs: slightly reorganize AGENTS.md * docs: update Claude skill setup guidance * docs: Instruction change * docs: update CLAUDE.md to reflect current status * docs: revise some comments in build.gradle.kts * docs: remove invisible text * docs: revise Discord integration doc formatting * docs: revise customization.md formatting * docs: use ellipses when quoting whole build script is unneccessary * docs: revise version map example * docs: replace 'repo' with 'plugin' in documentation * chore(docs): fix missing changes after merging skills-and-claudemd * docs: add additional README customization guidance * docs: new skill maintenance skill * docs: remove Claude-specific maintenance instructions * chore(docs): allow .claude folder to coexist * chore(docs): add .claude as clone of .agents
1 parent 30ec6d8 commit d3b53f9

12 files changed

Lines changed: 221 additions & 171 deletions

File tree

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
name: fill-template-plugin
3+
description: Customize this PaperMC/Spigot plugin template for a real plugin. Use when asked to fill in, adapt, rename, fork, or customize the template project.
4+
---
5+
6+
If information required in the checklist below is missing, end your turn and ask for it before editing.
7+
8+
# Template Customization Checklist
9+
10+
When adapting this template for a real plugin, update:
11+
1. `settings.gradle.kts``rootProject.name`
12+
2. `build.gradle.kts``group` (Java package)
13+
3. `src/main/resources/plugin.yml``author`, `description`, `permissions`
14+
4. Rename the Java package and source directory from `com.crimsonwarpedcraft.exampleplugin`
15+
5. `.github/CODEOWNERS`, `.github/FUNDING.yml` — replace `leviem1`
16+
6. `CODE_OF_CONDUCT.md` line 63 — contact method
17+
7. README badges and Discord invite link

.agents/skills/run-plugin/SKILL.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
name: run-plugin
3+
description: Build, test, and release this PaperMC/Spigot plugin from source. Use when asked to build the plugin, run its tests, run a single test class, or produce a release JAR.
4+
---
5+
6+
This is a PaperMC/Spigot plugin — "running" it means building from source, executing the test
7+
suite, and optionally producing the shaded JAR that gets dropped into a server's `plugins/`
8+
folder.
9+
10+
## Commands
11+
12+
**OneDrive locking**: If the project resides in OneDrive, the build fails with `Unable to delete directory '...\build\test-results\test\binary'`, delete that directory manually before retrying — OneDrive holds a sync lock on it.
13+
14+
```bash
15+
# Build (runs Checkstyle, SpotBugs, and tests)
16+
./gradlew build
17+
```
18+
19+
### Testing
20+
21+
```bash
22+
# Run tests only
23+
./gradlew test
24+
25+
# Run a single test class
26+
./gradlew test --tests "com.example.plugin.command.PingTest"
27+
28+
# Run a single test method
29+
./gradlew test --tests "com.example.plugin.command.GreetTest.greetsTarget"
30+
```
31+
32+
Checkstyle enforces Google Java style with `maxWarnings = 0` — the build fails on any warning. SpotBugs runs FindSecBugs. Both run as part of `build`; fix all findings before committing.
33+
34+
Command executor unit tests (`Ping`, `Greet`, etc.) use Mockito directly — mock `CommandArguments` and `CommandSender`/`Player`, then call `run()`. No server or plugin lifecycle needed. Mockito must be declared explicitly as `testImplementation 'org.mockito:mockito-core:...'` — it is not provided transitively.
35+
36+
## Release JAR
37+
38+
```bash
39+
./gradlew -Pver="v1.0.0" release
40+
# → build/libs/<project-name>.jar (version stripped from filename for stable tags)
41+
```
42+
43+
Versioning logic (`build.gradle.kts`):
44+
- No `-Pver``yyMMdd-HHmm-SNAPSHOT`
45+
- `-Pver=vX.Y.Z-RC-N``X.Y.Z-SNAPSHOT`
46+
- `-Pver=vX.Y.Z``X.Y.Z` (stable; the `release` task then renames the shadow jar to
47+
`${rootProject.name}.jar`)
48+
49+
Quote the `-Pver` value to stop the shell/PowerShell from mangling the `=`.
50+
51+
## Maintenance
52+
53+
After adding a dependency, check whether `shadowJar` in `build.gradle.kts` needs a new
54+
`relocate(...)` entry (to avoid classloader clashes with other plugins on the same server) and
55+
a `minimize { exclude(...) }` entry — see the first Gotcha below for why this matters.
56+
57+
Keep these in sync with the current state of the project:
58+
59+
- **`AGENTS.md`** — architecture, versioning logic
60+
- **`.agents/skills/fill-template-plugin/SKILL.md`** — customization checklist
61+
- **`README.md`**, **`docs/usage.md`**, **`docs/customization.md`**, **`docs/releases.md`**
62+
feature list, extension recipes, fork checklist, PaperMC version mapping
63+
- **`.agents/skills/run-plugin/SKILL.md`** (this file) — build commands, release
64+
process, shaded package list
65+
66+
## Gotchas
67+
68+
- **`minimize()` silently strips reflection/SPI-only dependencies**`shadowJar`'s `minimize()`
69+
only treats a dependency as "used" if *this project's own compiled classes* reference it
70+
directly. A library only referenced from inside an already-`exclude`d dependency (e.g.
71+
cw-commons calling into a JDBC/driver library) looks unused and gets stripped down to empty
72+
`package-info.class` stubs, causing `NoClassDefFoundError` at runtime even though the build
73+
succeeds. Add an `exclude(dependency("group:artifact:.*"))` entry under `minimize` for any
74+
such dependency, mirroring the existing `cw-commons` entry (which works around the same
75+
problem for its bundled SQLite driver).
76+
- **OneDrive build lock** — if this repo lives under OneDrive, `./gradlew build` can fail with
77+
`Unable to delete directory '...\build\classes\java\main'` (or `...\test\binary`, or other
78+
`build/` subdirectories) because OneDrive holds a sync lock on it. Delete the offending
79+
directory manually (e.g. `rm -rf build/classes/java/main`) and retry.
80+
- **Commands declared in both `plugin.yml` and `onEnable()`** — CommandAPI registers commands
81+
programmatically; don't add a matching `commands:` entry to `plugin.yml` or Bukkit
82+
double-registers it, which CommandAPI flags at startup with a warning.
83+
- **Mockito javaagent**`mockito-core` is wired into a dedicated `mockitoAgent` configuration
84+
and attached via `-javaagent` in `tasks.test` to avoid the inline-mock-maker self-attach
85+
warning. Don't drop this wiring when customizing the template, and remember Mockito must stay
86+
declared explicitly as `testImplementation` — it isn't provided transitively.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
name: update-local-skills
3+
description: Update this repo's agent skills. Use when asked to sync, mirror, refresh, or add skills for this project.
4+
---
5+
6+
This repo keeps local skills in two agent-specific locations:
7+
8+
- `.agents/skills/` is the source of truth for shared skills.
9+
- `.claude/skills/` mirrors the same skill folders for Claude-compatible local use.
10+
11+
## Workflow
12+
13+
1. Inspect both trees before changing files.
14+
2. Make the requested skill change in `.agents/skills/<skill-name>/SKILL.md` first.
15+
3. `cp SKILL.md` to `.claude/skills/<skill-name>/SKILL.md`.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
name: fill-template-plugin
3+
description: Customize this PaperMC/Spigot plugin template for a real plugin. Use when asked to fill in, adapt, rename, fork, or customize the template project.
4+
---
5+
6+
If information required in the checklist below is missing, end your turn and ask for it before editing.
7+
8+
# Template Customization Checklist
9+
10+
When adapting this template for a real plugin, update:
11+
1. `settings.gradle.kts``rootProject.name`
12+
2. `build.gradle.kts``group` (Java package)
13+
3. `src/main/resources/plugin.yml``author`, `description`, `permissions`
14+
4. Rename the Java package and source directory from `com.crimsonwarpedcraft.exampleplugin`
15+
5. `.github/CODEOWNERS`, `.github/FUNDING.yml` — replace `leviem1`
16+
6. `CODE_OF_CONDUCT.md` line 63 — contact method
17+
7. README badges and Discord invite link

.claude/skills/run-plugin/SKILL.md

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,32 @@ This is a PaperMC/Spigot plugin — "running" it means building from source, exe
77
suite, and optionally producing the shaded JAR that gets dropped into a server's `plugins/`
88
folder.
99

10-
## Build
10+
## Commands
11+
12+
**OneDrive locking**: If the project resides in OneDrive, the build fails with `Unable to delete directory '...\build\test-results\test\binary'`, delete that directory manually before retrying — OneDrive holds a sync lock on it.
1113

1214
```bash
13-
./gradlew build # macOS / Linux / Git Bash
14-
gradlew.bat build # Windows cmd/PowerShell
15+
# Build (runs Checkstyle, SpotBugs, and tests)
16+
./gradlew build
1517
```
1618

17-
Runs compilation, Checkstyle (Google Java Style, `maxWarnings = 0`), SpotBugs with FindSecBugs,
18-
and all tests. Fix every warning — the build fails on the first one.
19-
20-
## Verify
19+
### Testing
2120

2221
```bash
22+
# Run tests only
2323
./gradlew test
24-
```
2524

26-
All tests pass. Subset by class:
27-
28-
```bash
25+
# Run a single test class
2926
./gradlew test --tests "com.example.plugin.command.PingTest"
30-
```
31-
32-
Subset by method:
3327

34-
```bash
28+
# Run a single test method
3529
./gradlew test --tests "com.example.plugin.command.GreetTest.greetsTarget"
3630
```
3731

32+
Checkstyle enforces Google Java style with `maxWarnings = 0` — the build fails on any warning. SpotBugs runs FindSecBugs. Both run as part of `build`; fix all findings before committing.
33+
34+
Command executor unit tests (`Ping`, `Greet`, etc.) use Mockito directly — mock `CommandArguments` and `CommandSender`/`Player`, then call `run()`. No server or plugin lifecycle needed. Mockito must be declared explicitly as `testImplementation 'org.mockito:mockito-core:...'` — it is not provided transitively.
35+
3836
## Release JAR
3937

4038
```bash
@@ -58,10 +56,11 @@ a `minimize { exclude(...) }` entry — see the first Gotcha below for why this
5856

5957
Keep these in sync with the current state of the project:
6058

61-
- **`CLAUDE.md`** — architecture, versioning logic, customization checklist
59+
- **`AGENTS.md`** — architecture, versioning logic
60+
- **`.agents/skills/fill-template-plugin/SKILL.md`** — customization checklist
6261
- **`README.md`**, **`docs/usage.md`**, **`docs/customization.md`**, **`docs/releases.md`**
6362
feature list, extension recipes, fork checklist, PaperMC version mapping
64-
- **`.claude/skills/run-plugin/SKILL.md`** (this file) — build commands, release
63+
- **`.agents/skills/run-plugin/SKILL.md`** (this file) — build commands, release
6564
process, shaded package list
6665

6766
## Gotchas
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
name: update-local-skills
3+
description: Update this repo's agent skills. Use when asked to sync, mirror, refresh, or add skills for this project.
4+
---
5+
6+
This repo keeps local skills in two agent-specific locations:
7+
8+
- `.agents/skills/` is the source of truth for shared skills.
9+
- `.claude/skills/` mirrors the same skill folders for Claude-compatible local use.
10+
11+
## Workflow
12+
13+
1. Inspect both trees before changing files.
14+
2. Make the requested skill change in `.agents/skills/<skill-name>/SKILL.md` first.
15+
3. `cp SKILL.md` to `.claude/skills/<skill-name>/SKILL.md`.

AGENTS.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
This is a **PaperMC/Spigot Minecraft plugin template**. The intent is that users fork/copy it and replace the example scaffolding with their own plugin.
2+
3+
## Architecture
4+
5+
**Entry point**: `ExamplePlugin extends JavaPlugin` — Bukkit/Paper calls `onEnable()` and `onDisable()` on the plugin lifecycle. The main class is referenced in `plugin.yml` via the `${PACKAGE}.${NAME}` substitution, which is filled at build time by `processResources` from `group` (build.gradle.kts) and `rootProject.name` (settings.gradle.kts).
6+
7+
**JAR packaging**: The standard `jar` task is disabled. `shadowJar` is the sole output — it shades CommandAPI (relocated to `<group>.commandapi`). CommandAPI is excluded from `minimize()` because it loads classes via reflection. `assemble` depends on `shadowJar`.
8+
9+
**cw-commons dependency**: `Command`/`BaseCommand` (command registration) and `Config`/`ConfigManager` (YAML config loading + Jakarta validation) come from [cw-commons](https://github.com/CrimsonWarpedcraft/cw-commons), not local code — consumed via JitPack (`com.github.CrimsonWarpedcraft:cw-commons`). `build.gradle.kts` pins a tagged release (e.g. `v0.1.0`) rather than the unstable `main-SNAPSHOT`; bump that tag deliberately. Jackson and Hibernate Validator remain direct dependencies here because `PluginConfig` uses their annotations (`@JsonProperty`, `@NotBlank`) directly — cw-commons exposes them as `api` (transitive, unbundled) dependencies specifically so each consumer shades/relocates its own copy without classloader conflicts. Note that cw-commons' `api` deps already put Jackson/Hibernate Validator on this project's classpath transitively, so the explicit declarations here are redundant for resolution — kept anyway since `PluginConfig` references them directly and shouldn't rely on another project's transitive exposure choices.
10+
11+
**Command declaration**: CommandAPI registers commands programmatically in `onEnable()` (see `ExampleCommand`/`BaseCommand`). Adding a matching entry under `commands:` in `plugin.yml` makes Bukkit register the same command a second time, which CommandAPI flags at startup with a "Plugin command ... is registered by Bukkit" warning. `permissions:` entries are unaffected and still required.
12+
13+
**Versioning logic** (in `build.gradle.kts`):
14+
- No `-Pver` supplied → `yyMMdd-HHmm-SNAPSHOT`
15+
- `-Pver=vX.Y.Z-RC-N``X.Y.Z-SNAPSHOT`
16+
- `-Pver=vX.Y.Z``X.Y.Z` (stable release)
17+
18+
**CI workflows** (`.github/workflows/`):
19+
- `pr.yml` — builds and tests on Ubuntu + Windows for PRs and merge queue
20+
- `main.yml` — builds, tests, and cuts a snapshot release on push to `main`
21+
- `tag.yml` / `release.yml` — handle tagged releases and Discord notifications

CLAUDE.md

Lines changed: 1 addition & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,2 @@
1-
# CLAUDE.md
21

3-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4-
5-
## Commands
6-
7-
**OneDrive locking**: If the project resides in OneDrive, the build fails with `Unable to delete directory '...\build\test-results\test\binary'`, delete that directory manually before retrying — OneDrive holds a sync lock on it.
8-
9-
```bash
10-
# Build (runs Checkstyle, SpotBugs, and tests)
11-
./gradlew build
12-
13-
# Run tests only
14-
./gradlew test
15-
16-
# Run a single test class
17-
./gradlew test --tests "com.crimsonwarpedcraft.exampleplugin.command.PingTest"
18-
19-
# Run a single test method
20-
./gradlew test --tests "com.crimsonwarpedcraft.exampleplugin.command.GreetTest.greetsTarget"
21-
22-
# Build a release JAR (strips version from filename for stable tags)
23-
./gradlew -Pver="X.Y.Z" release
24-
25-
# Output is in build/libs/
26-
```
27-
28-
Checkstyle enforces Google Java style with `maxWarnings = 0` — the build fails on any warning. SpotBugs runs FindSecBugs. Both run as part of `build`; fix all findings before committing.
29-
30-
## Architecture
31-
32-
This is a **PaperMC/Spigot Minecraft plugin template**. The intent is that users fork/copy it and replace the example scaffolding with their own plugin.
33-
34-
**Entry point**: `ExamplePlugin extends JavaPlugin` — Bukkit/Paper calls `onEnable()` and `onDisable()` on the plugin lifecycle. The main class is referenced in `plugin.yml` via the `${PACKAGE}.${NAME}` substitution, which is filled at build time by `processResources` from `group` (build.gradle.kts) and `rootProject.name` (settings.gradle.kts).
35-
36-
**JAR packaging**: The standard `jar` task is disabled. `shadowJar` is the sole output — it shades CommandAPI (relocated to `<group>.commandapi`). CommandAPI is excluded from `minimize()` because it loads classes via reflection. `assemble` depends on `shadowJar`.
37-
38-
**cw-commons dependency**: `Command`/`BaseCommand` (command registration) and `Config`/`ConfigManager` (YAML config loading + Jakarta validation) come from [cw-commons](https://github.com/CrimsonWarpedcraft/cw-commons), not local code — consumed via JitPack (`com.github.CrimsonWarpedcraft:cw-commons`). `build.gradle.kts` pins a tagged release (e.g. `v0.1.0`) rather than the unstable `main-SNAPSHOT`; bump that tag deliberately. Jackson and Hibernate Validator remain direct dependencies here because `PluginConfig` uses their annotations (`@JsonProperty`, `@NotBlank`) directly — cw-commons exposes them as `api` (transitive, unbundled) dependencies specifically so each consumer shades/relocates its own copy without classloader conflicts. Note that cw-commons' `api` deps already put Jackson/Hibernate Validator on this project's classpath transitively, so the explicit declarations here are redundant for resolution — kept anyway since `PluginConfig` references them directly and shouldn't rely on another project's transitive exposure choices.
39-
40-
**Commands are not declared in `plugin.yml`**: CommandAPI registers commands programmatically in `onEnable()` (see `ExampleCommand`/`BaseCommand`). Adding a matching entry under `commands:` in `plugin.yml` makes Bukkit register the same command a second time, which CommandAPI flags at startup with a "Plugin command ... is registered by Bukkit" warning. `permissions:` entries are unaffected and still required.
41-
42-
**Versioning logic** (in `build.gradle.kts`):
43-
- No `-Pver` supplied → `yyMMdd-HHmm-SNAPSHOT`
44-
- `-Pver=vX.Y.Z-RC-N``X.Y.Z-SNAPSHOT`
45-
- `-Pver=vX.Y.Z``X.Y.Z` (stable release)
46-
47-
**CI workflows** (`.github/workflows/`):
48-
- `pr.yml` — builds and tests on Ubuntu + Windows for PRs and merge queue
49-
- `main.yml` — builds, tests, and cuts a snapshot release on push to `main`
50-
- `tag.yml` / `release.yml` — handle tagged releases and Discord notifications
51-
52-
## Testing
53-
54-
Command executor unit tests (`Ping`, `Greet`, etc.) use Mockito directly — mock `CommandArguments` and `CommandSender`/`Player`, then call `run()`. No server or plugin lifecycle needed. Mockito must be declared explicitly as `testImplementation 'org.mockito:mockito-core:...'` — it is not provided transitively.
55-
56-
## Template Customization Checklist
57-
58-
When adapting this template for a real plugin, update:
59-
1. `settings.gradle.kts``rootProject.name`
60-
2. `build.gradle.kts``group` (Java package)
61-
3. `src/main/resources/plugin.yml``author`, `description`, `commands`, `permissions`
62-
4. Rename the Java package and source directory from `com.crimsonwarpedcraft.exampleplugin`
63-
5. `.github/dependabot.yml`, `.github/CODEOWNERS`, `.github/FUNDING.yml` — replace `leviem1`
64-
6. `CODE_OF_CONDUCT.md` line 63 — contact method
65-
7. README badges and Discord invite link
2+
@AGENTS.md

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
A template for building PaperMC/Spigot Minecraft server plugins!
33

44
<!-- TODO: CHANGE ME -->
5-
[![Test and Release](https://github.com/CrimsonWarpedcraft/plugin-template/actions/workflows/main.yml/badge.svg)](https://github.com/CrimsonWarpedcraft/plugin-template/actions/workflows/main.yml)
5+
[![](https://github.com/CrimsonWarpedcraft/plugin-template/actions/workflows/main.yml/badge.svg)](https://github.com/CrimsonWarpedcraft/plugin-template/actions/workflows/main.yml)
66

77
<!-- TODO: CHANGE ME -->
88
[![](https://dcbadge.limes.pink/api/server/5XMmeV6EtJ)](https://discord.gg/5XMmeV6EtJ)

build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ val mockitoAgent by configurations.creating
6767
dependencies {
6868
compileOnly("io.papermc.paper:paper-api:26.1.2.build.70-stable")
6969

70-
// The below dependencies relate to code quality and unit testing and can be remove if desired
70+
// Code quality and unit testing. Not required for code functionality.
7171
compileOnly("com.github.spotbugs:spotbugs-annotations:4.10.2")
7272
spotbugsPlugins("com.h3xstream.findsecbugs:findsecbugs-plugin:1.14.0")
7373
testCompileOnly("com.github.spotbugs:spotbugs-annotations:4.10.2")
@@ -76,7 +76,7 @@ dependencies {
7676
testRuntimeOnly("org.junit.platform:junit-platform-launcher:6.1.0")
7777

7878

79-
// The below dependencies relate to the provided example code and can be removed if desired
79+
// Dependencies used by the example code. Not required for Paper plugins.
8080
implementation("com.github.CrimsonWarpedcraft:cw-commons:v0.1.1")
8181
// Jackson + Hibernate Validator: also exposed transitively via cw-commons' `api` deps,
8282
// but declared directly anyway since PluginConfig imports their annotations — don't

0 commit comments

Comments
 (0)