143 lines
8.2 KiB
Markdown
143 lines
8.2 KiB
Markdown
# CLAUDE.md
|
|
|
|
This repo **is** a `dotnet new` project template (identity `SCPSL.LabApi.PluginTemplate`,
|
|
shortName `labapi-plugin`), not a runnable plugin. It scaffolds SCP: Secret Laboratory
|
|
LabAPI plugins. `AGENTS.md` carries a shorter, tool-agnostic version of the essentials
|
|
for non-Claude agents; this file is the authoritative one — keep both in sync when a
|
|
rule below changes.
|
|
|
|
The next section only applies while you're editing **this template repository**
|
|
(i.e. a `.template.config/` folder is present next to this file). It does not apply
|
|
if you're instead looking at a plugin someone already generated from this template —
|
|
that folder never contains `.template.config/`, and its `EntryPoint.cs`/`Config.cs`
|
|
are ordinary project files at that point, not template scaffolding.
|
|
|
|
## Repo is template *source* — read before touching any file
|
|
|
|
`.template.config/template.json` sets this folder's name as the template's
|
|
`sourceName` and defines two text-replacement `symbols` (plus a third, `skipRestore`,
|
|
that only toggles the post-generation `dotnet restore` and replaces no text). The
|
|
dotnet templating engine does a literal, repo-wide **string replacement** at
|
|
generation time — not semantic renaming — driven by that config:
|
|
|
|
- The folder/project name (`sourceName` in `template.json`, currently this repo's own
|
|
folder name) → whatever `-n`/`--name` the consumer passes to `dotnet new`.
|
|
- The placeholder value of the `PluginAuthor` symbol (the string currently sitting in
|
|
`EntryPoint.cs`'s `Author` property) → the consumer's `--PluginAuthor`.
|
|
- The placeholder value of the `LabApiVersion` symbol (the version string currently in
|
|
the `.csproj`'s `PackageReference` and in `EntryPoint.cs`'s `RequiredApiVersion`) →
|
|
the consumer's `--LabApiVersion`.
|
|
|
|
Open `template.json` to see the exact current literal for each — don't hardcode them
|
|
again here or anywhere else in prose, because this file itself ships inside every
|
|
generated project and any exact match gets rewritten too (self-referential text like
|
|
"the project is called X" would silently turn into nonsense after generation).
|
|
|
|
Consequences:
|
|
- Never introduce an exact match of one of those three literals elsewhere in the repo
|
|
unless you intend it to be substituted too.
|
|
- If you add a new thing that should be configurable at generation time, add a symbol
|
|
to `template.json` (`type: parameter`, `replaces: "<literal>"`) instead of
|
|
hardcoding a magic string.
|
|
- `EntryPoint` and `Config` (the class names) are **not** substituted and must stay
|
|
literally named that — LabAPI's `PluginLoader` discovers plugins by type
|
|
inheritance, not by name, and the file names `EntryPoint.cs`/`Config.cs` are a fixed
|
|
part of this template's contract. Only the *namespace* tracks the project name.
|
|
|
|
## Repo layout (only what affects decisions)
|
|
|
|
- `.template.config/template.json` — template identity, the 3 symbols above,
|
|
`primaryOutputs` (points at the project file using its pre-substitution literal
|
|
name — that's correct and expected, not a bug), and a `postActions` restore step
|
|
(the standard dotnet-templating "restore NuGet packages" action, id
|
|
`210D431B-...`; skipped in Visual Studio, which restores on its own).
|
|
- The `.csproj` at the repo root — the project file every generated plugin ships with.
|
|
- `EntryPoint.cs` / `Config.cs` — the scaffolded plugin (`Plugin<Config>`) and its
|
|
YAML-backed settings class.
|
|
- `.editorconfig` — formatting/naming only (indentation, brace style). It does **not**
|
|
enforce the comment/language rules below — those aren't analyzer-checkable.
|
|
- No `.sln`, no test project, no CI, no packaging (`.nupkg`) project, no git repo, and
|
|
no GitHub Copilot instructions file currently exist in this folder. Don't assume
|
|
any of them.
|
|
|
|
## LabAPI contract (verified against northwood-studios/LabAPI source, not guessed)
|
|
|
|
`Plugin<TConfig>` (`LabApi.Loader.Features.Plugins`) requires implementing:
|
|
`Name`, `Description`, `Author`, `RequiredApiVersion` (all abstract get-only) plus
|
|
`Enable()`/`Disable()`. Overridable but optional: `Version` (defaults to the
|
|
assembly's version), `Priority` (`LoadPriority`, defaults to `Medium`),
|
|
`ConfigFileName` (defaults to `"config.yml"`). `Config` is a plain `class` with a
|
|
public parameterless constructor and public get/set properties — the base class
|
|
(de)serializes it via YamlDotNet automatically; don't hand-roll config I/O.
|
|
|
|
**Never invent a LabAPI class/namespace/method/property/attribute.** Before using one
|
|
you haven't already seen in this repo, check the restored package (`LabApi.dll` +
|
|
`LabApi.xml` under `%userprofile%\.nuget\packages\northwood.labapi\<version>\lib\net48\`)
|
|
or https://github.com/northwood-studios/LabAPI. If you can't verify a member exists,
|
|
say so instead of guessing. No Skill/plugin specific to C#, .NET, MSBuild, NuGet, or
|
|
LabAPI exists in the Claude Code skill catalog as of this writing — check
|
|
`ToolSearch`/`SearchSkills` for one before editing in case that has changed, but don't
|
|
assume one exists.
|
|
|
|
## Toolchain choices — don't "fix" these without being asked
|
|
|
|
- The project's `TargetFramework` is `netstandard2.1` on purpose, even though
|
|
LabAPI's own docs and the `Northwood.LabAPI` NuGet package only target
|
|
`net48`/`net481`. This is a deliberate compatibility choice (compiled output still
|
|
loads under the game's Mono/.NET Framework 4.8 host) that trades away some
|
|
netstandard2.1 BCL/language surface .NET Framework can't actually run (e.g. default
|
|
interface members). Don't switch it to `net48`, don't add multi-targeting, unless
|
|
the user asks.
|
|
- `LangVersion` is pinned explicitly (currently `14.0`) — don't let it drift to
|
|
`latest`.
|
|
- The `.csproj` suppresses exactly two warnings, both scoped as narrowly as MSBuild
|
|
allows, because of the netstandard2.1/net48-only-package combination above:
|
|
`NU1701` (via a per-`PackageReference` `<NoWarn>`, not a project-wide one) and
|
|
`MSB3270` (via `ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch=None`). Don't
|
|
broaden either into a blanket suppression and don't remove them without
|
|
understanding why (comments sit next to both in the `.csproj`).
|
|
|
|
## Code style for anything you write here
|
|
|
|
- No `//`, `/* */`, or `///` comments unless the user explicitly asks for
|
|
comments/documentation in that request. No comments restating self-explanatory code.
|
|
`EntryPoint.cs`/`Config.cs` are already comment-free — keep them that way and follow
|
|
the same standard for any new file.
|
|
- All text embedded in code defaults to **English**: string/log/console messages,
|
|
exception messages, `[Description]`/config text, any user-facing string. Example:
|
|
`Logger.Info("Plugin initialized successfully")`, not a Spanish equivalent.
|
|
- This never applies to identifiers the user picked — project name, namespace,
|
|
class/method/property/variable names stay exactly as requested (standard C# casing
|
|
rules aside). Honor an explicit request for a specific piece of text in another
|
|
language.
|
|
|
|
## How to verify a change (no test suite exists — this is the actual check)
|
|
|
|
There is no automated test project. Verify any template change by actually
|
|
generating a project from it and building that output. Replace `<repo-name>` below
|
|
with this repo's actual folder name (the value you'd see in `sourceName`):
|
|
|
|
```bash
|
|
dotnet new uninstall .
|
|
dotnet new install .
|
|
dotnet new labapi-plugin -n VerifyPlugin -o ../_verify/VerifyPlugin
|
|
cd ../_verify/VerifyPlugin
|
|
dotnet build
|
|
```
|
|
|
|
Expect `Build succeeded. 0 Warning(s) 0 Error(s)`. If it isn't 0/0, the change broke
|
|
either the template's own warning suppressions or something in `EntryPoint.cs`/
|
|
`Config.cs`/the `.csproj`.
|
|
|
|
Notes:
|
|
- Re-run `dotnet new uninstall .` + `dotnet new install .` after **any** edit to
|
|
`.template.config/template.json` or the scaffolded files — the template cache
|
|
keys off the installed path and stale content otherwise gets regenerated.
|
|
- `dotnet build` also works directly inside `<repo-name>` (the placeholder project
|
|
is itself valid and compilable), but that only proves the *unsubstituted*
|
|
placeholder compiles — it does not exercise symbol substitution. Always additionally
|
|
verify through an actual `dotnet new` generation before calling a change done.
|
|
- On Windows, if cleaning up `../_verify` fails with "resource busy", run
|
|
`dotnet build-server shutdown` first, then retry.
|
|
- Delete the `../_verify` scratch output when done; it isn't part of the template.
|