KRWCLASSIC.UMK 0.1.4

dotnet tool install --global KRWCLASSIC.UMK --version 0.1.4
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local KRWCLASSIC.UMK --version 0.1.4
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=KRWCLASSIC.UMK&version=0.1.4
                    
nuke :add-package KRWCLASSIC.UMK --version 0.1.4
                    

UMK — Unity Modding Kit

<div align="center">

A CLI-only, shell-driven project configurator and task runner for Unity mod development.

NuGet Version License: MIT .NET 10 Platform

</div>


Overview

UMK does not implement a custom build system, compiler, or mod templates. Instead, it acts as a lightweight task runner that executes raw system shell commands (cmd or powershell) defined by the user in umk.json.

It standardizes the repetitive Unity mod development loop (compile $\to$ copy DLL to BepInEx\plugins $\to$ kill process $\to$ launch game) into clean, composable scripts with recursive variable interpolation and fail-fast sequential execution.


Installation

Install UMK globally as a .NET tool:

dotnet tool install -g KRWCLASSIC.UMK

To update an existing installation:

dotnet tool update -g KRWCLASSIC.UMK

CLI Reference

# Project initialization wizard (auto-detects Steam libraries, game paths, and outputs)
umk init

# Quick setup after git clone (reconfigures local game path & creates libs\ junctions)
umk setup

# Upgrade umk.json format version to match the installed UMK tool
umk upgrade

# Zero-copy game library linker (creates junctions in libs\ and references in .csproj)
umk linkgamelibs

# Run user-defined scripts from umk.json
umk build
umk run
umk <script>

# Preview resolved shell commands without executing them
umk run --dry-run
umk <script> --dry-run

# Bypass UMK version mismatch check with umk.json
umk build --ignore-umkv

# Inspect available scripts and resolved variables
umk list

# Help & documentation
umk help
umk help variables
umk help scripts

Configuration: umk.json

The manifest defines project variables and executable scripts:

{
  "umk": "0.1.0",
  "name": "MyMod",
  "shell": "cmd",
  "variables": {
    "configuration": "Release",
    "steamId": "123456",
    "game": "E:\\SteamLibrary\\steamapps\\common\\MyGame",
    "gameExe": "MyGame.exe",
    "plugins": "${game}\\BepInEx\\plugins",
    "output": "bin\\${configuration}\\netstandard2.1"
  },
  "scripts": {
    "kill": [
      "taskkill /F /IM \"${gameExe}\" >nul 2>&1 || ver >nul"
    ],
    "compile": [
      "dotnet build MyMod.csproj -c ${configuration}"
    ],
    "copy": [
      "copy /Y \"${output}\\MyMod.dll\" \"${plugins}\""
    ],
    "build": [
      "@compile",
      "@copy"
    ],
    "run": [
      "@kill",
      "@build",
      "start \"\" \"steam://rungameid/${steamId}\""
    ],
    "clean": [
      "dotnet clean"
    ]
  }
}

Variables

  • Syntax: ${variableName}
  • Variables can reference other variables (e.g. ${game}\BepInEx\plugins).
  • On Windows, forward slashes (/) in path variables are automatically normalized to backslashes (\) for shell compatibility.
  • Circular variable references are detected and rejected before execution.
Advanced Dynamic Variables & Lazy Evaluation

Variables are resolved on-demand based on the execution cascade: if you run umk clean, dynamic variables required only by umk pack are never triggered.

  • Shell Command ($[command:...]): Runs a shell command and captures its trimmed output.
    "gitHash": "$[command:git rev-parse --short HEAD]"
    
  • Script-Backed ($[script:...]): Executes a user-defined or private script and captures its standard output.
    "version": "$[script:*version-checker]"
    
  • File Content ($[file:...] or ${file:...}): Reads raw text directly from disk.
    "notes": "$[file:docs\\changelog.txt]"
    
  • Return / Exit Code ($[exitcode:...]): Captures the return code of a command or script as an integer string ("0", "1"):
    "buildStatus": "$[exitcode:script:*test-build]"
    

Scripts

  • Sequential arrays of ordinary shell commands or references to other script keys.
  • Script References (@ prefix): Prefix a step with @ to invoke another script inline (e.g. "@compile", "@copy", "@*test"). Lines without @ are executed as raw shell commands, eliminating collisions with binaries or system utilities.
  • Escaping: Use @@ if a literal shell command starts with @.
  • Private Scripts (* prefix): Prefixing a script definition with an asterisk (e.g. "*modlessrun") marks it as private. Private scripts are hidden from umk list and cannot be called from the CLI, but can be referenced and chained inside other scripts via @*name.
  • Execution stops immediately on the first non-zero exit code (fail-fast).

Post-Setup Tasks ("post-setup")

Automate initialization tasks directly after umk setup creates the libs\ junctions (e.g. downloading native binaries, pulling submodules, generating local files, or chaining scripts via @):

{
  "umk": "0.1.4",
  "name": "MyMod",
  "shell": "cmd",
  "variables": {
    "game": "E:\\Games\\MyGame"
  },
  "post-setup": [
    "echo Preparing additional assets...",
    "@*download-extras"
  ],
  "scripts": {
    "*download-extras": [
      "powershell -Command \"Invoke-WebRequest -Uri 'https://example.com/extras.zip' -OutFile 'extras.zip'\""
    ]
  }
}

When you run umk setup, it configures the game directory, links libs\, and then executes all steps in "post-setup" with full variable interpolation and fail-fast guarantees.

Manifest Versioning & --ignore-umkv

UMK validates that umk.json's "umk" version matches the installed tool version:

  • If the project manifest is older than your tool: run umk upgrade to update umk.json.
  • If the project manifest requires a newer tool: run dotnet tool update -g KRWCLASSIC.UMK.
  • To bypass the version check entirely: pass --ignore-umkv (e.g. umk build --ignore-umkv).

Zero-Copy Game Library Linking (umk linkgamelibs)

Instead of copying 100+ MB of game DLLs into every mod project folder:

  1. umk linkgamelibs reads the game path from umk.json.
  2. Creates two Windows directory junctions (mklink /J) inside ./libs/:
    • libs\bepinex $\to$ <game>\BepInEx\core
    • libs\managed $\to$ <game>\<Game>_Data\Managed
  3. Injects a compact wildcard block into your .csproj:
<ItemGroup Label="UMKGameLibs">
  <Reference Include="libs\bepinex\0Harmony.dll" Private="False" />
  <Reference Include="libs\bepinex\BepInEx*.dll" Private="False" />
  <Reference Include="libs\managed\*.dll" Private="False" />
  <Reference Remove="libs\managed\mscorlib.dll" />
  <Reference Remove="libs\managed\netstandard.dll" />
  <Reference Remove="libs\managed\WindowsBase.dll" />
  <Reference Remove="libs\managed\Accessibility.dll" />
  <Reference Remove="libs\managed\nunit.framework.dll" />
  <Reference Remove="libs\managed\System*.dll" />
  <Reference Remove="libs\managed\Mono*.dll" />
  <Reference Remove="libs\managed\Microsoft*.dll" />
  <Reference Remove="libs\managed\I18N*.dll" />
</ItemGroup>
  • 0 MB disk duplicate: Junctions point directly to the game files.
  • No local paths in .csproj: References are purely relative (libs\...), safe for git commits and sharing.
  • No BCL conflicts: Automatically excludes base class library assemblies (mscorlib, netstandard, System.*, Mono.*) while linking all game modules, UnityEngine*.dll, and Unity.*.dll.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
0.1.4 0 11/10/2026
0.1.3 3 11/10/2026
0.1.2 59 11/9/2026
0.1.1 53 11/9/2026
0.1.0 60 11/9/2026