· Freddie K.
UXTerminalDesign

Terminal UX principles that apply to any interface

Terminals have survived for 50 years because they get a few things exactly right. These principles aren't just for CLI tools — they make any interface better.

I spend a lot of time in terminals. Not because GUIs are bad — some GUIs are excellent — but because well-designed CLI tools have properties that most graphical interfaces don’t. Understanding what makes terminals work well is useful even if you never build a CLI.

Principle 1: Output is permanent, not ephemeral

In a GUI, most state is transient. Modals appear and disappear. Notifications fade. Hover states exist only while hovering. The interface assumes the user is watching constantly and can catch everything as it happens.

In a terminal, every command output is permanent — it scrolls up and stays in the buffer. You can scroll back, pipe to a file, grep through it. The history is the record.

This forces a discipline: every piece of output has to be worth keeping. Terminals rarely show loading spinners because there’s no frame to show them in. They show status messages: Compiling... done (3.2s). That message is still there after compilation finishes. You can verify it happened.

Applied to GUI: Show state changes as events, not just current state. A “last saved: 2 minutes ago” message is more trustworthy than a “saved” toast that disappears.

Principle 2: Composition over features

The Unix philosophy: write programs that do one thing well, and write programs that work together. A tool that does one thing can be composed with other single-purpose tools using pipes.

ps aux | grep node | awk '{print $2}' | xargs kill

Four tools, each simple, combined to do something none of them could do alone.

GUI applications typically don’t compose. Figma doesn’t pipe to Notion. Slack doesn’t pipe to Linear. Every integration is a special-case feature that someone had to build explicitly.

Applied to GUI: Design data export/import first. An app that can import and export structured data composes with other apps via the filesystem, even if there’s no native integration.

Principle 3: Errors tell you what to do next

Bad terminal errors:

Error: EACCES

Good terminal errors:

Error: EACCES: permission denied, open '/etc/hosts'
→ Try running with sudo, or change the file permissions: chmod 644 /etc/hosts

The good error identifies what failed, where it failed, and what to do about it. It assumes the user wants to fix the problem, not just know that a problem occurred.

Most GUI error messages optimize for not being blamed. “An error occurred” tells the user nothing actionable. “Couldn’t save: the file is locked by another application. Close the other application and try again.” — that tells them what to do.

Applied to GUI: Every error message should answer: what failed, why it failed, and what the user can do about it. If you don’t know why it failed, say so honestly: “We’re not sure what happened. Try again, and if this keeps happening, check [status page].”

Principle 4: Confirmation is for destructive actions only

Terminal tools don’t ask “are you sure?” for every operation. They ask once, for destructive operations:

rm -rf /important-directory
Are you sure? This will permanently delete /important-directory and all its contents. [y/N]

Everything else just happens. ls, cat, grep, cp — no confirmation dialogs. You asked for it, you get it.

GUIs over-confirm. “Are you sure you want to logout?” Yes. I clicked logout. “Are you sure you want to close this tab?” Yes. I clicked the X.

Confirmation dialogs that appear constantly train users to dismiss them without reading. When a genuinely important confirmation appears, users dismiss it out of habit.

Applied to GUI: Reserve confirmations for irreversible actions with significant consequences. Everything reversible should just happen. Undo is a better safety mechanism than confirmation dialogs for most operations.

Principle 5: The interface disappears

A well-used terminal doesn’t feel like an interface. You’re thinking about what you want to accomplish, not about how to interact with the tool. The keystrokes are automatic. The commands are vocabulary.

This takes time to achieve in a terminal — there’s a learning curve. But the payoff is that the tool eventually has zero friction. GUI tools that are frequently used should aspire to the same: keyboard shortcuts for everything, muscle memory as a first-class goal.

Applied to GUI: The measure of a mature interface is how little users have to think about it. If power users still have to think about where things are, the interface hasn’t matured. Keyboard shortcuts, consistent patterns, and predictable layouts all contribute to the tool getting out of the way.

What terminals don’t do well

Fairness requires noting where terminals genuinely fail:

  • Visual information: Terminals are bad at images, diagrams, spatial information. A map, a photo, a circuit diagram — these belong in GUIs.
  • Discoverability: You can’t browse a terminal to find what’s available. You have to already know the command or search documentation. Tab completion helps; it doesn’t fully solve the problem.
  • Accessibility: Screen readers work with terminals, but the experience is significantly worse than a well-built GUI. High-contrast and zoom options are limited.
  • Collaboration: Terminals are personal workspaces. Real-time collaboration requires different architecture.

The terminal aesthetic in this portfolio borrows the visual language of terminals, not the interaction model. The grid, the monospace type, the status indicators — these suggest precision and intentionality without requiring a command line.

The principles above, though, apply everywhere. Permanent output, composable design, useful errors, minimal confirmation, and an interface that disappears — these make any tool better.