--- name: beatsaber-plugin-builder description: Build, test-compile, or package Beat Saber PC BSIPA plugin source on Linux from local checkouts, GitHub branches, or pull requests. Use when asked to build a Beat Saber plugin, compile a plugin PR, produce a DLL/zip artifact, configure BeatSaberDir/local refs for dotnet builds, or diagnose Linux build failures for .NET Framework BSIPA projects. --- # Beat Saber Plugin Builder Use this skill to compile PC BSIPA plugin projects on this Linux host, especially from the `plugin-helper` repo. The workflow is adapted from the Setlist repo's Linux/Cursor build notes. For detailed Linux/BSMT behavior, read [linux-bsipa-build.md](references/linux-bsipa-build.md) when you need to configure a project, fix missing references, package artifacts, or explain a failure. ## Core Workflow 1. Confirm context. ```bash pwd git status --short sed -n '1,220p' plugin-helper.local.toml ``` In `plugin-helper`, run commands from repo root. Treat `plugin-helper.local.toml` as the source of truth for profile `instances_root` and `state_dir` values, and keep temporary source checkouts under the chosen profile's `state_dir` such as `/build/`. Do not disturb unrelated dirty files. 2. Resolve source. For a GitHub PR, clone or reuse a checkout under the selected profile's `/build`, add/fetch the upstream remote if needed, and check out the PR head: ```bash git clone https://github.com//.git /build/ git -C /build/ fetch origin pull//head:pr- git -C /build/ checkout pr- ``` If the PR is from a fork and the repo already has a fork remote, preserve it. Never overwrite local source changes without explicit approval. 3. Inspect build shape. ```bash find -maxdepth 3 -name '*.sln' -o -name '*.csproj' -o -name 'manifest.json' -o -name 'Directory.Build.props' sed -n '1,240p' .csproj ``` Note target framework, `BeatSaberDir`, `LocalRefsDir`, package references, and whether `DisableCopyToPlugins` is already set. 4. Choose Beat Saber references. Prefer a BSManager instance matching the plugin or manifest `gameVersion`. Read `plugin-helper.local.toml` and select the intended profile, then use that profile's `instances_root` and matching `state_dir` instead of searching default BSManager paths manually: ```bash PYTHONPATH=src .venv/bin/python -m plugin_helper --profile instances ``` Use a local `.csproj.user` or MSBuild properties rather than committing machine paths. For test builds, pass `-p:DisableCopyToPlugins=True` and, for BSMT projects that expose it, `-p:DisableCopyToGame=True` so compilation does not mutate the game install. 5. Restore and build. Prefer the solution when present; otherwise build the plugin `.csproj`: ```bash dotnet restore dotnet build -c Release -p:DisableCopyToPlugins=True -p:DisableCopyToGame=True ``` If the project lacks .NET Framework reference assemblies on Linux, add or pass the package matching the project's target framework, usually `Microsoft.NETFramework.ReferenceAssemblies.net48` for current BSIPA projects, as described in the reference file. 6. Verify Beat Saber API changes before patching gameplay code. When a Beat Saber upgrade breaks a type/member reference, first determine whether the API moved assemblies before substituting another type. Inspect the target game DLLs and nearby mod sources: ```bash strings "/Beat Saber_Data/Managed/Main.dll" | rg 'TypeOrMemberName' strings "/Beat Saber_Data/Managed/HMLib.dll" | rg 'TypeOrMemberName' ilspycmd -t TypeName "/Beat Saber_Data/Managed/Main.dll" | sed -n '1,220p' rg -n 'TypeOrMemberName|NearbyConcept' ~/src// ~/src/Auros/SiraUtil ~/src/nike4613/BeatSaber-IPA-Reloaded ``` 7. Collect artifacts. Find produced DLLs and release zips: ```bash find -path '*/bin/*' \( -name '*.dll' -o -name '*.zip' \) -print ``` Verify the DLL name, version, and manifest. If the result is meant for `plugin-helper`, place a copy under `/instances//downloads//` for the selected profile and use the helper plan/apply workflow rather than hand-copying into a BSManager instance. 8. Validate. For skill edits inside this repo, run: ```bash python /home/pleb/.codex/skills/.system/skill-creator/scripts/quick_validate.py .agents/skills/beatsaber-plugin-builder PYTHONPATH=src .venv/bin/python -m compileall -q src tests PYTHONPATH=src .venv/bin/python -m unittest discover -s tests ``` For a plugin build, at minimum report the exact `dotnet build` result and artifact paths. For live game validation, use `docs/SMOKETEST.md` and tear down Beat Saber processes afterward. ## Failure Triage - Missing `Microsoft.NETFramework.ReferenceAssemblies`: add the package matching the target framework, usually `Microsoft.NETFramework.ReferenceAssemblies.net48` for current projects, or pass an equivalent MSBuild/package restore fix. - Missing `Main.dll`, `HMUI.dll`, `IPA.Loader.dll`, `BSML.dll`, `SongCore.dll`, or similar: `BeatSaberDir` points at the wrong/unmodded instance, or dependencies are absent from `Plugins/`/`Libs/`. - BSMT copies to `IPA/Pending` or `Plugins` during build: rebuild with `-p:DisableCopyToPlugins=True -p:DisableCopyToGame=True` unless the user explicitly wants deployment. - NuGet package restore fails because a source is missing: inspect `NuGet.config` and installed package sources; use repo-local configuration where possible. - API compile errors from a PR: inspect the target game/dependency versions before changing code. Prefer one target version rather than compatibility branches unless the user asks for multi-version support.