Building CLIs for AI Agents

This content was generated with the assistance of AI and should be verified against the official documentation of each tool and framework before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

A command-line tool that an AI agent can drive is the same kind of tool a careful engineer would want anyway: predictable streams, honest exit codes, structured output, no surprise prompts and safe defaults. This sub-section collects those practices, shows them on one running example, and then shows how to wrap the finished tool as an MCP server or an agent tool. The versions used are listed in Version baseline, all checked on 2026-09-30, and every page repeats the subset it needs in its own lead paragraph.

Why CLIs work well with agents

An agent that can run a shell command can already use a very large tool ecosystem, and a CLI has properties that suit that style of work:

  • Nothing to load up front. A command costs context only when it is run, and only its output is paid for. Claude Code’s own guidance treats command-line tools as a context-efficient way to reach external services (see Claude Code — Best practices). Tool schemas, by contrast, are usually loaded before the first call.

  • Models already know the common ones. git, gh, curl and jq appear throughout training data, so little description is needed; an unfamiliar tool costs one --help call, which is why Self-Describing Help matters.

  • Composition is built in. Pipes, redirection and exit codes let an agent chain steps without a bespoke integration, which only works when the tool respects Streams & Exit Codes.

  • Humans and CI use the same interface. One implementation serves a terminal, a script and an agent, and the same contract can later be exposed as an MCP tool (see CLI vs. MCP for the honest trade-offs, including where MCP is the better fit).

  • Guardrails already exist. Hosts gate shell access with permission rules and sandboxes, described for Claude Code on Permissions & Settings; a well-designed CLI adds dry-runs, confirmations and least-privilege credentials on top.

The price is that a CLI written only for people is hostile to agents: colour codes and spinners in captured output, prompts that hang, human-only error text, unbounded output and unparseable tables. The pages below remove each of those problems in turn. The tool-design ideas behind them are the ones in Tool Design and Designing Good MCP Servers, applied to a process instead of a protocol.

Three audiences, one tool

A command-line tool has three kinds of caller, and a good design serves all of them from one implementation.

flowchart LR H(["Human
terminal, TTY"]) --> CLI S(["Script or CI job
pipes, exit codes"]) --> CLI A(["AI agent
shell tool, MCP or agent-framework tool"]) --> CLI CLI["docsctl
one command line, one contract"] --> SVC[("Service
documentation site, credentials, gh-pages")] CLI -.->|"stdout: data (text or JSON)
stderr: messages
exit code: outcome"| H CLI -.-> S CLI -.-> A
Table 1. What each audience needs from the same command line
Audience Needs Where it is covered

Humans

Readable text, colour and progress on a terminal, helpful errors, examples in --help, prompts before risky actions, completion and man pages.

TTY, Colour & Interactivity, Self-Describing Help, TUIs vs. CLIs

Scripts and CI

Stable stdout, nothing on stdout but data, meaningful exit codes, no prompts, configuration through flags and environment variables, predictable installation.

Streams & Exit Codes, Configuration & Auth, Packaging & Distribution

AI agents

Everything scripts need, plus JSON with a stable schema, small default outputs with pagination, errors that say what to do next, dry-run and confirmation for anything destructive, a machine-readable description of the commands, and input validation that assumes the arguments came from a model.

Machine-Readable Output, Agent Ergonomics, Safety & Idempotency, Security

The reading map

The pages can be read in any order, but this route works for most readers:

  1. Start with CLI Design Fundamentals and Streams & Exit Codes; they are the foundation of everything else.

  2. Read the agent-specific pages: Machine-Readable Output, Agent Ergonomics and Safety & Idempotency.

  3. Pick your language on the framework pages, from Python to Swift & .NET.

  4. Decide how the tool reaches the agent: CLI vs. MCP, wrapping as an MCP server or as an agent tool, and the Security rules that apply either way.

  5. Ship it with Packaging & Distribution, Testing CLIs and Documenting CLIs, and review it against the Agent-Readiness Checklist.

Readers who only need a reminder can use the Cheat Sheet, which has a printable one-page PDF.

The docsctl running example

Every page uses the same small, fictional tool, docsctl, a command-line client for the documentation of this site. It exists only on these pages, its behaviour is illustrative, and its contract is repeated identically wherever it is used so that snippets in different languages stay comparable.

Table 2. The docsctl commands
Command What it does Safety

docsctl search QUERY

Full-text search over the documentation; supports --component, --limit and --cursor.

Read-only, idempotent

docsctl show PAGE

Returns one page such as irurueta-algebra::index.adoc, optionally one section, with --max-chars.

Read-only, idempotent

docsctl list-components

Lists the documented components and their versions.

Read-only, idempotent

docsctl validate [PATH]

Checks a documentation tree for broken references and reports problems with a code, a line and a hint.

Read-only, idempotent

docsctl publish --component NAME

Publishes a component; --dry-run prints a JSON plan and a confirmation token is required to apply it.

Destructive, needs confirmation, idempotent with the same key

docsctl login, logout, schema, completion

Credentials, the machine-readable command tree, and shell completion.

Credentials only, or read-only

Every command accepts --json (or --format json|jsonl|text), --no-input, --yes, --timeout and --no-color, writes data to stdout and messages to stderr, and ends with one of a small set of documented exit codes. A search looks like this from a script or an agent:

Searching from a script: data on stdout, nothing else
docsctl search kalman --component irurueta-statistics --limit 3 --json --fields id,title,score

Output (illustrative):

{"nextCursor":null,"query":"kalman","results":[{"id":"irurueta-statistics::kalman.adoc","score":0.91,"title":"Kalman filter"}],"schemaVersion":1,"total":1,"truncated":false}

The primary implementations are in Python with Typer (Python CLI Frameworks) and in Java with picocli, compiled to a native binary with GraalVM Native Image (Java CLI Frameworks). Shorter equivalents cover Node.js (commander), Go and Rust (Cobra; clap, with a Ratatui interface and a Rig agent) and Swift and .NET (swift-argument-parser with SwiftTUI; System.CommandLine). The finished tool is then wrapped three ways: as an MCP server (Python FastMCP, the TypeScript SDK and Spring AI @McpTool) on Wrapping a CLI as an MCP Server, and as a LangChain @tool, a Spring AI @Tool and a LangChain4j @Tool on Wrapping a CLI as an Agent Tool, which also shows using the CLI directly from Claude Code and from Copilot agent mode.

Version baseline

Every version below was read from PyPI, npm, Maven Central, crates.io, the Go module proxy, NuGet, the projects' release pages and their official documentation on 2026-09-30. Each page repeats the subset it uses in its own lead paragraph, and facts that could not be confirmed, or snippets that could not be run in the environment used to write the pages (Go, Rust, .NET and GraalVM native compilation), are said so on the page that uses them. If a page and this baseline disagree after a later update, trust this baseline.

Area Versions

Python

Python 3.12 (the AI-section baseline); Typer 0.27.2, Click 8.5.0, Rich 15.0.0, Textual 8.2.8; argparse from the standard library.

Java

Java 21; picocli and picocli-codegen 4.7.7; Spring Shell 4.0.3; JLine 4.4.6; GraalVM Native Image (the GraalVM SDK artifact on Maven Central is 25.4.4.1.1; check the GraalVM JDK release you install); Spring Boot 4.1.1 with Spring AI 2.0.1 and the MCP Java SDK 2.0.1, as on Model Context Protocol (MCP).

Node.js and TypeScript

Node.js 24 LTS; commander 15.0.0, oclif 6.0.2, Ink 7.1.1; @modelcontextprotocol/server 2.2.0; TypeScript 7.0.2.

Go

Go 1.27.1; Cobra v1.10.2 with pflag v1.0.10.

Rust

clap 4.6.7, clap_complete 4.6.11, clap_mangen 0.3.3, Ratatui 0.30.2, Rig (the rig-core crate) 0.42.0; Rust snippets were not compiled for these pages.

Swift

Swift 6.4; swift-argument-parser 1.8.2; SwiftTUI 0.1.0, whose repository has seen no push since 2024-07-09, so treat it as dormant.

.NET

System.CommandLine 2.0.12 (a 3.0.0 release candidate exists and is not used); Spectre.Console and Spectre.Console.Cli 0.57.2; .NET snippets were not compiled for these pages.

Agents and MCP

MCP specification revision 2026-07-28; the official Python mcp SDK 2.2.0 and the standalone fastmcp 4.0.10; LangChain 1.4.3; Spring AI 2.0.1; the Claude Code MCP output cap of 25,000 tokens by default, which applies to MCP tool results.

What’s covered

The pages are grouped the same way as the navigation.

Fundamentals

  • CLI Design Fundamentals — the clig.dev principles, POSIX and GNU conventions, the 12 Factor CLI Apps checklist, subcommand design and naming, flags versus positional arguments and why ambiguous prefix matching is a trap.

  • Streams & Exit Codes — stdout for data and stderr for messages, piping, crash-only design and the exit-code taxonomy, including 126, 127 and 128+N.

  • TTY, Colour & Interactivity — isatty, NO_COLOR, prompting only on a TTY, --no-input and --yes, and progress output only on a terminal.

  • Configuration & Auth — flag, environment, project, user and system precedence, XDG directories, and the token file, keychain and environment-variable trade-off.

Designing for agents

  • Machine-Readable Output — --json, JSON Lines, field projection, deterministic ordering, schemaVersion and published JSON Schemas.

  • Agent Ergonomics — token budgets, pagination with small defaults, truncation markers, errors that carry remediation, timeouts and fast startup.

  • Safety & Idempotency — read-only defaults, --dry-run plans, the confirmation envelope, --force and idempotency keys.

  • Self-Describing Help — --help written for LLMs, a machine-readable command tree, completion, man pages and a bundled agent skill.

  • CLI vs. MCP — an even-handed comparison, the gh plus GitHub MCP server case study and when to ship both.

Frameworks by language

Integration

  • Wrapping a CLI as an MCP Server — subcommands to tools, exit codes to isError, JSON stdout to structuredContent, in Python, TypeScript and Spring AI.

  • Wrapping a CLI as an Agent Tool — narrow LangChain, Spring AI and LangChain4j tools versus a generic shell tool, and direct use from Claude Code and Copilot.

  • Security — argument injection, argv discipline, allowlists, least privilege, sandboxing and output sanitisation.

Shipping

  • Packaging & Distribution — pipx, Homebrew, npm, JBang, native binaries, cargo install, winget, .NET tools, GoReleaser, containers, signing and checksums.

  • Testing CLIs — golden tests of JSON output, no-TTY and exit-code tests, bats-core, framework test runners and agent evals.

  • Documenting CLIs — man pages and reference docs generated from the command tree, kept in sync from one source.

  • Agent-Readiness Checklist — a one-page review list linking every concept page.

  • Cheat Sheet — a grouped index of quick back-links and the printable one-page PDF.

Bibliography

The following sources were consulted while preparing this sub-section’s pages. Every command, flag, environment variable, package name, API name and version was checked against the projects' official documentation, specifications and package registries on 2026-09-30 — never copied from a book. Where something could not be confirmed or run, the page that cites it says so. Every URL cited on any page of this sub-section appears in this list.

Requester-provided books, consulted for tool-design principles only and never the source of an example:

oreilly.com answers automated fetches with an HTTP 403 response, but the publisher page above is a live page when opened in a browser.

Official documentation

Guidelines for command-line tools:

Agent hosts and guidance:

MCP and tool wrapping:

Python:

Java:

Node.js:

Go and Rust:

Swift and .NET:

Packaging, signing and containers:

Testing and documentation:

Specifications and standards

Papers and engineering articles

These books are consulted references, not the primary source of any example on this sub-section’s pages. On any discrepancy between a book and a tool’s own official documentation, that documentation is authoritative.