Skip to content
Draft
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
22 changes: 16 additions & 6 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ operational rules.

### Lifecycle and setup

- **Pre-setup:** `setup` and `status` use only the bundled stdlib CLI.
- **Pre-setup:** `setup`, `status`, `doctor`, and `wait-ready` use only the
bundled stdlib CLI.
- **Post-setup:** the full CLI is available after
`com.zh1zh1.csharpconsole` is installed and Unity resolves it.

Expand Down Expand Up @@ -68,6 +69,8 @@ through because their contracts are project-specific.
|---------|-------|---------|
| `cs setup` | pre | Install/version-check the Unity package |
| `cs status` | pre | Package, connection, and version status |
| `cs doctor [--operation UUID]` | pre | Unity/project-read-only diagnosis; probes the machine-local outbox |
| `cs wait-ready [--timeout TIMEOUT]` | pre | Wait without Unity/project mutation; optionally bind a refresh op/generation |
| `cs exec --file FILE` | post | Execute raw C# as a fallback |
| `cs command --input FILE --json` | post | Run one framework command |
| `cs batch --input FILE --json` | post | Run multiple commands in one request |
Expand Down Expand Up @@ -95,10 +98,16 @@ package so client and service versions stay aligned:
2. `Library/PackageCache/com.zh1zh1.csharpconsole@*/Editor/ExternalTool~/console-client/`.

`ConsoleSession` wires the core client, command protocol, configuration, output,
response parser, and HTTP transport into the CLI operations. Clearly refused
connections are retried once after one second to tolerate Unity domain reloads.
Timeouts, HTTP errors, and connection resets are not retried because a mutation may
already have executed.
response parser, and HTTP transport into the CLI operations. `reliability.py`
owns project identity, readiness reduction, diagnostics, and the machine-local
invocation outbox. Protocol-v2 operations use a stable invocation id and exact
request bytes for one bounded retry; the Unity-side durable journal either
replays the original response or prevents a second dispatch within its advertised
dedupe window. `outcome_unknown` and `operation_in_progress` exit 4 and must be
inspected with `cs doctor --operation UUID`; never replace that UUID with a new
one while the outcome is unresolved. Once the outbox records an id as sent, a
later CLI run never dispatches it again, including after the server window
expires; use a new id only for a new intent.

### Version and machine-local state

Expand All @@ -108,7 +117,7 @@ already have executed.
source to the newest tag on the CLI's `major.minor` line when setup writes the
manifest; `file:` sources, explicit fragments, and failed tag queries are left
unpinned.
- Package-path cache and snippet usage statistics live in a per-project user cache
- Package-path cache, invocation audit records, and snippet usage statistics live in a per-project user cache
(`%LOCALAPPDATA%\unity-cli\<project-key>\` on Windows or
`$XDG_CACHE_HOME/unity-cli/<project-key>/` elsewhere), never in the project tree.
- The committed custom-command catalog and snippet audit remain project state; see
Expand All @@ -123,6 +132,7 @@ skills/unity-cli/scripts/cli/cs.py CLI dispatcher
skills/unity-cli/scripts/cli/command_index.py
skills/unity-cli/scripts/cli/command_manifest.json
skills/unity-cli/scripts/cli/core_bridge.py
skills/unity-cli/scripts/cli/reliability.py
skills/unity-cli/scripts/cli/paths.py Per-project cache paths
skills/unity-cli/scripts/cli/VERSION Release version
```
Expand Down
28 changes: 24 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,26 @@ the section matching the pushed tag (without the leading `v`) as release notes.

## [Unreleased]

### Added

- **Unity/project-read-only reliability workflow** — `cs doctor` reports project/package,
target identity, protocol, journal, compile, and readiness findings;
`cs wait-ready` follows the matching Unity 2022 service across reload and
local port changes without triggering a mutation, and can resume a specific
refresh by operation id and generation. `cs doctor --operation <UUID>`
reconciles an uncertain HTTP invocation with local and server receipts. These
diagnostics may create and delete a probe in the machine-local outbox cache.

### Changed

- **Protocol-v2 operations are at-most-once** — command, batch, exec, compile,
and refresh requests are bound to a durable invocation id and exact bytes.
One bounded retry reuses both; within the advertised dedupe window Unity
replays a persisted result or blocks a second dispatch. Unresolved or
in-progress work exits 4 instead of being blindly repeated. Once the outbox
records an id as sent, later CLI runs diagnose it rather than redispatching it,
including after the server retention window expires.

## [2.0.8] - 2026-07-23

### Removed
Expand Down Expand Up @@ -65,13 +85,13 @@ the section matching the pushed tag (without the leading `v`) as release notes.
JSON-escaped) is demoted to a stdin-piping edge case. Scratch `.cs` / `req.json`
files now have a **mandatory location**: the absolute path
`<project-root>/Temp/CSharpConsole/AgentScratch/` — inside Unity's own `Temp/`
(never imported, auto-cleaned on editor close, write-sandbox-friendly for
workspace-bound agents, and colocated with the service's existing
`Temp/CSharpConsole/` state). Semantic file names, overwritten per task; one-shot
(never imported, auto-cleaned on editor close, and write-sandbox-friendly for
workspace-bound agents). Semantic file names, overwritten per task; one-shot
suffix only under known same-project concurrency. Never under `Assets/` (a typical
REPL snippet fails project compilation there — blocking refresh workflows and,
after an editor restart, potentially preventing the service from starting), and
never delete `Temp/CSharpConsole/` itself. Decided in an adversarial CC↔Codex
never delete `Temp/CSharpConsole/` itself because older package versions may
retain compatibility state there. Decided in an adversarial CC↔Codex
review (local audit transcript:
`cc-codex-discussion-history/20260722-213810-scratch-file-conventions.md`, kept
untracked by repo policy), which replaced the earlier
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,22 @@ operation, and the agent triggers it automatically (in any skills-compatible age
| ---------- | ----------- |
| `cs setup` | Install the package into the manifest (version-check if present) |
| `cs status` / `cs health` | Package and service status |
| `cs doctor` / `cs wait-ready` | Diagnose or wait for the matching Unity 2022 service |
| `cs command --input` | Structured Unity Editor commands |
| `cs exec` | Run raw C# in the Editor (fallback) |
| `cs refresh` | Trigger asset refresh / recompile |
| `cs catalog sync` / `cs list-commands` | Custom-command catalog + maintainer audit |
| `cs snippets …` | Reusable C# snippet library |
| `cs snippets doctor` | Snippet library health audit |

Protocol-v2 operations are protected by a durable, windowed at-most-once journal.
A lost response is retried only with the same operation id and exact request
bytes; Unity replays the original result or blocks a second dispatch within the
advertised dedupe window. Unknown and in-progress results exit 4 and point to
`cs doctor --operation <UUID>`. Once the local outbox records that an id was
sent, later CLI runs diagnose that id instead of dispatching it again; use a new
id only for a genuinely new intent.


### 📦 Commands

Expand Down Expand Up @@ -294,7 +303,7 @@ Auto-detects project root and service port. No manual configuration.
| ---------------------- | ------------------------------------------------------------------------------------------ |
| `service: UNREACHABLE` | Make sure Unity Editor is open with the project loaded |
| `package: NOT FOUND` | Run `cs setup` to add the package, then open Unity to let it resolve |
| Port conflict | Service auto-advances to the next free port. Check `Temp/CSharpConsole/refresh_state.json` |
| Port conflict | Service auto-advances to the next free port. Check `Library/CSharpConsole/RefreshState/v1/refresh_state.json` |
| Commands not found | Ensure the package compiled successfully (no errors in Unity Console) |
| Version mismatch | Run `cs status` to see versions; align the Unity package with the CLI `major.minor` |

Expand Down
10 changes: 9 additions & 1 deletion README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,21 @@ Claude 会自动选择合适的命令,或在需要时编写 C# 代码。
| ----- | ---- |
| `cs setup` | 安装包到 manifest(已安装则做版本校验) |
| `cs status` / `cs health` | 包与服务状态 |
| `cs doctor` / `cs wait-ready` | 诊断或等待属于当前项目的 Unity 2022 服务 |
| `cs command --input` | 结构化 Unity 编辑器命令 |
| `cs exec` | 在编辑器中执行原始 C#(兜底) |
| `cs refresh` | 触发资产刷新 / 重编译 |
| `cs catalog sync` / `cs list-commands` | 自定义命令目录 + 维护者审计 |
| `cs snippets …` | 可复用 C# 片段库 |
| `cs snippets doctor` | 片段库健康审计 |

协议 v2 的操作由持久化、带去重窗口的 at-most-once 日志保护。响应丢失时,
CLI 只会用同一个 operation id 和完全相同的请求字节重试;在服务声明的窗口内,
Unity 会重放原结果或阻止二次执行。结果未知或仍在执行时,CLI 以退出码 4
返回,并提示运行 `cs doctor --operation <UUID>`。本地 outbox 一旦记录某个 id
已经发送,后续 CLI 进程只会诊断该 id,不会再次派发;只有新的操作意图才使用新
id。


### 📦 命令

Expand Down Expand Up @@ -292,7 +300,7 @@ AI Agent Unity Editor
| ---------------------- | ---------------------------------------------------------- |
| `service: UNREACHABLE` | 确保 Unity 编辑器已打开并加载了项目 |
| `package: NOT FOUND` | 运行 `cs setup` 添加包,再打开 Unity 解析它 |
| 端口冲突 | 服务会自动切换到下一个可用端口,查看 `Temp/CSharpConsole/refresh_state.json` |
| 端口冲突 | 服务会自动切换到下一个可用端口,查看 `Library/CSharpConsole/RefreshState/v1/refresh_state.json` |
| 找不到命令 | 确保包编译成功(Unity Console 中无报错) |
| 版本不匹配 | 运行 `cs status` 查看版本;把 Unity 包对齐到 CLI 的 `major.minor` |

Expand Down
19 changes: 15 additions & 4 deletions skills/unity-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ description: >
or change Unity scenes, GameObjects, components, transforms, prefabs, materials,
project assets, play mode, screenshots, profiler recording, or execute C# inside
Unity; also use for Unity console maintenance and unity-cli setup, status,
refresh, snippets, or custom commands. Do not use for source-only Unity coding
that does not require interaction with the live Editor or Player.
readiness diagnosis, uncertain-operation recovery, refresh, snippets, or
custom commands. Do not use for source-only Unity coding that does not require
interaction with the live Editor or Player.
---

# Unity CLI
Expand Down Expand Up @@ -57,7 +58,8 @@ overwrite the same file when revising it serially; use a random suffix only when
another agent is known to work on the same Unity project concurrently.

Scratch payloads are one-shot. Put reusable C# in the snippet library. Clean only
`AgentScratch/`; never delete `Temp/CSharpConsole/`, which contains service state.
`AgentScratch/`; never delete the parent `Temp/CSharpConsole/`, which older package
versions may still use for compatibility state.
Never write REPL payloads under `Assets/`: importing them can break project
compilation and prevent the service from restarting.

Expand Down Expand Up @@ -123,7 +125,9 @@ Do not load or print the unfiltered 59-command registry during routine work.
| Snippet audit | `cs snippets doctor` / `stats` | `references/snippets-audit.md` |
| Refresh and compile | `cs refresh` | `references/refresh.md` |
| Custom-command catalog | `cs catalog sync` / `list` | `references/catalog.md` |
| Package / connection state | `cs status` / `cs health` | `references/status.md` |
| Diagnose readiness / uncertain operation | `cs doctor` / `cs doctor --operation UUID` | `references/status.md` |
| Wait without Unity/project mutation | `cs wait-ready --timeout N` (bind refresh op/generation when resuming) | `references/status.md` |
| Package / raw service state | `cs status` / `cs health` | `references/status.md` |
| Package setup | `cs setup` | `references/setup.md` |

## Output conventions
Expand All @@ -135,6 +139,13 @@ Do not load or print the unfiltered 59-command registry during routine work.
- A version-mismatch warning means the installed package and CLI use different
`major.minor` lines. Follow `references/setup.md`; the warning does not itself
block execution.
- `outcome_unknown` or `operation_in_progress` (exit 4) means the operation is
unresolved and the CLI deliberately did not create a second dispatch. Run
`cs doctor --operation <UUID> --json` and verify the affected state; never
replace that UUID with a new one while it is unresolved.
- Once the local outbox records an operation id as sent, later CLI runs diagnose
it instead of dispatching it again, even after server retention expires. A new
UUID represents a new intent, not a retry.
- Expanded CLI commands and JSON payloads are agent-internal. When Unity must be
opened or focused, tell the user what action is needed in plain language, then
run `cs status` yourself to verify the result.
10 changes: 7 additions & 3 deletions skills/unity-cli/references/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,13 @@ state was reached.
screenshot.
3. After asset or C# file changes that require compilation, follow
`references/refresh.md`; a domain reload clears REPL sessions.
4. If transport fails after a mutation may have been accepted, read back before
retrying. Never blindly repeat a create, duplicate, destroy, import, or other
mutation whose execution state is unknown.
4. Protocol-v2 operations are durably claimed before dispatch. The CLI may retry
once with the same operation id and exact bytes; Unity replays the original
response or refuses a second dispatch within the advertised dedupe window. If
the result is `outcome_unknown` or `operation_in_progress` (exit 4), run
`cs doctor --operation <UUID> --json`, read back the affected state, and never
replace the unresolved UUID with a new one. After the outbox records an id as
sent, later CLI runs will diagnose rather than dispatch it again.
5. Report completion only when read-back matches the requested state. Otherwise
report the observed state and the next recoverable action.

Expand Down
4 changes: 3 additions & 1 deletion skills/unity-cli/references/exec-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,6 @@ durable storage.

- `exec` output is text; the process exit code carries success/failure. Use `--json`
only when the structured envelope is needed (then check `ok` / `exitCode`)
- Port is auto-detected from `Temp/CSharpConsole/refresh_state.json`
- Port is auto-detected from
`Library/CSharpConsole/RefreshState/v1/refresh_state.json`, with the old
`Temp/CSharpConsole/refresh_state.json` retained as a compatibility fallback.
23 changes: 20 additions & 3 deletions skills/unity-cli/references/refresh.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,27 @@ cs refresh --exit-playmode --wait 120
```

- `--exit-playmode` automatically exits play mode before refreshing if needed
- `--wait TIMEOUT` blocks until the refresh + compile + domain-reload cycle completes (default 120s, max 600s)
- Domain reload restarts the HTTP service and clears REPL sessions; `--wait` handles reconnection
- `--wait TIMEOUT` blocks until the refresh + compile + domain-reload cycle completes (default 60s, max 600s)
- Domain reload restarts the HTTP service and clears REPL sessions; `--wait`
follows the matching project and requires this refresh's operation id /
generation before accepting `ready`

After completion, verify with `cs status` if needed.
After completion, use `cs doctor` for a full readiness check if needed. To wait
without triggering another refresh, use `cs wait-ready --timeout 120`.

If `refresh --wait` exits 4, do not issue another refresh. Its JSON contains
`expectedRefreshOperationId` and `expectedGeneration`; resume that exact wait:

```bash
cs wait-ready --refresh-operation "<OP_ID>" --generation <N> --timeout 120
```

`operation_in_progress` means the matching refresh is still active.
`outcome_unknown` means the matching target/state could not be confirmed. In
either case inspect `cs doctor`; if the result also includes an HTTP
`invocation.invocationId`, use that UUID with `cs doctor --operation <UUID>` to
diagnose the acceptance request. The refresh operation id and HTTP invocation id
are different identifiers.

**Manual control (when you need fine-grained steps):**

Expand Down
Loading