cli-design
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAgent-First CLI Design
以Agent为先的CLI设计
CLIs in this system are agent-first, human-distant-second. Every command returns structured JSON that an agent can parse, act on, and follow. Humans are welcome to pipe through .
jq本系统中的CLI遵循Agent优先,人类次之的原则。每个命令都会返回结构化JSON,供Agent解析、执行和跟进。人类用户可通过工具处理输出。
jqCore Principles
核心原则
1. JSON always
1. 始终返回JSON
Every command returns JSON. No plain text. No tables. No color codes. Agents parse JSON; they don't parse prose.
bash
undefined每个命令都返回JSON格式输出,不支持纯文本、表格或颜色代码。Agent仅能解析JSON,无法处理自然语言文本。
bash
undefinedThis is the ONLY output format
这是唯一的输出格式
joelclaw status
joelclaw status
→ { "ok": true, "command": "joelclaw status", "result": {...}, "next_actions": [...] }
→ { "ok": true, "command": "joelclaw status", "result": {...}, "next_actions": [...] }
No `--json` flag. No `--human` flag. JSON is the default and only format.
无需`--json`或`--human`参数,JSON是默认且唯一的输出格式。2. HATEOAS — every response tells you what to do next
2. HATEOAS — 每个响应都告知后续操作
Every response includes — an array of commands the agent can run next, with descriptions. The agent never has to guess what's available.
next_actionsjson
{
"ok": true,
"command": "joelclaw send pipeline/video.download",
"result": {
"event_id": "01KHF98SKZ7RE6HC2BH8PW2HB2",
"status": "accepted"
},
"next_actions": [
{
"command": "joelclaw run 01KHF98SKZ7RE6HC2BH8PW2HB2",
"description": "Check run status for this event"
},
{
"command": "joelclaw logs --follow",
"description": "Watch worker logs in real-time"
},
{
"command": "joelclaw health",
"description": "Check system health"
}
]
}next_actions每个响应都包含字段——一个数组,列出Agent接下来可执行的命令及描述。Agent无需猜测可用操作。
next_actionsjson
{
"ok": true,
"command": "joelclaw send pipeline/video.download",
"result": {
"event_id": "01KHF98SKZ7RE6HC2BH8PW2HB2",
"status": "accepted"
},
"next_actions": [
{
"command": "joelclaw run 01KHF98SKZ7RE6HC2BH8PW2HB2",
"description": "Check run status for this event"
},
{
"command": "joelclaw logs --follow",
"description": "Watch worker logs in real-time"
},
{
"command": "joelclaw health",
"description": "Check system health"
}
]
}next_actions3. Self-documenting command tree
3. 自文档化命令树
The root command (no args) returns the full command tree so an agent can discover everything in one call:
json
{
"ok": true,
"command": "joelclaw",
"result": {
"description": "JoelClaw — personal AI system CLI",
"health": { "server": {...}, "worker": {...} },
"commands": [
{ "name": "send", "description": "Send event to Inngest", "usage": "joelclaw send <event> -d '<json>'" },
{ "name": "status", "description": "System status", "usage": "joelclaw status" },
{ "name": "health", "description": "Health check all services", "usage": "joelclaw health" }
]
},
"next_actions": [...]
}根命令(无参数)会返回完整的命令树,Agent可通过一次调用发现所有可用命令:
json
{
"ok": true,
"command": "joelclaw",
"result": {
"description": "JoelClaw — personal AI system CLI",
"health": { "server": {...}, "worker": {...} },
"commands": [
{ "name": "send", "description": "Send event to Inngest", "usage": "joelclaw send <event> -d '<json>'" },
{ "name": "status", "description": "System status", "usage": "joelclaw status" },
{ "name": "health", "description": "Health check all services", "usage": "joelclaw health" }
]
},
"next_actions": [...]
}4. Context-protecting output
4. 上下文保护输出
Agents have finite context windows. CLI output must not blow them up.
Rules:
- Terse by default — minimum viable output
- Auto-truncate large outputs (logs, lists) at a reasonable limit
- When truncated, include a file path to the full output
- Never dump raw logs, full transcripts, or unbounded lists
json
{
"ok": true,
"command": "joelclaw logs",
"result": {
"lines": 20,
"total": 4582,
"truncated": true,
"full_output": "/var/folders/.../joelclaw-logs-abc123.log",
"entries": ["...last 20 lines..."]
},
"next_actions": [
{ "command": "joelclaw logs --tail 100", "description": "Show more log lines" }
]
}Agent的上下文窗口有限,CLI输出不能超出其承载范围。
规则:
- 默认简洁输出——仅返回必要信息
- 自动截断大型输出(日志、列表)至合理长度
- 截断时提供完整输出的文件路径
- 绝不输出原始日志、完整记录或无限制列表
json
{
"ok": true,
"command": "joelclaw logs",
"result": {
"lines": 20,
"total": 4582,
"truncated": true,
"full_output": "/var/folders/.../joelclaw-logs-abc123.log",
"entries": ["...last 20 lines..."]
},
"next_actions": [
{ "command": "joelclaw logs --tail 100", "description": "Show more log lines" }
]
}5. Errors suggest fixes
5. 错误提示包含修复建议
When something fails, the response includes a field — plain language telling the agent what to do about it.
fixjson
{
"ok": false,
"command": "joelclaw send pipeline/video.download",
"error": {
"message": "Inngest server not responding",
"code": "SERVER_UNREACHABLE"
},
"fix": "Start the Inngest server: cd ~/Code/system-bus && docker compose up -d",
"next_actions": [
{ "command": "joelclaw health", "description": "Re-check system health after fix" },
{ "command": "docker ps", "description": "Check if Docker containers are running" }
]
}当操作失败时,响应包含字段——用自然语言告知Agent解决方法。
fixjson
{
"ok": false,
"command": "joelclaw send pipeline/video.download",
"error": {
"message": "Inngest server not responding",
"code": "SERVER_UNREACHABLE"
},
"fix": "Start the Inngest server: cd ~/Code/system-bus && docker compose up -d",
"next_actions": [
{ "command": "joelclaw health", "description": "Re-check system health after fix" },
{ "command": "docker ps", "description": "Check if Docker containers are running" }
]
}Response Envelope
响应信封格式
Every command uses this exact shape:
每个命令都使用以下统一格式:
Success
成功响应
typescript
{
ok: true,
command: string, // the command that was run
result: object, // command-specific payload
next_actions: Array<{
command: string, // exact command to copy-paste/run
description: string // what it does
}>
}typescript
{
ok: true,
command: string, // 执行的命令
result: object, // 命令专属返回数据
next_actions: Array<{
command: string, // 可直接复制执行的命令
description: string // 命令说明
}>
}Error
错误响应
typescript
{
ok: false,
command: string,
error: {
message: string, // what went wrong
code: string // machine-readable error code
},
fix: string, // plain-language suggested fix
next_actions: Array<{
command: string,
description: string
}>
}typescript
{
ok: false,
command: string,
error: {
message: string, // 错误信息
code: string // 机器可读的错误码
},
fix: string, // 自然语言描述的修复建议
next_actions: Array<{
command: string,
description: string
}>
}Reference implementations
参考实现
- —
slog(Effect CLI, system log)~/Code/system-bus/ - —
igs(Effect CLI, Inngest operations)~/Code/system-bus/
Both follow this exact envelope. Copy their patterns.
- —
slog(Effect CLI,系统日志工具)~/Code/system-bus/ - —
igs(Effect CLI,Inngest操作工具)~/Code/system-bus/
两者均严格遵循上述响应格式,可直接参考其实现模式。
Implementation
实现方案
Framework: Effect CLI (@effect/cli)
框架:Effect CLI (@effect/cli)
All CLIs use with Bun. This is non-negotiable — consistency across the system matters more than framework preference.
@effect/clitypescript
import { Command, Options } from "@effect/cli"
import { NodeContext, NodeRuntime } from "@effect/platform-node"
const send = Command.make("send", {
event: Options.text("event"),
data: Options.optional(Options.text("data").pipe(Options.withAlias("d"))),
}, ({ event, data }) => {
// ... execute, return JSON envelope
})
const root = Command.make("joelclaw", {}, () => {
// Root: return health + command tree
}).pipe(Command.withSubcommands([send, status, health]))所有CLI均使用搭配Bun构建。这是硬性要求——系统一致性优先于框架偏好。
@effect/clitypescript
import { Command, Options } from "@effect/cli"
import { NodeContext, NodeRuntime } from "@effect/platform-node"
const send = Command.make("send", {
event: Options.text("event"),
data: Options.optional(Options.text("data").pipe(Options.withAlias("d"))),
}, ({ event, data }) => {
// ... 执行逻辑,返回JSON信封格式
})
const root = Command.make("joelclaw", {}, () => {
// 根命令:返回健康状态 + 命令树
}).pipe(Command.withSubcommands([send, status, health]))Binary distribution
二进制分发
Build with Bun, install to :
~/.bun/bin/bash
bun build src/cli.ts --compile --outfile joelclaw
cp joelclaw ~/.bun/bin/使用Bun构建,安装至:
~/.bun/bin/bash
bun build src/cli.ts --compile --outfile joelclaw
cp joelclaw ~/.bun/bin/Adding a new command
添加新命令
- Define the command with
Command.make - Return the standard JSON envelope (ok, command, result, next_actions)
- Include contextual — what makes sense AFTER this specific command
next_actions - Handle errors with the error envelope (ok: false, error, fix, next_actions)
- Add to the root command's subcommands
- Add to the root command's array in the self-documenting output
commands - Rebuild and install
- 使用定义命令
Command.make - 返回标准JSON信封格式(ok、command、result、next_actions)
- 包含上下文相关的——即当前命令执行后合理的后续操作
next_actions - 使用错误信封格式处理错误(ok: false、error、fix、next_actions)
- 将命令添加至根命令的子命令列表
- 在根命令的自文档化输出中,将该命令加入数组
commands - 重新构建并安装
Anti-Patterns
反模式
| Don't | Do |
|---|---|
| Plain text output | JSON envelope |
| Tables with ANSI colors | JSON arrays |
| JSON is the only format |
| Dump 10,000 lines | Truncate + file pointer |
| |
| Undiscoverable commands | Root returns full command tree |
| Static help text | HATEOAS next_actions |
| |
| Exit code as the only error signal | Error in JSON + exit code |
| Require the agent to read --help | Root command self-documents |
| 禁止做法 | 正确做法 |
|---|---|
| 纯文本输出 | JSON信封格式 |
| 带ANSI颜色的表格 | JSON数组 |
通过 | JSON是唯一输出格式 |
| 输出10000行内容 | 截断输出并提供文件路径 |
| |
| 命令不可被发现 | 根命令返回完整命令树 |
| 静态帮助文本 | HATEOAS风格的next_actions |
| |
| 仅通过退出码传递错误信号 | JSON中包含错误信息 + 退出码 |
| 要求Agent阅读--help内容 | 根命令提供自文档化信息 |
Naming Conventions
命名规范
- Commands are nouns or verbs, lowercase, no hyphens: ,
send,status,healthlogs - Subcommands follow naturally: ,
joelclaw memory searchjoelclaw loop start - Flags use :
--kebab-case,--max-quality--follow - Short flags for common options: for
-d,--datafor-f--follow - Event names use :
domain/action,pipeline/video.downloadcontent/summarize
- 命令使用名词或动词,小写,无连字符:、
send、status、healthlogs - 子命令自然延伸:、
joelclaw memory searchjoelclaw loop start - 标志使用:
--kebab-case、--max-quality--follow - 常用选项使用短标志:对应
-d、--data对应-f--follow - 事件名称使用格式:
domain/action、pipeline/video.downloadcontent/summarize
Checklist for New Commands
新命令检查清单
- Returns JSON envelope (ok, command, result, next_actions)
- Error responses include fix field
- Root command lists this command in its tree
- Output is context-safe (truncated if potentially large)
- next_actions are contextual to what just happened
- No plain text output anywhere
- No ANSI colors or formatting
- Works when piped (no TTY detection)
- Builds and installs to ~/.bun/bin/
- 返回JSON信封格式(ok、command、result、next_actions)
- 错误响应包含fix字段
- 根命令的命令树中包含该命令
- 输出具备上下文安全性(可能过大时自动截断)
- next_actions与当前操作上下文相关
- 无任何纯文本输出
- 无ANSI颜色或格式化内容
- 支持管道操作(无TTY检测)
- 可构建并安装至~/.bun/bin/