refactor: use --json flag alias instead of --format json throughout CLI
This commit is contained in:
+8
-13
@@ -32,7 +32,8 @@ export function createCli(): Command {
|
||||
.description('Paseo CLI - control your AI coding agents from the command line')
|
||||
.version(VERSION, '-v, --version', 'output the version number')
|
||||
// Global output options
|
||||
.option('-f, --format <format>', 'output format: table, json, yaml', 'table')
|
||||
.option('-o, --format <format>', 'output format: table, json, yaml', 'table')
|
||||
.option('--json', 'output in JSON format (alias for --format json)')
|
||||
.option('-q, --quiet', 'minimal output (IDs only)')
|
||||
.option('--no-headers', 'omit table headers')
|
||||
.option('--no-color', 'disable colored output')
|
||||
@@ -47,12 +48,7 @@ export function createCli(): Command {
|
||||
.option('--ui', 'Show only UI agents (equivalent to --label ui=true)')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action((options, command) => {
|
||||
if (options.json) {
|
||||
command.parent.opts().format = 'json'
|
||||
}
|
||||
return withOutput(runLsCommand)(options, command)
|
||||
})
|
||||
.action(withOutput(runLsCommand))
|
||||
|
||||
program
|
||||
.command('run')
|
||||
@@ -69,6 +65,7 @@ export function createCli(): Command {
|
||||
.option('--cwd <path>', 'Working directory (default: current)')
|
||||
.option('--label <key=value>', 'Add label(s) to the agent (can be used multiple times)', collectMultiple, [])
|
||||
.option('--ui', 'Mark as UI agent (equivalent to --label ui=true)')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runRunCommand))
|
||||
|
||||
@@ -96,6 +93,7 @@ export function createCli(): Command {
|
||||
.argument('[id]', 'Agent ID (or prefix) - optional if --all or --cwd specified')
|
||||
.option('--all', 'Stop all agents')
|
||||
.option('--cwd <path>', 'Stop all agents in directory')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runStopCommand))
|
||||
|
||||
@@ -106,6 +104,7 @@ export function createCli(): Command {
|
||||
.argument('<prompt>', 'The message to send')
|
||||
.option('--no-wait', 'Return immediately without waiting for completion')
|
||||
.option('--image <path>', 'Attach image(s) to the message', collectMultiple, [])
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runSendCommand))
|
||||
|
||||
@@ -115,18 +114,14 @@ export function createCli(): Command {
|
||||
.argument('<id>', 'Agent ID (or prefix)')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action((id, options, command) => {
|
||||
if (options.json) {
|
||||
command.parent.opts().format = 'json'
|
||||
}
|
||||
return withOutput(runInspectCommand)(id, options, command)
|
||||
})
|
||||
.action(withOutput(runInspectCommand))
|
||||
|
||||
program
|
||||
.command('wait')
|
||||
.description('Wait for an agent to become idle')
|
||||
.argument('<id>', 'Agent ID (or prefix)')
|
||||
.option('--timeout <seconds>', 'Maximum wait time (default: 600)')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runWaitCommand))
|
||||
|
||||
|
||||
@@ -29,12 +29,7 @@ export function createAgentCommand(): Command {
|
||||
.option('--ui', 'Show only UI agents (equivalent to --label ui=true)')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action((options, command) => {
|
||||
if (options.json) {
|
||||
command.parent.parent.opts().format = 'json'
|
||||
}
|
||||
return withOutput(runLsCommand)(options, command)
|
||||
})
|
||||
.action(withOutput(runLsCommand))
|
||||
|
||||
agent
|
||||
.command('run')
|
||||
@@ -48,6 +43,7 @@ export function createAgentCommand(): Command {
|
||||
.option('--cwd <path>', 'Working directory (default: current)')
|
||||
.option('--label <key=value>', 'Add label(s) to the agent (can be used multiple times)', collectMultiple, [])
|
||||
.option('--ui', 'Mark as UI agent (equivalent to --label ui=true)')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runRunCommand))
|
||||
|
||||
@@ -74,6 +70,7 @@ export function createAgentCommand(): Command {
|
||||
.argument('[id]', 'Agent ID (or prefix) - optional if --all or --cwd specified')
|
||||
.option('--all', 'Stop all agents')
|
||||
.option('--cwd <path>', 'Stop all agents in directory')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runStopCommand))
|
||||
|
||||
@@ -83,6 +80,7 @@ export function createAgentCommand(): Command {
|
||||
.argument('<id>', 'Agent ID (or prefix)')
|
||||
.argument('<prompt>', 'The message to send')
|
||||
.option('--no-wait', 'Return immediately without waiting for completion')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runSendCommand))
|
||||
|
||||
@@ -90,6 +88,7 @@ export function createAgentCommand(): Command {
|
||||
.command('inspect')
|
||||
.description('Show detailed information about an agent')
|
||||
.argument('<id>', 'Agent ID (or prefix)')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runInspectCommand))
|
||||
|
||||
@@ -98,6 +97,7 @@ export function createAgentCommand(): Command {
|
||||
.description('Wait for an agent to become idle')
|
||||
.argument('<id>', 'Agent ID (or prefix)')
|
||||
.option('--timeout <seconds>', 'Maximum wait time (default: 600)')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runWaitCommand))
|
||||
|
||||
@@ -108,6 +108,7 @@ export function createAgentCommand(): Command {
|
||||
.argument('<id>', 'Agent ID (or prefix)')
|
||||
.argument('[mode]', 'Mode to set (required unless --list)')
|
||||
.option('--list', 'List available modes for this agent')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runModeCommand))
|
||||
|
||||
@@ -116,6 +117,7 @@ export function createAgentCommand(): Command {
|
||||
.description('Archive an agent (soft-delete)')
|
||||
.argument('<id>', 'Agent ID (or prefix)')
|
||||
.option('--force', 'Force archive running agent')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runArchiveCommand))
|
||||
|
||||
|
||||
@@ -20,6 +20,15 @@ export interface AgentLogsOptions extends CommandOptions {
|
||||
export type AgentLogsResult = void
|
||||
|
||||
|
||||
function parseTailCount(raw: string | undefined): number | undefined {
|
||||
if (raw === undefined) return undefined
|
||||
const parsed = Number.parseInt(raw, 10)
|
||||
if (Number.isNaN(parsed) || parsed < 0) {
|
||||
return undefined
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a timeline item matches the filter type
|
||||
*/
|
||||
@@ -110,6 +119,12 @@ export async function runLogsCommand(
|
||||
|
||||
// For follow mode, we stream events continuously
|
||||
if (options.follow) {
|
||||
if (options.tail !== undefined && parseTailCount(options.tail) === undefined) {
|
||||
console.error(`Error: Invalid --tail value: ${options.tail}`)
|
||||
console.error('Usage: --tail <n> (where n is >= 0)')
|
||||
await client.close().catch(() => {})
|
||||
process.exit(1)
|
||||
}
|
||||
await runFollowMode(client, resolvedId, options)
|
||||
return
|
||||
}
|
||||
@@ -159,18 +174,22 @@ export async function runLogsCommand(
|
||||
timelineItems = timelineItems.filter((item) => matchesFilter(item, options.filter))
|
||||
}
|
||||
|
||||
// Apply tail limit
|
||||
if (options.tail) {
|
||||
const tailCount = parseInt(options.tail, 10)
|
||||
if (!isNaN(tailCount) && tailCount > 0) {
|
||||
timelineItems = timelineItems.slice(-tailCount)
|
||||
}
|
||||
const tailCount = parseTailCount(options.tail)
|
||||
if (options.tail !== undefined && tailCount === undefined) {
|
||||
console.error(`Error: Invalid --tail value: ${options.tail}`)
|
||||
console.error('Usage: --tail <n> (where n is >= 0)')
|
||||
await client.close().catch(() => {})
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
await client.close()
|
||||
|
||||
// Use curateAgentActivity to format the transcript
|
||||
const transcript = curateAgentActivity(timelineItems)
|
||||
if (tailCount === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const transcript = curateAgentActivity(timelineItems, tailCount !== undefined ? { maxItems: tailCount } : undefined)
|
||||
console.log(transcript)
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err)
|
||||
@@ -188,6 +207,9 @@ async function runFollowMode(
|
||||
agentId: string,
|
||||
options: AgentLogsOptions
|
||||
): Promise<void> {
|
||||
const DEFAULT_FOLLOW_TAIL = 10
|
||||
const tailCount = parseTailCount(options.tail) ?? DEFAULT_FOLLOW_TAIL
|
||||
|
||||
// First, get existing timeline
|
||||
const snapshotPromise = new Promise<AgentTimelineItem[]>((resolve) => {
|
||||
const timeout = setTimeout(() => resolve([]), 10000)
|
||||
@@ -218,22 +240,17 @@ async function runFollowMode(
|
||||
existingItems = existingItems.filter((item) => matchesFilter(item, options.filter))
|
||||
}
|
||||
|
||||
// Apply tail to existing items
|
||||
if (options.tail) {
|
||||
const tailCount = parseInt(options.tail, 10)
|
||||
if (!isNaN(tailCount) && tailCount > 0) {
|
||||
existingItems = existingItems.slice(-tailCount)
|
||||
// Print existing transcript (tail-like behavior)
|
||||
if (tailCount > 0) {
|
||||
const existingTranscript = curateAgentActivity(existingItems, { maxItems: tailCount })
|
||||
if (existingTranscript !== 'No activity to display.') {
|
||||
console.log(existingTranscript)
|
||||
}
|
||||
}
|
||||
|
||||
// Print existing transcript
|
||||
const existingTranscript = curateAgentActivity(existingItems)
|
||||
if (existingTranscript !== 'No activity to display.') {
|
||||
console.log(existingTranscript)
|
||||
}
|
||||
|
||||
// Subscribe to new events
|
||||
console.log('\n--- Following logs (Ctrl+C to stop) ---\n')
|
||||
const tailLabel = tailCount === 0 ? 'no history' : `last ${tailCount} entr${tailCount === 1 ? 'y' : 'ies'}`
|
||||
console.log(`\n--- Following logs (${tailLabel}; Ctrl+C to stop) ---\n`)
|
||||
|
||||
const unsubscribe = client.on('agent_stream', (msg: unknown) => {
|
||||
const message = msg as AgentStreamMessage
|
||||
|
||||
@@ -15,22 +15,19 @@ export function createDaemonCommand(): Command {
|
||||
.description('Show daemon status')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action((options, command) => {
|
||||
if (options.json) {
|
||||
command.parent.parent.opts().format = 'json'
|
||||
}
|
||||
return withOutput(runStatusCommand)(options, command)
|
||||
})
|
||||
.action(withOutput(runStatusCommand))
|
||||
|
||||
daemon
|
||||
.command('stop')
|
||||
.description('Stop the daemon')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runStopCommand))
|
||||
|
||||
daemon
|
||||
.command('restart')
|
||||
.description('Restart the daemon')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runRestartCommand))
|
||||
|
||||
|
||||
@@ -12,12 +12,7 @@ export function createPermitCommand(): Command {
|
||||
.description('List all pending permissions')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action((options, command) => {
|
||||
if (options.json) {
|
||||
command.parent.parent.opts().format = 'json'
|
||||
}
|
||||
return withOutput(runLsCommand)(options, command)
|
||||
})
|
||||
.action(withOutput(runLsCommand))
|
||||
|
||||
permit
|
||||
.command('allow')
|
||||
@@ -26,6 +21,7 @@ export function createPermitCommand(): Command {
|
||||
.argument('[req_id]', 'Permission request ID (optional if --all)')
|
||||
.option('--all', 'Allow all pending permissions for this agent')
|
||||
.option('--input <json>', 'Modified input parameters (JSON)')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runAllowCommand))
|
||||
|
||||
@@ -37,6 +33,7 @@ export function createPermitCommand(): Command {
|
||||
.option('--all', 'Deny all pending permissions for this agent')
|
||||
.option('--message <msg>', 'Denial reason message')
|
||||
.option('--interrupt', 'Stop agent after denial')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runDenyCommand))
|
||||
|
||||
|
||||
@@ -11,12 +11,7 @@ export function createProviderCommand(): Command {
|
||||
.description('List available providers and status')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action((options, command) => {
|
||||
if (options.json) {
|
||||
command.parent.parent.opts().format = 'json'
|
||||
}
|
||||
return withOutput(runLsCommand)(options, command)
|
||||
})
|
||||
.action(withOutput(runLsCommand))
|
||||
|
||||
provider
|
||||
.command('models')
|
||||
@@ -24,12 +19,7 @@ export function createProviderCommand(): Command {
|
||||
.argument('<provider>', 'Provider name (claude, codex, opencode)')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action((provider, options, command) => {
|
||||
if (options.json) {
|
||||
command.parent.parent.opts().format = 'json'
|
||||
}
|
||||
return withOutput(runModelsCommand)(provider, options, command)
|
||||
})
|
||||
.action(withOutput(runModelsCommand))
|
||||
|
||||
return provider
|
||||
}
|
||||
|
||||
@@ -11,17 +11,13 @@ export function createWorktreeCommand(): Command {
|
||||
.description('List Paseo-managed git worktrees')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action((options, command) => {
|
||||
if (options.json) {
|
||||
command.parent.parent.opts().format = 'json'
|
||||
}
|
||||
return withOutput(runLsCommand)(options, command)
|
||||
})
|
||||
.action(withOutput(runLsCommand))
|
||||
|
||||
worktree
|
||||
.command('archive')
|
||||
.description('Archive a worktree (removes worktree and associated branch)')
|
||||
.argument('<name>', 'Worktree name or branch name')
|
||||
.option('--json', 'Output in JSON format')
|
||||
.option('--host <host>', 'Daemon host:port (default: localhost:6767)')
|
||||
.action(withOutput(runArchiveCommand))
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import type { Command } from 'commander'
|
||||
import type { AnyCommandResult, OutputOptions } from './types.js'
|
||||
import type { AnyCommandResult, CommandError, OutputOptions } from './types.js'
|
||||
import { render, renderError, toCommandError, defaultOutputOptions } from './render.js'
|
||||
|
||||
/** Options that include output settings from global options */
|
||||
@@ -13,10 +13,26 @@ export interface CommandOptions extends Partial<OutputOptions> {
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
function normalizeFormat(raw: unknown): OutputOptions['format'] {
|
||||
const value = typeof raw === 'string' ? raw.trim().toLowerCase() : ''
|
||||
|
||||
// Common user expectation: "cli" means "table/human"
|
||||
if (value === 'cli') return 'table'
|
||||
|
||||
if (value === 'table' || value === 'json' || value === 'yaml') return value
|
||||
|
||||
const error: CommandError = {
|
||||
code: 'INVALID_FORMAT',
|
||||
message: `Unsupported output format: ${String(raw)}`,
|
||||
details: 'Supported formats: table, json, yaml',
|
||||
}
|
||||
throw error
|
||||
}
|
||||
|
||||
/** Extract output options from command options */
|
||||
function extractOutputOptions(options: CommandOptions): OutputOptions {
|
||||
return {
|
||||
format: (options.format as OutputOptions['format']) ?? defaultOutputOptions.format,
|
||||
format: options.json ? 'json' : normalizeFormat(options.format ?? defaultOutputOptions.format),
|
||||
quiet: options.quiet ?? defaultOutputOptions.quiet,
|
||||
noHeaders: options.headers === false, // Commander uses --no-headers -> headers: false
|
||||
noColor: options.color === false, // Commander uses --no-color -> color: false
|
||||
|
||||
Reference in New Issue
Block a user