CLI Reference
This page documents the current Tsonic CLI surface.
tsonic <command> [options]
Workspace Model (Required)
Tsonic always operates in a workspace:
- Workspace root contains
tsonic.workspace.json - Projects live under
packages/<name>/tsonic.json - External deps are workspace-scoped (
libs/+dotnet.*intsonic.workspace.json)
Commands
tsonic init
Initialize a new Tsonic workspace (and default project).
mkdir my-app
cd my-app
tsonic init
Options:
--skip-types— skip installing type packages--types-version <ver>— pin the installed type package versions
Creates:
tsonic.workspace.json,libs/,packages/<name>/tsonic.json, workspacepackage.json,.gitignore
tsonic add npm <packageSpec>
Install an npm bindings package and apply its .NET dependency manifest to the workspace.
Airplane-grade rule: the npm package must include a tsonic.bindings.json at its root. That file is the
only way Tsonic discovers the .NET dependencies for an npm bindings package.
Examples:
tsonic add npm @tsonic/js
tsonic add npm @tsonic/nodejs
tsonic add npm @tsonic/express
Behavior:
npm install --save-dev <packageSpec>- Reads
<pkg>/tsonic.bindings.json - Merges
dotnet.frameworkReferences,dotnet.packageReferences,dotnet.msbuildProperties(andtestDotnet.*) intotsonic.workspace.json - Installs any additional
typespackages referenced by the manifest
After adding a bindings package, run tsonic restore to materialize NuGet dependencies and generate any missing
bindings packages.
tsonic add package <dll> [types]
Add a local DLL (and optional bindings) to the workspace.
tsonic add package ./path/to/MyLib.dll
tsonic add package ./path/to/MyLib.dll @acme/mylib-types
If types is omitted, Tsonic:
- Resolves the deterministic DLL dependency closure
- Copies all non-framework DLLs into
libs/ - Generates bindings into
.tsonic/bindings/dll/<asm>-types/ - Mirrors generated bindings into
node_modules/<asm>-types/
If types is provided, Tsonic installs it and skips auto-generation.
Tsonic also records the mapping in tsonic.workspace.json so tsonic restore knows to treat
the DLL as “externally bound”:
{
"dotnet": {
"libraries": [
{ "path": "libs/MyLib.dll", "types": "@acme/mylib-types" }
]
}
}
Options:
--deps <dir>(repeatable) — extra probe directories for assembly resolution--strict— strict bindings generation (constructor constraint loss becomes a hard error)
tsonic add nuget <id> <version> [types]
Add a NuGet package reference (and optional bindings) to the workspace.
tsonic add nuget Microsoft.Extensions.Logging 10.0.0
tsonic add nuget Microsoft.EntityFrameworkCore 10.0.1 @tsonic/efcore
If types is omitted, Tsonic generates bindings for the full transitive closure
of NuGet packages (one bindings package per NuGet package) under:
.tsonic/bindings/nuget/<id>-types/→ mirrored tonode_modules/<id>-types/
If types is provided, Tsonic records it in tsonic.workspace.json and does not auto-generate.
tsonic add framework <frameworkReference> [types]
Add a .NET FrameworkReference (and optional bindings) to the workspace.
tsonic add framework Microsoft.AspNetCore.App
tsonic add framework Microsoft.AspNetCore.App @tsonic/aspnetcore
If types is omitted, Tsonic generates bindings from the installed shared framework.
tsonic remove nuget <id>
Remove a NuGet package reference from tsonic.workspace.json and refresh bindings.
tsonic update nuget <id> <version> [types]
Update a NuGet package reference (and optional bindings) in tsonic.workspace.json.
tsonic restore
Restore NuGet deps and (re)generate local bindings (workspace-scoped).
This is the “clone a repo and get to green” command.
By default, bindings generation allows constructor-constraint loss (C# still enforces it at build time).
Use --strict to treat constructor-constraint loss as fatal.
tsonic generate [entry]
Generate C# only (no dotnet build/publish).
tsonic build [entry]
Build an executable or library.
- For executables: runs
dotnet publish(NativeAOT by default) - For libraries: runs
dotnet build, copies artifacts todist/, and emitsdist/tsonic/bindings/
tsonic run [entry] -- [args...]
Build and run an executable.
tsonic test
Generate a non-NativeAOT test assembly and run dotnet test.
This gives you a normal .NET unit test workflow (xUnit/NUnit/MSTest) while keeping your production build in NativeAOT.
Requirements:
packages/<project>/tsonic.jsonmust definetests.entryPointtsonic.workspace.jsonshould declare test frameworks undertestDotnet.*- For csproj-only test tooling packages (e.g.
Microsoft.NET.Test.Sdk,xunit.runner.visualstudio), set"types": falsesince you typically won’t import them from TypeScript.
- For csproj-only test tooling packages (e.g.
Example:
tsonic test --project my-app
tsonic pack
Create a NuGet package from a library project.
Global Options
Common options:
-c, --config <file>— workspace config path (default: auto-detecttsonic.workspace.json)--project <name>— select project underpackages/<name>/-V, --verbose/-q, --quiet--deps <dir>(repeatable) — extra probe dirs for assembly resolution (deps/bindings generation)--strict— strict bindings generation
Build/generate/run options:
-s, --src <dir>— override source root directory-o, --out <name>— override output name-n, --namespace <ns>— override root namespace-r, --rid <rid>— runtime identifier (e.g.linux-x64)-O, --optimize <size|speed>-k, --keep-temp— keepgenerated/output--no-strip— keep debug symbols-L, --lib <path>(repeatable) — extra assembly probe paths
Config Discovery and Project Selection
When --config is not supplied, Tsonic walks up from the current directory looking for tsonic.workspace.json.
When --project is not supplied, Tsonic selects:
- The nearest
packages/<name>/tsonic.jsonwhen run from inside that project directory tree, otherwise - If the workspace has exactly one project, it is selected automatically