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

199 lines
7.4 KiB
Markdown

---
name: beatsaber-plugin-manager
description: Install or update a Beat Saber plugin in the plugin-helper repo by using the local helper workflow. Use when the user asks to add, install, update, bump, lock, bootstrap BSIPA, or manage a Beat Saber plugin release for a BSManager instance. Prefer upstream GitHub release artifacts for normal plugins; use BeatMods primarily as compatibility/dependency metadata, with CDN artifacts only for inaccessible upstream assets, BeatMods-only packages, or framework/library dependencies.
---
# Beat Saber Plugin Installer
Use the repository's own `plugin-helper` commands to manage plugins for BSManager instances whenever the helper supports the operation.
Before acting, read the shared policy references:
- [repo-workflow.md](../references/repo-workflow.md) for repo root, `.venv`, `PYTHONPATH=src`, dirty worktree handling, and validation commands.
- [state-and-profiles.md](../references/state-and-profiles.md) for `.state`, profiles, install identity, instance selection, and checkout locations.
- [artifact-policy.md](../references/artifact-policy.md) for GitHub/BeatMods/private-source/checksum/bootstrap policy.
- [live-validation.md](../references/live-validation.md) for smoke tests, logs, and process cleanup.
## Workflow
1. Confirm the workspace is the `plugin-helper` repo.
```bash
test -f pyproject.toml && test -d src/plugin_helper && test -d registry && test -d locks
```
2. Read the local helper behavior before changing files.
Inspect at least:
```bash
sed -n '1,220p' README.md
sed -n '1,260p' src/plugin_helper/cli.py
sed -n '1,260p' src/plugin_helper/planner.py
sed -n '1,220p' src/plugin_helper/models.py
sed -n '1,220p' registry/plugins.toml
sed -n '1,220p' locks/<instance>.lock.toml
sed -n '1,220p' docs/SMOKETEST.md
```
3. Determine the instance.
Prefer the instance the user names. If omitted, use the latest available
BSInstance unless the current task context clearly points at another
instance:
```bash
PYTHONPATH=src .venv/bin/python -m plugin_helper instances
```
4. Resolve the release source.
For BeatMods bootstrap or verified packages, query BeatMods with a browser-like user agent:
```bash
PYTHONPATH=src .venv/bin/python - <<'PY'
import json, urllib.request
from plugin_helper.beatmods import by_version_id, normalize_mods
game_version = "<instance>"
url = f"https://beatmods.com/api/mods?status=verified&gameVersion={game_version}&gameName=BeatSaber&platform=steampc"
req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0 plugin-helper"})
with urllib.request.urlopen(req, timeout=20) as response:
data = json.load(response)
mods = normalize_mods(data)
mods_by_version_id = by_version_id(mods)
print(json.dumps(
[
{
"name": mod.name,
"modId": mod.mod_id,
"gitUrl": mod.git_url,
"category": mod.category,
"versionId": mod.version_id,
"modVersion": mod.mod_version,
"zipHash": mod.zip_hash,
"dependencies": mod.dependencies,
"dependencyNames": [
mods_by_version_id[dep].name
for dep in mod.dependencies
if dep in mods_by_version_id
],
}
for mod in mods
],
indent=2,
)[:20000])
PY
```
Follow the artifact policy for GitHub-first sourcing, BeatMods exceptions,
and dependency closure. BeatMods CDN URLs are:
```text
https://beatmods.com/cdn/mod/<zipHash>.zip
```
For GitHub URLs, resolve the release from the user-provided repository or
release URL only.
Derive `<owner>/<repo>` and optional `<tag>` from the URL. Query the GitHub API directly for metadata:
```bash
curl -sS https://api.github.com/repos/<owner>/<repo>/releases
curl -sS https://api.github.com/repos/<owner>/<repo>/releases/tags/<tag>
```
Pick the asset that matches the Beat Saber instance/version. Prefer an exact versioned asset such as `1.40.8.zip` over broad or source archives. If multiple plausible assets remain, ask the user.
5. Inspect the asset before selecting an install strategy.
Download to the helper state directory:
```bash
mkdir -p .state/instances/<instance>/downloads/<plugin-id>
curl -L --fail -o .state/instances/<instance>/downloads/<plugin-id>/<asset-name> "<browser_download_url>"
sha256sum .state/instances/<instance>/downloads/<plugin-id>/<asset-name>
```
Match the checksum against GitHub's `digest` when available. Inspect zip contents:
```bash
unzip -l .state/instances/<instance>/downloads/<plugin-id>/<asset-name>
```
Use the install strategy guide in the artifact policy.
6. Update the registry and lockfile.
Add or update exactly one `[[plugins]]` entry in `registry/plugins.toml` with:
```toml
[[plugins]]
id = "<stable-plugin-id>"
name = "<human name>"
repo = "<owner>/<repo>"
asset_patterns = ["<asset-name-or-pattern>"]
install_strategy = "<strategy>"
category = "<category-if-obvious>"
```
Add or update the matching `[[plugins]]` entry in `locks/<instance>.lock.toml` with:
```toml
[[plugins]]
id = "<stable-plugin-id>"
repo = "<owner>/<repo>"
tag = "<tag>"
asset = "<asset-name>"
sha256 = "<asset-sha256>"
```
Preserve unrelated registry and lockfile content. Do not invent dependency versions unless they are explicitly stated by the provided release notes or existing local metadata.
7. Use the helper to validate, plan, and apply.
Always pass `--state-dir .state` so the helper uses the repo-local downloaded asset:
```bash
PYTHONPATH=src .venv/bin/python -m plugin_helper --state-dir .state check --instance <instance>
PYTHONPATH=src .venv/bin/python -m plugin_helper --state-dir .state plan --instance <instance> --plugin <plugin-id>
PYTHONPATH=src .venv/bin/python -m plugin_helper --state-dir .state apply <generated-plan-path>
```
Before applying, read or summarize the generated plan enough to confirm it changes only the intended plugin files.
8. Verify the result.
Confirm the installed file hashes match the plan or archive members:
```bash
PYTHONPATH=src .venv/bin/python -m plugin_helper --state-dir .state state --instance <instance>
PYTHONPATH=src .venv/bin/python -m plugin_helper --state-dir .state check --instance <instance>
PYTHONPATH=src .venv/bin/python -m compileall -q src tests
PYTHONPATH=src .venv/bin/python -m unittest discover -s tests
```
For live Beat Saber validation, follow the live-validation reference. Also
record when a BeatMods CDN artifact was used so it can be migrated to
upstream GitHub later if possible.
9. Final response.
Include:
- release URL/tag/asset used
- files changed in the repo and helper state
- live instance files changed
- backup path created by the helper
- validation commands and results
## Mistake Recovery
If you installed from the wrong release or repo during the current task:
1. Restore affected live files from the helper backup created by that mistaken apply.
2. Remove mistaken downloaded assets and mistaken plan files from `.state`.
3. Correct the registry and lockfile to the user-provided release URL.
4. Rerun `check`, `plan`, and `apply` with `--state-dir .state`.
5. Keep or report only the backup relevant to the final correct apply unless the user asks for full audit history.