This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Claude Code plugin providing a thin Python CLI for interacting with Unity Editor/Player via the C# Console HTTP service (com.zh1zh1.csharpconsole). Pure stdlib Python — no external dependencies.
Entry point: python "${CLAUDE_PLUGIN_ROOT}/cli/cs.py" <command> [--json] [args]
Shared flags: --project <path>, --ip (default 127.0.0.1), --port (default 14500), --mode editor|runtime, --compile-ip (runtime mode only, default 127.0.0.1), --compile-port (runtime mode only, default auto-detect), --timeout (default 30), --json
- Pre-setup: only
setupandstatuswork (pure stdlib, no Unity package needed) - Post-setup: full CLI available after
com.zh1zh1.csharpconsoleis installed and Unity resolves it
When a built-in framework command exists, prefer cs command <ns> <action> over cs exec <code>. Code execution is a fallback, not the default. Use cs list-commands --json to discover available commands.
| Command | Phase | Description |
|---|---|---|
cs setup [--source URL] [--update] |
pre | Add/update package in Packages/manifest.json |
cs status |
pre | Package + connection status + version info |
cs exec <code> | --file FILE |
post | Execute C# code (inline or from file) |
cs command <ns> <action> [args] |
post | Run framework command |
cs batch <json-array> [--stop-on-error] |
post | Execute multiple commands in one HTTP roundtrip |
cs health |
post | Service health check |
cs refresh [--wait TIMEOUT] [--exit-playmode] |
post | Trigger asset refresh + script compilation |
cs list-commands |
post | List available commands |
cs complete <code> <cursor> |
post | Get completions |
cs check-update |
post | Version alignment + update check |
cs catalog sync |
post | Sync custom command catalog from live editor |
cs catalog list |
post | List cached custom commands (offline) |
cs snippets list | show | search | use |
post | Browse and run reusable C# snippets |
cs snippets add | update | deprecate | prune | stats |
post | Manage snippet library |
cs snippets doctor [--revalidate] |
post | Library health check / anti-rot audit |
Claude Code harness
├── Skills (skills/unity-cli-command/, skills/unity-cli-exec-code/)
├── Slash commands (commands/*.md): /unity-cli-setup, /unity-cli-status, /unity-cli-refresh, /unity-cli-sync-catalog
└── CLI (cli/cs.py)
└── core_bridge.py → dynamically imports csharpconsole_core from Unity package
└── HTTP POST → Unity Editor/Player service (port 14500 editor / 15500 player)
The CLI does not bundle csharpconsole_core. It locates and imports it at runtime from the installed Unity package to guarantee version consistency. Resolution order:
Packages/manifest.jsonfile:entry (resolves both default and custom local paths)Library/PackageCache/com.zh1zh1.csharpconsole@*/Editor/ExternalTool~/console-client/
ConsoleSession is a facade that wires up the core modules (client_base, command_protocol, config_base, output, response_parser, transport_http) into one-liner methods: exec(), command(), batch(), health(), complete(), list_commands(), refresh(), emit().
Connection errors are automatically retried once (1s delay) to handle transient failures during domain reload.
PACKAGE_NAME and DEFAULT_SOURCE are defined once in cli/__init__.py and imported by both cs.py and core_bridge.py.
.claude-plugin/plugin.json Plugin manifest
cli/__init__.py Shared constants (PACKAGE_NAME, DEFAULT_SOURCE)
cli/cs.py CLI dispatcher (argparse → pre-setup handlers or ConsoleSession)
cli/core_bridge.py Dynamic import bridge + ConsoleSession facade
commands/*.md Slash command definitions
skills/.../SKILL.md Skill definition with trigger conditions and usage docs
All post-setup commands return: { "ok": bool, "exitCode": int, "summary": str, "data": {...} }
Built-in commands are statically documented in skills/unity-cli-command/SKILL.md.
User-defined custom commands are cached per-project as JSON (default {project}/.unity-cli/catalog.json; the path is remembered after the first sync and can be overridden via cs catalog sync --catalog-path ...). The agent reads this cache via cs catalog list --json.
Run /unity-cli-refresh-commands (i.e. cs catalog sync) after registering new C# commands to refresh the cache.
Run /unity-cli-sync-catalog (maintainer-only) to audit the built-in tables in SKILL.md against the live Editor and surface upstream additions/removals/signature changes.
Self-evolving project-local library of reusable C# snippets executed via cs exec (no Unity compilation involvement). Snippet bodies live at <project>/.unity-cli/snippets~/<id>.md; audit is committed, stats are gitignored. The plugin ships a unity-cli-snippets skill as the agent's operator manual; the skill instructs the agent to follow the decision order: built-in/custom command → snippet → ad-hoc cs exec.
See skills/unity-cli-snippets/SKILL.md for usage rules and cs snippets --help for the full CLI. Library maintenance (integrity, staleness, Unity API drift) is driven by cs snippets doctor via the unity-cli-snippets-audit skill — run doctor --revalidate after Unity version upgrades.
When bumping the version (e.g. on user request "bump to X.Y.Z and tag"), do all of the following in one commit before tagging — do not ask for clarification on the protocol:
CHANGELOG.md— rename## [Unreleased]to## [X.Y.Z] - YYYY-MM-DD(use today's date). Insert a fresh empty## [Unreleased]block above it. The release workflow extracts this section verbatim as the GitHub Release body, so make sure pending entries already live under[Unreleased]before the bump (move stray notes if needed)..claude-plugin/plugin.json— bumpversionfield..claude-plugin/marketplace.json— bump the matchingversionentry (must stay in lockstep withplugin.json).- Commit with a
chore:orfeat:subject naming the version. git tag vX.Y.Zlocally; never push without explicit user confirmation (memory rule).
The release.yml and convert-codex.yml workflows handle the rest:
they read the matching CHANGELOG section, fall back to --generate-notes
when no section is found, and create matching vX.Y.Z and vX.Y.Z-codex
releases with proper titles.
- Always ask before pushing — never
git pushwithout explicit user confirmation - No build step, no tests, no external deps — just stdlib Python
- Unity project detection: walks up from cwd looking for an
Assets/directory find_project_root()incs.pyhandles project auto-detection;--projectflag overrides- Slash commands in
commands/use$ARGUMENTSand${CLAUDE_PLUGIN_ROOT}template variables