MTC 1.1.0
dotnet tool install --global MTC --version 1.1.0
dotnet new tool-manifest
dotnet tool install --local MTC --version 1.1.0
#tool dotnet:?package=MTC&version=1.1.0
nuke :add-package MTC --version 1.1.0
MTC — Modular Template CLI
Scaffolding for .NET that understands the project you're already in.
dotnet new creates projects from scratch. MTC does that too, but its real job starts
afterwards: run mtc add feature Product anywhere inside your solution and MTC detects
whether you're in Clean Architecture, MVC or Vertical Slice, then writes each
generated file into the layer where it belongs.
cd MyShop # a Clean Architecture solution
mtc add feature Product --fields "Name:string Price:decimal"
# → MyShop.Domain/Entities/Product.cs
# → MyShop.Application/Features/Products/Commands/CreateProduct/...
# → MyShop.API/Controllers/ProductsController.cs
No config file, no flags telling it what your architecture is. It looks at your solution and figures it out.
Install
Pick whichever fits your setup.
| Method | Command |
|---|---|
| .NET tool (any OS) | dotnet tool install -g MTC |
| Arch Linux (AUR) | yay -S mtc-bin |
| Debian / Ubuntu | download the .deb from Releases, then sudo dpkg -i mtc_<version>_amd64.deb |
| Manual binary | download the .tar.gz for your OS from Releases |
Manual install details
- Linux / macOS — extract the archive, move the
mtcbinary somewhere on yourPATH(/usr/local/binworks), and keep thetemplates/folder next to it. - Windows — extract the archive (Windows 10/11 handles
.tar.gznatively) and add the extracted folder to yourPATH.
Requires the .NET 10 SDK if you install as a .NET tool. The standalone binaries are self-contained and need nothing.
Quick start
Create a project, then grow it.
# 1. Make a folder and scaffold the solution into it
mkdir MyShop && cd MyShop
mtc new CleanArch MyShop
# 2. Add a feature — MTC places the files for you
mtc add feature Product --fields "Name:string Price:decimal Stock:int"
That's the whole loop. Step 2 is the one you'll run over and over.
mtc newwrites into the current directory (or--output), it does not create a containing folder for you. Make the folder first, as above.
Commands
mtc new <template> [name]
Creates a new project from a template.
mtc new ConsoleApp MyApp
mtc new MvcMonolith MyWebApp
mtc new CleanArch MyShop
mtc new VerticalSlice MyApi
| Option | Description |
|---|---|
[name] |
Project name. Defaults to the output directory name. |
-o, --output |
Where to create it. Defaults to the current directory. |
-n, --name |
Same as the positional [name]. Takes precedence if both are given. |
--force |
Overwrite files that already exist. |
mtc add feature <name> [--fields "..."]
Generates a full feature — entity, commands/queries, and controller — placed according to the detected architecture.
mtc add feature Product --fields "Name:string Price:decimal Stock:int"
| Architecture | Where the files land |
|---|---|
| Clean Architecture | split across *.Domain, *.Application and *.API |
| Vertical Slice | a new folder under Features/ |
| MVC Monolith | Controllers/, Models/ and Views/ |
mtc add value-object <name> [--fields "..."]
mtc add value-object Money --fields "Amount:decimal Currency:string"
Goes to *.Domain/ValueObjects in Clean Architecture, Models/ValueObjects in MVC, and
./ValueObjects otherwise.
mtc add dto <name> [--fields "..."]
mtc add dto UserDto --fields "Username:string Email:string Age:int"
Goes to *.Application/DTOs in Clean Architecture, Models/DTOs in MVC, and ./DTOs
otherwise.
mtc list
Lists every available template with its description, author and version.
mtc config <set|get|list>
Persists preferences in ~/.mtc/config.json.
mtc config set Author "Your Name"
mtc config get Author
mtc config list
mtc debug-context
Shows what MTC detected — solution path and architecture. Run this first whenever a generate command says it can't figure out your project.
mtc debug-context
MTC never overwrites your work
Every generate command checks its targets first. If a file it would write already exists, MTC writes nothing at all and tells you what got in the way:
$ mtc add feature Product --fields "Name:string Price:decimal"
Error: 4 file(s) already exist and would be overwritten:
MyShop.Domain/Entities/Product.cs
MyShop.Application/Features/Products/Queries/GetProducts/GetProductsQuery.cs
MyShop.Application/Features/Products/Commands/CreateProduct/CreateProductCommand.cs
MyShop.API/Controllers/ProductsController.cs
Nothing was written. Re-run with --force to replace them.
It exits with code 1, so scripts and CI notice. Pass --force when you do want the
files regenerated. Generation is all-or-nothing — a conflict never leaves you with a
half-written feature.
Field types
--fields takes a space-separated list of Name:type pairs:
--fields "Name:string Price:decimal IsActive:bool CreatedAt:datetime Id:guid"
| Alias | Generates |
|---|---|
string |
string |
int, long, short, byte |
int, long, short, byte |
float, double, decimal |
float, double, decimal |
bool |
bool |
char |
char |
datetime |
DateTime |
dateonly |
DateOnly |
timeonly |
TimeOnly |
guid |
Guid |
Anything else is passed through unchanged, so Status:OrderStatus works if that type
exists in your project.
Reference-typed properties are generated with the required modifier, so the code MTC
writes compiles clean under <Nullable>enable</Nullable>.
How detection works
MTC walks up from your current directory until it finds a .sln, then inspects the
projects around it:
- projects ending in
.Domain,.Application,.Infrastructureand.API→ Clean Architecture - a
Features/folder → Vertical Slice - a project holding
Controllers/,Views/andModels/→ MVC Monolith
If none match, MTC stops and tells you rather than guessing. mtc debug-context shows
exactly what it saw.
Development
dotnet build
dotnet test
Integration tests drive the compiled binary, so build before testing.
Maintainer scripts: ./publish.sh (cross-platform binaries), ./publish_aur.sh,
./publish_deb.sh.
License
MIT — see LICENSE.
| Product | Versions 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. |
This package has no dependencies.