Starflinger
← All posts

· 5 min read

Why AI agents love the command line

LLMs are trained to continue documents, and a terminal session is a document. Notes, with numbers, on why the oldest interface we have turned out to be the best one for agents.

  • ai
  • agents
  • cli
  • llm

I spend most of my working day in a terminal with an AI agent in it. The day job is keeping multi-client Ethereum test networks alive, which mostly means digging through logs on machines that disagree with each other. The Proxmox cluster at home was built the same way, with an agent in a terminal and me reading its diffs. After a year of this I keep noticing the same thing. In a browser, the model fumbles: it clicks the wrong button, loses its tab, accepts the same cookie banner twice. In a terminal, the same model is fast and reliable.

This post is my current explanation for why.

For anyone who doesn’t live in a terminal: a terminal (command line, CLI, same thing here) is a text window. You type a command, the computer prints text back. ls lists your files. That’s the whole interface.

What a language model actually does

A large language model is trained on one task: given some text, predict the text that comes next. “Autocomplete on steroids” is roughly right, except it’s autocomplete over whole documents, not single words. Give it half a recipe and it continues the recipe. Give it half a program and it continues the program. When the model answers your question, it continues a document that ends with your question. There is no second mechanism. Everything the model does is this one move.

A terminal session is a document

A terminal session is a transcript: command, output, command, output. The internet is full of these transcripts. They appear in tutorials (“run this, you should see…”), Stack Overflow answers, README files, and man pages (the built-in manuals). A large share of all technical writing online is shell transcripts with commentary. The model was trained on millions of them. It doesn’t just know the commands. It knows what healthy output looks like, what suspicious output looks like, and what a competent operator types next in either case.

An example:

$ ./backup.sh
Error: BACKUP_DIR is not set

$ BACKUP_DIR=/mnt/backup ./backup.sh
Done. 312 files copied.

You followed that with no training. The script complained that a setting was missing, the second run supplied the setting, and the backup finished. A transcript reads like a story because it is one.

The loop

When an agent runs a command, the output comes back as text and lands in the agent’s context window. The context window is the model’s working memory, the document it is currently continuing. So acting and observing become the same operation. Append to the transcript, predict what comes next. People call this the “agentic loop”, and in a terminal it is nothing more than the training task pointed at a document that answers back.

Everywhere else there’s a translation layer. In a browser the model works through screenshots and click coordinates, pixels it reads secondhand and not very well. In a terminal the state of the world is already text.

Discovery is cheap

CLIs describe themselves on demand. Nearly every tool answers --help with a page of usage instructions, and man has the rest. The agent doesn’t need the manual up front. It pulls what it needs, when it needs it, a few hundred tokens at a time. (A token is a word-sized chunk of text. Models read text as tokens and are billed per token.)

The usual alternative is preloading. You connect the agent to its tools through MCP, a standard for plugging tools into agents, and every tool’s full description is loaded into the model’s memory before work starts. I’ve watched setups spend tens of thousands of tokens on tool definitions before the first real command. This waste is why I prefer plain CLIs over MCP servers for most agent work. A CLI is simply more token-efficient. Anthropic measured the same thing: when the agent discovered tools and called them with code instead of reading preloaded definitions, one workflow dropped from about 150,000 tokens to about 2,000. Keep the manual where the agent can look it up, not preloaded in the model’s memory.

We hit the same wall at work, where the monitoring stack (metrics, logs, a large analytics database) started as one MCP tool per datasource. A single query could dump seven thousand rows of JSON into the model’s context window. The fix was panda, which hands the agent an isolated Python environment with every datasource already wired in. The rows stay inside that environment, and only the few-line summary the agent prints comes back to the model. Panda has both a CLI and a small MCP server in front of the same engine, and the interface turned out to matter less than keeping the rows out of the model’s memory. The panda write-up has the details.

Panda data flow. The agent sends one command to panda, which runs the code in a Python sandbox that holds no credentials. The sandbox queries ClickHouse, Prometheus, Loki, and Ethereum nodes through a credential proxy. Seven thousand rows flow back into the sandbox, and only a few-line summary returns to the agent.

Errors are text

When a graphical program fails, you often get a greyed-out button or a dialog box with no stated reason. When a CLI fails, you get a sentence: Error: BACKUP_DIR is not set. That sentence goes straight into the transcript and shapes the next prediction. The model has read ten thousand documents in which this exact error is followed by its fix.

In practice this is the difference I notice most. An agent that hits a CLI error doesn’t flail. It reads the error, because the error was written to be read.

Pipes

The terminal has one more property, and it is older than everything above. Unix tools can be chained. The | character (a “pipe”) feeds one command’s output into the next. history | grep ssh searches everything I’ve ever typed for “ssh”. A few dozen small tools combine into millions of possible one-line programs. Small vocabulary, huge expressiveness. Language works the same way, with finite words and infinite sentences.

Doug McIlroy wrote the rule down in 1978: “Write programs to handle text streams, because that is a universal interface.” He meant the interface between programs, and between programs and people. Fifty years later the rule covers a reader nobody planned for: a machine that has read most of the internet and can read only text.

What doesn’t work

I’ve tried to get an agent to find bugs and then improve its own bug-finding method from run to run. So far I have failed. The agent overfits to whatever it found in the last run. Agents also report success without checking. My standing rule is that a claim doesn’t count until the agent proves it with a command. Run the test, fetch the URL, read the file it claims to have changed. The terminal makes verification cheap. It doesn’t make verification automatic.

The old bet

The terminal is over fifty years old and has outlived every prediction of its death. Nobody designed an interface for AI agents. The Unix people bet on text. Text became the format technical knowledge was written down in, and that text is what these models were trained on. The best interface for agents already existed.

@starflinger.eu · Vienna, August 2026