-
Notifications
You must be signed in to change notification settings - Fork 0
Getting Started
Three commands from zero to running your first target.
- A supported .NET SDK installed: .NET 8, 9, or 10. Tamp's first-party packages multi-target all three; pick whichever is on your dev machine. (See ADR 0015 for why.)
-
git(for repository discovery — Tamp walks up looking for.gitto find the project root).
dotnet tool install -g dotnet-tamp # one-time, on your machine
cd your-repo # any .NET solution layout
dotnet tamp init # scaffold build/Build.cs
dotnet tool restore && dotnet tamp Test # restore the local tool, run the scaffolded Test targetThat's it. tamp init writes five files into the current directory:
| Path | Purpose |
|---|---|
build/Build.cs |
Build script (shape varies by template) with Clean / Restore / Compile / Test / Default targets |
build/Build.csproj |
Pins Tamp.Core and Tamp.NetCli.V10 at the version of the CLI that scaffolded you |
.config/dotnet-tools.json |
Registers dotnet-tamp as a local tool (only if absent — your existing manifest is preserved) |
tamp.sh |
POSIX entry-point shim that auto-restores the tool manifest on first run, then forwards to dotnet tamp
|
tamp.cmd |
Windows entry-point shim (same behavior as tamp.sh) |
The scaffold is embedded in the CLI binary, so tamp init works offline. It refuses to overwrite an existing build/Build.cs unless --force is passed; re-running it on a tamped repo without --force is a clean no-op.
Pick the shape that matches your repo. Default is minimal:
tamp init --template minimal # Clean / Restore / Compile / Test (the default)
tamp init --template library # minimal + typed Pack target with nupkg output dir
tamp init --template monorepo # per-project Test fan-out + Ci aggregate + PackAll three are embedded — no network round-trip, no template-package install. Run tamp init --list-templates to enumerate.
After tamp init, your build/Build.cs looks like:
using Tamp;
using Tamp.NetCli.V10;
class Build : TampBuild
{
public static int Main(string[] args) => Execute<Build>(args);
[Parameter("Build configuration")]
Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release;
[Solution] readonly Solution Solution = null!;
AbsolutePath Artifacts => RootDirectory / "artifacts";
Target Clean => _ => _.Executes(() => CleanArtifacts());
Target Restore => _ => _
.Internal()
.Executes(() => DotNet.Restore(s => s.SetProject(Solution.Path)));
Target Compile => _ => _
.DependsOn(Restore)
.Executes(() => DotNet.Build(s => s
.SetProject(Solution.Path)
.SetConfiguration(Configuration)
.SetNoRestore(true)));
Target Test => _ => _
.DependsOn(Compile)
.Executes(() => DotNet.Test(s => s
.SetProject(Solution.Path)
.SetConfiguration(Configuration)
.SetNoBuild(true)));
Target Default => _ => _
.Default()
.DependsOn(Compile);
}Five elements doing the work:
-
class Build : TampBuild— your build inherits the framework's entry point and statics. -
Execute<Build>(args)— the framework'sMainshim. Reflects over your class, builds the target graph, parses args, dispatches. -
[Parameter]onConfiguration— auto-bound from--configuration <value>on the CLI or theCONFIGURATIONenvironment variable, withIsLocalBuild ? Debug : Releaseas the default. -
Targetproperties — declarative target definitions. Every target is top-level by default in 1.1.0+; mark internal helpers with.Internal()..Default()on a target makes it the no-args entry point (replaces the legacy "literally-named-Default" convention, which still works as a fallback). -
DotNet.Build(...)— typed wrapper that returns aCommandPlanthe runner dispatches.
dotnet tamp # runs Default → Compile (Debug locally, Release on CI)
dotnet tamp Test # the scaffolded test target
dotnet tamp Compile --configuration Release # override the parameter
dotnet tamp Compile --dry-run # print the dotnet build command, execute nothing
dotnet tamp --list # show top-level targetsThe output ends with a build summary table:
─── Build Summary ───
Target Status Duration
Compile ✓ Done 1.4 s
─────
Total 1.4 s
tamp init # default minimal template in cwd
tamp init --template library # pick a non-default template (0.2.0+)
tamp init --template monorepo # per-project Test fan-out (0.2.0+)
tamp init --solution path/to/Foo.slnx # explicit solution (otherwise auto-detected)
tamp init --dry-run # print would-write list; touch nothing
tamp init --force # overwrite existing files (0.2.0+)
tamp init --list-templates # list templates from registered sources
tamp init --help # full helpSolution detection: if there's exactly one .slnx (preferred) or .sln at the repo root, tamp init picks it up. Zero or multiple solutions — the scaffold falls back to [Solution]'s auto-discovery and tells you in the output.
Versions in the generated build/Build.csproj are pinned to the CLI's own version — the CLI that scaffolded you ships with a known-good Tamp.Core. Floating versions in build scripts have caused enough pain that we don't generate them. To upgrade Tamp later, edit the two PackageReference lines manually (or wait for tamp upgrade, deferred).
tamp init ships only the minimal template today. The architecture supports additional templates via NuGet packages (Tamp.Templates.Fullstack, Tamp.Templates.AspNet, third-party packages) — that landed-channel turns on in a later release. The minimal template stays embedded in the CLI so the on-ramp keeps working offline regardless of which other templates exist.
The reserved flags (--template, --template-source, --offline, --force, --with-ci, --interactive) parse today and exit with a clean "lands in 0.X" message; we picked the names early so we don't paint ourselves into a corner later.
tamp init works on existing repos that already have a .slnx / .sln solution. The probe finds your solution; the generated Build.cs references it via [Solution]. If you already have a build/Build.cs — tamp init refuses to overwrite and tells you. --force lands in 0.2.0.
For repos with a layout the probe doesn't understand (multi-solution monorepos, Yarn-workspace polyglots), tamp init still scaffolds the minimal Build.cs and you wire up the [Solution] / sub-build details by hand. Monorepo / Yarn / Turborepo probes land in 0.2.0.
Tamp's build script is .NET (that's the framework runtime), but what it builds can be anything — a pure-React app, a Python package, a Rust crate, a Helm chart, a polyrepo with one Yarn workspace and three Bicep modules. The tamp init minimal template happens to scaffold against a .NET solution because that's the common starter shape, but adopters with a different stack just remove the [Solution] field from Build.cs and use wrapper packages for whatever toolchain they have — Tamp.Yarn.V4, Tamp.Bicep, Tamp.Docker.V27, Tamp.Playwright.V1, anything from the Module Catalog.
For multi-repo products, declare the logical project name + area on your build class so telemetry rolls up across components:
[BuildProject("HoldFast", Area = "frontend")] // language-agnostic; works for any stack
class Build : TampBuild { ... }That surfaces on the diagnostic spans as tamp.build.project.name="HoldFast" and tamp.build.project.area="frontend". Without the attribute, Tamp falls back to the [Solution] filename (when present) or the repo directory name — pick the attribute when neither is the right product identifier.
- Build Script Authoring — the full DSL surface: dependencies, ordering, triggers, conditionals, failure handlers.
-
Parameter & Secret Injection —
[Solution],[GitRepository],[NuGetPackage],[Secret],[BuildProject]. - Module Catalog — every wrapper Tamp ships and how its surface is shaped.
- Pitfalls — destructive Clean patterns, yarn berry recovery, BuildKit migration warnings. Worth a five-minute read before your first non-trivial build.
Start here
Modules
- Module Catalog (canonical list, 50+ satellites)
- .NET toolchain
- Containers
- JS toolchain
- Supply-chain security
Analyzers
Tooling
Execution
CI integration
Editor integration
Migration
Reference
Project