docs: unify cli help examples

This commit is contained in:
Peter Steinberger
2026-01-21 04:46:15 +00:00
parent 1ad4a7194e
commit a74c19feed
8 changed files with 177 additions and 111 deletions

View File

@@ -5,6 +5,7 @@ import { defaultRuntime } from "../runtime.js";
import { formatDocsLink } from "../terminal/links.js"; import { formatDocsLink } from "../terminal/links.js";
import { theme } from "../terminal/theme.js"; import { theme } from "../terminal/theme.js";
import { formatCliCommand } from "./command-format.js"; import { formatCliCommand } from "./command-format.js";
import { formatHelpExamples } from "./help-format.js";
import { registerBrowserActionInputCommands } from "./browser-cli-actions-input.js"; import { registerBrowserActionInputCommands } from "./browser-cli-actions-input.js";
import { registerBrowserActionObserveCommands } from "./browser-cli-actions-observe.js"; import { registerBrowserActionObserveCommands } from "./browser-cli-actions-observe.js";
import { registerBrowserDebugCommands } from "./browser-cli-debug.js"; import { registerBrowserDebugCommands } from "./browser-cli-debug.js";
@@ -26,7 +27,10 @@ export function registerBrowserCli(program: Command) {
.addHelpText( .addHelpText(
"after", "after",
() => () =>
`\nExamples:\n ${[...browserCoreExamples, ...browserActionExamples].join("\n ")}\n\n${theme.muted("Docs:")} ${formatDocsLink( `\n${theme.heading("Examples:")}\n${formatHelpExamples(
[...browserCoreExamples, ...browserActionExamples].map((cmd) => [cmd, ""]),
true,
)}\n\n${theme.muted("Docs:")} ${formatDocsLink(
"/cli/browser", "/cli/browser",
"docs.clawd.bot/cli/browser", "docs.clawd.bot/cli/browser",
)}\n`, )}\n`,

21
src/cli/help-format.ts Normal file
View File

@@ -0,0 +1,21 @@
import { theme } from "../terminal/theme.js";
export type HelpExample = [command: string, description: string];
export function formatHelpExample(command: string, description: string): string {
return ` ${theme.command(command)}\n ${theme.muted(description)}`;
}
export function formatHelpExampleLine(command: string, description: string): string {
if (!description) return ` ${theme.command(command)}`;
return ` ${theme.command(command)} ${theme.muted(`# ${description}`)}`;
}
export function formatHelpExamples(examples: HelpExample[], inline = false): string {
const formatter = inline ? formatHelpExampleLine : formatHelpExample;
return examples.map(([command, description]) => formatter(command, description)).join("\n");
}
export function formatHelpExampleGroup(label: string, examples: HelpExample[], inline = false) {
return `${theme.muted(label)}\n${formatHelpExamples(examples, inline)}`;
}

View File

@@ -12,6 +12,7 @@ import { defaultRuntime } from "../../runtime.js";
import { formatDocsLink } from "../../terminal/links.js"; import { formatDocsLink } from "../../terminal/links.js";
import { theme } from "../../terminal/theme.js"; import { theme } from "../../terminal/theme.js";
import { hasExplicitOptions } from "../command-options.js"; import { hasExplicitOptions } from "../command-options.js";
import { formatHelpExamples } from "../help-format.js";
import { createDefaultDeps } from "../deps.js"; import { createDefaultDeps } from "../deps.js";
import { runCommandWithRuntime } from "../cli-utils.js"; import { runCommandWithRuntime } from "../cli-utils.js";
import { collectOption } from "./helpers.js"; import { collectOption } from "./helpers.js";
@@ -48,13 +49,24 @@ export function registerAgentCommands(program: Command, args: { agentChannelOpti
"after", "after",
() => () =>
` `
Examples: ${theme.heading("Examples:")}
clawdbot agent --to +15555550123 --message "status update" ${formatHelpExamples([
clawdbot agent --agent ops --message "Summarize logs" ['clawdbot agent --to +15555550123 --message "status update"', "Start a new session."],
clawdbot agent --session-id 1234 --message "Summarize inbox" --thinking medium ['clawdbot agent --agent ops --message "Summarize logs"', "Use a specific agent."],
clawdbot agent --to +15555550123 --message "Trace logs" --verbose on --json [
clawdbot agent --to +15555550123 --message "Summon reply" --deliver 'clawdbot agent --session-id 1234 --message "Summarize inbox" --thinking medium',
clawdbot agent --agent ops --message "Generate report" --deliver --reply-channel slack --reply-to "#reports" "Target a session with explicit thinking level.",
],
[
'clawdbot agent --to +15555550123 --message "Trace logs" --verbose on --json',
"Enable verbose logging and JSON output.",
],
['clawdbot agent --to +15555550123 --message "Summon reply" --deliver', "Deliver reply."],
[
'clawdbot agent --agent ops --message "Generate report" --deliver --reply-channel slack --reply-to "#reports"',
"Send reply to a different channel/target.",
],
])}
${theme.muted("Docs:")} ${formatDocsLink("/cli/agent", "docs.clawd.bot/cli/agent")}`, ${theme.muted("Docs:")} ${formatDocsLink("/cli/agent", "docs.clawd.bot/cli/agent")}`,
) )
@@ -140,10 +152,15 @@ ${theme.muted("Docs:")} ${formatDocsLink("/cli/agent", "docs.clawd.bot/cli/agent
"after", "after",
() => () =>
` `
Examples: ${theme.heading("Examples:")}
clawdbot agents set-identity --agent main --name "Clawd" --emoji "🦞" ${formatHelpExamples([
clawdbot agents set-identity --workspace ~/clawd --from-identity ['clawdbot agents set-identity --agent main --name "Clawd" --emoji "🦞"', "Set name + emoji."],
clawdbot agents set-identity --identity-file ~/clawd/IDENTITY.md --agent main ["clawdbot agents set-identity --workspace ~/clawd --from-identity", "Load from IDENTITY.md."],
[
"clawdbot agents set-identity --identity-file ~/clawd/IDENTITY.md --agent main",
"Use a specific IDENTITY.md.",
],
])}
`, `,
) )
.action(async (opts) => { .action(async (opts) => {

View File

@@ -1,6 +1,7 @@
import type { Command } from "commander"; import type { Command } from "commander";
import { formatDocsLink } from "../../terminal/links.js"; import { formatDocsLink } from "../../terminal/links.js";
import { theme } from "../../terminal/theme.js"; import { theme } from "../../terminal/theme.js";
import { formatHelpExamples } from "../help-format.js";
import type { ProgramContext } from "./context.js"; import type { ProgramContext } from "./context.js";
import { createMessageCliHelpers } from "./message/helpers.js"; import { createMessageCliHelpers } from "./message/helpers.js";
import { registerMessageDiscordAdminCommands } from "./message/register.discord-admin.js"; import { registerMessageDiscordAdminCommands } from "./message/register.discord-admin.js";
@@ -28,11 +29,22 @@ export function registerMessageCommands(program: Command, ctx: ProgramContext) {
"after", "after",
() => () =>
` `
Examples: ${theme.heading("Examples:")}
clawdbot message send --target +15555550123 --message "Hi" ${formatHelpExamples([
clawdbot message send --target +15555550123 --message "Hi" --media photo.jpg ['clawdbot message send --target +15555550123 --message "Hi"', "Send a text message."],
clawdbot message poll --channel discord --target channel:123 --poll-question "Snack?" --poll-option Pizza --poll-option Sushi [
clawdbot message react --channel discord --target 123 --message-id 456 --emoji "✅" 'clawdbot message send --target +15555550123 --message "Hi" --media photo.jpg',
"Send a message with media.",
],
[
'clawdbot message poll --channel discord --target channel:123 --poll-question "Snack?" --poll-option Pizza --poll-option Sushi',
"Create a Discord poll.",
],
[
'clawdbot message react --channel discord --target 123 --message-id 456 --emoji "✅"',
"React to a message.",
],
])}
${theme.muted("Docs:")} ${formatDocsLink("/cli/message", "docs.clawd.bot/cli/message")}`, ${theme.muted("Docs:")} ${formatDocsLink("/cli/message", "docs.clawd.bot/cli/message")}`,
) )

View File

@@ -7,6 +7,7 @@ import { defaultRuntime } from "../../runtime.js";
import { formatDocsLink } from "../../terminal/links.js"; import { formatDocsLink } from "../../terminal/links.js";
import { theme } from "../../terminal/theme.js"; import { theme } from "../../terminal/theme.js";
import { runCommandWithRuntime } from "../cli-utils.js"; import { runCommandWithRuntime } from "../cli-utils.js";
import { formatHelpExamples } from "../help-format.js";
import { parsePositiveIntOrUndefined } from "./helpers.js"; import { parsePositiveIntOrUndefined } from "./helpers.js";
function resolveVerbose(opts: { verbose?: boolean; debug?: boolean }): boolean { function resolveVerbose(opts: { verbose?: boolean; debug?: boolean }): boolean {
@@ -36,15 +37,18 @@ export function registerStatusHealthSessionsCommands(program: Command) {
.option("--debug", "Alias for --verbose", false) .option("--debug", "Alias for --verbose", false)
.addHelpText( .addHelpText(
"after", "after",
` () =>
Examples: `\n${theme.heading("Examples:")}\n${formatHelpExamples([
clawdbot status # show linked account + session store summary ["clawdbot status", "Show channel health + session summary."],
clawdbot status --all # full diagnosis (read-only) ["clawdbot status --all", "Full diagnosis (read-only)."],
clawdbot status --json # machine-readable output ["clawdbot status --json", "Machine-readable output."],
clawdbot status --usage # show model provider usage/quota snapshots ["clawdbot status --usage", "Show model provider usage/quota snapshots."],
clawdbot status --deep # run channel probes (WA + Telegram + Discord + Slack + Signal) [
clawdbot status --deep --timeout 5000 # tighten probe timeout "clawdbot status --deep",
clawdbot channels status # gateway channel runtime + probes`, "Run channel probes (WA + Telegram + Discord + Slack + Signal).",
],
["clawdbot status --deep --timeout 5000", "Tighten probe timeout."],
])}`,
) )
.addHelpText( .addHelpText(
"after", "after",
@@ -113,14 +117,15 @@ Examples:
.option("--active <minutes>", "Only show sessions updated within the past N minutes") .option("--active <minutes>", "Only show sessions updated within the past N minutes")
.addHelpText( .addHelpText(
"after", "after",
` () =>
Examples: `\n${theme.heading("Examples:")}\n${formatHelpExamples([
clawdbot sessions # list all sessions ["clawdbot sessions", "List all sessions."],
clawdbot sessions --active 120 # only last 2 hours ["clawdbot sessions --active 120", "Only last 2 hours."],
clawdbot sessions --json # machine-readable output ["clawdbot sessions --json", "Machine-readable output."],
clawdbot sessions --store ./tmp/sessions.json ["clawdbot sessions --store ./tmp/sessions.json", "Use a specific session store."],
])}\n\n${theme.muted(
Shows token usage per session when the agent reports it; set agents.defaults.contextTokens to see % of your model window.`, "Shows token usage per session when the agent reports it; set agents.defaults.contextTokens to see % of your model window.",
)}`,
) )
.addHelpText( .addHelpText(
"after", "after",

View File

@@ -5,6 +5,7 @@ import { sandboxExplainCommand } from "../commands/sandbox-explain.js";
import { defaultRuntime } from "../runtime.js"; import { defaultRuntime } from "../runtime.js";
import { formatDocsLink } from "../terminal/links.js"; import { formatDocsLink } from "../terminal/links.js";
import { theme } from "../terminal/theme.js"; import { theme } from "../terminal/theme.js";
import { formatHelpExamples } from "./help-format.js";
// --- Types --- // --- Types ---
@@ -12,58 +13,34 @@ type CommandOptions = Record<string, unknown>;
// --- Helpers --- // --- Helpers ---
const EXAMPLES = { const SANDBOX_EXAMPLES = {
main: ` main: [
Examples: ["clawdbot sandbox list", "List all sandbox containers."],
clawdbot sandbox list # List all sandbox containers ["clawdbot sandbox list --browser", "List only browser containers."],
clawdbot sandbox list --browser # List only browser containers ["clawdbot sandbox recreate --all", "Recreate all containers."],
clawdbot sandbox recreate --all # Recreate all containers ["clawdbot sandbox recreate --session main", "Recreate a specific session."],
clawdbot sandbox recreate --session main # Recreate specific session ["clawdbot sandbox recreate --agent mybot", "Recreate agent containers."],
clawdbot sandbox recreate --agent mybot # Recreate agent containers ["clawdbot sandbox explain", "Explain effective sandbox config."],
clawdbot sandbox explain # Explain effective sandbox config`, ],
list: [
list: ` ["clawdbot sandbox list", "List all sandbox containers."],
Examples: ["clawdbot sandbox list --browser", "List only browser containers."],
clawdbot sandbox list # List all sandbox containers ["clawdbot sandbox list --json", "JSON output."],
clawdbot sandbox list --browser # List only browser containers ],
clawdbot sandbox list --json # JSON output recreate: [
["clawdbot sandbox recreate --all", "Recreate all containers."],
Output includes: ["clawdbot sandbox recreate --session main", "Recreate a specific session."],
• Container name and status (running/stopped) ["clawdbot sandbox recreate --agent mybot", "Recreate a specific agent (includes sub-agents)."],
• Docker image and whether it matches current config ["clawdbot sandbox recreate --browser --all", "Recreate only browser containers."],
• Age (time since creation) ["clawdbot sandbox recreate --all --force", "Skip confirmation."],
• Idle time (time since last use) ],
• Associated session/agent ID`, explain: [
["clawdbot sandbox explain", "Show effective sandbox config."],
recreate: ` ["clawdbot sandbox explain --session agent:main:main", "Explain a specific session."],
Examples: ["clawdbot sandbox explain --agent work", "Explain an agent sandbox."],
clawdbot sandbox recreate --all # Recreate all containers ["clawdbot sandbox explain --json", "JSON output."],
clawdbot sandbox recreate --session main # Specific session ],
clawdbot sandbox recreate --agent mybot # Specific agent (includes sub-agents) } as const;
clawdbot sandbox recreate --browser --all # All browser containers only
clawdbot sandbox recreate --all --force # Skip confirmation
Why use this?
After updating Docker images or sandbox configuration, existing containers
continue running with old settings. This command removes them so they'll be
recreated automatically with current config when next needed.
Filter options:
--all Remove all sandbox containers
--session Remove container for specific session key
--agent Remove containers for agent (includes agent:id:* variants)
Modifiers:
--browser Only affect browser containers (not regular sandbox)
--force Skip confirmation prompt`,
explain: `
Examples:
clawdbot sandbox explain
clawdbot sandbox explain --session agent:main:main
clawdbot sandbox explain --agent work
clawdbot sandbox explain --json`,
};
function createRunner( function createRunner(
commandFn: (opts: CommandOptions, runtime: typeof defaultRuntime) => Promise<void>, commandFn: (opts: CommandOptions, runtime: typeof defaultRuntime) => Promise<void>,
@@ -84,7 +61,10 @@ export function registerSandboxCli(program: Command) {
const sandbox = program const sandbox = program
.command("sandbox") .command("sandbox")
.description("Manage sandbox containers (Docker-based agent isolation)") .description("Manage sandbox containers (Docker-based agent isolation)")
.addHelpText("after", EXAMPLES.main) .addHelpText(
"after",
() => `\n${theme.heading("Examples:")}\n${formatHelpExamples(SANDBOX_EXAMPLES.main)}\n`,
)
.addHelpText( .addHelpText(
"after", "after",
() => () =>
@@ -101,7 +81,17 @@ export function registerSandboxCli(program: Command) {
.description("List sandbox containers and their status") .description("List sandbox containers and their status")
.option("--json", "Output result as JSON", false) .option("--json", "Output result as JSON", false)
.option("--browser", "List browser containers only", false) .option("--browser", "List browser containers only", false)
.addHelpText("after", EXAMPLES.list) .addHelpText(
"after",
() =>
`\n${theme.heading("Examples:")}\n${formatHelpExamples(SANDBOX_EXAMPLES.list)}\n\n${theme.heading(
"Output includes:",
)}\n${theme.muted("- Container name and status (running/stopped)")}\n${theme.muted(
"- Docker image and whether it matches current config",
)}\n${theme.muted("- Age (time since creation)")}\n${theme.muted(
"- Idle time (time since last use)",
)}\n${theme.muted("- Associated session/agent ID")}`,
)
.action( .action(
createRunner((opts) => createRunner((opts) =>
sandboxListCommand( sandboxListCommand(
@@ -124,7 +114,25 @@ export function registerSandboxCli(program: Command) {
.option("--agent <id>", "Recreate containers for specific agent") .option("--agent <id>", "Recreate containers for specific agent")
.option("--browser", "Only recreate browser containers", false) .option("--browser", "Only recreate browser containers", false)
.option("--force", "Skip confirmation prompt", false) .option("--force", "Skip confirmation prompt", false)
.addHelpText("after", EXAMPLES.recreate) .addHelpText(
"after",
() =>
`\n${theme.heading("Examples:")}\n${formatHelpExamples(SANDBOX_EXAMPLES.recreate)}\n\n${theme.heading(
"Why use this?",
)}\n${theme.muted(
"After updating Docker images or sandbox configuration, existing containers continue running with old settings.",
)}\n${theme.muted(
"This command removes them so they'll be recreated automatically with current config when next needed.",
)}\n\n${theme.heading("Filter options:")}\n${theme.muted(
" --all Remove all sandbox containers",
)}\n${theme.muted(
" --session Remove container for specific session key",
)}\n${theme.muted(
" --agent Remove containers for agent (includes agent:id:* variants)",
)}\n\n${theme.heading("Modifiers:")}\n${theme.muted(
" --browser Only affect browser containers (not regular sandbox)",
)}\n${theme.muted(" --force Skip confirmation prompt")}`,
)
.action( .action(
createRunner((opts) => createRunner((opts) =>
sandboxRecreateCommand( sandboxRecreateCommand(
@@ -148,7 +156,10 @@ export function registerSandboxCli(program: Command) {
.option("--session <key>", "Session key to inspect (defaults to agent main)") .option("--session <key>", "Session key to inspect (defaults to agent main)")
.option("--agent <id>", "Agent id to inspect (defaults to derived agent)") .option("--agent <id>", "Agent id to inspect (defaults to derived agent)")
.option("--json", "Output result as JSON", false) .option("--json", "Output result as JSON", false)
.addHelpText("after", EXAMPLES.explain) .addHelpText(
"after",
() => `\n${theme.heading("Examples:")}\n${formatHelpExamples(SANDBOX_EXAMPLES.explain)}\n`,
)
.action( .action(
createRunner((opts) => createRunner((opts) =>
sandboxExplainCommand( sandboxExplainCommand(

View File

@@ -1,6 +1,7 @@
import type { Command } from "commander"; import type { Command } from "commander";
import { formatDocsLink } from "../terminal/links.js"; import { formatDocsLink } from "../terminal/links.js";
import { theme } from "../terminal/theme.js"; import { theme } from "../terminal/theme.js";
import { formatHelpExampleGroup } from "./help-format.js";
import { createDefaultDeps } from "./deps.js"; import { createDefaultDeps } from "./deps.js";
import { import {
runDaemonInstall, runDaemonInstall,
@@ -20,12 +21,6 @@ import {
} from "./node-cli/daemon.js"; } from "./node-cli/daemon.js";
export function registerServiceCli(program: Command) { export function registerServiceCli(program: Command) {
const formatExample = (cmd: string, desc: string) =>
` ${theme.command(cmd)}\n ${theme.muted(desc)}`;
const formatGroup = (label: string, examples: Array<[string, string]>) =>
`${theme.muted(label)}\n${examples.map(([cmd, desc]) => formatExample(cmd, desc)).join("\n")}`;
const gatewayExamples: Array<[string, string]> = [ const gatewayExamples: Array<[string, string]> = [
["clawdbot service gateway status", "Show gateway service status + probe."], ["clawdbot service gateway status", "Show gateway service status + probe."],
[ [
@@ -50,10 +45,12 @@ export function registerServiceCli(program: Command) {
.addHelpText( .addHelpText(
"after", "after",
() => () =>
`\n${theme.heading("Examples:")}\n${formatGroup("Gateway:", gatewayExamples)}\n\n${formatGroup( `\n${theme.heading("Examples:")}\n${formatHelpExampleGroup(
"Node:", "Gateway:",
nodeExamples, gatewayExamples,
)}\n\n${theme.muted("Docs:")} ${formatDocsLink("/cli/service", "docs.clawd.bot/cli/service")}\n`, )}\n\n${formatHelpExampleGroup("Node:", nodeExamples)}\n\n${theme.muted(
"Docs:",
)} ${formatDocsLink("/cli/service", "docs.clawd.bot/cli/service")}\n`,
); );
const gateway = service.command("gateway").description("Manage the Gateway service"); const gateway = service.command("gateway").description("Manage the Gateway service");

View File

@@ -32,6 +32,7 @@ import { formatCliCommand } from "./command-format.js";
import { stylePromptMessage } from "../terminal/prompt-style.js"; import { stylePromptMessage } from "../terminal/prompt-style.js";
import { theme } from "../terminal/theme.js"; import { theme } from "../terminal/theme.js";
import { renderTable } from "../terminal/table.js"; import { renderTable } from "../terminal/table.js";
import { formatHelpExamples } from "./help-format.js";
import { import {
formatUpdateAvailableHint, formatUpdateAvailableHint,
formatUpdateOneLiner, formatUpdateOneLiner,
@@ -734,17 +735,15 @@ ${theme.muted("Docs:")} ${formatDocsLink("/cli/update", "docs.clawd.bot/cli/upda
.addHelpText( .addHelpText(
"after", "after",
() => () =>
` `\n${theme.heading("Examples:")}\n${formatHelpExamples([
Examples: ["clawdbot update status", "Show channel + version status."],
clawdbot update status ["clawdbot update status --json", "JSON output."],
clawdbot update status --json ["clawdbot update status --timeout 10", "Custom timeout."],
clawdbot update status --timeout 10 ])}\n\n${theme.heading("Notes:")}\n${theme.muted(
"- Shows current update channel (stable/beta/dev) and source",
Notes: )}\n${theme.muted("- Includes git tag/branch/SHA for source checkouts")}\n\n${theme.muted(
- Shows current update channel (stable/beta/dev) and source "Docs:",
- Includes git tag/branch/SHA for source checkouts )} ${formatDocsLink("/cli/update", "docs.clawd.bot/cli/update")}`,
${theme.muted("Docs:")} ${formatDocsLink("/cli/update", "docs.clawd.bot/cli/update")}`,
) )
.action(async (opts) => { .action(async (opts) => {
try { try {