Designing CLIs for Better Agent Experiences
For a long time, the command line was an interface for people already closest to the system, mostly engineers who knew the vocabulary and held the relevant context, and could recover from a failed command without the interface explaining itself.
That is changing because agents can work directly with a CLI. Their training gives them a working familiarity with the language and conventions of command line , making it a natural execution surface.
In a sandbox, an agent can work through a task independently and involve a person only where judgment is genuinely needed.
The human interaction with CLI is not disappearing, but that they move from typing every command to deciding what should happen and reviewing the result. As the CLI becomes where an agent turns human intent into product work, it is part of the product experience rather than merely a developer convenience layer over an API.
Why sandboxes make the CLI important again
AI Product teams are adding sandboxes because many useful tasks cannot be reduced to one tool call. A sandbox gives an agent room to understand the state of a system, carry out work, and verify the outcome safely. People are saying CLI is more token efficient too :)).
MCP remains valuable because it gives agents curated, well-bounded access to a product, but overall MCP and a CLI are not competing choices. MCP is often the right interface for a focused capability, while a CLI is useful when work is exploratory, stateful, or composed from several operations. In that setting, the CLI becomes the durable, inspectable surface that the agent can reason over while it works.
| Choose MCP when | Choose a CLI when |
|---|---|
| The agent needs one bounded product capability with a clear contract. | The agent needs to carry a task through several steps. |
| Inputs and expected outputs are known before the call. | The agent needs to discover context as it works. |
| You want a narrow permission boundary around an operation. | The agent needs to inspect state, rehearse a change, or verify an outcome. |
| The interaction is a product action such as creating a ticket or reading a record. | The work involves a repository, an environment, or a sequence of related commands. |
| The agent only has access to curated product tools. | The agent has a sandboxed shell and the files or environment needed for the task. |
| Tool schemas add a baseline context cost, while bounded responses keep each call predictable. | Commands are compact, but discovery and unbounded terminal output can grow the transcript. |
Neither interface is inherently cheaper in tokens. Compare the cost of the whole execution loop: MCP tool definitions and responses on one side, and CLI commands, help text, and output on the other. In both cases, concise, structured responses are what keep an agent's context under control.
The useful design question is not which interface wins. It is where the boundary belongs: use MCP to provide deliberate access to a capability, and a CLI when the agent needs an execution surface for the surrounding work.
Having an API is therefore no longer enough: an API can be complete while still offering a really poor agent experience. The real challenge is whether an agent can use the interface to get from a request to a trustworthy result, just like how human navigating a product UI.
Design for the task, not the endpoint
The easiest CLI to build mirrors API endpoints: projects.create,
projects.list, members.add. Although that can be useful, it forces the
agent to reconstruct the workflow and infer what a successful result looks
like.
A better CLI begins with the task and supports the full path to completion.
Creating a project, for example, should be one legible action with a clear outcome and enough options to make the result useful in the next step, rather than a raw transport call.
| Bad: endpoint-shaped | Good: task-shaped |
|---|---|
product api post /projects --body '{"name":"launch-plan"}' | product project create --name launch-plan --owner team-platform --json |
| The agent must discover the endpoint, construct a request body, and work out what to do next. | The command expresses the outcome, accepts the context needed to achieve it, and returns a result for the next step. |
The endpoint-shaped command still has a place as an escape hatch. It is a poor default when the product already knows the task the agent is trying to finish.
The same standard applies to human UI: a good interface gives its user orientation, clear states, and a path forward. Since a CLI is an agent's UI, it deserves the same attention to flow and detail.
Make the result easy to reason about
People can often read a loosely formatted response and work out what happened, but agents should not have to rely on that interpretation. A stable result lets an agent verify the outcome and continue without guessing.
Structured output is not only about JSON. It is an agreement about what an agent can rely on, reducing ambiguity at the point where it decides what to do next. The structured result should follow a concrete invocation.
product project create --name launch-plan --owner team-platform --json
{
"status": "created",
"project": { "id": "prj_123", "name": "launch-plan" },
"suggested_next_actions": ["product project show prj_123 --json"]
}
That final field is small but important because a command should not end a workflow with a dead end. It should help an agent find the next reliable move.
Let the agent rehearse before it changes anything
The most capable agent is not the one that acts fastest, but the one that knows when to stop and inspect the consequence of an action.
Dry runs make that restraint possible by showing an agent the consequence of a change before it alters a real system. They create a reviewable boundary between planning and execution.
product access grant --project prj_123 --member alex@example.com --role editor \
--dry-run --json
Although dry runs are useful for people too, they are essential for agents because they make reasoning visible, expose assumptions, and reserve escalation for decisions that genuinely need a person.
Keep intent in the execution context
Every tool invocation should have a concise statement of intent in its execution record when that context is available. This is not a request for an agent's private reasoning. It is a durable account of the outcome being sought, which gives a person reviewing the trace enough context to understand why an action happened.
The product command should remain the same for people and agents. An agent runtime can take the intent from its assigned task and attach it to every command automatically. When a person runs the CLI directly, the system should record a direct human action unless they deliberately provide intent in the surrounding workflow.
product access grant --project prj_123 --member alex@example.com --role editor --json
Outside the CLI response, the execution system can record the agent's task context alongside the result.
{
"actor_type": "agent",
"intent": "Grant Alex editor access to launch-plan",
"tool": "product access grant",
"status": "failed"
}
Treat failures as part of the interface
Most agent experiences fail not because the happy path is missing, but because a command fails and the interface offers no way back.
An error should explain what happened in a form the agent can act on. "Request failed" leaves it nowhere to go, whereas an actionable failure gives it a way to correct itself instead of retrying blindly or handing an opaque problem to a person.
product access grant --project prj_123 --member alex@example.com --role editor --json
{
"status": "failed",
"error": {
"code": "member_not_found",
"message": "No member matches alex@example.com.",
"suggested_next_actions": ["product member list --json"]
}
}
Failures are also product research: they show where the CLI lacks context, where an instruction is unclear, and where an evaluation should be added. A feedback mechanism turns an agent's failed attempt into evidence for the next improvement.
Agents can provide feedback too
Agent-facing products should give agents a direct way to report when the interface has failed them. A dedicated feedback tool can capture the context of an error or a blocked task while it is still available, instead of relying on a person to reconstruct the problem later.
The human equivalent is a "Report a problem" path inside a product UI. When a person cannot complete a settings flow, the interface can let them describe the problem while preserving the relevant state for the team. An agent needs the same escape hatch, expressed as a tool rather than a button.
Keep the feedback tool simple. The agent already has the task it was attempting and the observation that blocked it, so the command can accept one message rather than require it to manufacture a product-specific taxonomy.
The agent needs guidance before it uses the tool. Its instructions should ask for concise feedback that explains the intended outcome, the observed problem, and the context needed to continue. That gives the model a standard for useful feedback while leaving it to describe the situation in its own words.
product feedback report \
--message "I could not grant Alex editor access to launch-plan because the member lookup returned member_not_found. Confirm the account email before retrying." \
--json
The product can acknowledge that report in a form the agent can retain in its own work log.
{
"status": "recorded",
"feedback_id": "fbk_123",
"suggested_next_actions": ["Ask the user to confirm Alex's account email"]
}
That feedback closes the loop between use and evaluation. It gives the product team evidence for improving the CLI, its instructions, and the scenarios used to test whether agents can complete real work.
The practical test
When designing a CLI, the practical question is whether an agent with a clear goal can carry the work safely through to completion, including recovery when something fails.
When that sequence cannot happen, the interface is unfinished: it may be a capable API wrapper, but it is not yet a reliable product surface for agents. Teams that take this seriously will not only give agents more access. They will give them interfaces that make good outcomes more likely.