Files
plugin-helper/.agents/skills/beatsaber-plugin-builder/SKILL.md
T
2026-07-10 08:42:55 -07:00

6.4 KiB

name, description
name description
beatsaber-plugin-builder 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.

Before building, read the shared policy references:

For detailed Linux/BSMT behavior, read 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.

    pwd
    git status --short
    sed -n '1,220p' plugin-helper.local.toml
    

    In plugin-helper, run commands from repo root. Treat shared profile and dirty-worktree policy as binding.

  2. Resolve source.

    For a GitHub PR, clone or reuse a checkout according to the shared source checkout policy, add/fetch the upstream remote if needed, and check out the PR head:

    git clone https://github.com/<owner>/<repo>.git <state_dir>/build/<name>
    git -C <state_dir>/build/<name> fetch origin pull/<pr>/head:pr-<pr>
    git -C <state_dir>/build/<name> checkout pr-<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.

    find <checkout> -maxdepth 3 -name '*.sln' -o -name '*.csproj' -o -name 'manifest.json' -o -name 'Directory.Build.props'
    sed -n '1,240p' <project>.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. If the user did not specify an instance and the plugin does not require a narrower version, use the latest available BSInstance. 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:

    PYTHONPATH=src .venv/bin/python -m plugin_helper --profile <profile-id> 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:

    dotnet restore <solution-or-project>
    dotnet build <solution-or-project> -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:

    strings "<BeatSaberDir>/Beat Saber_Data/Managed/Main.dll" | rg 'TypeOrMemberName'
    strings "<BeatSaberDir>/Beat Saber_Data/Managed/HMLib.dll" | rg 'TypeOrMemberName'
    ilspycmd -t TypeName "<BeatSaberDir>/Beat Saber_Data/Managed/Main.dll" | sed -n '1,220p'
    rg -n 'TypeOrMemberName|NearbyConcept' ~/src/<owner>/<repo> ~/src/Auros/SiraUtil ~/src/nike4613/BeatSaber-IPA-Reloaded
    
  7. Collect artifacts.

    Find produced DLLs and release zips:

    find <checkout> -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 <state_dir>/instances/<instance>/downloads/<plugin-id>/ 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 the shared skill validation plus:

    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.