---
description: MessageBox is for attention. Command results use Report.
alwaysApply: false
---

# stderr: box for attention, report for results

Never use `eprintln!` from command code. User-facing stderr goes through
`message_box`.

- **`MessageBox`** when the user must notice: errors, warnings, disclaimers,
  pre-exec / pre-tool access failures, a new Lade release. The bordered
  box is the point.
- **`Report`** for the result of a verb (`lade setup`, `lade update`,
  `lade teardown`, `lade hook enable`, add/remove, upgrade already
  current). Bold headings and colour when the terminal allows it. No
  border.

`UiMode` / `is_interactive()` gates prompts, countdowns, and sleeps. It
must never suppress a `MessageBox`.

```rust
// ❌ BAD — setup success in a box
MessageBox::new().info().line("pre-exec  this shell").print_stderr();

// ✅ GOOD — command result
Report::new().heading("pre-exec  this shell").dim("Wraps commands you type.").print();

// ✅ GOOD — attention (pre-exec failure, or a new Lade release)
MessageBox::new().error().paragraph(e.to_string()).print_stderr();
```

Do not box `lade setup` / `lade update` success. After that report, if a
newer Lade binary is available, emit a `MessageBox` (`upgrade::nudge_if_available`).
Do not nag on `lade set`: stdout is the shell protocol.

Live setup / update: one tracker row per step (spinner, then ✔︎), same
machinery as provider resolve. Mise logs update the current row. Never
inherit the child stdio. `mise env --json-extended` stays captured and quiet.
