A tools for Unity command line development.
npm install @notask/unity-cli-toolsbash
npm install @notask/unity-cli-tools
`
Dual Module Support
This package publishes separate builds for both ES Modules (ESM) and CommonJS (CJS). You can consume it either way:
ESM (Node and bundlers):
`ts
import { UnityHub } from "@notask/unity-cli-tools";
`
CJS:
`js
const { UnityHub } = require("@notask/unity-cli-tools");
`
Requirements
- Node.js 20+
- Unity Hub installed
- Unity Editor (for editor operations)
Core Concepts
Unity CLI Tools provides two main modules:
- UnityHub - For interacting with Unity Hub
- UnityEditor - For interacting with Unity Editor
$3
All operations return a Result type instead of throwing exceptions. This provides:
- Type-safe error handling - Errors are explicit in the return type
- Rich error context - Each error includes error codes, messages, and contextual data
- Composable operations - Chain operations with map, andThen, etc.
- No unexpected exceptions - All errors are handled explicitly
`typescript
import { UnityHub, isOk, isErr } from "@notask/unity-cli-tools";
const result = await UnityHub.getUnityInstallations();
if (isOk(result)) {
// Type-safe access to the value
const installations = result.value;
console.log("Installed versions:", Object.keys(installations));
} else {
// Type-safe access to the error
console.error(Error [${result.error.code}]:, result.error.message);
console.error("Context:", result.error.context);
}
`
UnityHub API Reference
$3
`typescript
import { UnityHub } from "@notask/unity-cli-tools";
// Check if Unity Hub is available
const isAvailable = await UnityHub.isUnityHubAvailable();
`
$3
`typescript
import { UnityHub, isOk } from "@notask/unity-cli-tools";
// Get all installed Unity versions
const result = await UnityHub.getUnityInstallations();
if (isOk(result)) {
const installations = result.value;
// Returns: { '2022.3.60f1': 'C:/Program Files/Unity/Hub/Editor/2022.3.60f1', ... }
console.log("Installed versions:", Object.keys(installations));
} else {
console.error("Failed to get installations:", result.error.message);
}
`
$3
`typescript
import { UnityHub, UnityModules, isOk } from "@notask/unity-cli-tools";
// Install a new Unity version
const result = await UnityHub.addEditor("2022.3.60f1");
if (isOk(result)) {
const installer = result.value;
// Wait for installation to complete
await installer.completed;
console.log("Installation completed!");
} else {
console.error("Failed to start installation:", result.error.message);
}
// Install with specific modules
const resultWithModules = await UnityHub.addEditor(
"2022.3.60f1",
[UnityModules.AndroidBuildSupport, UnityModules.WebGLBuildSupport]
);
// Add modules to existing installation
const moduleResult = await UnityHub.addModule(
"2022.3.60f1",
[UnityModules.IOSBuildSupport]
);
if (isOk(moduleResult)) {
console.log("Module installation started");
}
`
$3
`typescript
import { UnityHub, UnityModules, InstallerEventType, isOk } from "@notask/unity-cli-tools";
// Install with event tracking
const result = await UnityHub.addEditor("2022.3.60f1");
if (!isOk(result)) {
console.error("Failed to start installation:", result.error);
return;
}
const installer = result.value;
// Listen to progress events
installer.on(InstallerEventType.Progress, (events) => {
console.log("Progress:", events.map(e => ${e.module}: ${e.status} ${e.progress || 0}%));
});
installer.on(InstallerEventType.Error, (errorEvents) => {
console.error("Installation error:", errorEvents);
});
installer.on(InstallerEventType.Completed, (events) => {
console.log("Installation completed!");
});
// Or use the promise
try {
const completedEvents = await installer.completed;
console.log("Installation finished:", completedEvents);
} catch (error) {
console.error("Installation failed:", error);
}
// Cancel installation if needed
installer.Cancel();
`
$3
`typescript
import { UnityHub, isOk } from "@notask/unity-cli-tools";
// Get projects from Unity Hub
const result = await UnityHub.getProjects();
if (isOk(result)) {
const projects = result.value;
// Returns: [{ name: 'ProjectName', path: '/path/to/project', version: '2022.3.60f1' }, ...]
console.log("Projects:", projects);
}
// Get default projects directory
const dirResult = await UnityHub.getDefaultProjectsDirectory();
if (isOk(dirResult)) {
const defaultDir = dirResult.value; // string | null
console.log("Default directory:", defaultDir);
}
`
$3
`typescript
import { UnityHub, isOk } from "@notask/unity-cli-tools";
// Execute any Hub command directly
const result = await UnityHub.execUnityHubCommand(["editors", "-r"]);
if (isOk(result)) {
console.log(result.value.stdout);
console.log("Exit code:", result.value.exitCode);
} else {
console.error("Command failed:", result.error.stderr);
}
`
UnityEditor API Reference
UnityEditor provides an interface for automating tasks directly in the Unity Editor:
$3
`typescript
import { UnityEditor } from "@notask/unity-cli-tools";
// Get the executable path and verify installation
const unityPath = UnityEditor.getUnityExecutablePath("2022.3.15f1");
const isInstalled = await UnityEditor.isUnityVersionInstalled("2022.3.15f1");
console.log(Installed: ${isInstalled}, unityPath);
`
$3
`typescript
import { UnityEditor, isOk } from "@notask/unity-cli-tools";
const editorInfo = { version: "2022.3.15f1", path: unityPath };
const result = await UnityEditor.execUnityEditorCommand(
editorInfo,
["-batchmode", "-quit", "-projectPath", "/path/to/project"]
);
if (isOk(result)) {
console.log("Command output:", result.value.stdout);
console.log("Exit code:", result.value.exitCode);
} else {
console.error("Command failed:", result.error.message);
console.error("Error output:", result.error.stderr);
}
`
$3
`typescript
import { UnityEditor, ProjectInfo, isOk } from "@notask/unity-cli-tools";
const projectInfo: ProjectInfo = {
projectName: "MyAwesomeGame",
projectPath: "/path/to/new/project",
editorVersion: "2022.3.15f1"
};
// Create project
const createResult = await UnityEditor.createProject(projectInfo);
if (isOk(createResult)) {
console.log("Project created successfully!");
// Open project
const openResult = await UnityEditor.openProject(projectInfo, true, true);
if (isOk(openResult)) {
console.log("Project opened successfully!");
}
} else {
console.error("Failed to create project:", createResult.error.message);
}
`
$3
`typescript
import { UnityEditor, ProjectInfo, TestMode, isOk } from "@notask/unity-cli-tools";
const projectInfo: ProjectInfo = {
projectName: "MyGame",
projectPath: "/path/to/project",
editorVersion: "2022.3.15f1"
};
const result = await UnityEditor.runTests(projectInfo, TestMode.EditMode);
if (isOk(result)) {
console.log("All tests passed!");
console.log("Test output:", result.value);
} else {
console.error("Tests failed:", result.error.message);
// UnityTestError includes the test output
if (result.error.code === "UNITY_TEST_ERROR") {
console.error("Test output:", result.error.testOutput);
}
}
`
$3
`typescript
import { UnityEditor, ProjectInfo, isOk } from "@notask/unity-cli-tools";
const projectInfo: ProjectInfo = {
projectName: "MyGame",
projectPath: "/path/to/project",
editorVersion: "2022.3.15f1"
};
// Activate license
const activateResult = await UnityEditor.activateLicense(
projectInfo,
"XXXX-XXXX-XXXX-XXXX-XXXX",
"user@example.com",
"password"
);
if (isOk(activateResult)) {
console.log("License activated successfully!");
// Do work...
// Return license when done
const returnResult = await UnityEditor.returnLicense(projectInfo);
if (isOk(returnResult)) {
console.log("License returned successfully!");
}
} else {
console.error("License activation failed:", activateResult.error.message);
}
`
$3
`typescript
import { UnityEditor, ProjectInfo, isOk } from "@notask/unity-cli-tools";
const projectInfo: ProjectInfo = {
projectName: "MyGame",
projectPath: "/path/to/project",
editorVersion: "2022.3.15f1"
};
// Export package
const exportResult = await UnityEditor.exportPackage(
projectInfo,
["Assets/UI", "Assets/Scripts"],
"/path/to/output/MyPackage.unitypackage"
);
if (isOk(exportResult)) {
console.log("Package exported successfully!");
}
// Import package
const importResult = await UnityEditor.importPackage(
projectInfo,
"/path/to/downloads/OtherPackage.unitypackage"
);
if (isOk(importResult)) {
console.log("Package imported successfully!");
}
`
$3
`typescript
import { UnityEditor, ProjectInfo, isOk } from "@notask/unity-cli-tools";
const projectInfo: ProjectInfo = {
projectName: "MyGame",
projectPath: "/path/to/project",
editorVersion: "2022.3.15f1"
};
const result = await UnityEditor.executeMethod(
projectInfo,
"MyCompany.BuildTools.PerformBuild"
);
if (isOk(result)) {
console.log("Method executed successfully!");
console.log("Output:", result.value.stdout);
} else {
console.error("Method execution failed:", result.error.message);
}
`
Error Handling
$3
The library provides specific error types for different failure scenarios:
`typescript
import {
UnityHubNotFoundError,
UnityEditorNotFoundError,
UnityCommandError,
UnityInstallationError,
UnityProjectError,
UnityLicenseError,
UnityPackageError,
UnityTestError,
InvalidArgumentError,
} from "@notask/unity-cli-tools";
`
Each error includes:
- code - Error code for programmatic handling
- message - Human-readable error message
- context - Additional contextual information
- stack - Stack trace
$3
Basic Pattern Matching:
`typescript
const result = await UnityHub.getUnityInstallations();
if (result.success) {
// Handle success
const installations = result.value;
} else {
// Handle error
const error = result.error;
console.error([${error.code}] ${error.message});
}
`
Type Guards:
`typescript
import { isOk, isErr } from "@notask/unity-cli-tools";
const result = await UnityHub.getUnityInstallations();
if (isOk(result)) {
// TypeScript knows result.value exists
const installations = result.value;
}
if (isErr(result)) {
// TypeScript knows result.error exists
const error = result.error;
}
`
Specific Error Handling:
`typescript
const result = await UnityHub.getUnityInstallations();
if (!result.success) {
switch (result.error.code) {
case "UNITY_HUB_NOT_FOUND":
console.error("Please install Unity Hub");
break;
case "UNITY_INSTALLATION_ERROR":
console.error("No Unity versions found");
break;
default:
console.error("Unexpected error:", result.error.message);
}
}
`
Chaining Operations:
`typescript
import { map, andThen } from "@notask/unity-cli-tools";
const result = await UnityHub.getUnityInstallations();
// Transform the result
const versions = map(result, (installations) => Object.keys(installations));
// Chain operations
const firstVersion = andThen(result, async (installations) => {
const versions = Object.keys(installations);
if (versions.length === 0) {
return err(new UnityInstallationError("No installations found"));
}
return ok(versions[0]);
});
`
Unwrapping (Use with Caution):
`typescript
import { unwrap, unwrapOr } from "@notask/unity-cli-tools";
// Throws if result is an error
const installations = unwrap(await UnityHub.getUnityInstallations());
// Returns default value if result is an error
const installations = unwrapOr(await UnityHub.getUnityInstallations(), {});
`
Available Constants
$3
| Constant | Description |
| -------------------------- | ------------------------- |
| Documentation | Unity documentation |
| AndroidBuildSupport | Android platform support |
| AndroidSDKNDKTools | Android SDK/NDK tools |
| OpenJDK | Java Development Kit |
| IOSBuildSupport | iOS platform support |
| TvOSBuildSupport | tvOS platform support |
| LinuxBuildSupportMono | Linux Mono support |
| LinuxBuildSupportIL2CPP | Linux IL2CPP support |
| WebGLBuildSupport | WebGL platform support |
| WindowsBuildSupport | Windows platform support |
| VuforiaAR | Vuforia AR support |
| WindowsBuildSupportMono | Windows Mono support |
| LuminBuildSupport | Magic Leap support |
| VisualStudioCommunity | Visual Studio integration |
| MacBuildSupportMono | macOS Mono support |
| MacBuildSupportIL2CPP | macOS IL2CPP support |
| UniversalWindowsPlatform | UWP support |
| UWPBuildSupportIL2CPP | UWP IL2CPP support |
| UWPBuildSupportDotNet | UWP .NET support |
$3
| Constant | Description |
| -------------------- | --------------------------------- |
| Japanese | Japanese language pack |
| Korean | Korean language pack |
| ChineseSimplified | Simplified Chinese language pack |
| ChineseTraditional | Traditional Chinese language pack |
| Chinese | Chinese language pack (legacy) |
$3
| Constant | Description |
| ------------------ | ------------------------------- |
| Queued | Queued for download |
| Validating | Validating download |
| InProgress | Installation in progress |
| Downloading | Downloading installation files |
| QueuedInstall | Queued for install |
| ValidatingInstall| Validating installation |
| Installing | Installing |
| Verifying | Verifying installation |
| Installed | Installed successfully |
| Error | Installation error |
$3
| Constant | Description |
| ------------ | ------------------------------------------- |
| Progress | Installation progress update event |
| Error | Installation error event |
| Completed | Installation completed successfully event |
| Cancelled | Installation cancelled by user event |
$3
| Code | Description |
| --------------------------- | ------------------------------------- |
| UNITY_HUB_NOT_FOUND | Unity Hub executable not found |
| UNITY_EDITOR_NOT_FOUND | Unity Editor version not found |
| UNITY_COMMAND_ERROR | Command execution failed |
| UNITY_INSTALLATION_ERROR | Installation operation failed |
| UNITY_PROJECT_ERROR | Project operation failed |
| UNITY_LICENSE_ERROR | License operation failed |
| UNITY_PACKAGE_ERROR | Package operation failed |
| UNITY_TEST_ERROR | Tests failed |
| INVALID_ARGUMENT | Invalid argument provided |
Configuration
$3
- UNITY_HUB_PATH - Custom path to Unity Hub executable
$3
The library automatically detects and uses the correct paths for:
- Windows
- macOS
- Linux
Examples
$3
`typescript
import { UnityHub, UnityModules, isOk } from "@notask/unity-cli-tools";
async function manageUnityInstallation() {
// Check if hub is available
const isAvailable = await UnityHub.isUnityHubAvailable();
if (!isAvailable) {
console.error("Unity Hub not found");
return;
}
// List installations
const installsResult = await UnityHub.getUnityInstallations();
if (!isOk(installsResult)) {
console.error("Failed to get installations:", installsResult.error.message);
return;
}
const installations = installsResult.value;
console.log("Installed versions:", Object.keys(installations));
// Install WebGL support for specific version
if (installations["2022.3.60f1"]) {
const moduleResult = await UnityHub.addModule(
"2022.3.60f1",
[UnityModules.WebGLBuildSupport]
);
if (isOk(moduleResult)) {
const installer = moduleResult.value;
await installer.completed;
console.log("WebGL support added");
}
}
// Get recent projects
const projectsResult = await UnityHub.getProjects();
if (isOk(projectsResult)) {
const projects = projectsResult.value;
console.log("Recent projects:", projects.map((p) => p.name));
}
}
manageUnityInstallation().catch(console.error);
`
$3
`typescript
import { UnityEditor, ProjectInfo, TestMode, isOk } from "@notask/unity-cli-tools";
async function ciPipeline() {
const projectInfo: ProjectInfo = {
projectName: "MyGame",
projectPath: process.cwd(),
editorVersion: "2022.3.15f1"
};
// Activate license
const licenseResult = await UnityEditor.activateLicense(
projectInfo,
process.env.UNITY_SERIAL!,
process.env.UNITY_EMAIL!,
process.env.UNITY_PASSWORD!
);
if (!isOk(licenseResult)) {
console.error("License activation failed:", licenseResult.error.message);
process.exit(1);
}
try {
// Run tests
const testResult = await UnityEditor.runTests(projectInfo, TestMode.EditMode);
if (!isOk(testResult)) {
console.error("Tests failed:", testResult.error.message);
if (testResult.error.code === "UNITY_TEST_ERROR") {
console.error("Test output:", testResult.error.testOutput);
}
process.exit(1);
}
console.log("All tests passed!");
// Build project
const buildResult = await UnityEditor.executeMethod(
projectInfo,
"BuildScript.PerformBuild"
);
if (!isOk(buildResult)) {
console.error("Build failed:", buildResult.error.message);
process.exit(1);
}
console.log("Build completed successfully!");
} finally {
// Always return license
await UnityEditor.returnLicense(projectInfo);
}
}
ciPipeline().catch(console.error);
`
Advanced Usage
$3
`typescript
import { UnityHub, isOk } from "@notask/unity-cli-tools";
// List all editors with detailed output
const result = await UnityHub.execUnityHubCommand(["editors", "-a"], {
timeout: 30000, // 30 second timeout
env: { UNITY_HUB_VERBOSE: "1" }, // Custom environment variables
});
if (isOk(result)) {
// Process output
const editorList = result.value.stdout
.split("\n")
.filter((line) => line.includes("Unity Version"));
console.log("Editors:", editorList);
} else {
console.error("Command failed:", result.error.message);
}
`
$3
`typescript
import { UnityHub, isOk } from "@notask/unity-cli-tools";
const result = await UnityHub.execUnityHubCommand(["editors", "-i"], {
onStdout: (line) => {
console.log("STDOUT:", line);
},
onStderr: (line) => {
console.error("STDERR:", line);
}
});
if (isOk(result)) {
console.log("Command completed");
}
`
Migration Guide
$3
Version 2.x introduces breaking changes with the Result pattern:
Before (v1.x):
`typescript
try {
const installations = await UnityHub.getUnityInstallations();
console.log(installations);
} catch (error) {
console.error(error);
}
`
After (v2.x):
`typescript
import { isOk } from "@notask/unity-cli-tools";
const result = await UnityHub.getUnityInstallations();
if (isOk(result)) {
console.log(result.value);
} else {
console.error(result.error.message);
}
`
Method Return Type Changes:
| Method | Old Return Type | New Return Type |
|--------|----------------|-----------------|
| getUnityInstallations() | Promise (throws) | Promise |
| runTests() | Promise<{success: boolean, output: string}> | Promise |
| activateLicense() | Promise | Promise |
| createProject() | Promise | Promise |
TypeScript Support
This library is written in TypeScript and provides full type definitions:
`typescript
import {
UnityHub,
UnityEditor,
ProjectInfo,
UnityModules,
TestMode,
Result,
UnityError,
isOk,
isErr,
} from "@notask/unity-cli-tools";
// All types are exported and fully typed
const projectInfo: ProjectInfo = {
projectName: "MyGame",
projectPath: "/path/to/project",
editorVersion: "2022.3.15f1"
};
``