The Terminal Is a Design Tool

January 8, 2026 · 3 min read
designclitools

I've been building CLI tools for years, and somewhere along the way I realized something: the terminal teaches you more about interface design than any design system ever will.

Not because it's better than a GUI. Because it's more constrained. And constraints are where good design lives.

80 columns of truth

In a GUI, you can always add another panel, another modal, another tooltip. In a terminal, you have roughly 80 columns and whatever fits on one screen. That's it.

This forces you to answer the hardest design question first: what does the user actually need to see right now?

# Bad: showing everything
┌─────────────────────────────────────────────────┐
│ Build #4521                                     │
│ Status: SUCCESS                                 │
│ Branch: main                                    │
│ Commit: a1b2c3d                                 │
│ Author: david                                   │
│ Duration: 3m 42s                                │
│ Started: 2026-01-08T14:32:00Z                   │
│ Finished: 2026-01-08T14:35:42Z                  │
│ Artifacts: 3                                    │
│ Coverage: 87.2%                                 │
│ Warnings: 12                                    │
│ Node: v20.18.0                                  │
│ OS: linux-x64                                   │
└─────────────────────────────────────────────────┘

# Good: showing what matters
✓ Build #4521 passed (3m 42s) — main@a1b2c3d

One line. Everything you need. The rest is available if you ask for it (--verbose), but the default is the useful answer, not the complete answer.

Progressive disclosure, but honest

GUIs hide complexity behind menus and settings panels. CLIs hide it behind flags and subcommands. The difference is that CLIs make the hiding explicit.

deploy                    # sensible defaults
deploy --dry-run          # show me what would happen
deploy --region us-west-2 # override one thing
deploy --verbose          # show me everything

Each flag is a question the user is asking. If you design your flags well, they read like a conversation:

  • "Deploy." → Done.
  • "Wait, show me first." → Here's what would happen.
  • "Actually, deploy to this region." → OK, deploying to us-west-2.
  • "Something went wrong, show me everything." → Here's the full log.

Error messages are the real UI

The moment that matters most in any interface is when something goes wrong. CLIs force you to get this right because you can't fall back on a red banner or a modal with a sad face emoji.

# Bad
Error: ENOENT

# Better
Error: config file not found at ./config.yaml

# Best
Error: config file not found at ./config.yaml

  Expected: ./config.yaml
  Searched: /Users/david/project, /Users/david, /etc

  To create one: run `mytool init`
  To use a different path: --config /path/to/file

The best error message tells you three things: what happened, why it happened, and what to do about it. Most GUIs get the first one right. Few get all three.

The lesson for all interfaces

Whether you're building a CLI, a web app, or an API, the terminal's constraints teach the same lessons:

  1. Default to the useful answer, not the complete one
  2. Make complexity opt-in, not hidden
  3. Error states are your most important UI
  4. If you can't explain it in 80 columns, you don't understand it yet

The terminal didn't teach me to love constraints. It taught me that constraints are where clarity comes from.