Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]

### Added
- **Window > Unity CLI Manager** can now install the AI Agent Skill for Grok Build, next to Claude Code and Codex. Project scope writes to `<project-root>/.grok/skills/`; global scope writes to `~/.grok/skills/`.

### Changed
- The installed AI-agent skill now carries the same execute timeout, force-gate, backup, dirty-scene, and `qa --button right` rules as the maintainer copy. Reinstall the skill from **Window > Unity CLI Manager** to pick them up. QA examples in the skill now use `--output compact` and the default JPEG screenshot instead of a full-resolution PNG.

### Fixed
- The README still said this package pins Unity Recorder `5.1.6`. Recorder is optional and is not installed with the package — add it yourself if you record. On Unity `6000.4` and newer, use Recorder `5.1.6` or later.
- The **Overwrite Skill?** confirmation in **Window > Unity CLI Manager** is now in English, matching the rest of the window.

## [0.5.3] - 2026-08-15

### Added
Expand Down
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ Tests live in `tests/UnityCli.Cli.Tests/` (xUnit, `.NET`-testable surface only).
- **Headless editors are first-class:** the bridge starts in any main editor process (GUI or `-batchmode`); only secondary Unity processes (MPE / `-adb2` AssetImportWorker) are excluded. Recommended headless launch is `-batchmode` *without* `-nographics` so the GPU stays available. Commands whose catalog entry sets `requiresGraphics` fail with `HEADLESS_NO_GRAPHICS` when `SystemInfo.graphicsDeviceType == Null`.
- **`editor launch` / `editor stop`:** `editor launch` is a local command — pre-flight (live registry match → idempotent reuse; stray editor process → `EDITOR_ALREADY_RUNNING_CONFLICT`) then spawn + registry-readiness polling (default 300 s). The spawned editor's stdio is detached (Unix: `sh -c 'exec …'` wrapper redirecting to the null device, so `Process.Id` stays the editor PID) — never let it inherit the CLI's streams, or `editor launch | grep …` pipelines hang forever after the CLI exits. `editor stop` is the `editor-quit` wire command (ForceRule OnDestructiveOp): the bridge replies first and schedules `EditorApplication.Exit` via an `EditorApplication.update` one-shot callback (+0.5 s grace), then the CLI waits for PID exit (default 30 s). The deferred quit must stay `update`-based, not `delayCall` — `delayCall` rides the inspector-update cycle and starves in an unfocused GUI editor, timing out every stop. A graceful quit removes the registry entry and token sidecar. The CLI is installed per version under `~/.unity-cli-bridge/versions/<version>/` (binary + `meta.json` = `{"cliVersion","protocolVersion"}`), and `~/.unity-cli-bridge/unity-cli/` stays the PATH target — a symlink to the newest version on macOS/Linux, a copy on Windows, plus a `meta.json` marker naming the version it resolves to. `CliInstallLayout` (`Runtime/Protocol/`) owns that layout for both sides. On a `PROTOCOL_MISMATCH` the CLI reads the bridge's protocol off `response.protocolVersion`, finds the newest installed version speaking it, and re-execs with the original argv (`execve` on macOS/Linux, child process on Windows) with `UNITY_CLI_DISPATCHED=1` set; if that guard is already set it reports the mismatch instead of dispatching again. This works because the bridge checks the protocol before auth and before dispatch and `return`s, so nothing ran and re-sending cannot double-execute — do not move that check. `LocalIpcClient.EnsureCompatibleResponse` must keep the *peer's* `protocolVersion` on the envelope it synthesizes; that field is what routing depends on. Local-only commands (`status`, `instances`, `doctor`) never dispatch. Happy path pays nothing: the decision short-circuits before touching disk.
- **CLI install target = package version:** The Manager downloads the CLI release matching *its own package version*, never the newest release. Only the same-version CLI is guaranteed to speak the package's protocol, and the Manager writes that protocol into `meta.json` from `ProtocolConstants.ProtocolVersion`. Old versions are never garbage-collected; removal is a per-version button in the Manager.
- **AI Agent Skill install scope:** Default to project-scoped installs under `<UnityProjectRoot>/.claude/skills/` or `<UnityProjectRoot>/.codex/skills/`; global installs remain available, can shadow project copies, and can be updated or removed from the manager.
- **AI Agent Skill install scope:** Default to project-scoped installs under `<UnityProjectRoot>/.claude/skills/`, `<UnityProjectRoot>/.codex/skills/`, or `<UnityProjectRoot>/.grok/skills/`; global installs remain available, can shadow project copies, and can be updated or removed from the manager.
- **Scene paths:** Format `/Root[0]/Child[0]` with array notation for sibling indexing; `/` is the virtual scene root.
- **Scene/prefab node flags:** Convenience commands that point at a hierarchy node use `--node`; JSON patch specs still use `target`/`parent`.
- **Prefab editing:** Based on `SerializedProperty.propertyPath` (run `prefab inspect --with-values` to verify paths before patching).
Expand All @@ -103,8 +103,8 @@ Tests live in `tests/UnityCli.Cli.Tests/` (xUnit, `.NET`-testable surface only).
1. `dotnet run --project cli/UnityCli.DocGen -- --write` — auto-updates `docs/cli-reference.md`
2. `README.md` — update examples for new/changed commands in both Scene and Prefab sections
3. `CLAUDE.md` — update Architecture tree if new files are added, update Key Conventions if behavior changes
4. **The AI-agent skill ships in two copies — update both.** `tools/skills/unity-cli-operator/` is the maintainer copy; `unity-package/com.yhc509.unity-cli-bridge/SkillTemplates~/` is what `SkillInstaller` actually installs into a user's project, and nothing in CI compares them.
- `references/*.md` must stay **byte-identical** between the two (`diff -rq` on the two `references/` folders reports nothing).
4. **The AI-agent skill ships in two copies — update both.** `tools/skills/unity-cli-operator/` is the maintainer copy; `unity-package/com.yhc509.unity-cli-bridge/SkillTemplates~/` is what `SkillInstaller` actually installs into a user's project.
- `references/*.md` must stay identical between the two. `SkillTemplateReferenceSyncTests` fails if they drift.
- `SKILL.md` is a deliberate fork: the shipped copy drops maintainer-only content (`## 진입 규칙`). Sync it *where the content applies to end users* — do not make the two identical.
5. `dotnet run --project cli/UnityCli.DocGen -- --check` — verify cli-reference is up to date
- **Release checklist:** Cutting a new version:
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@ Extract and add the binary to your PATH. A manually placed binary carries no ver

### 3. Install AI Agent Skill

In the Unity Editor, open `Window > Unity CLI Manager`. Select your AI tool (Claude Code or Codex), keep **Scope** set to **Project** unless you need a global install, and click **Install Skill**.
In the Unity Editor, open `Window > Unity CLI Manager`. Select your AI tool (Claude Code, Codex, or Grok Build), keep **Scope** set to **Project** unless you need a global install, and click **Install Skill**.

Once installed, the same section offers **Remove Skill** for the selected tool and scope.

Project-scoped installs go under `<project-root>/.claude/skills/` or `<project-root>/.codex/skills/`. Commit that folder if you want the team to share the same skill version as the Unity package.
Project-scoped installs go under `<project-root>/.claude/skills/`, `<project-root>/.codex/skills/`, or `<project-root>/.grok/skills/`. Commit that folder if you want the team to share the same skill version as the Unity package.

The skill teaches AI agents how to pick the right commands, run them safely, and verify results with `read-console`. The installed `SKILL.md` records the package version it came from, so the CLI Manager can tell you when the skill needs an update.

Expand Down Expand Up @@ -181,7 +181,7 @@ Assign a value to `__pucResult` when the caller needs a structured return value.

`record start` captures the Play Mode Game View as mp4 via Unity Recorder. It returns `STARTED` plus a `recordingId` immediately; add `--duration N --wait` to auto-stop and poll until the mp4 is finalized. Without `--duration`, stop manually with `record stop`. Outputs default to `Library/com.yhc509.unity-cli-bridge/recordings/`; pass `--path` to move the finalized mp4.

Recording depends on Unity Recorder. The package requires Unity `2023.1` or newer and pins `com.unity.recorder` `5.1.6`, which includes the compatibility fixes older Recorder releases need for Unity `6000.4` and newer.
Recording depends on Unity Recorder, which this package does not install. Add `com.unity.recorder` if you want `record` or `qa run-sequence --record`. On Unity `6000.4` and newer, use Recorder `5.1.6` or later — older Recorder releases fail to compile there.

### Assets

Expand Down Expand Up @@ -443,7 +443,7 @@ A disabled bridge constructs nothing and logs one line saying so.

The `unity-cli-bridge` skill teaches AI agents how to use the CLI safely: pick the right command, verify with `read-console`, follow inspect-before-patch patterns.

Install from **Window > Unity CLI Manager** in the Unity Editor — select your AI tool and scope, then click **Install Skill**. Once installed, use **Remove Skill** from the same section to remove that scoped copy. Project scope is the default and writes to `<project-root>/.claude/skills/` or `<project-root>/.codex/skills/`; global scope writes to the user's agent skills directory. Supports Claude Code and Codex.
Install from **Window > Unity CLI Manager** in the Unity Editor — select your AI tool and scope, then click **Install Skill**. Once installed, use **Remove Skill** from the same section to remove that scoped copy. Project scope is the default and writes to `<project-root>/.claude/skills/`, `<project-root>/.codex/skills/`, or `<project-root>/.grok/skills/`; global scope writes to the user's agent skills directory. Supports Claude Code, Codex, and Grok Build.

## Development

Expand Down
4 changes: 2 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

- `cli/`: the .NET CLI that receives user commands and routes them to live IPC
- `unity-package/com.yhc509.unity-cli-bridge/`: the bridge package that starts automatically inside the Unity Editor
- `tools/skills/unity-cli-operator/`: the Codex skill that keeps `unity-cli` usage consistent
- `tools/skills/unity-cli-operator/`: the AI-agent skill that keeps `unity-cli` usage consistent

## Runtime Flow

Expand Down Expand Up @@ -39,7 +39,7 @@
- `cli/UnityCli.Cli`: user-facing CLI
- `cli/UnityCli.Protocol`: protocol models shared by the CLI and Unity package
- `unity-package/com.yhc509.unity-cli-bridge`: UPM package
- `tools/skills/unity-cli-operator`: Codex skill
- `tools/skills/unity-cli-operator`: AI-agent skill (maintainer copy)

## Editor Bridge Layout

Expand Down
32 changes: 32 additions & 0 deletions tests/UnityCli.Cli.Tests/SkillTemplateReferenceSyncTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using UnityCli.DocGen;

namespace UnityCli.Cli.Tests;

public sealed class SkillTemplateReferenceSyncTests
{
[Fact]
public void MaintainerAndShippedSkillReferences_AreIdentical()
{
string repoRoot = RepositoryPaths.FindRepoRoot(AppContext.BaseDirectory);
string maintainerRoot = Path.Combine(repoRoot, "tools", "skills", "unity-cli-operator", "references");
string shippedRoot = Path.Combine(
repoRoot,
"unity-package",
"com.yhc509.unity-cli-bridge",
"SkillTemplates~",
"references");

Assert.True(Directory.Exists(maintainerRoot), "Maintainer skill references are missing: " + maintainerRoot);
Assert.True(Directory.Exists(shippedRoot), "Shipped skill references are missing: " + shippedRoot);
Assert.Equal(ReadTree(maintainerRoot), ReadTree(shippedRoot));
}

private static Dictionary<string, string> ReadTree(string root)
{
return Directory.GetFiles(root, "*", SearchOption.AllDirectories)
.ToDictionary(
path => Path.GetRelativePath(root, path).Replace('\\', '/'),
path => File.ReadAllText(path).Replace("\r\n", "\n"),
StringComparer.Ordinal);
}
}
16 changes: 8 additions & 8 deletions tools/skills/unity-cli-operator/references/qa-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ ucli screenshot --view game --format png --max-width 0 --path /tmp/qa-check.png

### qa ui-dump Workflow
1. Enter Play Mode and, if you already captured a reference image, keep its `width`/`height` available
2. Dump candidates: `qa ui-dump --limit 30 --interactable-only --omit-rect` -> inspect each element's `path`, `text`, `interactable`, `centerX`, `centerY`
2. Dump candidates: `qa ui-dump --limit 30 --interactable-only --omit-rect --output compact` -> inspect each element's `path`, `text`, `interactable`, `centerX`, `centerY`
3. Prefer path click: `qa click --target <path>`
4. If a coordinate tap is better, use `qa tap --x <centerX> --y <centerY>`

Expand All @@ -172,7 +172,7 @@ If the visible label is known, add `--text <substring>` so filtering happens in
UI elements come from `qa ui-dump`. For non-UI world objects (units on a battle grid, world-space interactables), the game opts them in:

- Implement `UnityCliBridge.Bridge.IQaTappable` on your own component, or attach the `QaTappable` marker component (set `label`, optional `anchor`, optional `onQaTap`).
- `qa world-dump --limit 30` then lists them with `label`, `path`, image-space `centerX`/`centerY`, `onScreen`, `hasAction`; add `--text <substring>` when the label is known.
- `qa world-dump --limit 30 --output compact` then lists them with `label`, `path`, image-space `centerX`/`centerY`, `onScreen`, `hasAction`; add `--text <substring>` when the label is known.
- Tap with `qa tap --target <path>`. If the object's `TryQaTap()` handles it (e.g. `onQaTap` is wired), the bridge invokes it directly; otherwise the bridge simulates an Input System tap at the anchor, which reaches games that poll the Input System directly (where `qa tap --x --y`'s EventSystem path does not).
- Off-screen objects are hidden unless you pass `--include-offscreen`.
- Same-named sibling world objects share a path and resolve to the first match; give tappable objects unique names/labels to target them individually.
Expand Down Expand Up @@ -335,18 +335,18 @@ The bridge converts automatically when screenshot dimensions are known.
```bash
P="$(pwd -P)"

ucli play --project "$P" --json
ucli play --project "$P" --output compact
sleep 1

ucli qa click --target "/Canvas/Button" --project "$P" --json
ucli qa click --target "/Canvas/Button" --project "$P" --output compact

# 로그 검증
ucli read-console --type log --limit 5 --no-stacktrace --project "$P" --json
ucli read-console --type log --limit 5 --no-stacktrace --project "$P" --output compact

# 시각 검증
ucli screenshot --view game --path /tmp/qa-click.png --project "$P" --json
# 시각 검증 — 기본값이 이미 jpg q75 + 1024px 축소
ucli screenshot --view game --path /tmp/qa-click.jpg --project "$P" --output compact

ucli stop --project "$P" --json
ucli stop --project "$P" --output compact
```

## 예시: 조건 대기 후 검증
Expand Down
10 changes: 10 additions & 0 deletions unity-package/com.yhc509.unity-cli-bridge/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]

### Added
- **Window > Unity CLI Manager** can now install the AI Agent Skill for Grok Build, next to Claude Code and Codex. Project scope writes to `<project-root>/.grok/skills/`; global scope writes to `~/.grok/skills/`.

### Changed
- The installed AI-agent skill now carries the same execute timeout, force-gate, backup, dirty-scene, and `qa --button right` rules as the maintainer copy. Reinstall the skill from **Window > Unity CLI Manager** to pick them up. QA examples in the skill now use `--output compact` and the default JPEG screenshot instead of a full-resolution PNG.

### Fixed
- The README still said this package pins Unity Recorder `5.1.6`. Recorder is optional and is not installed with the package — add it yourself if you record. On Unity `6000.4` and newer, use Recorder `5.1.6` or later.
- The **Overwrite Skill?** confirmation in **Window > Unity CLI Manager** is now in English, matching the rest of the window.

## [0.5.3] - 2026-08-15

### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ private void InstallSkill()
{
bool shouldOverwrite = EditorUtility.DisplayDialog(
"Overwrite Skill?",
"기존 스킬이 이미 설치되어 있습니다: " + _skillDestinationPath + "\n덮어쓰시겠습니까?",
"A skill is already installed at:\n" + _skillDestinationPath + "\nOverwrite it?",
"Overwrite",
"Cancel");
if (!shouldOverwrite)
Expand Down
Loading