{"id":47283675,"url":"https://github.com/hatayama/unity-cli-loop","last_synced_at":"2026-05-29T01:03:06.797Z","repository":{"id":299257839,"uuid":"1002447118","full_name":"hatayama/unity-cli-loop","owner":"hatayama","description":"Let AI Drive Unity, from Editor to Play Mode.","archived":false,"fork":false,"pushed_at":"2026-05-18T10:00:29.000Z","size":99695,"stargazers_count":360,"open_issues_count":2,"forks_count":32,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-18T11:28:19.614Z","etag":null,"topics":["ai","automation","cli","mcp","unity","unity3d"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hatayama.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":"hatayama"}},"created_at":"2025-06-15T13:54:05.000Z","updated_at":"2026-05-18T10:00:37.000Z","dependencies_parsed_at":"2025-07-26T01:25:46.790Z","dependency_job_id":"3f9c3d39-a698-427a-aad1-bcd0a8136436","html_url":"https://github.com/hatayama/unity-cli-loop","commit_stats":null,"previous_names":["hatayama/umcp","hatayama/uloopmcp"],"tags_count":230,"template":false,"template_full_name":null,"purl":"pkg:github/hatayama/unity-cli-loop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hatayama%2Funity-cli-loop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hatayama%2Funity-cli-loop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hatayama%2Funity-cli-loop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hatayama%2Funity-cli-loop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hatayama","download_url":"https://codeload.github.com/hatayama/unity-cli-loop/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hatayama%2Funity-cli-loop/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33379721,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T01:21:08.577Z","status":"online","status_checked_at":"2026-05-23T02:00:05.530Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","automation","cli","mcp","unity","unity3d"],"created_at":"2026-03-16T04:14:02.305Z","updated_at":"2026-05-23T02:05:41.557Z","avatar_url":"https://github.com/hatayama.png","language":"C#","funding_links":["https://github.com/sponsors/hatayama"],"categories":[],"sub_categories":[],"readme":"# Unity CLI Loop\n[日本語](README_ja.md)\n\n[![Unity](https://img.shields.io/badge/Unity-2022.3+-red.svg)](https://unity3d.com/)\n[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE.md)\u003cbr\u003e\n![ClaudeCode](https://img.shields.io/badge/Claude_Code-555?logo=claude)\n![Cursor](https://img.shields.io/badge/Cursor-111?logo=Cursor)\n![Codex](https://img.shields.io/badge/Codex-111?logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSJ3aGl0ZSIgZD0iTTIyLjI4MTkgOS44MjExYTUuOTg0NyA1Ljk4NDcgMCAwIDAtLjUxNTctNC45MTA4IDYuMDQ2MiA2LjA0NjIgMCAwIDAtNi41MDk4LTIuOUE2LjA2NTEgNi4wNjUxIDAgMCAwIDQuOTgwNyA0LjE4MThhNS45ODQ3IDUuOTg0NyAwIDAgMC0zLjk5NzcgMi45IDYuMDQ2MiA2LjA0NjIgMCAwIDAgLjc0MjcgNy4wOTY2IDUuOTggNS45OCAwIDAgMCAuNTExIDQuOTEwNyA2LjA1MSA2LjA1MSAwIDAgMCA2LjUxNDYgMi45MDAxQTUuOTg0NyA1Ljk4NDcgMCAwIDAgMTMuMjU5OSAyNGE2LjA1NTcgNi4wNTU3IDAgMCAwIDUuNzcxOC00LjIwNTggNS45ODk0IDUuOTg5NCAwIDAgMCAzLjk5NzctMi45MDAxIDYuMDU1NyA2LjA1NTcgMCAwIDAtLjc0NzUtNy4wNzI5em0tOS4wMjIgMTIuNjA4MWE0LjQ3NTUgNC40NzU1IDAgMCAxLTIuODc2NC0xLjA0MDhsLjE0MTktLjA4MDQgNC43NzgzLTIuNzU4MmEuNzk0OC43OTQ4IDAgMCAwIC4zOTI3LS42ODEzdi02LjczNjlsMi4wMiAxLjE2ODZhLjA3MS4wNzEgMCAwIDEgLjAzOC4wNTJ2NS41ODI2YTQuNTA0IDQuNTA0IDAgMCAxLTQuNDk0NSA0LjQ5NDR6bS05LjY2MDctNC4xMjU0YTQuNDcwOCA0LjQ3MDggMCAwIDEtLjUzNDYtMy4wMTM3bC4xNDIuMDg1MiA0Ljc4MyAyLjc1ODJhLjc3MTIuNzcxMiAwIDAgMCAuNzgwNiAwbDUuODQyOC0zLjM2ODV2Mi4zMzI0YS4wODA0LjA4MDQgMCAwIDEtLjAzMzIuMDYxNUw5Ljc0IDE5Ljk1MDJhNC40OTkyIDQuNDk5MiAwIDAgMS02LjE0MDgtMS42NDY0ek0yLjM0MDggNy44OTU2YTQuNDg1IDQuNDg1IDAgMCAxIDIuMzY1NS0xLjk3MjhWMTEuNmEuNzY2NC43NjY0IDAgMCAwIC4zODc5LjY3NjVsNS44MTQ0IDMuMzU0My0yLjAyMDEgMS4xNjg1YS4wNzU3LjA3NTcgMCAwIDEtLjA3MSAwbC00LjgzMDMtMi43ODY1QTQuNTA0IDQuNTA0IDAgMCAxIDIuMzQwOCA3Ljg3MnptMTYuNTk2MyAzLjg1NThMMTMuMTAzOCA4LjM2NCAxNS4xMTkyIDcuMmEuMDc1Ny4wNzU3IDAgMCAxIC4wNzEgMGw0LjgzMDMgMi43OTEzYTQuNDk0NCA0LjQ5NDQgMCAwIDEtLjY3NjUgOC4xMDQydi01LjY3NzJhLjc5Ljc5IDAgMCAwLS40MDctLjY2N3ptMi4wMTA3LTMuMDIzMWwtLjE0Mi0uMDg1Mi00Ljc3MzUtMi43ODE4YS43NzU5Ljc3NTkgMCAwIDAtLjc4NTQgMEw5LjQwOSA5LjIyOTdWNi44OTc0YS4wNjYyLjA2NjIgMCAwIDEgLjAyODQtLjA2MTVsNC44MzAzLTIuNzg2NmE0LjQ5OTIgNC40OTkyIDAgMCAxIDYuNjgwMiA0LjY2ek04LjMwNjUgMTIuODYzbC0yLjAyLTEuMTYzOGEuMDgwNC4wODA0IDAgMCAxLS4wMzgtLjA1NjdWNi4wNzQyYTQuNDk5MiA0LjQ5OTIgMCAwIDEgNy4zNzU3LTMuNDUzN2wtLjE0Mi4wODA1TDguNzA0IDUuNDU5YS43OTQ4Ljc5NDggMCAwIDAtLjM5MjcuNjgxM3ptMS4wOTc2LTIuMzY1NGwyLjYwMi0xLjQ5OTggMi42MDY5IDEuNDk5OHYyLjk5OTRsLTIuNTk3NCAxLjQ5OTctMi42MDY3LTEuNDk5N1oiLz48L3N2Zz4=)\n![Antigravity](https://img.shields.io/badge/Antigravity-111?logo=google)\n![GitHubCopilot](https://img.shields.io/badge/GitHub_Copilot-111?logo=githubcopilot)\n\n\u003cp align=\"center\"\u003e\n    \u003cimg height=\"450\" alt=\"logo-black-bg\" src=\"https://github.com/user-attachments/assets/fca3047f-9042-4bf9-83bd-58b03f061082\" /\u003e\u003cbr\u003e\n    \u003csub\u003e(Logo inspired by Daft Punk's \u003ci\u003eDiscovery\u003c/i\u003e album art)\u003c/sub\u003e  \n\u003c/p\u003e\n  \n\nLet an AI agent compile, test, and operate your Unity project from popular LLM tools via CLI.\n\nDesigned to keep AI-driven development loops running autonomously inside your existing Unity projects.\n\n\u003e **Note**: This project was formerly known as **uLoopMCP**.\n\n# Concept\nUnity CLI Loop is a Unity integration tool designed so that **AI can drive your Unity project forward with minimal human intervention**.\nTasks that humans typically handle manually—compiling, running the Test Runner, checking logs, editing scenes, and capturing windows to verify UI layouts—are exposed as tools that LLMs can orchestrate.\n\nUnity CLI Loop is built around four core ideas:\n\n1. **A self-hosted development loop where AI autonomously compiles, tests, inspects logs, and fixes issues.** Uses `compile`, `run-tests`, `get-logs`, `clear-console`.\n2. **AI-driven Unity Editor operation—scene building, object manipulation, menu execution, and UI refinement from screenshots.** Uses `execute-dynamic-code`, `screenshot`.\n3. **PlayMode automated testing—AI clicks buttons, drags elements, presses keys, records and replays input, and verifies game behavior.** Uses `simulate-mouse-ui`, `simulate-mouse-input`, `simulate-keyboard`, `record-input`, `replay-input`, `execute-dynamic-code`, `screenshot`.\n4. **Achieving the above with a minimal set of tools.** See [Design Philosophy](#design-philosophy).\n\nhttps://github.com/user-attachments/assets/569a2110-7351-4cf3-8281-3a83fe181817\n\n# Installation\n\n\u003e [!WARNING]\n\u003e The following software is required\n\u003e\n\u003e - **Unity 2022.3 or later**\n\u003e - **Node.js 22.0 or later** - Required for CLI execution\n\u003e - Install via the [official site](https://nodejs.org/en/download) or your preferred version manager\n\n## Via Unity Package Manager\n\n1. Open Unity Editor\n2. Open Window \u003e Package Manager\n3. Click the \"+\" button\n4. Select \"Add package from git URL\"\n5. Enter the following URL:\n```text\nhttps://github.com/hatayama/unity-cli-loop.git?path=/Packages/src\n```\n\n\u003e **If you installed via git URL before v1.0.0**: The repository was renamed from `uLoopMCP` to `unity-cli-loop` in v1.0.0. Please update your `manifest.json`:\n\u003e ```text\n\u003e Old: https://github.com/hatayama/uLoopMCP.git?path=/Packages/src\n\u003e New: https://github.com/hatayama/unity-cli-loop.git?path=/Packages/src\n\u003e ```\n\u003e The old URL still works via GitHub redirect, but updating is recommended. OpenUPM users are not affected.\n\n## Via OpenUPM (Recommended)\n\n## Using Scoped registry in Unity Package Manager\n1. Open Project Settings window and go to Package Manager page\n2. Add the following entry to the Scoped Registries list:\n```text\nName: OpenUPM\nURL: https://package.openupm.com\nScope(s): io.github.hatayama.uloopmcp\n```\n\n3. Open Package Manager window and select OpenUPM in the My Registries section. Unity CLI Loop will be displayed.\n\n\u003e [!NOTE]\n\u003e `com.unity.inputsystem` is now an optional dependency. Install it only if you want Input System features such as `simulate-keyboard`, `simulate-mouse-input`, `record-input`, `replay-input`, and the Recordings window.\n\u003e `com.unity.test-framework` is also optional. Install it only if you want the `run-tests` tool to execute Unity Test Runner.\n\n# Quickstart\n\n## Step 1: Install the CLI\n\nSelect Window \u003e Unity CLI Loop \u003e Settings. A dedicated window will open — confirm that the **CLI** button is highlighted in blue.\n\nPress the **Install CLI** button.  \n\u003cimg width=\"277\" height=\"306\" alt=\"1\" src=\"https://github.com/user-attachments/assets/0e25c327-73bf-4af6-997b-eebb3c26b372\" /\u003e\n\n\n\nIf you see the following display, the installation was successful.  \n\u003cimg width=\"272\" height=\"309\" alt=\"2\" src=\"https://github.com/user-attachments/assets/ec14f73b-53be-4435-af95-84bb9125e3e4\" /\u003e\n\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003eTo install from terminal\u003c/summary\u003e\n\n```bash\nnpm install -g uloop-cli\n```\n\nSee [uloop-cli on npm](https://www.npmjs.com/package/uloop-cli) for details.\n\u003c/details\u003e\n\n## Step 2: Install Skills\n\nSelect your target (Claude Code, Codex, etc.) and press the **Install Skills** button.  \n\u003cimg width=\"272\" height=\"306\" alt=\"3\" src=\"https://github.com/user-attachments/assets/492e9680-726a-425b-8bf1-e5983f4f15a5\" /\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003eTo install from terminal\u003c/summary\u003e\n\n```bash\n# Install for Claude Code project\nuloop skills install --claude\n\n# Install for OpenAI Codex project\nuloop skills install --codex\n\n# Or install globally\nuloop skills install --claude --global\n```\n\u003c/details\u003e\n\nThat's it! After installing Skills, LLM tools can automatically handle instructions like these:\n\n| Your Instruction | Skill Used by LLM Tools |\n|---|---|\n| \"Launch Unity for this project\" | `/uloop-launch` |\n| \"Fix the compile errors\" | `/uloop-compile` |\n| \"Run the tests and tell me why they failed\" | `/uloop-run-tests` + `/uloop-get-logs` |\n| \"Check the scene hierarchy\" | `/uloop-get-hierarchy` |\n| \"Play the game and bring Unity to the front\" | `/uloop-control-play-mode` + `/uloop-focus-window` |\n| \"Bulk-update prefab parameters\" | `/uloop-execute-dynamic-code` |\n| \"Take a screenshot of Game View and adjust the UI layout\" | `/uloop-screenshot` + `/uloop-execute-dynamic-code` |\n| \"Record my gameplay input\" | `/uloop-record-input` |\n| \"Replay the recorded input\" | `/uloop-replay-input` |\n\n\n\u003cdetails\u003e\n\u003csummary\u003eAll 16 Bundled Skills\u003c/summary\u003e\n\n- `/uloop-launch` - Launch Unity with correct version\n- `/uloop-compile` - Execute compilation\n- `/uloop-get-logs` - Get console logs\n- `/uloop-run-tests` - Run tests\n- `/uloop-clear-console` - Clear console\n- `/uloop-focus-window` - Bring Unity Editor to front\n- `/uloop-get-hierarchy` - Get scene hierarchy\n- `/uloop-find-game-objects` - Find GameObjects\n- `/uloop-screenshot` - Capture EditorWindow\n- `/uloop-simulate-mouse-ui` - Simulate mouse click, long-press, and drag on PlayMode UI elements\n- `/uloop-simulate-mouse-input` - Simulate mouse input in PlayMode via Input System\n- `/uloop-simulate-keyboard` - Simulate keyboard input in PlayMode via Input System\n- `/uloop-record-input` - Record keyboard and mouse input during PlayMode\n- `/uloop-replay-input` - Replay recorded input during PlayMode\n- `/uloop-control-play-mode` - Control Play Mode\n- `/uloop-execute-dynamic-code` - Execute dynamic C# code\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eDirect CLI Usage (Advanced)\u003c/summary\u003e\n\nYou can also call the CLI directly without using Skills:\n\n```bash\n# List available tools\nuloop list\n\n# Launch Unity project with correct version\nuloop launch\n\n# Launch with build target (Android, iOS, StandaloneOSX, etc.)\nuloop launch -p Android\n\n# Kill running Unity and restart\nuloop launch -r\n\n# Execute compilation\nuloop compile\n\n# Compile and wait for Domain Reload to complete\nuloop compile --wait-for-domain-reload true\n\n# Get logs\nuloop get-logs --max-count 10\n\n# Run tests\nuloop run-tests --filter-type all\n\n# Execute dynamic code\nuloop execute-dynamic-code --code 'using UnityEngine; Debug.Log(\"Hello from CLI!\");'\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eShell Completion (Optional)\u003c/summary\u003e\n\nYou can install Bash/Zsh/PowerShell completion:\n\n```bash\n# Add completion script to shell config (auto-detects shell)\nuloop completion --install\n\n# Explicitly specify shell (when auto-detection fails on Windows)\nuloop completion --shell bash --install        # Git Bash / MINGW64\nuloop completion --shell powershell --install  # PowerShell\n\n# Check completion script\nuloop completion\n```\n\n\u003c/details\u003e\n\n## Project Path Specification\n\nIf `--project-path` is omitted, the port is automatically selected from the Unity project detected in the current directory.\n\nTo operate multiple Unity instances from a single LLM tool, explicitly specify a project path:\n\n```bash\n# Specify by project path (absolute or relative)\nuloop compile --project-path /Users/foo/my-unity-project\nuloop compile --project-path ../other-project\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eUsing MCP instead of CLI\u003c/summary\u003e\n\n\u003e [!WARNING]\n\u003e MCP connection may be deprecated or removed in a future release. We recommend using the CLI instead.\n\nYou can also connect via MCP (Model Context Protocol). CLI and Skills installation is not required for MCP.\n\n### MCP Connection Steps\n\n1. Select Window \u003e Unity CLI Loop \u003e Settings. A dedicated window will open — press the **MCP** button.\n\u003cimg width=\"274\" height=\"289\" alt=\"CleanShot 2026-02-26 at 20 37 16\" src=\"https://github.com/user-attachments/assets/5f2fc5db-fd33-4b5d-9f0e-3e2e0d134cf6\" /\u003e\n\n2. Next, select the target IDE in the LLM Tool Settings section. Press the yellow \"Configure {LLM Tool Name}\" button to automatically connect to the IDE.\n\u003cimg width=\"335\" alt=\"image\" src=\"https://github.com/user-attachments/assets/25f1f4f9-e3c8-40a5-a2f3-903f9ed5f45b\" /\u003e\n\n3. IDE Connection Verification\n  - For example, with Cursor, check the Tools \u0026 MCP in the settings page and find uLoopMCP. Click the toggle to enable MCP.\n\n\u003cimg width=\"657\" height=\"399\" alt=\"image\" src=\"https://github.com/user-attachments/assets/5137491d-0396-482f-b695-6700043b3f69\" /\u003e\n\n\u003e [!WARNING]\n\u003e **About Windsurf**\n\u003e Project-level configuration is not supported; only a global configuration is available.\n\n\u003cdetails\u003e\n\u003csummary\u003eManual Setup (Usually Unnecessary)\u003c/summary\u003e\n\n\u003e [!NOTE]\n\u003e Usually automatic setup is sufficient, but if needed, you can manually edit the configuration file (e.g., `mcp.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"uLoopMCP\": {\n      \"command\": \"node\",\n      \"args\": [\n        \"[Unity Package Path]/TypeScriptServer~/dist/server.bundle.js\"\n      ],\n      \"env\": {\n        \"UNITY_TCP_PORT\": \"{port}\"\n      }\n    }\n  }\n}\n```\n\n**Path Examples**:\n- **Via Package Manager**: `\"/Users/username/UnityProject/Library/PackageCache/io.github.hatayama.uloopmcp@[hash]/TypeScriptServer~/dist/server.bundle.js\"`\n\u003e [!NOTE]\n\u003e When installed via Package Manager, the package is placed in `Library/PackageCache` with a hashed directory name. Using the \"Auto Configure Cursor\" button will automatically set the correct path.\n\n\u003c/details\u003e\n\n### Multiple Unity Instance Support\n\u003e [!NOTE]\n\u003e Multiple Unity instances can be supported by changing port numbers. Unity CLI Loop automatically assigns unused ports when starting up.\n\n\u003c/details\u003e\n\n# Design Philosophy\n\nUnity CLI Loop does not chase tool count. With dynamic C# code execution (`execute-dynamic-code`), almost any Unity Editor operation can be accomplished through a single tool.\n\nToo many tools make it harder for AI to choose the right one. And even when tools are packaged as Skills, each tool's description still consumes the context window. We believe keeping tools to the essential minimum is good design.\n\nDedicated tools exist only for operations that dynamic code execution cannot handle by nature — such as frame-spanning input simulation and screenshot capture — and for operations called so frequently in the development loop, like `compile` and `get-logs`, that generating C# code each time would waste tokens.\n\n# Key Features\n## Development Loop Tools\n### 1. compile - Execute Compilation\nPerforms AssetDatabase.Refresh() and then compiles, returning the results. Can detect errors and warnings that built-in linters cannot find.\nYou can choose between incremental compilation and forced full compilation.\nWith `WaitForDomainReload=true`, results are returned after Domain Reload completes, regardless of the `ForceRecompile` value.\n```text\n→ Execute compile, analyze error and warning content\n→ Automatically fix relevant files\n→ Verify with compile again\n```\n\n### 2. get-logs - Retrieve Logs Same as Unity Console\nFilter by LogType or search target string with advanced search capabilities. You can also choose whether to include stacktrace.\nThis allows you to retrieve logs while keeping the context small.\n**MaxCount behavior**: Returns the latest logs (tail-like behavior). When MaxCount=10, returns the most recent 10 logs.\n**Advanced Search Features**:\n- **Regular Expression Support**: Use `UseRegex: true` for powerful pattern matching\n- **Stack Trace Search**: Use `SearchInStackTrace: true` to search within stack traces\n```\n→ get-logs (LogType: Error, SearchText: \"NullReference\", MaxCount: 10)\n→ get-logs (LogType: All, SearchText: \"(?i).*error.*\", UseRegex: true, MaxCount: 20)\n→ get-logs (LogType: All, SearchText: \"MyClass\", SearchInStackTrace: true, MaxCount: 50)\n→ Identify cause from stacktrace, fix relevant code\n```\n\n### 3. run-tests - Execute TestRunner (PlayMode, EditMode supported)\nExecutes Unity Test Runner and retrieves test results. This tool requires the Unity Test Framework package. If the package is not installed, `run-tests` returns an unsupported message while the rest of Unity CLI Loop keeps working. You can set conditions with FilterType and FilterValue.\n- FilterType: all (all tests), exact (individual test method name), regex (class name or namespace), assembly (assembly name)\n- FilterValue: Value according to filter type (class name, namespace, etc.)\n- SaveBeforeRun: Saves unsaved loaded Scene changes and current Prefab Stage changes before running tests when explicitly enabled\nTest results can be output as xml. The output path is returned so AI can read it.\nThis is also a strategy to avoid consuming context.\n```text\n→ run-tests (FilterType: exact, FilterValue: \"PlayerControllerTests.TestJump\")\n→ run-tests (SaveBeforeRun: true)\n→ Check failed tests, fix implementation to pass tests\n```\n\u003e [!WARNING]\n\u003e During PlayMode test execution, Domain Reload is forcibly turned OFF. (Settings are restored after test completion)\n\u003e Note that static variables will not be reset during this period.\n\n### Unity Editor Automation \u0026 Discovery Tools\n### 4. clear-console - Log Cleanup\nClear logs that become noise during log searches.\n```text\n→ clear-console\n→ Start new debug session\n```\n\n### 5. find-game-objects - Search Scene Objects\nRetrieve objects and examine component parameters. Also retrieve information about currently selected GameObjects (multiple selection supported) in Unity Editor.\n```text\n→ find-game-objects (RequiredComponents: [\"Camera\"])\n→ Investigate Camera component parameters\n\n→ find-game-objects (SearchMode: \"Selected\")\n→ Get detailed information about currently selected GameObjects in Unity Editor (supports multiple selection)\n```\n\n### 6. get-hierarchy - Analyze Scene Structure\nRetrieve information about the currently active Hierarchy in nested JSON format. Works at runtime as well.\n**Automatic File Export**: Retrieved hierarchy data is always saved as JSON in `{project_root}/.uloop/outputs/HierarchyResults/` directory. The response only returns the file path, minimizing token consumption even for large datasets.\n**Selection Mode**: Use `UseSelection: true` to get hierarchy starting from currently selected GameObject(s) in Unity Editor. Supports multiple selection - when parent and child are both selected, only the parent is used as root to avoid duplicate traversal.\n```text\n→ Understand parent-child relationships between GameObjects, discover and fix structural issues\n→ Regardless of scene size, hierarchy data is saved to a file and the path is returned instead of raw JSON\n→ get-hierarchy (UseSelection: true)\n→ Get hierarchy of currently selected GameObjects without specifying paths manually\n```\n\n### 7. focus-window - Bring Unity Editor Window to Front (macOS \u0026 Windows)\nEnsures the Unity Editor window becomes the foreground application on macOS and Windows Editor builds.\nGreat for keeping visual feedback in sync after other apps steal focus. (Linux is currently unsupported.)\n\n### 8. screenshot - Take a Screenshot of EditorWindow\nTake a screenshot of any EditorWindow as a PNG. Specify the window name (the text displayed in the title bar/tab) to capture.\nWhen multiple windows of the same type are open (e.g., 3 Inspector windows), all windows are saved with numbered filenames.\nSupports three matching modes: `exact` (default), `prefix`, and `contains` - all case-insensitive.\n```text\n→ screenshot (WindowName: \"Console\")\n→ Save Console window state as PNG\n→ Provide visual feedback to AI\n```\n\n### 9. control-play-mode - Control Play Mode\nControl Unity Editor's Play Mode. Supports three actions: Play (start/resume), Stop, and Pause.\n```\n→ control-play-mode (Action: Play)\n→ Start Play Mode to verify game behavior\n→ control-play-mode (Action: Pause)\n→ Pause to inspect state\n```\n\n### 10. execute-dynamic-code - Dynamic C# Code Execution\nExecute C# code dynamically within Unity Editor.\n\nAsync support:\n- You can write await in your snippet (Task/ValueTask/UniTask and any awaitable type)\n- Cancellation is propagated when you pass a CancellationToken to the tool\n\n**Security Level Support**: Implements 2-tier security control to restrict executable code. To disable this tool entirely, use the tool on/off toggle in the MCP tool settings UI.\n\n  - **Level 1 - Restricted** 【Recommended Setting】\n    - All Unity APIs and .NET standard libraries are generally available\n    - User-defined assemblies (Assembly-CSharp, etc.) are also accessible\n    - Only pinpoint blocking of security-critical operations:\n      - **File deletion**: `File.Delete`, `Directory.Delete`, `FileUtil.DeleteFileOrDirectory`\n      - **File writing**: `File.WriteAllText`, `File.WriteAllBytes`, `File.Replace`\n      - **Network communication**: All `HttpClient`, `WebClient`, `WebRequest`, `Socket`, `TcpClient` operations\n      - **Process execution**: `Process.Start`, `Process.Kill`\n      - **Dynamic code execution**: `Assembly.Load*`, `Type.InvokeMember`, `Activator.CreateComInstanceFrom`\n      - **Thread manipulation**: Direct `Thread`, `Task` manipulation\n      - **Registry operations**: All `Microsoft.Win32` namespace operations\n    - Safe operations are allowed:\n      - File reading (`File.ReadAllText`, `File.Exists`, etc.)\n      - Path operations (all `Path.*` operations)\n      - Information retrieval (`Assembly.GetExecutingAssembly`, `Type.GetType`, etc.)\n    - Use cases: Normal Unity development, automation with safety assurance\n\n  - **Level 2 - FullAccess**\n    - **All assemblies are accessible (no restrictions)**\n    - ⚠️ **Warning**: Security risks exist, use only with trusted code\n```\n→ execute-dynamic-code (Code: \"GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube); return \\\"Cube created\\\";\")\n→ Rapid prototype verification, batch processing automation\n→ Unity API usage restricted according to security level\n```\n\n\n\u003e [!IMPORTANT]\n\u003e **Security Settings**\n\u003e\n\u003e Some tools are disabled by default for security reasons.\n\u003e To use these tools, enable the corresponding items in the uLoopMCP window \"Security Settings\":\n\u003e\n\u003e **Basic Security Settings**:\n\u003e - **Allow Tests Execution**: Enable `run-tests` tool\n\u003e - **Allow Third Party Tools**: Enable user-developed custom tools\n\u003e\n\u003e **Dynamic Code Security Level** (`execute-dynamic-code` tool):\n\u003e - **Level 1 (Restricted)**: Unity API only, dangerous operations blocked (recommended)\n\u003e - **Level 2 (FullAccess)**: All APIs available (use with caution)\n\u003e\n\u003e To disable `execute-dynamic-code` entirely, turn it off using the tool on/off toggle.\n\u003e\n\u003e Setting changes take effect immediately without server restart.\n\u003e\n\n### PlayMode Automated Testing Tools\n### 11. simulate-mouse-ui - Simulate Mouse Input on PlayMode UI\nSimulate mouse click, long-press, and drag on PlayMode UI elements. Uses EventSystem and ExecuteEvents to dispatch pointer events directly — works independently of both old and new Input System. For game logic that reads Input System (e.g. `Mouse.current.leftButton.wasPressedThisFrame`), use `simulate-mouse-input` instead.\n\nSupports 6 actions: Click, LongPress, Drag (one-shot), DragStart/DragMove/DragEnd (split drag).\n\n```text\n→ screenshot (CaptureMode: rendering, AnnotateElements: true)\n→ Get element coordinates from AnnotatedElements (SimX/SimY)\n→ simulate-mouse-ui (Action: Click, X: 400, Y: 300)\n→ simulate-mouse-ui (Action: LongPress, X: 400, Y: 300, Duration: 5.0)\n→ simulate-mouse-ui (Action: Drag, FromX: 100, FromY: 500, X: 400, Y: 300)\n→ simulate-mouse-ui (Action: DragStart, X: 100, Y: 500)\n→ simulate-mouse-ui (Action: DragMove, X: 200, Y: 400, DragSpeed: 300)\n→ simulate-mouse-ui (Action: DragEnd, X: 400, Y: 300)\n```\nhttps://github.com/user-attachments/assets/c7ee9103-c282-4f90-8b01-64bb17400f3e\n\n### 12. simulate-mouse-input - Simulate Mouse Input in PlayMode via Input System\nSimulate mouse input in PlayMode via Input System. Injects button clicks, mouse delta, and scroll wheel directly into `Mouse.current` for game logic that reads Input System. Unlike `simulate-mouse-ui` which fires EventSystem pointer events for uGUI, this tool targets game logic that reads `Mouse.current` directly. This tool is available only when the Input System package is installed, and Active Input Handling must be set to `Input System Package (New)` or `Both` in Player Settings.\n\nSupports 5 actions: Click, LongPress, MoveDelta, SmoothDelta, Scroll.\n\n```text\n→ simulate-mouse-input (Action: Click, X: 400, Y: 300)\n→ simulate-mouse-input (Action: Click, X: 400, Y: 300, Button: Right)\n→ simulate-mouse-input (Action: LongPress, X: 400, Y: 300, Duration: 2.0)\n→ simulate-mouse-input (Action: MoveDelta, DeltaX: 100, DeltaY: 0)\n→ simulate-mouse-input (Action: Scroll, ScrollY: 120)\n→ simulate-mouse-input (Action: SmoothDelta, DeltaX: 300, DeltaY: 0, Duration: 0.5)\n```\n\n### 13. simulate-keyboard - Simulate Keyboard Input in PlayMode\nSimulate keyboard key input in PlayMode via Input System. Supports single key taps, sustained holds, and multi-key combinations (e.g. Shift+W for sprinting). This tool is available only when the Input System package is installed, and Active Input Handling must be set to `Input System Package (New)` or `Both` in Player Settings. Game code must read input via Input System API (e.g. `Keyboard.current[Key.W].isPressed`), not legacy `Input.GetKey()`.\n\nSupports 3 actions: Press (one-shot tap or timed hold), KeyDown (hold key down), KeyUp (release held key).\n\n```text\n→ simulate-keyboard (Action: Press, Key: Space)\n→ simulate-keyboard (Action: Press, Key: W, Duration: 2.0)\n→ simulate-keyboard (Action: KeyDown, Key: LeftShift)\n→ simulate-keyboard (Action: KeyDown, Key: W)\n→ screenshot (CaptureMode: rendering)\n→ simulate-keyboard (Action: KeyUp, Key: W)\n→ simulate-keyboard (Action: KeyUp, Key: LeftShift)\n```\n\n### 14. record-input - Record Input During PlayMode\nRecord keyboard and mouse input during PlayMode frame-by-frame into a JSON file. Captures key presses, mouse movement, clicks, and scroll events via Input System device state diffing. This tool is available only when the Input System package is installed.\n\n```text\n→ record-input (Action: Start)\n→ record-input (Action: Start, Keys: \"W,A,S,D,Space\")\n→ record-input (Action: Stop)\n→ JSON file saved to .uloop/outputs/InputRecordings/\n```\n\n### 15. replay-input - Replay Recorded Input During PlayMode\nReplay recorded keyboard and mouse input during PlayMode. Loads a JSON recording and injects input frame-by-frame via Input System. Supports looping and progress monitoring. This tool is available only when the Input System package is installed.\n\n```text\n→ replay-input (Action: Start)\n→ replay-input (Action: Start, InputPath: \"scripts/my-play.json\", Loop: true)\n→ replay-input (Action: Status)\n→ replay-input (Action: Stop)\n```\n\n## Tool Reference\n\nFor detailed specifications of all tools (parameters, responses, examples), see **[TOOL_REFERENCE.md](/Packages/src/TOOL_REFERENCE.md)**.\n\n## Unity CLI Loop Extension Development\nUnity CLI Loop enables efficient development of project-specific tools without requiring changes to the core package.\nThe type-safe design allows for reliable custom tool implementation in minimal time.\n(If you ask AI, they should be able to make it for you soon ✨)\n\nYou can publish your extension tools on GitHub and reuse them across other projects. See [uLoopMCP-extensions-sample](https://github.com/hatayama/uLoopMCP-extensions-sample) for an example.\n\n\u003e [!TIP]\n\u003e **For AI-assisted development**: Detailed implementation guides are available in [.claude/rules/mcp-tools.md](/.claude/rules/mcp-tools.md) for tool development and [.claude/rules/cli.md](/.claude/rules/cli.md) for CLI/Skills development. These guides are automatically loaded by Claude Code when working in the relevant directories.\n\n\u003e [!IMPORTANT]\n\u003e **Security Settings**\n\u003e\n\u003e Project-specific tools require enabling **Allow Third Party Tools** in the uLoopMCP window \"Security Settings\".\n\u003e When developing custom tools that involve dynamic code execution, also consider the **Dynamic Code Security Level** setting.\n\n\u003cdetails\u003e\n\u003csummary\u003eView Implementation Guide\u003c/summary\u003e\n\n**Step 1: Create Schema Class** (define parameters):\n```csharp\nusing System.ComponentModel;\n\npublic class MyCustomSchema : BaseToolSchema\n{\n    [Description(\"Parameter description\")]\n    public string MyParameter { get; set; } = \"default_value\";\n\n    [Description(\"Example enum parameter\")]\n    public MyEnum EnumParameter { get; set; } = MyEnum.Option1;\n}\n\npublic enum MyEnum\n{\n    Option1 = 0,\n    Option2 = 1,\n    Option3 = 2\n}\n```\n\n**Step 2: Create Response Class** (define return data):\n```csharp\npublic class MyCustomResponse : BaseToolResponse\n{\n    public string Result { get; set; }\n    public bool Success { get; set; }\n\n    public MyCustomResponse(string result, bool success)\n    {\n        Result = result;\n        Success = success;\n    }\n\n    // Required parameterless constructor\n    public MyCustomResponse() { }\n}\n```\n\n**Step 3: Create Tool Class**:\n```csharp\nusing System.Threading;\nusing System.Threading.Tasks;\n\n[McpTool(Description = \"Description of my custom tool\")]  // ← Auto-registered with this attribute\npublic class MyCustomTool : AbstractUnityTool\u003cMyCustomSchema, MyCustomResponse\u003e\n{\n    public override string ToolName =\u003e \"my-custom-tool\";\n\n    // Executed on main thread\n    protected override Task\u003cMyCustomResponse\u003e ExecuteAsync(MyCustomSchema parameters, CancellationToken cancellationToken)\n    {\n        // Type-safe parameter access\n        string param = parameters.MyParameter;\n        MyEnum enumValue = parameters.EnumParameter;\n\n        // Check for cancellation before long-running operations\n        cancellationToken.ThrowIfCancellationRequested();\n\n        // Implement custom logic here\n        string result = ProcessCustomLogic(param, enumValue);\n        bool success = !string.IsNullOrEmpty(result);\n\n        // For long-running operations, periodically check for cancellation\n        // cancellationToken.ThrowIfCancellationRequested();\n\n        return Task.FromResult(new MyCustomResponse(result, success));\n    }\n\n    private string ProcessCustomLogic(string input, MyEnum enumValue)\n    {\n        // Implement custom logic\n        return $\"Processed '{input}' with enum '{enumValue}'\";\n    }\n}\n```\n\n\u003e [!IMPORTANT]\n\u003e **Important Notes**:\n\u003e - **Thread Safety**: Tools execute on Unity's main thread, so Unity API calls are safe without additional synchronization.\n\nPlease also refer to [Custom Tool Samples](/Assets/Editor/CustomToolSamples).\n\n\u003c/details\u003e\n\n### Custom Skills for Your Tools\n\nWhen you create a custom tool, you can create a `Skill/` subfolder within the tool folder and place a `SKILL.md` file there. This allows LLM tools to automatically discover and use your custom tool through the Skills system.\n\n**How it works:**\n1. Create a `Skill/` subfolder in your custom tool's folder\n2. Place `SKILL.md` inside the `Skill/` folder\n3. Run `uloop skills install --claude` to install all skills (bundled + project)\n4. LLM tools will automatically recognize your custom skill\n\n**Directory structure:**\n```\nAssets/Editor/CustomTools/MyTool/\n├── MyTool.cs           # Tool implementation\n└── Skill/\n    ├── SKILL.md        # Skill definition (required)\n    └── references/     # Additional files (optional)\n        └── usage.md\n```\n\n**SKILL.md format:**\n```markdown\n---\nname: uloop-my-custom-tool\ndescription: \"Description of what the tool does and when to use it.\"\n---\n\n# uloop my-custom-tool\n\nDetailed documentation for the tool...\n```\n\n**Scanned locations** (searches for `Skill/SKILL.md` files):\n- `Assets/**/Editor/\u003cToolFolder\u003e/Skill/SKILL.md`\n- `Packages/*/Editor/\u003cToolFolder\u003e/Skill/SKILL.md`\n- `Library/PackageCache/*/Editor/\u003cToolFolder\u003e/Skill/SKILL.md`\n\n\u003e [!TIP]\n\u003e - Add `internal: true` to the frontmatter to exclude a skill from installation (useful for internal/debug tools)\n\u003e - Additional files in the `Skill/` folder (such as `references/`, `scripts/`, `assets/`) are also copied during installation\n\nSee [HelloWorld sample](/Assets/Editor/CustomCommandSamples/HelloWorld/Skill/SKILL.md) for a complete example.\n\nFor a more comprehensive example project, see [uLoopMCP-extensions-sample](https://github.com/hatayama/uLoopMCP-extensions-sample).\n\n## Other\n\n### Unity CLI Loop Files\n\n`UserSettings/UnityMcpSettings.json` stores per-user editor session state and should always remain local-only.\n\nThe `.uloop/` directory at the project root stores CLI cache, tool registry, and runtime outputs. Most of its contents are local-only, but some files can optionally be git-tracked for team sharing.\n\n| File | Purpose | Git-track? |\n|------|---------|------------|\n| `settings.permissions.json` | Team-wide security policy (third-party tool access, dynamic code security level) | Optional |\n| `settings.tools.json` | Per-tool enable/disable preferences | Optional |\n| `tools.json` | Auto-generated MCP tool registry | No |\n| `outputs/` | Runtime outputs (test results, screenshots, hierarchy dumps) | No |\n\n\u003e [!TIP]\n\u003e **Recommended `.gitignore` pattern**\n\u003e\n\u003e ```gitignore\n\u003e **/.uloop/*\n\u003e !**/.uloop/settings.permissions.json\n\u003e !**/.uloop/settings.tools.json\n\u003e ```\n\u003e\n\u003e This ignores auto-generated files and runtime outputs while allowing team-shared configuration to be tracked.\n\u003e Adjust the `!` lines to match your team's needs — you can remove either line if you don't need to share that file.\n\n## License\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhatayama%2Funity-cli-loop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhatayama%2Funity-cli-loop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhatayama%2Funity-cli-loop/lists"}