Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>Unity Tools BaseNew to Visual Studio Code? Get it now.
Unity Tools Base

Unity Tools Base

gangdol

|
5 installs
| (0) | Free
Safely installs and maintains shared Unity Editor tooling for Unity Play Tools and Unity Edit Tools.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Unity Tools Base

Unity Tools Base is the shared dependency for Unity Play Tools and Unity Edit Tools. It installs one isolated Editor-only UPM package and owns the authenticated loopback bridge, capability state, optional-service registry, compatibility checks, validation, and transactional installer.

The VS Code extension runs workspace-first, with a local UI-host fallback, so filesystem operations and the 127.0.0.1 bridge stay co-located with the Unity project in supported remote workspaces.

Normal installation and update use a fast transactional structural path that may run while Unity is open. This path verifies the trusted signed payload, destination ownership, exact file hashes, and real Unity GUID claims before atomically publishing only suite-owned roots; a successful structural transaction is an installed, usable component. Untrusted workspaces, unowned destinations, modified owned files, incompatible dependencies, and unfinished or untrusted journals still block instead of being overwritten or guessed around. Project state, journals, and exact backups live under .gangdol-unity-tools-suite; no project-owned installer executable is installed.

In a trusted Unity workspace without a current receipt, Base activates after startup, discovers installed trusted Unity Play Tools and Unity Edit Tools host extensions, and best-effort reconciles Base plus every discovered child through the same per-project serialized transaction queue. Extension inventory changes trigger a debounced reconciliation, so children installed together with Base are not omitted merely because their activation order differed. Each child result is retained independently: one failure does not prevent the remaining discovered children from being attempted. An exact full receipt is written to host-global state only after the durable structural write succeeds, is never evicted by project count, and binds the canonical project plus the exact extension/build and workspace-composition identity. Non-Unity and untrusted workspaces are left untouched. True ownership, journal, dependency, or durable-state failures never return false full success and are surfaced with the affected component and reason.

Commands

  • Unity Tools: Install Unity Tools Base performs the fast, idempotent structural install or update and normally does not require Unity to close.
  • Unity Tools: Repair Unity Tools Installation recovers interrupted transactions, then performs the expensive Unity batch/deep validation. Repair may require Unity to be closed.
  • Unity Tools: Retry All Unity Tools Installations immediately retries Base and every currently installed trusted child extension without requiring a window reload.
  • Unity Tools: Remove a Unity Tools Package removes a selected package after Unity validation, then best-effort removes only its exact, unmodified project skill.
  • Unity Tools: Show Unity Tools Status reports effective capability and owned-file integrity state.

Extension API v1

Extensions that declare "extensionDependencies": ["gangdol.unity-tools-base"] can activate Base and use:

const base = await vscode.extensions.getExtension('gangdol.unity-tools-base').activate();
const automaticRoot = base.resolveAutomaticUnityProjectRoot(); // safe workspace-associated root
const projectRoot = base.resolveUnityProjectRoot(resourceUri); // synchronous string | undefined
const legacyProtected = base.isLegacyProtected({ projectRoot }); // read-only coherent-footprint check
await base.ensureComponentInstalled(extensionJsonPath, { projectRoot });
const status = await base.getStatus({ projectRoot });
const descriptor = await base.readBridgeDescriptor({ projectRoot });
const descriptorWatch = base.watchBridgeDescriptor({ projectRoot }, onDescriptorChanged);
// descriptorWatch.dispose() when the consumer is disposed.

activate() returns apiVersion, extensionId, resolveAutomaticUnityProjectRoot, resolveUnityProjectRoot, isWorkspaceTrusted, isLegacyProtected, ensureBaseInstalled, ensureComponentInstalled, retryInstalledComponents, getStatus, repair, isCapabilityEnabled, and readBridgeDescriptor and watchBridgeDescriptor. The descriptor watcher only marks a bridge-file generation change. On that generation only, the runtime provider performs one bounded direct read of the fixed project-local file and strict schema parse; the consumer's requested token-authenticated route is the live authority. It does not invoke installer status, inventory hashing, ACL/native verification, PID probing, or an extra status challenge. Automatic discovery accepts a canonical Unity workspace folder, a trusted configured Unity root contained by an open workspace, or the Unity ancestor of the active file when that ancestor is inside an open workspace. Resource-driven/manual discovery may likewise walk to the containing project. Normal ensure operations use the fast transactional structural path. Deep Unity batch validation is reserved for explicit Repair or an explicitly requested capability revalidation.

Ensures are serialized per canonical project and duplicate component requests are coalesced. Base also reconciles all installed trusted child extensions on startup and when the VS Code extension inventory changes. Retry All Unity Tools Installations re-enters that aggregate reconciliation directly, including after a prior failed attempt, so reloading the window is unnecessary. Normal activation with an exact same-build full receipt performs no installer status, manifest parse, hash, ACL, process, or revalidation work. Ambient Unity/dependency drift does not trigger an automatic deep-validation prompt or change successful runtime behavior. Missing setup may start detached best-effort reconciliation; true conflicts remain blocked and visible instead of silently disappearing.

The normal structural install path never probes or launches Unity and therefore needs no Unity-launch agreement. Before an explicit Repair, removal, or other deep operation may probe or launch Unity, Base shows a modal agreement containing the canonical project, its declared Unity version, every component and operation in the plan, the exact installed extension source and manifest digest, and either the resolved executable path/digest or the standard Unity-discovery plan. On macOS, the prompt states that Unity loads only a private same-volume copy-on-write project snapshot: existing InitializeOnLoad and AssetPostprocessor code can run, but Unity's ordinary project and import-cache writes through the loaded project path remain in that snapshot. The snapshot is not an OS sandbox; Editor code can still perform external side effects allowed to the current account. On Windows, the prompt retains the warning that Unity loads the real project and existing Editor code can modify project files or import state as in an ordinary Editor load. Agreement is in-memory, exact-plan-bound, single-use, and never persisted. Dismissal or Not Now launches nothing and starts no new mutation; a deferred retry asks again. Exact read-only status and doctor health checks need no agreement.

Journal recovery has its own separate modal agreement because it can restore or roll back files even though it never launches Unity. Before recovery, Base shows the canonical project, exact .gangdol-unity-tools-suite storage, and the exact suite-owned journal path, status, and SHA-256. The installer rechecks that binding before loading the recovery plan, so a same-name replacement is preserved rather than recovered. Dismissal or Not Now performs zero recovery mutation and returns recovery-agreement-declined with state preserved. An exact in-memory grant may be reused only for the same deferred journal identity after a Unity-lock race; it never authorizes installation, removal, or a Unity launch.

For a future incompatible Base release, publish a child update whose dependency range overlaps both the installed and target Base versions. Base installs and validates that bridging child first, then updates Base. A non-overlapping child/Base pair is deliberately blocked so no update can strand an installed component.

All automated operations execute assets/base/installer.js with VS Code's bundled runtime (ELECTRON_RUN_AS_NODE=1), without a shell, PATH lookup, Python installation, or project-owned executable. The Python implementation remains source-only as a development oracle and is excluded from the VSIX and installed project.

The following launch isolation applies only to explicit Repair/deep validation and other operations that actually need Unity; it is not part of the normal structural install path. On macOS, an approved Unity source is never launched by its mutable pathname. After agreement, Base passes its hash-pinned universal clone helper to the already attested installer over a retained descriptor. The helper uses fclonefileat with CLONE_NOFOLLOW_ANY | CLONE_NOOWNERCOPY to create a clone-only, same-volume Unity.app snapshot in a random owner-private directory. Base rejects absolute, broken, or escaping bundle symlinks, verifies the staged executable SHA-256, then runs strict/deep code-sign validation against Unity's exact identifier and team before launching only the staged executable. There is no source-path, copy, or reduced-security fallback. The snapshot is kept through validation and removed only when its ownership and post-run integrity remain exact. Cloning and code-sign verification affect explicit deep validation or validation-requiring removal only; normal structural installation and Play/Edit runtime paths do not use them.

The macOS batch-validation project is independently isolated. Base creates a private same-volume copy-on-write snapshot of the project and passes only that snapshot to Unity, so Unity never opens the real project or its real Library cache. Existing Editor initialization and asset-processing code can run normally; Unity's ordinary writes through the loaded snapshot path are not published. After a successful validation, the only Unity-produced project postimage that may be published to the real project is a bounded Packages/packages-lock.json, and only after its transition passes the exact semantic dependency rules and the real preimage is still unchanged. Declared local file: package dependencies outside the project are copy-on-write cloned into the same private stage and rebound only inside the snapshot; their exact original lock specifications are restored before validation and publication. Unsafe, ambiguous, or cross-filesystem local-package topology fails before Unity launches rather than exposing the external source to Editor writes. Cleanup removes only the exactly identified private snapshot; if safe cleanup cannot be proven, Base fails safely and preserves the snapshot for inspection rather than widening deletion. The snapshot confines normal Unity writes to the project path, but does not sandbox arbitrary Editor code from other files, processes, or services accessible to the current account. This project-snapshot isolation is macOS-specific; Windows validation behavior is unchanged.

The macOS tree preflight treats only a real root .git directory as VCS metadata, so normal Git filesystem-monitor sockets do not block installation and are not touched. A root .git symlink is still inspected and rejected if unsafe, worktree-style .git files remain ordinary validated files, and special entries outside that exact VCS directory remain installation-blocking conflicts.

Unity Multiplayer Play Mode may generate absolute project links and cached absolute paths under Library/VP. Base leaves the real cache completely untouched, omits only a real Library/VP directory from source-content scanning, and removes only its copy inside the private validation project before the normal snapshot boundary scan and Unity launch. A symlinked or otherwise unsafe Library/VP root is rejected, active virtual-project lockfiles block mutation, and absolute links elsewhere remain conflicts.

On Windows, Base ships a source-available, SHA-256-pinned native verifier and passes its exact bytes to the installer over a retained descriptor. The verifier accepts only local fixed NTFS paths, opens every ancestor and leaf without following reparse points, validates handle-bound owner/DACL and file identity, rejects hard links, and rechecks the same handles before and after bounded reads. Consent and operation-lock files are consumed by their exact identity and digest, so a raced replacement is preserved. Unity candidates require handle-bound ACL validation and Authenticode trust; the verifier retains the validated path chain across a shell-free launch and revalidates it afterward. These checks affect only explicit repair/revalidation, validation-requiring removal, and Unity batch validation. Normal Play/Edit descriptor reads and routes never invoke the verifier. After a successful installation, Windows exposes the same Base bridge and runtime capabilities as other supported hosts, without a reduced-performance path. Unsafe or unverifiable installer input fails closed before Unity or project mutation. Linux Unity-validating operations remain unavailable pending an equivalent native launch boundary.

The Windows process boundary is itself release-pinned: a bounded PowerShell bootstrap authenticates a source-available launcher and a deterministic launcher assembly, which retain every verifier path component and the verifier file without delete/write sharing through process creation. The main verifier and launcher assembly have VM-reproducible Roslyn build scripts that pin the compiler itself by SHA-256. Release tests compile each artifact twice on local NTFS, compare the resulting SHA-256 values to the bundled bytes, and run both ordinary and elevated adversarial suites against the exact bundled verifier. A VM-only discovery regression also proves that a safe candidate with the wrong version is skipped in favor of a later exact-version candidate.

Installer and Unity child processes receive a minimal cross-platform environment: OS/runtime paths, temporary directories, locale/time-zone, display/session, and explicit graphics-device variables only. API keys, *_TOKEN values, proxy credentials, CODEX_HOME, auth paths, NODE_OPTIONS, and other ambient extension-host variables are not forwarded to project-controlled Unity Editor code.

Payload manifest v1 gives each capability independent required and requiresGraphics flags. A normal install establishes the signed package structurally: Base verifies the manifest-bound payload and exact installed inventory, records it as installed, and does not launch a second Unity process merely to repeat those checks. Explicit Repair/deep validation additionally exercises the package in Unity. That deep pass first validates with graphics, then may retry headlessly when the required core permits it. If every required capability validates but an optional capability is explicitly disabled with a reason, Base records the deep result as non-success partial; individually enabled unaffected capabilities remain usable, and no lower-performance substitute is introduced. The exact deep-validation path is persisted with the result. The Base bridge itself is required.

An exact headless-fallback installation may remain a validated partial core, but is never reported as healthy success and never enables a reduced graphics implementation. Once per component and project during each VS Code extension-host session, Base may offer Retry Graphics Validation when a graphics-preferred component was last validated without graphics, or when an older valid state predates the validation-path field. The validated unaffected capability set is returned immediately; activation never waits for this offer. The offer itself does not resolve, probe, or launch Unity. Accepting it only routes the component to the existing exact Unity agreement dialog; Unity can run only after that second agreement. Declining either step leaves the installed last-known-good state untouched. Here last-known-good means the exact installed payload that completed structural installation or later Unity validation; only an all-capabilities-enabled payload has aggregate state enabled. A changed candidate that would disable or remove a previously enabled capability is rolled back so the prior payload remains active. A failed graphics attempt may validate headlessly as non-success partial.

A child may isolate its exact project skill from its Unity package with installDomains: [{"id":"project-skill","kind":"host","root":".agents/skills/<extension-id>","validation":"structure","componentRequired":true,"minimumComponentVersion":"0.1.0","maximumComponentVersionExclusive":"0.2.0"}]. Base commits that narrowly allowlisted root alongside the normal structural package transaction and records it separately in state.json.installDomains. With componentRequired:false, a Unity package conflict leaves the verified host skill available while the package result reports the failure. With componentRequired:true, a domain failure blocks the dependent package so unusable guidance is never advertised as enabled. Conflicting skill roots are preserved untouched. Domain and component digests are independent, so changing one does not force replacement of the other. Fresh installs commit the standalone skill first. Updates use the installed and target declared compatibility ranges to choose package-first or bridge-safe skill-first order; if no safe order exists, nothing changes. If a compatible package update succeeds but a later required domain update conflicts, the package may remain validated but the aggregate result is non-success partial with operation component-enabled-domain-disabled, never a fully completed extension update.

Each child manifest and installed state must retain exactly one canonical, versioned unity-tools-base dependency. Unity's -version result must exactly match ProjectSettings/ProjectVersion.txt before an explicit deep operation starts Unity against the project. If state was lost, a complete orphaned package, skill, or Base installer artifact may be adopted only when its recursive inventory and every hash exactly match the manifest; an exact structural adoption is considered installed, while Repair remains available for deep validation.

Unity validation snapshots bounded, regular, single-link protected project files, including Packages/manifest.json, Packages/packages-lock.json, the project version, and declared validation fingerprints. On macOS these checks are applied to the private project snapshot first; no real-project Unity postimage other than the semantically accepted bounded package lock is publishable. The target package's exact embedded lock entry and only its causally reachable, exclusively owned dependency closure may be added, removed, or updated. A direct project dependency or a dependency also reachable from any unrelated retained package is protected and must remain semantically identical. If a project has no lock preimage and Unity creates entries outside that exact closure, the operation rolls back the package, state, and new lock rather than guessing ownership. Opening the project once normally to let Unity establish its lock baseline is the supported preparation for that case.

Automatic Unity discovery checks the documented Hub candidate paths in order and uses the first executable whose exact -version matches the project. On Windows, the Hub candidates are followed by the official direct-installer roots C:\Program Files\Unity <version>\Editor\Unity.exe and its Program Files (x86) equivalent; the native-architecture verifier rejects an emulated executable before its version probe. Multiple same-version installs are therefore supported deterministically; an explicitly configured executable remains authoritative and must itself match exactly.

The bridge descriptor is Library/com.gangdol.unity-tools/bridge.json. Normal Unity startup publishes it through the original same-directory temporary-file delete/move sequence, with the original owner-only 0700/0600 chmod behavior on POSIX. It does not run private-storage ACL verification, PID challenges, or installer policy; shutdown directly removes only a descriptor whose token still belongs to that listener. The durable .base-owner.json, transaction roots, leases, and strict storage validation remain installer/Unity-batch concerns and are not consulted by successful routes.

While the listener is healthy, Base retains no EditorApplication.update callback and runs no periodic file-hash timer. Authenticated main-thread demand is coalesced through Unity's captured synchronization context. Requests present at one stable queue cutoff are dispatched together without installer-state or file integrity checks in the route path. An Editor update callback is attached only while a failed listener retry is pending, or as a wake fallback on Editors that do not expose a synchronization context, and is removed after success or shutdown.

Base owns the namespaced GET /v1/base/status and GET /v1/base/prefab-preview routes. Unity batch validation attempts that exact runtime route pair through the real ownership-enforcing router and releases the temporary registrations before it can enable the required bridge capability.

Child Editor packages acquire durable journal storage through UnityToolsPrivateProjectStorage.TryAcquireExtensionDirectory; the returned lease owns Library/com.gangdol.unity-tools/transactions/<extension-id> across processes and resolves direct filenames only. The same API provides durably flushed atomic UTF-8 writes, non-reparse path checks, and exact-identity regular-file reads/deletes that reject hard links and detect replacement. Separate extensions may retain independent leases without cleaning or blocking another extension's active journal staging. On macOS and Linux, every Base-owned storage directory/file is owner-only (0700/0600) and unsafe existing permissions are never repaired in place. Windows requires the canonical project Library path and inherited, unprotected DACLs for every Base-owned child; the owner must be the current user, and effective allow entries are limited to that owner, LocalSystem, and built-in Administrators. Those rules protect installer consent, locks, journals, validation artifacts, and transaction storage. They are never a successful runtime descriptor or route gate: the host performs the bounded direct descriptor read described above, then the actual token-authenticated requested route proves usability. Broader or unprovable access still fails the affected installer/validation operation safely before mutation; once validation succeeds, enabled is platform-neutral and unrestricted.

POSIX exact deletion holds an exclusive file handle and rechecks its device/inode, link count, size, and modification stamp before and after unlink while the Base lease is held. This contract treats the owning OS user as trusted; POSIX has no general compare-and-unlink primitive that can exclude a hostile same-UID process which deliberately bypasses the owner-private directory and lease protocol. Installer operation locks use an exact schema bound to the canonical project and host. A same-owner lock is reclaimed only after it is at least 60 seconds old and its PID is proven absent. POSIX holds an open descriptor and rechecks suite/path identity through randomized quarantine and unlink. Windows uses the native verifier's private ACL read plus exact NTFS identity-and-digest consumption; the opened object is marked for deletion while its handles remain held, and a raced replacement is preserved. Active, young, malformed, cross-project, replaced, or unprovable locks are preserved on every host.

Publication status

Version 0.1.0 is licensed for public distribution through the Visual Studio Marketplace under the bundled proprietary license.

Windows live release verification

The release-only Windows suite harness is tests/live/windowsSuiteInstallE2E.js. It is excluded from the VSIX and from ordinary test execution. Merely importing it cannot launch Unity. Execution requires Windows and the exact UNITY_TOOLS_WINDOWS_SUITE_LIVE_E2E_AGREEMENT value documented in tests/live/WINDOWS_SUITE_DRIVER.md.

The harness accepts only an exact GUID-marked project produced by the Windows Play live harness on a VM-local fixed NTFS volume. It rejects shared/network and reparse paths, requires Unity 6000.4.4f1 changeset 360f97ecca93, and pins the signed native ARM64 VS Code 1.135.0 build used by the authorized guest. It separately pins the official adjacent bin\code.cmd and the build's commit-specific resources\app\out\cli.js; CLI installs use only that launcher, while UI sessions use only the signed Code.exe. It stages all VS Code user data, extensions, VSIX artifacts, driver code, and results beneath that disposable project and sets extensions.autoUpdate to the exact VS Code 1.135 value off while disabling update checks in the isolated profile. The harness never installs an extension globally.

After the external CLI installs all three local VSIX files, a mandatory preactivation barrier revalidates Code.exe, code.cmd, and cli.js, then compares the extensions' complete archive and installed inventories, hashes, and exact isolated registry; duplicate, traversal, reparse, hard-link, missing, or extra entries fail closed before Code opens. The first fresh extension host exercises the production fast structural install path, including automatic Base/Play/Edit discovery and reconciliation, and proves the explicit no-change ensures plus fully enabled status without a Unity-launch agreement. After normal shutdown, a second fresh host reuses the same isolated profile, activates the real Base/Play/Edit runtime surfaces, and proves receipt-only startup initialized no installer loader, verifier bootstrap, retry, mutation, prompt, or timer and did not change the project. It deliberately invokes no installer or status API. Cleanup is bound to native verifier-originated Unity launch evidence and refuses changed identity, missing GUID/checkpoint, active driver, live Unity, project mutation, or bridge evidence. The exact two-session UI/process orchestration and its complementary no-prompt/no-Unity observation contract are documented in the linked driver guide.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft