dotnet / dotnet/sdk

Offer `dotnet install` (same as `cargo install`)

Open
#50,747 5 comments 1 reaction 0 assignees View on GitHub
Area-Tools untriaged
Dominant language
C#
Stars
3.2k
Forks
1.3k
PR merge metrics
PR metrics pending

Description

`cargo install` and `go install` enable important workflows for their respective ecosystems. We can offer much the same experience with `dotnet install` targeted at production-ready and PATH-resident single file executables.

## Command Behavior

### Core Functionality

`dotnet install` performs two atomic operations:
1. **Builds** a production (Release) executable from source
2. **Places** the resulting binary in a standard, PATH-friendly location

```bash
# Install current project
dotnet install # Builds and installs to ~/.dotnet/bin/

# Install to a different location
dotnet install -o ~/tools

# Install from local path
dotnet install src/my-tool # Builds specified project and installs

# Install from NuGet
dotnet install --package sometool # Downloads, builds, and installs
dotnet install --package sometool@1.2.3 # Specific version
```

### Key Principles

**Always Build Fresh**: Like `cargo install` and `go install`, this command always performs a new Release build. It never copies existing build outputs, ensuring predictable, production-ready binaries.

**Single File Focus**: The command is optimized for single-file deployments (Native AOT or single-file CoreCLR). This scheme also provides more incentive to use those build modalities.

**No Configuration Modes**: No `-c Debug` or `-c Release` flags. Install means production, always.

## Installation Target

Binaries are installed to a standardized location that should be added to PATH:
- **Windows**: `%USERPROFILE%\.dotnet\bin\`
- **Unix**: `~/.dotnet/bin/`

This mirrors the approach of:
- Rust: `~/.cargo/bin/`
- Go: `~/go/bin/`

For single-file applications (Native AOT or CoreCLR with PublishSingleFile), the experience is identical to Rust/Go:

```bash
dotnet install mytool
mytool --help # Just works
```

## Integration with .NET Tools

Current .NET tools distributed via NuGet can leverage this same infrastructure. Instead of the current deep folder structure:

```bash
~/.dotnet/tools/.store/mytool/1.0.0/mytool/1.0.0/tools/net8.0/any/
```

Tools would be distributed using the artifacts path layout and the install command becomes a "placer" that moves from the artifacts structure to the bin location:

```bash
~/.dotnet/bin/mytool
```

This positions `dotnet install` as the unifying command for all executable installations, whether local projects or NuGet-distributed tools.

## Project Configuration

Projects signal their install-readiness through existing MSBuild properties:

```xml


true


true


true

```

No new properties are required. If a project produces an executable and uses release configuration, it can be installed.

## Relationship to Existing Commands

`dotnet install` is additive and composable with existing verbs:

- **`dotnet build`**: Unchanged. Continues to build to traditional MSBuild paths
- **`dotnet publish`**: Unchanged. Continues to prepare deployable assets
- **`dotnet run`**: Unchanged. Continues to enable rapid development iteration
- **`dotnet tool install`**: Could eventually delegate to `dotnet install` for consistency

The command is essentially a specialized wrapper around `dotnet publish` that adds placement semantics:

```bash
dotnet install ≈ dotnet publish -c Release --output ~/.dotnet/bin/
```

## Why This Matters

### For Native AOT

Provides the missing "last mile" that makes Native AOT feel like a first-class citizen. Users can install and run Native AOT applications exactly like Go or Rust programs, highlighting the performance and deployment benefits.

### For Single-File CoreCLR

Offers the same streamlined experience for CoreCLR applications packaged as single files, bridging the gap between development convenience and production deployment.

### For the Ecosystem

- **LLM-Friendly**: Adopts the exact verb used by other ecosystems, making AI assistants more helpful
- **Beginner-Friendly**: Eliminates the need to understand .NET's build output structure
- **Tool Authors**: Simplifies distribution by unifying tools and applications under one model

## Success Metrics

- A developer can install and run a .NET application with the same ease as Rust or Go
- Single-file applications (both Native AOT and CoreCLR) become the preferred distribution format
- The question "How do I run my built .NET app?" disappears from forums
- `dotnet run` usage decreases as developers can easily run installed binaries directly
- More developers choose single-file and NAOT build types.

## Summary

`dotnet install` fill a key gap by providing a production-focused, ergonomic command for installing executables from source. It embraces a pattern proven by Rust and Go, making single-file applications — particularly Native AOT —s hine while maintaining full compatibility with the broader .NET ecosystem.

An underlying philsophy here is "no re-invention". Unless there is a strong reason, we just follow the crowd given the same need.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.