Make vs Just vs Mise vs go-task for .NET Apps in 2026

Mehdi Hadeli
@mehdihadeli
On this page
Table of contents
Introduction
Task runners look like a minor repo detail right up until the repo stops being small.
Early on, a few dotnet commands in a README are enough. Then the project picks up a local tool manifest, a frontend, a formatter, a couple of setup steps, and one command people always forget. That is usually when the question changes. It is no longer "should we script this?" It becomes "which tool should own the scripts?"
In 2026, the shortlist usually looks like this:
MakeJustMisego-task/task
All four can run a .NET app. That part is easy. The real differences show up later, when someone new clones the repo, when Windows and macOS users hit different shell behavior, or when the app quietly turns into a polyglot project.
I wanted the comparison to stay practical, so this article uses the same .NET Aspire sample for all four.
Runnable sample for this article:
task-runners-comparison sample
The sample includes four equivalent task definitions at the repository root:
mise.tomlJustfileTaskfile.ymlMakefile
The lifecycle is intentionally small:
- restore
- build
- test
- format
- clean
- hook
- prepare
- run
That is enough to expose the tradeoffs without hiding them under a pile of unrelated shell glue.
Objectives
By the end of this article, you should be able to:
- understand where
Make,Just,Mise, andgo-taskdiffer in practice - see equivalent task definitions for the same .NET Aspire app
- choose the right default for a new repository in 2026
- decide when the "winner" still should not be your choice
The sample we will use
The comparison is built around a small Aspire starter app generated with the Aspire CLI.
The sample root contains these core pieces:
task-runners-comparison/
├── TaskRunnersComparison.slnx
├── TaskRunnersComparison.AppHost/
├── TaskRunnersComparison.ApiService/
├── TaskRunnersComparison.Web/
├── TaskRunnersComparison.ServiceDefaults/
├── mise.toml
├── Justfile
├── Taskfile.yml
└── Makefile
This is a better test case than a single console app. Aspire projects usually come with a solution file, multiple projects, local tool restore, and an actual "run the app" command. That is enough surface area to make task runner differences show up quickly.
Architecture overview
The application lifecycle stays the same across all four tools. Only the layer that describes and wires those commands changes.
Prerequisites
To follow along, you need:
- .NET SDK 10
- Aspire CLI
- one or more of these tools installed:
make,just,mise,task - Git Bash, WSL, or another shell environment you already use comfortably
One small but real detail from the sample: the formatter command uses dotnet csharpier format ., not dnx csharpier format .. The reason is boring, which is exactly why it matters. The sample uses a local tool manifest, and dnx is not guaranteed to exist on every machine.
Why this comparison is harder than it looks
If the question is only "can this run shell commands?", all four pass and the article ends here.
That is not a useful way to choose.
The better questions are:
- How readable is the file for a teammate who did not write it?
- How well does it model dependencies between tasks?
- Does it help with tool installation or only command execution?
- Is it pleasant on Windows, macOS, and Linux?
- Does it age well as the repository becomes more polyglot?
- Does it reduce setup drift or merely organize commands?
There is no universal winner for every repo. I do think there is a very practical winner for a lot of new app repos in 2026, but it only becomes obvious once you care about setup drift and onboarding, not just command syntax.
The same workflow in four tools
All four sample files implement the same flow:
restore -> build -> test
format
clean
hook
prepare = restore + hook
run = aspire start
The restore step explicitly targets TaskRunnersComparison.slnx because the repository root contains multiple projects plus both .sln and .slnx files. That sounds like a tiny detail. It is also the sort of detail that decides whether your shiny task file works on day one or breaks the first time someone runs it from the repo root.
The actual commands side by side
At the command line, the four tools look like this for the same repo:
# Mise
mise run restore
mise run build
mise run test
mise run format
mise run prepare
mise run run
# Just
just restore
just build
just test
just format
just prepare
just run
# go-task
task restore
task build
task test
task format
task prepare
task run
# Make
make restore
make build
make test
make format
make prepare
make run
This is the first useful comparison point.
Just, task, and make all expose the task name directly. Mise adds run in the middle. That makes the command a bit longer, but it also makes the mental model more explicit: you are running a named task from a tool that also manages your environment.
The more interesting comparison is the task definition itself.
Mise
[tools]
node = "24"
dotnet = "10"
[tasks.restore]
run = ["dotnet restore TaskRunnersComparison.slnx", "dotnet tool restore"]
[tasks.build]
depends = ["restore"]
run = "dotnet build TaskRunnersComparison.slnx"
[tasks.prepare]
depends = ["restore", "hook"]
[tasks.run]
run = "aspire start"
The important part is not just the task syntax. It is that the same file also pins node and dotnet. None of the other tools in this comparison do that.
Just
restore: dotnet restore TaskRunnersComparison.slnx
dotnet tool restore
build: restore
dotnet build TaskRunnersComparison.slnx
prepare: restore hook
run: aspire start
This is the cleanest command-oriented file in the group. If you showed this to someone who had never seen the repo before, they would probably understand it in one pass.
go-task
tasks:
restore:
cmds:
- dotnet restore TaskRunnersComparison.slnx
- dotnet tool restore
build:
deps: [restore]
cmds:
- dotnet build TaskRunnersComparison.slnx
prepare:
deps: [restore, hook]
run:
cmds:
- aspire start
go-task is more verbose than Just, but the structure is very explicit. If your team likes metadata, descriptions, and dependency declarations that are easy to scan, this format holds up well.
Make
restore:
dotnet restore TaskRunnersComparison.slnx
dotnet tool restore
build: restore
dotnet build TaskRunnersComparison.slnx
prepare: restore hook
run:
aspire start
There is nothing wrong with this file. The issue is mostly ergonomic. It looks older because it is older. It still works, but it does not feel like the nicest fit for a new .NET developer workflow.
Comparing the commands themselves
If you look only at how a developer runs the tasks, the ranking changes a bit.
Just has the nicest command shape. just build and just run are short, obvious, and readable. task build is just as direct. make build is familiar to a huge number of developers, even if the file format behind it is less pleasant.
Mise is the only one that asks for mise run build instead of just build. On paper, that makes it the least elegant CLI in the group. In practice, I think the extra word is a small price for combining version management and task execution.
If I were ranking the command shape alone, not the full tool:
Justgo-taskMakeMise
If I were ranking the full workflow around those commands, including onboarding and tool setup:
MiseJustgo-taskMake
That split is worth calling out because it explains why people often disagree on this topic while both sounding reasonable. Some people are judging the command shape. Others are judging the whole repo experience.
1. Make
Make is still the most recognizable option.
That counts for something. A lot of developers have seen a Makefile even if they have never written one from scratch. It is old, stable, fast, and still completely usable.
If your team already lives comfortably in Unix-style tooling, Make can be a sensible choice. The actual make build and make run commands are simple enough. The friction is in authoring and maintaining the file, not in typing the command.
What Make does well:
- almost everyone recognizes it
- it is mature and stable
- target dependencies are simple and effective
- it works well for straightforward build pipelines
Where Make starts to drag:
- syntax remains odd if you do not already think in
make - tabs are still part of the UX, which is not a strength
- it is a build tool adapted into a task runner, not designed fresh for developer workflows
- Windows usage is better than it used to be, but it still does not feel like the most natural default for a .NET-first team
- tool version management is outside its scope
My short version: Make is still valid, but for new application repos it usually wins on familiarity, not on fit.
2. Just
Just is what many people wanted Make to feel like.
That is still the best one-line description I know. The file is cleaner, the recipes are easier to read, and the whole thing feels like it was designed for humans instead of inherited from a different era.
If all you want is command orchestration, Just is one of the nicest tools in this group. The just build and just run commands are probably the cleanest in the article.
What Just does well:
- very readable syntax
- great for short, explicit developer commands
- easy onboarding for teammates
- strong "command runner" feel instead of "build system" feel
- excellent for repositories where shell commands are the whole story
Where Just stops short:
- it does not solve tool installation/version management
- it is still mainly a command runner, not an environment manager
- more advanced cross-platform logic can become shell-heavy
If your team already handles SDK and tool versions somewhere else, Just is a very strong choice. In pure authoring ergonomics, it is probably my favorite file in this comparison.
3. Mise
Mise is the tool that changes the conversation because it combines two concerns that are often split:
- tool version management
- task execution
That combination matters more now than it used to. Repositories keep getting messier in a very normal way. Even a mostly .NET app often ends up wanting node, bun, pnpm, docker, java, python, or some infrastructure tool somewhere in the workflow.
What Mise does well:
- manages tool versions and tasks in one place
- gives one onboarding story instead of separate version-manager docs plus task-runner docs
- TOML is readable and structured
- task dependencies are clear enough for most application repos
- feels like a good fit for polyglot teams
- reduces "works on my machine" drift more directly than the other tools here
Where Mise is weaker:
- it is conceptually broader than
Just, so it can feel heavier - some teams only want a task runner and do not want a tool manager involved
- it is newer in many .NET teams than
Make
This is exactly why Mise stands out for new repos. mise run build is not as pretty as just build, but the file does more work for you. If I can declare SDK versions and standard tasks in one place, I remove one whole category of setup drift before it starts.
4. go-task / task
go-task sits in an interesting middle position.
It is more modern than Make, more structured than ad hoc shell scripts, and clearer about dependencies than a lot of home-grown wrappers. Teams that are already comfortable with YAML usually settle into it quickly.
What go-task does well:
- strong dependency modeling
- explicit task metadata and descriptions
- readable for teams comfortable with YAML
- cross-platform story is generally better than legacy
Makeassumptions - good fit for larger automation graphs
Where go-task loses me a bit:
- YAML is serviceable, but not my favorite format for command ergonomics
- it does not give the combined tool-management value that
Misedoes - for very small repos, it can feel slightly more formal than necessary
I would pick go-task ahead of Make for plenty of new repos, especially if the team already leans heavily on YAML and wants a runner that scales without getting weird. task build also lands in a nice middle ground: short like just build, but backed by a more structured file.
Side-by-side verdict
Here is the short version.
If you care most about readability of commands
Just wins.
If you care most about total developer onboarding
Mise wins.
If you want a structured task graph without buying into Mise
go-task is a strong option.
If your team already speaks Make fluently
Make is still viable, but it is usually no longer the best fresh choice.
Which one wins in 2026?
For a new .NET Aspire repository in 2026, my winner is Mise.
Not because it is trendy. Because it solves the two problems teams actually have.
Why Mise wins:
- It solves both environment setup and task execution.
- It scales better once the repo stops being purely .NET.
- It gives teams one place to declare tool versions and standard commands.
- It reduces onboarding friction more directly than
Make,Just, orgo-task. - It matches the reality that modern app repositories usually need more than a command launcher.
If the question is "what should I choose for most new application repositories starting now?" I would pick Mise first.
If the question is "which file do I most enjoy reading and writing?" the answer is often Just.
That distinction matters. Just wins on command authoring. Mise wins on the broader repo workflow.
My ranking for new repositories
For the kind of repository used in this article, my ranking in 2026 is:
MiseJustgo-taskMake
This is not me saying Make is obsolete or that go-task is weak. It is a ranking for new repos where onboarding, portability, and future tool sprawl matter more than legacy familiarity.
When the winner should not be your choice
You still should not force Mise everywhere.
Choose Just instead when:
- your tool versions are already managed elsewhere
- your team wants the simplest command runner possible
- developer ergonomics for authoring commands is the top priority
Choose go-task instead when:
- your team likes YAML and already uses it heavily
- your automation graph is growing beyond a tiny set of developer tasks
- you want structured task definitions without adopting an environment manager
Choose Make instead when:
- the team already has deep
Makefilehabits - the repository is highly Unix-centric
- consistency with existing repos matters more than adopting something newer
Recommended default for this sample
If I were keeping only one file in the sample repository, I would keep mise.toml.
If I were optimizing strictly for authoring experience and I already had SDK/tool version management elsewhere, I would keep Justfile.
That is the clearest version of the tradeoff.
Conclusion
Make, Just, Mise, and go-task can all automate the same .NET Aspire lifecycle. The real question is what each one asks your team to carry over time.
Make brings familiarity, plus some legacy friction. Just is clear and pleasant to write. go-task gives you a structured modern runner. Mise does the most overall because it combines environment management and task execution in one place.
So if you want the short answer for 2026:
- best overall winner:
Mise - best command authoring experience:
Just - best structured alternative without environment management:
go-task - best legacy-compatible option:
Make
That is the choice I would start with for a new .NET Aspire repository, unless the team already has conventions that point somewhere else.


