Build verbosity changes depending on whether stdout is a terminal or a pipe
- Dominant language
- C#
- Stars
- 5.5k
- Forks
- 1.5k
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 141
Description
### Problem
Running `dotnet build` interactively and running `dotnet build > log.txt` produce different output — not just in formatting, but in **content**. Messages that appear in the log file are completely absent from the interactive terminal, even at the same verbosity level.
This happens because interactive sessions use the terminal logger (default since .NET 9), while piped output falls back to the console logger. The two loggers apply different rules for which messages they display.
I understand this is by design with the terminal logger, but I believe it's a mistake — the effective verbosity of a build should not change based on where stdout is going.
### Impact on AI-assisted development
AI coding agents like GitHub Copilot interact with MSBuild by capturing stdout, so they always get the console logger. When an agent helps a developer write build targets or MSBuild plugins, it sees high-importance messages in its captured output and assumes the developer will see them too. But the developer, running interactively with the terminal logger, won't.
This means the agent and the developer are looking at different views of the same build without either side knowing it. As AI-assisted development becomes more common, this divergence becomes increasingly problematic — agents can't reliably reason about what the developer will actually see.
### Reproduction
Add a high-importance message to any project:
```xml
```
- `dotnet build` interactively → message is hidden
- `dotnet build > log.txt` → message appears in the file
### This breaks convention
Console tools routinely adjust *formatting* when piping — stripping colors, disabling progress bars, removing interactive elements. But they generally don't change *verbosity*. Users expect to see the same information whether they're watching the output live or capturing it.
`MessageImportance.High` is the documented contract for communicating with users. Targets, tasks, and plugins use it to surface information the user is expected to see. The terminal logger silently breaks this contract, leaving authors with no good way to reliably show a message to the user.
### Verbosity gap
The console logger shows `MessageImportance.High` messages at `minimal` verbosity and above. The terminal logger requires `detailed` — two levels higher.
| Verbosity | Piped to file | Interactive terminal |
|-----------|--------------|---------------------|
| `quiet` | ❌ | ❌ |
| `minimal` | ✅ | ❌ |
| `normal` | ✅ | ❌ |
| `detailed`| ✅ | ✅ |
### Workarounds (all unsatisfying)
- `/tl:false` — gives up the terminal logger entirely
- `/tlp:verbosity=detailed` — currently the best workaround, but requires every user/CI script to know about it; it should not be necessary for `MessageImportance.High` messages
- `LogWarning` — always visible, but semantically incorrect, repeated in the build summary, and inflates warning counts
### Suggestion
The terminal logger should display `MessageImportance.High` messages at the same verbosity levels as the console logger. Piping to a file should change formatting and interactivity — not what information is shown.
---
*This content was created with assistance from AI.*
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.