# Progress indication for long operations

- **Pattern:** `ab-000649` (`cli-quality.io-behavior.progress-indication`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000649
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000649)

## Why it matters

A CLI that sits silent for ten seconds during a deploy looks frozen. Users hit Ctrl+C, corrupt state, and open a support ticket. Progress indicators on stderr — spinners, counters, bars — tell the user the tool is alive without polluting stdout for scripts. Writing spinners to stdout is the opposite failure: `mytool deploy | tee log` captures terminal control sequences into the log file, and every subsequent `cat log` flickers the terminal.

## Severity rationale

Low because missing progress indication is a UX annoyance but does not cause data loss or failed operations.

## Remediation

Wrap operations over two seconds (network calls, installs, file scans) with a spinner or progress bar routed to stderr, and suppress when `!process.stderr.isTTY`. In `src/cli/commands/deploy.ts`:

```ts
import ora from 'ora'
const spinner = ora({ text: 'Deploying...', stream: process.stderr }).start()
try { await deploy(); spinner.succeed('Deployed') }
catch (e) { spinner.fail('Failed'); throw e }
```

## Detection

- **ID:** `progress-indication`
- **Severity:** `low`
- **What to look for:** Enumerate every long-running operation in the CLI (network calls, file processing, installations). For each, identify operations that may take more than 1-2 seconds (network requests, file processing, build steps). Check that these operations show progress feedback — a spinner (ora, cli-spinners, tqdm), a progress bar, or periodic status messages. Verify that progress output goes to stderr (not stdout). Check that progress indicators are suppressed when stdout is not a TTY.
- **Pass criteria:** Long-running operations provide visible progress feedback. Progress output goes to stderr. Progress is suppressed or simplified when not running in a TTY — 100% of operations taking over 2 seconds must show progress feedback. Report: "X long-running operations found, all Y show progress indication."
- **Fail criteria:** Long-running operations produce no output until completion (the user sees a hanging terminal), or progress output goes to stdout (corrupts piped data).
- **Skip (N/A) when:** All commands complete in under 1-2 seconds (no network calls, no large file processing). All checks skip when no CLI entry point is detected.
- **Detail on fail:** `"'deploy' command makes 5 API calls with no progress indication — terminal appears frozen for 10+ seconds"` or `"Spinner from ora writes to stdout by default — will corrupt piped output"`
- **Remediation:** Users need feedback that the CLI is working, not frozen:

  ```ts
  // Node.js — ora spinner on stderr
  import ora from 'ora'
  const spinner = ora({ text: 'Deploying...', stream: process.stderr }).start()
  try {
    await deploy()
    spinner.succeed('Deployed successfully')
  } catch (err) {
    spinner.fail('Deployment failed')
    throw err
  }
  ```

  ```python
  # Python — tqdm or click.progressbar to stderr
  import click
  with click.progressbar(files, label='Processing', file=sys.stderr) as bar:
      for f in bar:
          process_file(f)
  ```

Taxons: user-experience

HTML version: https://auditbuffet.com/patterns/ab-000649
