// CLI ↔ AGENT MIDDLEWARE
Two audiences.
One CLI.
murli is a middleware layer for CLIs. It adds dual-audience output, runtime introspection, structured errors, and token-efficient logging — with adapters for Go, Rust, and Python. Integration is a single function call.
go · stable v1.0.2
typescript · planned
rust · stable
python · stable
The same command, two listeners
murli checks whether stdout is connected to a terminal and routes output accordingly. The same command produces formatted text at a TTY and JSON when piped.
TTY — formatted
$ riffle query woodworking Searching index... Found 1 matching folder /docs/woodworking 0.95
Piped — JSON
$ riffle query woodworking | jq .
{
"status": "ok",
"schema_version": "1.0",
"tool_version": "1.0.2",
"message": "Found 1 matching folder",
"result": [
{ "path": "/docs/woodworking",
"score": 0.95 }
]
}The 5 principles
murli is built around five design principles. They describe the properties a CLI needs to be genuinely useful to both human and agent consumers.
| Principle | What it means in practice |
|---|---|
| Unified Interface | One tool, two audiences. No code branching on output format. |
| Self-Describing Tools | Complete command metadata available via describe and --schema at runtime, without consulting documentation. |
| Actionable Errors | Every error carries what failed, whether retrying helps, and what to do next. |
| Intentional Mutations | State-changing operations require explicit confirmation in non-interactive contexts. |
| Bounded Context | Consecutive log deduplication and NDJSON streaming keep per-session token consumption in check. |
Background and research: allankent.com/garden/projects/murli