uloop-cli 0.48.3 → 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/cli.bundle.cjs +211 -22
  2. package/dist/cli.bundle.cjs.map +3 -3
  3. package/jest.config.cjs +2 -1
  4. package/md-transformer.cjs +11 -0
  5. package/package.json +1 -1
  6. package/scripts/generate-bundled-skills.ts +87 -31
  7. package/src/__tests__/cli-e2e.test.ts +76 -10
  8. package/src/__tests__/skills-manager.test.ts +158 -0
  9. package/src/cli.ts +44 -2
  10. package/src/default-tools.json +1 -1
  11. package/src/skills/bundled-skills.ts +19 -16
  12. package/src/skills/skill-definitions/cli-only/uloop-get-version/SKILL.md +37 -0
  13. package/src/skills/skills-manager.ts +232 -9
  14. package/src/version.ts +1 -1
  15. package/CLAUDE.md +0 -61
  16. package/src/skills/skill-definitions/uloop-capture-unity-window/SKILL.md +0 -81
  17. package/src/skills/skill-definitions/uloop-clear-console/SKILL.md +0 -34
  18. package/src/skills/skill-definitions/uloop-compile/SKILL.md +0 -47
  19. package/src/skills/skill-definitions/uloop-control-play-mode/SKILL.md +0 -48
  20. package/src/skills/skill-definitions/uloop-execute-dynamic-code/SKILL.md +0 -79
  21. package/src/skills/skill-definitions/uloop-execute-menu-item/SKILL.md +0 -43
  22. package/src/skills/skill-definitions/uloop-find-game-objects/SKILL.md +0 -46
  23. package/src/skills/skill-definitions/uloop-focus-window/SKILL.md +0 -34
  24. package/src/skills/skill-definitions/uloop-get-hierarchy/SKILL.md +0 -44
  25. package/src/skills/skill-definitions/uloop-get-logs/SKILL.md +0 -45
  26. package/src/skills/skill-definitions/uloop-get-menu-items/SKILL.md +0 -44
  27. package/src/skills/skill-definitions/uloop-get-provider-details/SKILL.md +0 -45
  28. package/src/skills/skill-definitions/uloop-get-version/SKILL.md +0 -32
  29. package/src/skills/skill-definitions/uloop-run-tests/SKILL.md +0 -43
  30. package/src/skills/skill-definitions/uloop-unity-search/SKILL.md +0 -44
  31. /package/src/skills/skill-definitions/{uloop-get-project-info → cli-only/uloop-get-project-info}/SKILL.md +0 -0
@@ -5621,7 +5621,7 @@ var import_path3 = require("path");
5621
5621
 
5622
5622
  // src/default-tools.json
5623
5623
  var default_tools_default = {
5624
- version: "0.48.3",
5624
+ version: "0.49.0",
5625
5625
  tools: [
5626
5626
  {
5627
5627
  name: "compile",
@@ -6042,7 +6042,7 @@ function getCacheFilePath() {
6042
6042
  }
6043
6043
 
6044
6044
  // src/version.ts
6045
- var VERSION = "0.48.3";
6045
+ var VERSION = "0.49.0";
6046
6046
 
6047
6047
  // src/spinner.ts
6048
6048
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
@@ -6333,46 +6333,46 @@ var import_fs4 = require("fs");
6333
6333
  var import_path5 = require("path");
6334
6334
  var import_os = require("os");
6335
6335
 
6336
- // src/skills/skill-definitions/uloop-capture-unity-window/SKILL.md
6336
+ // ../Editor/Api/McpTools/CaptureUnityWindow/SKILL.md
6337
6337
  var SKILL_default = '---\nname: uloop-capture-unity-window\ndescription: Capture Unity EditorWindow and save as PNG image. Use when you need to: (1) Take a screenshot of Game View, Scene View, Console, Inspector, etc., (2) Capture visual state for debugging or verification, (3) Save editor output as an image file.\n---\n\n# uloop capture-unity-window\n\nCapture any Unity EditorWindow by name and save as PNG image.\n\n## Usage\n\n```bash\nuloop capture-unity-window [--window-name <name>] [--resolution-scale <scale>]\n```\n\n## Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `--window-name` | string | `Game` | Window name to capture (e.g., "Game", "Scene", "Console", "Inspector", "Project", "Hierarchy", or any EditorWindow title) |\n| `--resolution-scale` | number | `1.0` | Resolution scale (0.1 to 1.0) |\n\n## Window Name\n\nThe window name is the text displayed in the window\'s title bar (tab). The user (human) will tell you which window to capture. Common window names include:\n\n- **Game**: Game View window\n- **Scene**: Scene View window\n- **Console**: Console window\n- **Inspector**: Inspector window\n- **Project**: Project browser window\n- **Hierarchy**: Hierarchy window\n- **Animation**: Animation window\n- **Animator**: Animator window\n- **Profiler**: Profiler window\n- **Audio Mixer**: Audio Mixer window\n\nYou can also specify custom EditorWindow titles (e.g., "EditorWindow Capture Test").\n\n## Examples\n\n```bash\n# Capture Game View at full resolution\nuloop capture-unity-window\n\n# Capture Game View at half resolution\nuloop capture-unity-window --window-name Game --resolution-scale 0.5\n\n# Capture Scene View\nuloop capture-unity-window --window-name Scene\n\n# Capture Console window\nuloop capture-unity-window --window-name Console\n\n# Capture Inspector window\nuloop capture-unity-window --window-name Inspector\n\n# Capture Project browser\nuloop capture-unity-window --window-name Project\n\n# Capture custom EditorWindow by title\nuloop capture-unity-window --window-name "My Custom Window"\n```\n\n## Output\n\nReturns JSON with:\n- `CapturedCount`: Number of windows captured\n- `CapturedWindows`: Array of captured window info, each containing:\n - `ImagePath`: Absolute path to the saved PNG image\n - `FileSizeBytes`: Size of the saved file in bytes\n - `Width`: Captured image width in pixels\n - `Height`: Captured image height in pixels\n\nWhen multiple windows of the same type are open (e.g., multiple Inspector windows), all matching windows are captured with numbered filenames (e.g., `Inspector_1_*.png`, `Inspector_2_*.png`).\n\n## Notes\n\n- Use `uloop focus-window` first if needed\n- Target window must be open in Unity Editor\n- Window name matching is case-insensitive\n';
6338
6338
 
6339
- // src/skills/skill-definitions/uloop-clear-console/SKILL.md
6339
+ // ../Editor/Api/McpTools/ClearConsole/SKILL.md
6340
6340
  var SKILL_default2 = "---\nname: uloop-clear-console\ndescription: Clear Unity console logs via uloop CLI. Use when you need to: (1) Clear the console before running tests, (2) Start a fresh debugging session, (3) Clean up log output for better readability.\n---\n\n# uloop clear-console\n\nClear Unity console logs.\n\n## Usage\n\n```bash\nuloop clear-console [--add-confirmation-message]\n```\n\n## Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `--add-confirmation-message` | boolean | `false` | Add confirmation message after clearing |\n\n## Examples\n\n```bash\n# Clear console\nuloop clear-console\n\n# Clear with confirmation\nuloop clear-console --add-confirmation-message\n```\n\n## Output\n\nReturns JSON confirming the console was cleared.\n";
6341
6341
 
6342
- // src/skills/skill-definitions/uloop-compile/SKILL.md
6342
+ // ../Editor/Api/McpTools/Compile/SKILL.md
6343
6343
  var SKILL_default3 = '---\nname: uloop-compile\ndescription: Compile Unity project via uloop CLI. Use when you need to: (1) Verify C# code compiles successfully after editing scripts, (2) Check for compile errors or warnings, (3) Validate script changes before running tests.\n---\n\n# uloop compile\n\nExecute Unity project compilation.\n\n## Usage\n\n```bash\nuloop compile [--force-recompile]\n```\n\n## Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `--force-recompile` | boolean | Force full recompilation (triggers Domain Reload) |\n\n## Examples\n\n```bash\n# Check compilation\nuloop compile\n\n# Force full recompilation\nuloop compile --force-recompile\n```\n\n## Output\n\nReturns JSON:\n- `Success`: boolean\n- `ErrorCount`: number\n- `WarningCount`: number\n\n## Troubleshooting\n\nIf CLI hangs or shows "Unity is busy" errors after compilation, stale lock files may be preventing connection. Run the following to clean them up:\n\n```bash\nuloop fix\n```\n\nThis removes any leftover lock files (`compiling.lock`, `domainreload.lock`, `serverstarting.lock`) from the Unity project\'s Temp directory.\n';
6344
6344
 
6345
- // src/skills/skill-definitions/uloop-control-play-mode/SKILL.md
6346
- var SKILL_default4 = "---\nname: uloop-control-play-mode\ndescription: Control Unity Editor play mode via uloop CLI. Use when you need to: (1) Start play mode for testing, (2) Stop play mode after testing, (3) Pause play mode for debugging.\n---\n\n# uloop control-play-mode\n\nControl Unity Editor play mode (play/stop/pause).\n\n## Usage\n\n```bash\nuloop control-play-mode [options]\n```\n\n## Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `--action` | string | `Play` | Action to perform: `Play`, `Stop`, `Pause` |\n\n## Examples\n\n```bash\n# Start play mode\nuloop control-play-mode --action Play\n\n# Stop play mode\nuloop control-play-mode --action Stop\n\n# Pause play mode\nuloop control-play-mode --action Pause\n```\n\n## Output\n\nReturns JSON with the current play mode state:\n- `IsPlaying`: Whether Unity is currently in play mode\n- `IsPaused`: Whether play mode is paused\n- `Message`: Description of the action performed\n\n## Notes\n\n- Play action starts the game in the Unity Editor (also resumes from pause)\n- Stop action exits play mode and returns to edit mode\n- Pause action pauses the game while remaining in play mode\n- Useful for automated testing workflows\n\n";
6345
+ // ../Editor/Api/McpTools/ControlPlayMode/SKILL.md
6346
+ var SKILL_default4 = "---\nname: uloop-control-play-mode\ndescription: Control Unity Editor play mode via uloop CLI. Use when you need to: (1) Start play mode for testing, (2) Stop play mode after testing, (3) Pause play mode for debugging.\n---\n\n# uloop control-play-mode\n\nControl Unity Editor play mode (play/stop/pause).\n\n## Usage\n\n```bash\nuloop control-play-mode [options]\n```\n\n## Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `--action` | string | `Play` | Action to perform: `Play`, `Stop`, `Pause` |\n\n## Examples\n\n```bash\n# Start play mode\nuloop control-play-mode --action Play\n\n# Stop play mode\nuloop control-play-mode --action Stop\n\n# Pause play mode\nuloop control-play-mode --action Pause\n```\n\n## Output\n\nReturns JSON with the current play mode state:\n- `IsPlaying`: Whether Unity is currently in play mode\n- `IsPaused`: Whether play mode is paused\n- `Message`: Description of the action performed\n\n## Notes\n\n- Play action starts the game in the Unity Editor (also resumes from pause)\n- Stop action exits play mode and returns to edit mode\n- Pause action pauses the game while remaining in play mode\n- Useful for automated testing workflows\n";
6347
6347
 
6348
- // src/skills/skill-definitions/uloop-execute-dynamic-code/SKILL.md
6348
+ // ../Editor/Api/McpTools/ExecuteDynamicCode/SKILL.md
6349
6349
  var SKILL_default5 = "---\nname: uloop-execute-dynamic-code\ndescription: Execute C# code dynamically in Unity Editor via uloop CLI. Use for editor automation: (1) Prefab/material wiring and AddComponent operations, (2) Reference wiring with SerializedObject, (3) Scene/hierarchy edits and batch operations. NOT for file I/O or script authoring.\n---\n\n# uloop execute-dynamic-code\n\nExecute C# code dynamically in Unity Editor.\n\n## Usage\n\n```bash\nuloop execute-dynamic-code --code '<c# code>'\n```\n\n## Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `--code` | string | C# code to execute (direct statements, no class wrapper) |\n| `--compile-only` | boolean | Compile without execution |\n| `--auto-qualify-unity-types-once` | boolean | Auto-qualify Unity types |\n\n## Code Format\n\nWrite direct statements only (no classes/namespaces/methods). Return is optional.\n\n```csharp\n// Using directives at top are hoisted\nusing UnityEngine;\nvar x = Mathf.PI;\nreturn x;\n```\n\n## String Literals (Shell-specific)\n\n| Shell | Method |\n|-------|--------|\n| bash/zsh/MINGW64/Git Bash | `'Debug.Log(\"Hello!\");'` |\n| PowerShell | `'Debug.Log(\"\"Hello!\"\");'` |\n\n## Allowed Operations\n\n- Prefab/material wiring (PrefabUtility)\n- AddComponent + reference wiring (SerializedObject)\n- Scene/hierarchy edits\n- Inspector modifications\n\n## Forbidden Operations\n\n- System.IO.* (File/Directory/Path)\n- AssetDatabase.CreateFolder / file writes\n- Create/edit .cs/.asmdef files\n\n## Examples\n\n### bash / zsh / MINGW64 / Git Bash\n\n```bash\nuloop execute-dynamic-code --code 'return Selection.activeGameObject?.name;'\nuloop execute-dynamic-code --code 'new GameObject(\"MyObject\");'\nuloop execute-dynamic-code --code 'UnityEngine.Debug.Log(\"Hello from CLI!\");'\n```\n\n### PowerShell\n\n```powershell\nuloop execute-dynamic-code --code 'return Selection.activeGameObject?.name;'\nuloop execute-dynamic-code --code 'new GameObject(\"\"MyObject\"\");'\nuloop execute-dynamic-code --code 'UnityEngine.Debug.Log(\"\"Hello from CLI!\"\");'\n```\n\n## Output\n\nReturns JSON with execution result or compile errors.\n\n## Notes\n\nFor file/directory operations, use terminal commands instead.\n";
6350
6350
 
6351
- // src/skills/skill-definitions/uloop-execute-menu-item/SKILL.md
6351
+ // ../Editor/Api/McpTools/ExecuteMenuItem/SKILL.md
6352
6352
  var SKILL_default6 = '---\nname: uloop-execute-menu-item\ndescription: Execute Unity MenuItem via uloop CLI. Use when you need to: (1) Trigger menu commands programmatically, (2) Automate editor actions (save, build, refresh), (3) Run custom menu items defined in scripts.\n---\n\n# uloop execute-menu-item\n\nExecute Unity MenuItem.\n\n## Usage\n\n```bash\nuloop execute-menu-item --menu-item-path "<path>"\n```\n\n## Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `--menu-item-path` | string | - | Menu item path (e.g., "GameObject/Create Empty") |\n| `--use-reflection-fallback` | boolean | `true` | Use reflection fallback |\n\n## Examples\n\n```bash\n# Create empty GameObject\nuloop execute-menu-item --menu-item-path "GameObject/Create Empty"\n\n# Save scene\nuloop execute-menu-item --menu-item-path "File/Save"\n\n# Open project settings\nuloop execute-menu-item --menu-item-path "Edit/Project Settings..."\n```\n\n## Output\n\nReturns JSON with execution result.\n\n## Notes\n\n- Use `uloop get-menu-items` to discover available menu paths\n- Some menu items may require specific context or selection\n';
6353
6353
 
6354
- // src/skills/skill-definitions/uloop-find-game-objects/SKILL.md
6354
+ // ../Editor/Api/McpTools/FindGameObjects/SKILL.md
6355
6355
  var SKILL_default7 = '---\nname: uloop-find-game-objects\ndescription: Find GameObjects with search criteria via uloop CLI. Use when you need to: (1) Locate GameObjects by name pattern, (2) Find objects by tag or layer, (3) Search for objects with specific component types.\n---\n\n# uloop find-game-objects\n\nFind GameObjects with search criteria.\n\n## Usage\n\n```bash\nuloop find-game-objects [options]\n```\n\n## Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `--name-pattern` | string | - | Name pattern to search |\n| `--search-mode` | string | `Contains` | Search mode: `Exact`, `Path`, `Regex`, `Contains` |\n| `--required-components` | array | - | Required components |\n| `--tag` | string | - | Tag filter |\n| `--layer` | string | - | Layer filter |\n| `--max-results` | integer | `20` | Maximum number of results |\n| `--include-inactive` | boolean | `false` | Include inactive GameObjects |\n\n## Examples\n\n```bash\n# Find by name\nuloop find-game-objects --name-pattern "Player"\n\n# Find with component\nuloop find-game-objects --required-components Rigidbody\n\n# Find by tag\nuloop find-game-objects --tag "Enemy"\n\n# Regex search\nuloop find-game-objects --name-pattern "UI_.*" --search-mode Regex\n```\n\n## Output\n\nReturns JSON array of matching GameObjects with paths and components.\n';
6356
6356
 
6357
- // src/skills/skill-definitions/uloop-focus-window/SKILL.md
6357
+ // ../Editor/Api/McpTools/FocusUnityWindow/SKILL.md
6358
6358
  var SKILL_default8 = "---\nname: uloop-focus-window\ndescription: Bring Unity Editor window to front via uloop CLI. Use when you need to: (1) Focus Unity Editor before capturing screenshots, (2) Ensure Unity window is visible for visual checks, (3) Bring Unity to foreground for user interaction.\n---\n\n# uloop focus-window\n\nBring Unity Editor window to front.\n\n## Usage\n\n```bash\nuloop focus-window\n```\n\n## Parameters\n\nNone.\n\n## Examples\n\n```bash\n# Focus Unity Editor\nuloop focus-window\n```\n\n## Output\n\nReturns JSON confirming the window was focused.\n\n## Notes\n\n- Useful before `uloop capture-unity-window` to ensure the target window is visible\n- Brings the main Unity Editor window to the foreground\n";
6359
6359
 
6360
- // src/skills/skill-definitions/uloop-get-hierarchy/SKILL.md
6360
+ // ../Editor/Api/McpTools/GetHierarchy/SKILL.md
6361
6361
  var SKILL_default9 = '---\nname: uloop-get-hierarchy\ndescription: Get Unity Hierarchy structure via uloop CLI. Use when you need to: (1) Inspect scene structure and GameObject tree, (2) Find GameObjects and their parent-child relationships, (3) Check component attachments on objects.\n---\n\n# uloop get-hierarchy\n\nGet Unity Hierarchy structure.\n\n## Usage\n\n```bash\nuloop get-hierarchy [options]\n```\n\n## Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `--root-path` | string | - | Root GameObject path to start from |\n| `--max-depth` | integer | `-1` | Maximum depth (-1 for unlimited) |\n| `--include-components` | boolean | `true` | Include component information |\n| `--include-inactive` | boolean | `true` | Include inactive GameObjects |\n| `--include-paths` | boolean | `false` | Include full path information |\n\n## Examples\n\n```bash\n# Get entire hierarchy\nuloop get-hierarchy\n\n# Get hierarchy from specific root\nuloop get-hierarchy --root-path "Canvas/UI"\n\n# Limit depth\nuloop get-hierarchy --max-depth 2\n\n# Without components\nuloop get-hierarchy --include-components false\n```\n\n## Output\n\nReturns JSON with hierarchical structure of GameObjects and their components.\n';
6362
6362
 
6363
- // src/skills/skill-definitions/uloop-get-logs/SKILL.md
6363
+ // ../Editor/Api/McpTools/GetLogs/SKILL.md
6364
6364
  var SKILL_default10 = '---\nname: uloop-get-logs\ndescription: Retrieve Unity Console logs via uloop CLI. Use when you need to: (1) Check for errors or warnings after operations, (2) Debug runtime issues in Unity Editor, (3) Investigate unexpected behavior or exceptions.\n---\n\n# uloop get-logs\n\nRetrieve logs from Unity Console.\n\n## Usage\n\n```bash\nuloop get-logs [options]\n```\n\n## Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `--log-type` | string | `All` | Log type filter: `Error`, `Warning`, `Log`, `All` |\n| `--max-count` | integer | `100` | Maximum number of logs to retrieve |\n| `--search-text` | string | - | Text to search within logs |\n| `--include-stack-trace` | boolean | `true` | Include stack trace in output |\n| `--use-regex` | boolean | `false` | Use regex for search |\n| `--search-in-stack-trace` | boolean | `false` | Search within stack trace |\n\n## Examples\n\n```bash\n# Get all logs\nuloop get-logs\n\n# Get only errors\nuloop get-logs --log-type Error\n\n# Search for specific text\nuloop get-logs --search-text "NullReference"\n\n# Regex search\nuloop get-logs --search-text "Missing.*Component" --use-regex\n```\n\n## Output\n\nReturns JSON array of log entries with message, type, and optional stack trace.\n';
6365
6365
 
6366
- // src/skills/skill-definitions/uloop-get-menu-items/SKILL.md
6366
+ // ../Editor/Api/McpTools/GetMenuItems/SKILL.md
6367
6367
  var SKILL_default11 = '---\nname: uloop-get-menu-items\ndescription: Retrieve Unity MenuItems via uloop CLI. Use when you need to: (1) Discover available menu commands in Unity Editor, (2) Find menu paths for automation, (3) Prepare for executing menu items programmatically.\n---\n\n# uloop get-menu-items\n\nRetrieve Unity MenuItems.\n\n## Usage\n\n```bash\nuloop get-menu-items [options]\n```\n\n## Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `--filter-text` | string | - | Filter text |\n| `--filter-type` | string | `contains` | Filter type: `contains`, `exact`, `startswith` |\n| `--max-count` | integer | `200` | Maximum number of items |\n| `--include-validation` | boolean | `false` | Include validation functions |\n\n## Examples\n\n```bash\n# List all menu items\nuloop get-menu-items\n\n# Filter by text\nuloop get-menu-items --filter-text "GameObject"\n\n# Exact match\nuloop get-menu-items --filter-text "File/Save" --filter-type exact\n```\n\n## Output\n\nReturns JSON array of menu items with paths and metadata.\n\n## Notes\n\nUse with `uloop execute-menu-item` to run discovered menu commands.\n';
6368
6368
 
6369
- // src/skills/skill-definitions/uloop-get-provider-details/SKILL.md
6369
+ // ../Editor/Api/McpTools/UnitySearchProviderDetails/SKILL.md
6370
6370
  var SKILL_default12 = "---\nname: uloop-get-provider-details\ndescription: Get Unity Search provider details via uloop CLI. Use when you need to: (1) Discover available search providers, (2) Understand search capabilities and filters, (3) Configure searches with specific provider options.\n---\n\n# uloop get-provider-details\n\nGet detailed information about Unity Search providers.\n\n## Usage\n\n```bash\nuloop get-provider-details [options]\n```\n\n## Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `--provider-id` | string | - | Specific provider ID to query |\n| `--active-only` | boolean | `false` | Only show active providers |\n| `--include-descriptions` | boolean | `true` | Include descriptions |\n| `--sort-by-priority` | boolean | `true` | Sort by priority |\n\n## Examples\n\n```bash\n# List all providers\nuloop get-provider-details\n\n# Get specific provider\nuloop get-provider-details --provider-id asset\n\n# Active providers only\nuloop get-provider-details --active-only\n```\n\n## Output\n\nReturns JSON:\n- `Providers`: array of provider info (ID, name, description, priority)\n\n## Notes\n\nUse provider IDs with `uloop unity-search --providers` option.\n";
6371
6371
 
6372
- // src/skills/skill-definitions/uloop-run-tests/SKILL.md
6372
+ // ../Editor/Api/McpTools/RunTests/SKILL.md
6373
6373
  var SKILL_default13 = '---\nname: uloop-run-tests\ndescription: Execute Unity Test Runner via uloop CLI. Use when you need to: (1) Run unit tests (EditMode tests), (2) Run integration tests (PlayMode tests), (3) Verify code changes don\'t break existing functionality.\n---\n\n# uloop run-tests\n\nExecute Unity Test Runner.\n\n## Usage\n\n```bash\nuloop run-tests [options]\n```\n\n## Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `--test-mode` | string | `EditMode` | Test mode: `EditMode`, `PlayMode` |\n| `--filter-type` | string | `all` | Filter type: `all`, `exact`, `regex`, `assembly` |\n| `--filter-value` | string | - | Filter value (test name, pattern, or assembly) |\n| `--save-xml` | boolean | `false` | Save test results as XML |\n\n## Examples\n\n```bash\n# Run all EditMode tests\nuloop run-tests\n\n# Run PlayMode tests\nuloop run-tests --test-mode PlayMode\n\n# Run specific test\nuloop run-tests --filter-type exact --filter-value "MyTest.TestMethod"\n\n# Run tests matching pattern\nuloop run-tests --filter-type regex --filter-value ".*Integration.*"\n```\n\n## Output\n\nReturns JSON with test results including pass/fail counts and details.\n';
6374
6374
 
6375
- // src/skills/skill-definitions/uloop-unity-search/SKILL.md
6375
+ // ../Editor/Api/McpTools/UnitySearch/SKILL.md
6376
6376
  var SKILL_default14 = '---\nname: uloop-unity-search\ndescription: Search Unity project via uloop CLI. Use when you need to: (1) Find assets by name or type (scenes, prefabs, scripts, materials), (2) Search for project resources using Unity\'s search system, (3) Locate files within the Unity project.\n---\n\n# uloop unity-search\n\nSearch Unity project using Unity Search.\n\n## Usage\n\n```bash\nuloop unity-search [options]\n```\n\n## Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `--search-query` | string | - | Search query |\n| `--providers` | array | - | Search providers (e.g., `asset`, `scene`, `find`) |\n| `--max-results` | integer | `50` | Maximum number of results |\n| `--save-to-file` | boolean | `false` | Save results to file |\n\n## Examples\n\n```bash\n# Search for assets\nuloop unity-search --search-query "Player"\n\n# Search with specific provider\nuloop unity-search --search-query "t:Prefab" --providers asset\n\n# Limit results\nuloop unity-search --search-query "*.cs" --max-results 20\n```\n\n## Output\n\nReturns JSON array of search results with paths and metadata.\n\n## Notes\n\nUse `uloop get-provider-details` to discover available search providers.\n';
6377
6377
 
6378
6378
  // src/skills/bundled-skills.ts
@@ -6450,6 +6450,7 @@ var BUNDLED_SKILLS = [
6450
6450
  ];
6451
6451
 
6452
6452
  // src/skills/skills-manager.ts
6453
+ var EXCLUDED_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "Temp", "obj", "Build", "Builds", "Logs"]);
6453
6454
  function getGlobalSkillsDir(target) {
6454
6455
  return (0, import_path5.join)((0, import_os.homedir)(), target.projectDir, "skills");
6455
6456
  }
@@ -6481,12 +6482,125 @@ function getSkillStatus(skill, target, global) {
6481
6482
  }
6482
6483
  return "installed";
6483
6484
  }
6485
+ function parseFrontmatter(content) {
6486
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
6487
+ if (!frontmatterMatch) {
6488
+ return {};
6489
+ }
6490
+ const frontmatter = {};
6491
+ const lines = frontmatterMatch[1].split("\n");
6492
+ for (const line of lines) {
6493
+ const colonIndex = line.indexOf(":");
6494
+ if (colonIndex === -1) {
6495
+ continue;
6496
+ }
6497
+ const key = line.slice(0, colonIndex).trim();
6498
+ const value = line.slice(colonIndex + 1).trim();
6499
+ if (value === "true") {
6500
+ frontmatter[key] = true;
6501
+ } else if (value === "false") {
6502
+ frontmatter[key] = false;
6503
+ } else {
6504
+ frontmatter[key] = value;
6505
+ }
6506
+ }
6507
+ return frontmatter;
6508
+ }
6509
+ function scanEditorFolderForSkills(editorPath, skills) {
6510
+ if (!(0, import_fs4.existsSync)(editorPath)) {
6511
+ return;
6512
+ }
6513
+ const entries = (0, import_fs4.readdirSync)(editorPath, { withFileTypes: true });
6514
+ for (const entry of entries) {
6515
+ if (EXCLUDED_DIRS.has(entry.name)) {
6516
+ continue;
6517
+ }
6518
+ const fullPath = (0, import_path5.join)(editorPath, entry.name);
6519
+ if (entry.isDirectory()) {
6520
+ const skillMdPath = (0, import_path5.join)(fullPath, "SKILL.md");
6521
+ if ((0, import_fs4.existsSync)(skillMdPath)) {
6522
+ const content = (0, import_fs4.readFileSync)(skillMdPath, "utf-8");
6523
+ const frontmatter = parseFrontmatter(content);
6524
+ if (frontmatter.internal === true) {
6525
+ continue;
6526
+ }
6527
+ const name = typeof frontmatter.name === "string" ? frontmatter.name : entry.name;
6528
+ skills.push({
6529
+ name,
6530
+ dirName: name,
6531
+ content,
6532
+ sourcePath: skillMdPath
6533
+ });
6534
+ }
6535
+ scanEditorFolderForSkills(fullPath, skills);
6536
+ }
6537
+ }
6538
+ }
6539
+ function findEditorFolders(basePath, maxDepth = 2) {
6540
+ const editorFolders = [];
6541
+ function scan(currentPath, depth) {
6542
+ if (depth > maxDepth || !(0, import_fs4.existsSync)(currentPath)) {
6543
+ return;
6544
+ }
6545
+ const entries = (0, import_fs4.readdirSync)(currentPath, { withFileTypes: true });
6546
+ for (const entry of entries) {
6547
+ if (!entry.isDirectory() || EXCLUDED_DIRS.has(entry.name)) {
6548
+ continue;
6549
+ }
6550
+ const fullPath = (0, import_path5.join)(currentPath, entry.name);
6551
+ if (entry.name === "Editor") {
6552
+ editorFolders.push(fullPath);
6553
+ } else {
6554
+ scan(fullPath, depth + 1);
6555
+ }
6556
+ }
6557
+ }
6558
+ scan(basePath, 0);
6559
+ return editorFolders;
6560
+ }
6561
+ function collectProjectSkills() {
6562
+ const projectRoot = process.cwd();
6563
+ const skills = [];
6564
+ const seenNames = /* @__PURE__ */ new Set();
6565
+ const searchPaths = [
6566
+ (0, import_path5.join)(projectRoot, "Assets"),
6567
+ (0, import_path5.join)(projectRoot, "Packages"),
6568
+ (0, import_path5.join)(projectRoot, "Library", "PackageCache")
6569
+ ];
6570
+ for (const searchPath of searchPaths) {
6571
+ if (!(0, import_fs4.existsSync)(searchPath)) {
6572
+ continue;
6573
+ }
6574
+ const editorFolders = findEditorFolders(searchPath, 3);
6575
+ for (const editorFolder of editorFolders) {
6576
+ scanEditorFolderForSkills(editorFolder, skills);
6577
+ }
6578
+ }
6579
+ const uniqueSkills = [];
6580
+ for (const skill of skills) {
6581
+ if (!seenNames.has(skill.name)) {
6582
+ seenNames.add(skill.name);
6583
+ uniqueSkills.push(skill);
6584
+ }
6585
+ }
6586
+ return uniqueSkills;
6587
+ }
6484
6588
  function getAllSkillStatuses(target, global) {
6485
- return BUNDLED_SKILLS.map((skill) => ({
6589
+ const bundledStatuses = BUNDLED_SKILLS.map((skill) => ({
6590
+ name: skill.name,
6591
+ status: getSkillStatus(skill, target, global),
6592
+ path: isSkillInstalled(skill, target, global) ? getSkillPath(skill.dirName, target, global) : void 0,
6593
+ source: "bundled"
6594
+ }));
6595
+ const projectSkills = collectProjectSkills();
6596
+ const bundledNames = new Set(BUNDLED_SKILLS.map((s) => s.name));
6597
+ const projectStatuses = projectSkills.filter((skill) => !bundledNames.has(skill.name)).map((skill) => ({
6486
6598
  name: skill.name,
6487
6599
  status: getSkillStatus(skill, target, global),
6488
- path: isSkillInstalled(skill, target, global) ? getSkillPath(skill.dirName, target, global) : void 0
6600
+ path: isSkillInstalled(skill, target, global) ? getSkillPath(skill.dirName, target, global) : void 0,
6601
+ source: "project"
6489
6602
  }));
6603
+ return [...bundledStatuses, ...projectStatuses];
6490
6604
  }
6491
6605
  function installSkill(skill, target, global) {
6492
6606
  const baseDir = global ? getGlobalSkillsDir(target) : getProjectSkillsDir(target);
@@ -6505,7 +6619,13 @@ function uninstallSkill(skill, target, global) {
6505
6619
  return true;
6506
6620
  }
6507
6621
  function installAllSkills(target, global) {
6508
- const result = { installed: 0, updated: 0, skipped: 0 };
6622
+ const result = {
6623
+ installed: 0,
6624
+ updated: 0,
6625
+ skipped: 0,
6626
+ bundledCount: 0,
6627
+ projectCount: 0
6628
+ };
6509
6629
  for (const skill of BUNDLED_SKILLS) {
6510
6630
  const status = getSkillStatus(skill, target, global);
6511
6631
  if (status === "not_installed") {
@@ -6518,6 +6638,27 @@ function installAllSkills(target, global) {
6518
6638
  result.skipped++;
6519
6639
  }
6520
6640
  }
6641
+ result.bundledCount = BUNDLED_SKILLS.length;
6642
+ const projectSkills = collectProjectSkills();
6643
+ const bundledNames = new Set(BUNDLED_SKILLS.map((s) => s.name));
6644
+ for (const skill of projectSkills) {
6645
+ if (bundledNames.has(skill.name)) {
6646
+ continue;
6647
+ }
6648
+ const status = getSkillStatus(skill, target, global);
6649
+ if (status === "not_installed") {
6650
+ installSkill(skill, target, global);
6651
+ result.installed++;
6652
+ result.projectCount++;
6653
+ } else if (status === "outdated") {
6654
+ installSkill(skill, target, global);
6655
+ result.updated++;
6656
+ result.projectCount++;
6657
+ } else {
6658
+ result.skipped++;
6659
+ result.projectCount++;
6660
+ }
6661
+ }
6521
6662
  return result;
6522
6663
  }
6523
6664
  function uninstallAllSkills(target, global) {
@@ -6529,13 +6670,28 @@ function uninstallAllSkills(target, global) {
6529
6670
  result.notFound++;
6530
6671
  }
6531
6672
  }
6673
+ const projectSkills = collectProjectSkills();
6674
+ const bundledNames = new Set(BUNDLED_SKILLS.map((s) => s.name));
6675
+ for (const skill of projectSkills) {
6676
+ if (bundledNames.has(skill.name)) {
6677
+ continue;
6678
+ }
6679
+ if (uninstallSkill(skill, target, global)) {
6680
+ result.removed++;
6681
+ } else {
6682
+ result.notFound++;
6683
+ }
6684
+ }
6532
6685
  return result;
6533
6686
  }
6534
6687
  function getInstallDir(target, global) {
6535
6688
  return global ? getGlobalSkillsDir(target) : getProjectSkillsDir(target);
6536
6689
  }
6537
6690
  function getTotalSkillCount() {
6538
- return BUNDLED_SKILLS.length;
6691
+ const projectSkills = collectProjectSkills();
6692
+ const bundledNames = new Set(BUNDLED_SKILLS.map((s) => s.name));
6693
+ const uniqueProjectCount = projectSkills.filter((s) => !bundledNames.has(s.name)).length;
6694
+ return BUNDLED_SKILLS.length + uniqueProjectCount;
6539
6695
  }
6540
6696
 
6541
6697
  // src/skills/target-config.ts
@@ -7092,7 +7248,40 @@ function listOptionsForCommand(cmdName) {
7092
7248
  }
7093
7249
  console.log(options.join("\n"));
7094
7250
  }
7095
- if (!handleCompletionOptions()) {
7251
+ function commandExists(cmdName) {
7252
+ if (BUILTIN_COMMANDS.includes(cmdName)) {
7253
+ return true;
7254
+ }
7255
+ const tools = loadToolsCache();
7256
+ return tools.tools.some((t) => t.name === cmdName);
7257
+ }
7258
+ async function main() {
7259
+ if (handleCompletionOptions()) {
7260
+ return;
7261
+ }
7262
+ const args = process.argv.slice(2);
7263
+ const cmdName = args.find((arg) => !arg.startsWith("-"));
7264
+ if (cmdName && !commandExists(cmdName)) {
7265
+ console.log(`\x1B[33mUnknown command '${cmdName}'. Syncing tools from Unity...\x1B[0m`);
7266
+ try {
7267
+ await syncTools({});
7268
+ const newCache = loadToolsCache();
7269
+ const tool = newCache.tools.find((t) => t.name === cmdName);
7270
+ if (tool) {
7271
+ registerToolCommand(tool);
7272
+ console.log(`\x1B[32m\u2713 Found '${cmdName}' after sync.\x1B[0m
7273
+ `);
7274
+ } else {
7275
+ console.error(`\x1B[31mError: Command '${cmdName}' not found even after sync.\x1B[0m`);
7276
+ process.exit(1);
7277
+ }
7278
+ } catch (error) {
7279
+ const message = error instanceof Error ? error.message : String(error);
7280
+ console.error(`\x1B[31mError: Failed to sync tools: ${message}\x1B[0m`);
7281
+ process.exit(1);
7282
+ }
7283
+ }
7096
7284
  program2.parse();
7097
7285
  }
7286
+ void main();
7098
7287
  //# sourceMappingURL=cli.bundle.cjs.map