Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
---
title: "Design for the Human, Enable the Agent"
subtitle: "CLIs are not APIs. That principle hasn't changed - it's just become urgent."
date: "2026-04-07 10:00:00 -0500"
author: Lee Calcote
thumbnail: ./hero-image.svg
darkthumbnail: ./hero-image.svg
description: "CLIs are human interfaces - not APIs. But great CLI design has always enabled scriptability. Now that same principle enables agentic AI. Here's how Meshery CLI is being redesigned for both."
type: Blog
category: AI
tags:
- ai
- mesheryctl
- Meshery
- Engineering
- Platform Engineering
Comment on lines +11 to +16
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tag casing/style is inconsistent (mix of lowercase and Title Case). If tags are used for filtering/grouping, this can fragment taxonomy (e.g., Meshery vs meshery). Recommend normalizing tags to the site’s convention (commonly lowercase and, if needed, hyphenated).

Copilot generated this review using guidance from repository custom instructions.
resource: true
published: true
---

import { BlogWrapper } from "../../Blog.style.js";
import { Link } from "gatsby";
import Blockquote from "../../../../reusecore/Blockquote";
import Callout from "../../../../reusecore/Callout";
import CTA_FullWidth from "../../../../components/Call-To-Actions/CTA_FullWidth";
import CTAImg from "../../../../assets/images/meshery/icon-only/meshery-logo-shadow.webp";

<BlogWrapper>

<div className="intro">
<p>
I've been saying this for years, and I stand behind it now more than ever: CLIs are not APIs. Some people call them that. I understand the appeal of the framing - it's tidy, it sounds modern, and it gives CLI authors permission to think of their tools as integration surfaces. But the framing is wrong, and adopting it leads to wrong design decisions. A CLI is an interface designed for humans. That's not a limitation. That's the entire point.
</p>
</div>

## The Principle That Hasn't Changed

Good CLI design has always included a consideration that most people don't talk about enough: scriptability.

Not because a CLI is secretly an API waiting to be discovered. Because a well-designed human interface doesn't demand that a human be present. Every interactive prompt, every fuzzy picker, every paginated list that asks you to scroll and select - all of these exist to help the human. And every one of them should have a non-interactive equivalent that lets a script answer silently.

This isn't new thinking. It predates agentic AI by decades. It's why `--yes` flags exist. It's why `--output json` exists. It's why environment variables override interactive prompts. Cron jobs needed this. CI/CD pipelines needed this. Shell scripts chained with pipes needed this.

The principle is simple: design the interface for the human, but never require the human to be in the room.

<Blockquote
quote="A CLI is an interface for humans. It has never been an API. But a great CLI has always been considerate of its own scriptability - and that consideration is what makes it useful to agents today."
person="Lee Calcote"
title="Founder, Layer5"
/>

What's changed is not the principle. It's the urgency. Agentic AI is here, and it doesn't browse your `--help` text the way a developer does. It doesn't fuzzy-search through a list of options. It doesn't read your README. It needs to discover what your CLI can do, validate its own inputs before execution, and parse your output without guessing. The principle of scriptability hasn't changed. The bar for what scriptability means has gone through the roof.

## What Agents Actually Need

Human CLI users optimize for discoverability and forgiveness. They want tab completion, colorized output, interactive prompts that guide them through complex inputs. When they make a mistake, they want a helpful error message that tells them what to try next.

Agents optimize for predictability and defense-in-depth. They don't need color. They don't need interactive guidance. They need to know, at runtime, what commands exist, what inputs those commands accept, what the valid values are, and what the output schema looks like. They need this information in machine-readable form, queryable from the CLI itself - not baked into a 50-page system prompt that goes stale the moment you ship a new version.

The practical differences break down into four areas.

**Runtime schema introspection.** An agent should be able to ask the CLI: "What can you do? What does this command expect? What are the valid values for this field?" The CLI itself becomes the documentation. A command like `mesheryctl design schema apply` dumps the full input schema as JSON. The agent reads it, constructs its payload, and never hallucinates a field name that doesn't exist.

**Hallucination-resistant input validation.** Agents hallucinate. That's not a moral failing - it's a statistical property of how language models work. Your CLI needs to defend against it. This means strict enum validation (reject any value not in the set), structural validation (does this JSON conform to the schema?), and semantic validation (does this component reference actually resolve to something that exists?). Two layers of defense, minimum. The Meshery CLI spec calls this defense-in-depth, and it's not optional.

**Machine-readable output by default.** NDJSON - newline-delimited JSON - is the right default for agent consumption. Not pretty-printed JSON arrays that require buffering the entire response before parsing. NDJSON streams one record per line. The agent processes records as they arrive. For a CLI like mesheryctl that returns lists of models, components, and relationships - some numbering in the hundreds - streaming output is the difference between an agent that works and an agent that times out.

**Deterministic exit codes.** A human reads an error message. An agent reads an exit code. Exit 0 for success. Exit 1-2 for correctable user errors. Exit 3-125 for application-specific failures. Every exit code documented, every exit code stable across minor versions. The agent's retry logic depends on this.

<Callout type="note" title="The Historic Parallel">
<p>None of these requirements are alien to experienced CLI designers. Non-interactive flags, JSON output modes, deterministic exit codes - these have been best practices for scriptable CLIs for years. Agentic AI doesn't invent new principles. It raises the cost of violating old ones.</p>
</Callout>

## The Meshery CLI Case Study

<Link to="/cloud-native-management/meshery">Meshery</Link> is the collaborative cloud native manager - a CNCF project with thousands of contributors that enables teams to adopt, operate, and manage Kubernetes and its workloads. The Meshery CLI, `mesheryctl`, has been the primary interface for operators since the project's inception.

In early 2026, we published a functional design specification titled "mesheryctl for AI Agents" that lays out how we're evolving the CLI to serve both humans and autonomous agents. The redesign doesn't replace the human interface. It extends the same scriptability principles that have always been part of good CLI design - and raises them to the level that agentic AI demands.

The spec covers four command surfaces. Each one illustrates a different facet of agent-native CLI design.

### Design Management

The `mesheryctl design` surface manages infrastructure designs - the declarative configurations that describe what you want your cloud native stack to look like. For agents, the key additions are:

- A `--payload` flag that accepts raw JSON input, bypassing interactive prompts entirely
- A `schema` subcommand for runtime introspection of the design schema
- Field selection with `--fields` to limit output to only what the agent needs
- NDJSON pagination for listing designs across large catalogs
- `--dry-run` for safe exploration without side effects

```bash
# Agent introspects the schema before constructing input
mesheryctl design schema apply --output json

# Agent applies a design using raw JSON payload
mesheryctl design apply --payload '{"name":"prod-redis","config":{...}}' --output ndjson

# Agent lists designs, streaming results
mesheryctl design list --output ndjson --page-size 50
```

### Model Authorship

Models are the packaging unit in Meshery's registry system. A model defines a managed infrastructure component - its schema, its relationships, how Meshery should handle it. The `mesheryctl model` surface adds four agent-facing subcommands: `generate`, `schema`, `validate`, and `register`.

The pattern here is schema-driven authorship. The agent asks for the schema, generates a model definition that conforms to it, validates the definition against the schema before submission, and then registers it. At no point does the agent guess at the structure. The CLI enforces correctness at every step.

```bash
# Step 1: Get the model schema
mesheryctl model schema --output json

# Step 2: Validate a generated model
mesheryctl model validate --file ./my-model.json --output json

# Step 3: Register the validated model
mesheryctl model register --file ./my-model.json --output json
```

### Component Definitions

Components are the building blocks inside models - the individual infrastructure resources (a Kubernetes Deployment, an AWS Lambda function, a Terraform resource) that Meshery manages. The `mesheryctl component` surface follows the same generate/schema/validate/register pattern, but adds the ability to generate component definitions from existing CRDs, Terraform provider schemas, or OpenAPI specifications.

This is where agent-native design gets interesting. An agent can ingest a CRD from a running cluster, generate a Meshery component definition from it, validate the definition, and register it - all without a human touching a YAML file.

### Relationship Definitions

Relationships are the most complex surface in Meshery's model system. They define how components interact - hierarchical parent-child structures, network bindings, edge connections, sibling groupings, annotation attachments. The relationship taxonomy spans five top-level kinds, each with subtypes and specific selector semantics.

For agents, the challenge is that relationships require two layers of validation. Structural validation confirms the JSON conforms to the relationship schema. Semantic validation confirms that the referenced components actually exist and that the relationship kind makes sense for those component types. You can't have a network binding relationship between two components that don't expose network interfaces.

The `mesheryctl relationship` surface handles this with a `validate` subcommand that runs both layers and returns structured error output that tells the agent exactly what's wrong and why.

## The MCP Layer - and Why It's Not Enough on Its Own

There's a lively debate in the industry right now about whether the Model Context Protocol (MCP) is the right abstraction for AI-agent-to-tool integration. MCP adoption has exploded - [the number of MCP servers tripled to over 1,400 between August 2025 and February 2026](https://glama.ai/blog/2026-02-18-mcp-servers-growing-fast). [OpenAI adopted it](https://openai.com/index/new-tools-and-features-in-the-responses-api/). [Google DeepMind endorsed it](https://deepmind.google/discover/blog/mcp/). The momentum is real.

But MCP is not a replacement for a well-designed CLI. It's a complementary layer. MCP excels at governance - OAuth-based authentication, per-user permissions, structured audit trails, multi-agent orchestration across enterprise boundaries. These are real requirements that CLIs don't natively solve.

Where MCP stumbles is efficiency. [Benchmarks show CLI-based agent interactions achieving 28% higher task completion rates with equivalent token budgets](https://www.anthropic.com/engineering/claude-code-best-practices). MCP tool descriptions can consume tens of thousands of tokens - [GitHub's MCP server exposes over 40,000 tokens of tool definitions](https://github.com/github/github-mcp-server). That's context window space the agent can't use for reasoning. CLI interactions are leaner: the agent calls a command, reads stdout, moves on.

The Meshery CLI spec proposes a `mesheryctl mcp` command that exposes the CLI's capabilities as an MCP surface. The CLI does the work. MCP provides the governance wrapper. Both layers exist because they solve different problems.

We'll explore the MCP question in depth in a companion post - whether MCP is a durable standard or a transitional layer, and what that means for how you build your tools. For now, the takeaway is this: MCP doesn't replace good CLI design. It depends on it.

<Blockquote
quote="MCP doesn't replace good CLI design. It depends on it. The CLI is the execution layer. MCP is the governance layer. Conflating the two leads to tools that are neither efficient nor secure."
person="Lee Calcote"
title="Founder, Layer5"
/>

## Six Design Principles

The mesheryctl redesign is guided by six principles that generalize beyond Meshery to any CLI that needs to serve agents:

1. **Schema as Source of Truth.** Every input and output has a published JSON Schema. The agent never guesses at structure.

2. **Non-Interactive by Default.** Every interactive prompt has a `--flag` equivalent. Every question can be answered silently. This was always good CLI design. Now it's mandatory.

3. **Defense-in-Depth Validation.** Structural validation catches malformed input. Semantic validation catches meaningless input. Both run before any side effect occurs.

4. **Streaming Output.** NDJSON for lists. Single JSON objects for point queries. Never require the consumer to buffer an entire response.

5. **Deterministic Error Reporting.** Exit codes are documented and stable. Error output is structured JSON with error codes, not prose messages.

6. **Progressive Disclosure.** Don't dump every capability into the top-level `--help`. Organize commands as noun-verb hierarchies. Let the agent explore the tree: `mesheryctl --help` shows resources, `mesheryctl model --help` shows actions on models. Hierarchical structure turns CLI discovery into a deterministic tree search.

These principles don't conflict with human usability. They reinforce it. A CLI that validates inputs strictly is also a CLI that gives humans better error messages. A CLI with structured output is also a CLI that humans can pipe through `jq`. A CLI with non-interactive flags is also a CLI that humans can use in shell scripts.

The best CLIs have always worked this way. The age of agentic AI just made it impossible to ignore.

<CTA_FullWidth
image={CTAImg}
heading="Try Meshery"
alt="Meshery - Cloud Native Manager"
content="Meshery is the open source, cloud native management plane for Kubernetes and cloud native infrastructure. Explore the CLI, the catalog, and the playground."
button_text="Get Meshery"
url="/cloud-native-management/meshery"
external_link={false}
/>

<div className="outro">
<p>
The mesheryctl functional design spec is open for community input. Join the <a href="https://slack.meshery.io" target="_blank" rel="noopener noreferrer">Meshery Slack</a> to contribute, or explore the <Link to="/cloud-native-management/meshery">Meshery playground</Link> to see these patterns in action. Up next: a deep dive into whether MCP is a durable standard or a transitional layer - and what that means for how you build your tools.
</p>
</div>

</BlogWrapper>
Loading