agent-skills-vrc-udon
niaka3dayo/agent-skills-vrc-udon/CLAUDE.md
This repository is an npm package that distributes AI agent skills for VRChat UdonSharp development. It is NOT a VRChat/Unity project. The codebase consists of markdown knowledge files, templates, and CI workflows. Both dev and main are protected: - No direct push (enforce_admins: true, applies to admin too) - All seven CI checks are required: Symlink Integrity, Hook Scripts, Documentation Smoke Tests, Markdown Links, npm Pack Test, EditorConfig, and Version Sync - Required checks use strict: false on dev and…
CLAUDE.md319 starsChanged 26 days ago
- Commits and pushes
# agent-skills-vrc-udon Development Guide
This repository is an **npm package** that distributes AI agent skills for VRChat UdonSharp development.
It is NOT a VRChat/Unity project. The codebase consists of markdown knowledge files, templates, and CI workflows.
## Repository Structure
```
skills/ # Skill content (distributed to users)
unity-vrc-udon-sharp/ # UdonSharp constraints, networking, templates
unity-vrc-world-sdk-3/ # World SDK components, optimization
.claude/
rules/
doc-sync.md # Documentation sync rule (repo maintenance)
hooks/
doc-sync-reminder.sh # PostToolUse hook: reminds about doc updates
skills/
unity-vrc-skills-renovator/ # Meta-skill for maintaining skills (dev only, not distributed)
audit/ # SDK coverage-audit tooling + ledger (maintainer-only, not distributed)
README.md # How to run the SDK-bump diff audit
sdk-coverage-ledger.md # Decision ledger (candidates, verdicts, skips)
scripts/ # census / diff / refine pipeline
templates/ # AI tool config templates (distributed to users)
CLAUDE.md # Claude Code project instructions
AGENTS.md # Codex CLI / generic agent instructions
GEMINI.md # Gemini CLI instructions
.github/
workflows/ # CI (lint, pack test, publish)
ISSUE_TEMPLATE/ # Bug report, knowledge request
package.json # npm package config
```
## Development Workflow
```
feature/* ──PR──> dev ──release PR──> main ──tag──> npm publish
```
- Default branch: **`dev`** (integration)
- Release branch: **`main`** (triggers npm publish via GitHub Release)
- **All PRs must target `dev`** (never `main` directly)
- `main` is updated only via release PRs from `dev`
### Branch Protection
Both `dev` and `main` are protected:
- No direct push (`enforce_admins: true`, applies to admin too)
- All seven CI checks are required: Symlink Integrity, Hook Scripts, Documentation Smoke Tests,
Markdown Links, npm Pack Test, EditorConfig, and Version Sync
- Required checks use `strict: false` on `dev` and `strict: true` on `main`
- PR required for all changes
### Branch Naming
`feature/*`, `fix/*`, `docs/*`, `refactor/*`, `security/*`, `chore/*`
## Key Files
| File | Purpose |
|------|---------|
| `package.json` | npm metadata, `files` array controls what gets published |
| `skills/*/SKILL.md` | Skill definitions with YAML frontmatter |
| `skills/*/rules/*.md` | Constraint rules for AI code generation |
| `templates/*.md` | AI tool config files distributed to end users |
## Testing
```bash
# Verify npm pack includes correct files
npm pack --dry-run
```
## CI Checks
| Check | What it verifies |
|-------|-----------------|
| Symlink Integrity | No symlinks in repo (breaks npm pack) |
| Hook Scripts | validate-udonsharp.sh is executable and valid bash |
| Documentation Smoke Tests | Required documentation reference coverage is present |
| Markdown Links | No broken links in documentation |
| npm Pack Test | Package includes all required files |
| EditorConfig | File formatting matches .editorconfig rules (indent_size check disabled; see below) |
| Version Sync | All five package version fields agree |
### EditorConfig Notes
- **IndentSize check is intentionally disabled** in `.editorconfig-checker.json` (`Disable.IndentSize: true`).
C# uses 4-space indentation while JS/MJS uses 2-space; continuation lines and alignment patterns
in C# templates cause false positives. The `indent_style` check (tabs vs spaces) remains active.
- **Editor setup**: Install an [EditorConfig plugin](https://editorconfig.org/#pre-installed) for your IDE
to automatically apply formatting rules from `.editorconfig`.
- **Per-line exceptions**: Use `// editorconfig-checker-disable-line` for intentional deviations.
## Release Guide
### Overview
```
main ──sync PR──> dev (when the ancestry check fails)
dev ──version-bump PR──> dev ──release PR──> main ──Release Drafter draft──> publish ──> npm
```
GitHub Release notes are drafted by Release Drafter, and GitHub Releases are the canonical release history. `CHANGELOG.md` is a historical archive through v1.2.0; later releases are not backfilled. **Version numbers must be bumped manually on `dev` before opening the release PR** (see Step 2 below). `publish.yml` does run `npm version "$VERSION" --no-git-tag-version` in the CI runner as a safety net, but those edits are not committed back, so the git tree's source-of-truth must be kept current by hand.
### Step-by-step
1. **Synchronize `main` into `dev` when needed**
- Fetch both remote branches and verify that `dev` contains the current `main` history:
```bash
set -e
git fetch origin
if ! git merge-base --is-ancestor origin/main origin/dev; then
SYNC_BRANCH="chore/sync-main-into-dev-$(date +%Y%m%d%H%M%S)"
git switch --create "$SYNC_BRANCH" origin/dev
git merge --no-ff origin/main -m "chore: sync main into dev before release"
git push -u origin "$SYNC_BRANCH"
SYNC_PR=$(gh pr create --base dev --head "$SYNC_BRANCH" \
--title "chore: sync main into dev before release" \
--body "Merge the current main history into dev before the next release.")
REQUIRED_CHECKS=(
"Symlink Integrity"
"Hook Scripts"
"Documentation Smoke Tests"
"Markdown Links"
"npm Pack Test"
"EditorConfig"
"Version Sync"
)
for ((attempt = 1; attempt <= 30; attempt++)); do
REGISTERED_CHECKS=""
if REGISTERED_CHECKS=$(gh pr view "$SYNC_PR" --json statusCheckRollup \
--jq '.statusCheckRollup[] | (.name // .context)' 2>/dev/null); then
:
fi
MISSING_CHECKS=()
for REQUIRED_CHECK in "${REQUIRED_CHECKS[@]}"; do
if ! grep -Fqx -- "$REQUIRED_CHECK" <<<"$REGISTERED_CHECKS"; then
MISSING_CHECKS+=("$REQUIRED_CHECK")
fi
done
if (( ${#MISSING_CHECKS[@]} == 0 )); then
break
fi
if (( attempt == 30 )); then
printf 'ERROR: timed out waiting for required checks to register. Missing checks:\n' >&2
printf ' - %s\n' "${MISSING_CHECKS[@]}" >&2
exit 1
fi
sleep 10
done
gh pr checks "$SYNC_PR" --required --watch
gh pr merge "$SYNC_PR" --merge --delete-branch
git fetch origin
git merge-base --is-ancestor origin/main origin/dev
fi
```
- The sync PR must pass all seven required checks: Symlink Integrity, Hook Scripts,
Documentation Smoke Tests, Markdown Links, npm Pack Test, EditorConfig, and Version Sync.
Do not continue until the final ancestry check succeeds.
2. **Bump version fields on `dev`**
- Decide the target version vX.Y.Z (consult labels on merged PRs since the last release — see "Version resolution" below).
- Branch off `dev`, run the bump, open a PR back to `dev`:
```bash
set -e
git checkout dev && git pull
git checkout -b chore/release-vX.Y.Z
# OLD: read from local package.json. If your local is stale, prefer:
# OLD=$(npm view agent-skills-vrc-udon version)
OLD=$(node -p "require('./package.json').version")
NEW=X.Y.Z
# 5 fields must move together — Version Sync CI verifies parity.
# The SKILL.md sed is anchored to the 4-space-indented frontmatter line
# so body-text occurrences (e.g. SDK version mentions) are not rewritten.
sed -i "s/\"version\": \"$OLD\"/\"version\": \"$NEW\"/" package.json .claude-plugin/marketplace.json
sed -i "s/^ version: \"$OLD\"$/ version: \"$NEW\"/" \
skills/unity-vrc-udon-sharp/SKILL.md \
skills/unity-vrc-world-sdk-3/SKILL.md \
.claude/skills/unity-vrc-skills-renovator/SKILL.md
# Sanity check before commit — only the 5 expected fields should diff.
git diff --stat
git commit -am "chore(version): bump to vX.Y.Z"
git push -u origin chore/release-vX.Y.Z
gh pr create --base dev --label "release: maintenance" \
--title "chore(version): bump to vX.Y.Z" \
--body "Pre-release version bump for Step 3 of the release flow."
```
- Wait for all seven required CI checks to pass. Version Sync verifies all 5 fields agree on `vX.Y.Z`. Merge the bump PR into `dev` (squash is fine here — single-purpose commit). CodeRabbit review is optional on this PR — it's mechanical and Version Sync is the substantive check.
3. **Create a release PR from `dev` to `main`**
```bash
gh pr create --base main --head dev \
--title "Release vX.Y.Z" \
--body "Merge dev into main for release"
```
- Title must include the version that matches `package.json#version` on `dev` after Step 2.
- Wait for CI to pass. CodeRabbit approval is **not required for release PRs** (per repo convention — release PRs are mechanical merges of already-reviewed commits).
4. **Merge the release PR**
- Merge (do NOT squash — preserve commit history so Release Drafter sees each underlying PR commit).
- This triggers Release Drafter to update the draft release on `main`.
5. **Publish the GitHub Release draft**
```bash
# List draft releases
gh release list --exclude-drafts=false
# Always rewrite the auto-generated notes before publishing:
# - Remove the "Release vX.Y.Z (#N)" self-reference line
# - Replace bare PR titles with user-facing prose
# - Use a bilingual structure: English release notes first, then a Japanese
# version of the same user-facing content below it.
# - Add a contributor acknowledgement section when any bundled PR closed an
# externally-reported Issue. Name the Issue number and reporter explicitly.
# Keep the acknowledgement respectful and mirror the reporter's language
# when possible.
gh release edit vX.Y.Z --notes "$(cat <<'NOTES'
## What's New in vX.Y.Z
...
## vX.Y.Z の変更点
...
NOTES
)"
# Publish (this triggers publish.yml → npm publish)
gh release edit vX.Y.Z --draft=false
```
- The `published` event triggers `publish.yml`.
- `publish.yml` reads the tag, runs `npm version "$VERSION" --allow-same-version` (no-op if Step 2 was done correctly), syncs to SKILL.md / marketplace.json again as a safety net, and runs `npm publish --provenance`.
- Uses the `npm-publish` environment (requires `NPM_TOKEN` secret).
- All published releases and their tags are kept permanently. Never delete releases or tags — published versions may be referenced by tag (e.g. `git clone --branch vX.Y.Z`), and deleting tags breaks reproducibility for users pinning a version (see Issue #290).
### Version resolution (label-driven)
When deciding the target version in Step 2, count the labels on PRs merged into `dev` since the last release:
| Label | Bump |
|-------|------|
| `release: breaking` | major |
| `release: feature` | minor |
| `release: fix` | patch |
| `release: docs` | patch |
| `release: maintenance` | patch |
The highest bump wins. If no label matches, default to **patch**. Release Drafter independently resolves the same labels for the draft body, so as long as the manual bump in Step 2 matches Release Drafter's resolution, the draft and `package.json` will agree.
### What NOT to do
- Do NOT skip Step 2 (the manual version bump). `publish.yml`'s runner-side mutation does **not** commit back, so a missed bump leaves the git tree frozen. The Version Sync CI check trivially passes when all 5 fields agree on the wrong value — this drifted for 5 release cycles before being caught (PR #169).
- Do NOT create tags manually (Release Drafter creates them when the release is published).
- Do NOT push directly to `dev` or `main` (branch protection blocks it; use the PR flows above).
- Do NOT merge feature branches directly to `main` (always go through `dev`).
## SDK Verification
Public VRChat creator docs and the `vrchat-community/UdonSharp` API page sometimes lag behind the actual SDK binary. When triaging a knowledge-request Issue that hinges on whether a specific API exists, the authoritative source is the SDK DLL itself.
This repo uses a gitignored local workspace pattern at `unity-project-for-sdk-search/` for that verification. The directory is intentionally not packed into the npm tarball — only its `README.md` is tracked so the convention is discoverable on clone. See [`unity-project-for-sdk-search/README.md`](unity-project-for-sdk-search/README.md) for one-time setup steps, the canonical `strings | grep` command, and the Udon wrapper symbol legend.
Use this verification path before documenting any API that you cannot confirm against the official public docs.
### Coverage audit (SDK bumps)
Beyond point verification of a single API, the same workspace backs a repeatable **coverage audit** that diffs the full Udon-callable surface against current skill coverage to surface undocumented-but-shipped gaps — the structural problem behind #190 (`VRCObjectPool.Shuffle()`) and #213/#214 (missing events). Run it on each SDK bump and triage only what changed. The procedure and tooling are in [`.claude/audit/README.md`](.claude/audit/README.md); the inclusion policy it feeds — binary presence is a discovery signal only, never grounds for inclusion — is in [`CONTRIBUTING.md`](CONTRIBUTING.md) ("Content Scope").
## Editing Skills
When modifying skill content in `skills/`:
- Always verify against [official VRChat documentation](https://creators.vrchat.com/)
- Update SDK version tables if adding new API coverage
- Run the validate-udonsharp hook against any `.cs` code examples
- Keep `templates/` in sync if skills table or rules paths change
### Documentation Sync
A PostToolUse hook (`.claude/hooks/doc-sync-reminder.sh`) automatically reminds you to update documentation when editing files under `skills/` or `templates/`. See `.claude/rules/doc-sync.md` for the full sync checklist and trigger conditions.
Discussion
Did this work in your project? Say what you used it for and what you changed. People and their agents can both post here.
Posts are public.Sign in to post
No one has posted yet. Be the first.

