uloop-cli 1.6.1 → 1.6.3

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uloop-cli",
3
- "version": "1.6.1",
3
+ "version": "1.6.3",
4
4
  "//version": "x-release-please-version",
5
5
  "description": "CLI tool for Unity Editor communication via Unity CLI Loop",
6
6
  "main": "dist/cli.bundle.cjs",
@@ -57,11 +57,11 @@
57
57
  "eslint-plugin-prettier": "5.5.5",
58
58
  "eslint-plugin-security": "4.0.0",
59
59
  "jest": "30.3.0",
60
- "knip": "6.0.6",
60
+ "knip": "6.1.1",
61
61
  "prettier": "3.8.1",
62
62
  "ts-jest": "29.4.6",
63
63
  "typescript": "5.9.3",
64
- "typescript-eslint": "8.57.2"
64
+ "typescript-eslint": "8.58.0"
65
65
  },
66
66
  "overrides": {
67
67
  "minimatch": "10.2.4"
@@ -0,0 +1,5 @@
1
+ // User-facing display name for the product (shown in error messages, diagnostics)
2
+ export const PRODUCT_DISPLAY_NAME = 'Unity CLI Loop';
3
+
4
+ // Unity Editor menu path to the server window
5
+ export const MENU_PATH_SERVER = 'Window > Unity CLI Loop > Server';
package/src/cli.ts CHANGED
@@ -8,6 +8,7 @@
8
8
  // and object keys come from tool definitions which are internal trusted data
9
9
  /* eslint-disable no-console, security/detect-non-literal-fs-filename, security/detect-object-injection */
10
10
 
11
+ import { PRODUCT_DISPLAY_NAME, MENU_PATH_SERVER } from './cli-constants';
11
12
  import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync } from 'fs';
12
13
  import { join, basename, dirname } from 'path';
13
14
  import { homedir } from 'os';
@@ -133,7 +134,7 @@ program.helpCommand(true);
133
134
  program
134
135
  .command('list')
135
136
  .description('List all available tools from Unity')
136
- .option('-p, --port <port>', 'Unity TCP port')
137
+ .addOption(createHiddenPortOption())
137
138
  .option('--project-path <path>', 'Unity project path')
138
139
  .action(async (options: CliOptions) => {
139
140
  await runWithErrorHandling(() => listAvailableTools(extractGlobalOptions(options)));
@@ -142,7 +143,7 @@ program
142
143
  program
143
144
  .command('sync')
144
145
  .description('Sync tool definitions from Unity to local cache')
145
- .option('-p, --port <port>', 'Unity TCP port')
146
+ .addOption(createHiddenPortOption())
146
147
  .option('--project-path <path>', 'Unity project path')
147
148
  .action(async (options: CliOptions) => {
148
149
  await runWithErrorHandling(() => syncTools(extractGlobalOptions(options)));
@@ -210,8 +211,7 @@ function registerToolCommand(tool: ToolDefinition, helpGroup: string): void {
210
211
  }
211
212
  }
212
213
 
213
- // Add global options
214
- cmd.option('-p, --port <port>', 'Unity TCP port');
214
+ cmd.addOption(createHiddenPortOption());
215
215
  cmd.option('--project-path <path>', 'Unity project path');
216
216
 
217
217
  cmd.action(async (options: CliOptions) => {
@@ -364,6 +364,11 @@ function getToolHelpGroup(toolName: string, defaultToolNames: ReadonlySet<string
364
364
  return defaultToolNames.has(toolName) ? HELP_GROUP_BUILTIN_TOOLS : HELP_GROUP_THIRD_PARTY_TOOLS;
365
365
  }
366
366
 
367
+ // Option instances are mutated by commander, so each command needs its own
368
+ function createHiddenPortOption(): Option {
369
+ return new Option('-p, --port <port>', 'Unity TCP port').hideHelp();
370
+ }
371
+
367
372
  function extractGlobalOptions(options: Record<string, unknown>): GlobalOptions {
368
373
  return {
369
374
  port: options['port'] as string | undefined,
@@ -382,7 +387,8 @@ function printToolDisabledError(cmdName: string): void {
382
387
 
383
388
  function printConnectionError(): void {
384
389
  console.error('\x1b[31mError: Cannot connect to Unity.\x1b[0m');
385
- console.error('Make sure Unity Editor is open and uLoopMCP server is running.');
390
+ console.error(`Make sure Unity Editor is open and ${PRODUCT_DISPLAY_NAME} server is running.`);
391
+ console.error(`You can start the server from: ${MENU_PATH_SERVER}`);
386
392
  console.error('');
387
393
  console.error('[For AI] Please report the above to the user.');
388
394
  }
@@ -440,7 +446,7 @@ async function runWithErrorHandling(fn: () => Promise<void>): Promise<void> {
440
446
  console.error('');
441
447
  console.error('Another Unity instance was found, but it belongs to a different project.');
442
448
  console.error(
443
- 'Start the Unity Editor for this project, or use --port to specify the target.',
449
+ 'Start the Unity Editor for this project, or use --project-path to specify the target.',
444
450
  );
445
451
  process.exit(1);
446
452
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.6.1",
2
+ "version": "1.6.3",
3
3
  "tools": [
4
4
  {
5
5
  "name": "compile",
@@ -7,6 +7,7 @@
7
7
  // and lock file paths are constructed from trusted project root detection
8
8
  /* eslint-disable no-console, security/detect-object-injection, security/detect-non-literal-fs-filename */
9
9
 
10
+ import { PRODUCT_DISPLAY_NAME } from './cli-constants';
10
11
  import * as readline from 'readline';
11
12
  import { existsSync } from 'fs';
12
13
  import { join } from 'path';
@@ -138,7 +139,7 @@ function printVersionWarning(cliVersion: string, serverVersion: string): void {
138
139
  const isCliOlder = isVersionOlder(cliVersion, serverVersion);
139
140
  const updateCommand = isCliOlder
140
141
  ? `npm install -g uloop-cli@${serverVersion}`
141
- : `Update uLoopMCP package to ${cliVersion} via Unity Package Manager`;
142
+ : `Update ${PRODUCT_DISPLAY_NAME} package to ${cliVersion} via Unity Package Manager`;
142
143
 
143
144
  console.error('\x1b[33m⚠️ Version mismatch detected!\x1b[0m');
144
145
  console.error(` uloop-cli version: ${cliVersion}`);
@@ -6,6 +6,7 @@
6
6
  // File paths are constructed from Unity project root detection, not from user input
7
7
  /* eslint-disable security/detect-non-literal-fs-filename */
8
8
 
9
+ import { PRODUCT_DISPLAY_NAME } from './cli-constants';
9
10
  import { readFile } from 'fs/promises';
10
11
  import { existsSync } from 'fs';
11
12
  import { join, resolve } from 'path';
@@ -61,7 +62,7 @@ export function validateProjectPath(projectPath: string): string {
61
62
 
62
63
  if (!hasUloopInstalled(resolved)) {
63
64
  throw new Error(
64
- `uLoopMCP is not installed in this project (UserSettings/UnityMcpSettings.json not found): ${resolved}`,
65
+ `${PRODUCT_DISPLAY_NAME} is not installed in this project (UserSettings/UnityMcpSettings.json not found): ${resolved}`,
65
66
  );
66
67
  }
67
68
 
@@ -87,9 +88,7 @@ export async function resolveUnityPort(
87
88
 
88
89
  const projectRoot = findUnityProjectRoot();
89
90
  if (projectRoot === null) {
90
- throw new Error(
91
- 'Unity project not found. Use --port or --project-path option to specify the target.',
92
- );
91
+ throw new Error('Unity project not found. Use --project-path option to specify the target.');
93
92
  }
94
93
 
95
94
  return await readPortFromSettingsOrThrow(projectRoot);
@@ -100,7 +99,7 @@ function createSettingsReadError(projectRoot: string): Error {
100
99
  return new Error(
101
100
  `Could not read Unity server port from settings.\n\n` +
102
101
  ` Settings file: ${settingsPath}\n\n` +
103
- `Run 'uloop launch -r' to restart Unity, or use --port to specify the port directly.`,
102
+ `Run 'uloop launch -r' to restart Unity.`,
104
103
  );
105
104
  }
106
105
 
@@ -6,6 +6,7 @@
6
6
  // Paths come from trusted Unity responses and validated project root, console.error for user warnings
7
7
  /* eslint-disable security/detect-non-literal-fs-filename, no-console */
8
8
 
9
+ import { PRODUCT_DISPLAY_NAME } from './cli-constants';
9
10
  import assert from 'node:assert';
10
11
  import { realpath } from 'fs/promises';
11
12
  import { dirname } from 'path';
@@ -41,7 +42,7 @@ export async function validateConnectedProject(
41
42
  try {
42
43
  response = await client.sendRequest<GetVersionResponse>('get-version', {});
43
44
  } catch (error) {
44
- // Method not found: old uLoopMCP version without get-version tool
45
+ // Method not found: old package version without get-version tool
45
46
  if (
46
47
  error instanceof Error &&
47
48
  (error.message.includes(`${JSON_RPC_METHOD_NOT_FOUND}`) ||
@@ -49,7 +50,7 @@ export async function validateConnectedProject(
49
50
  /unknown tool/i.test(error.message))
50
51
  ) {
51
52
  console.error(
52
- 'Warning: Could not verify project identity (get-version not available). Consider updating uLoopMCP package.',
53
+ `Warning: Could not verify project identity (get-version not available). Consider updating ${PRODUCT_DISPLAY_NAME} package.`,
53
54
  );
54
55
  return;
55
56
  }
@@ -21,8 +21,7 @@ None.
21
21
 
22
22
  | Option | Description |
23
23
  |--------|-------------|
24
- | `--project-path <path>` | Target a specific Unity project (mutually exclusive with `--port`). Path resolution follows the same rules as `cd` — absolute paths are used as-is, relative paths are resolved from cwd. |
25
- | `-p, --port <port>` | Specify Unity TCP port directly (mutually exclusive with `--project-path`). |
24
+ | `--project-path <path>` | Target a specific Unity project. Path resolution follows the same rules as `cd` — absolute paths are used as-is, relative paths are resolved from cwd. |
26
25
 
27
26
  ## Examples
28
27
 
@@ -7,6 +7,7 @@
7
7
  // File paths are constructed from home directory and skill names, not from untrusted user input
8
8
  /* eslint-disable security/detect-non-literal-fs-filename */
9
9
 
10
+ import { PRODUCT_DISPLAY_NAME } from '../cli-constants';
10
11
  import { existsSync, mkdirSync, readFileSync, writeFileSync, rmSync, readdirSync } from 'fs';
11
12
  import { join, dirname, resolve, isAbsolute, sep } from 'path';
12
13
  import { homedir } from 'os';
@@ -84,8 +85,8 @@ function getProjectSkillsDir(target: TargetConfig): string {
84
85
  }
85
86
  if (!status.hasUloop) {
86
87
  throw new Error(
87
- `uLoopMCP is not installed in this Unity project (${status.path}).\n` +
88
- 'Please install uLoopMCP package first, then run this command again.',
88
+ `${PRODUCT_DISPLAY_NAME} is not installed in this Unity project (${status.path}).\n` +
89
+ `Please install ${PRODUCT_DISPLAY_NAME} package first, then run this command again.`,
89
90
  );
90
91
  }
91
92
  return join(status.path as string, target.projectDir, 'skills');
package/src/version.ts CHANGED
@@ -4,4 +4,4 @@
4
4
  * This file exists to avoid bundling the entire package.json into the CLI bundle.
5
5
  * This version is automatically updated by release-please.
6
6
  */
7
- export const VERSION = '1.6.1'; // x-release-please-version
7
+ export const VERSION = '1.6.3'; // x-release-please-version