feat: make CLI agent-friendly (--yes, --json, --help examples, --dry-run)#12
feat: make CLI agent-friendly (--yes, --json, --help examples, --dry-run)#12ryanmcmillan merged 2 commits intomainfrom
Conversation
…run)
Add features to make the CLI scriptable and agent-friendly:
- Add --yes/-y flag to `tasks delete` and `agents rotate` to skip
interactive confirmation prompts (blocker for non-interactive use)
- Add --json flag to `tasks complete`, `tasks delete`, `tasks delegate`,
and `agents rotate` (previously human-readable text only)
- Add usage examples via addHelpText("after") to every subcommand
- Add --dry-run flag to `tasks delete`, `agents rotate`, and `reset`
for previewing destructive operations without executing them
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Greptile SummaryThis PR adds agent/scripting-friendly flags ( Key changes:
Confidence Score: 4/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
CMD["CLI Command\ne.g. tasks delete, agents rotate, reset"]
CMD --> DRY{--dry-run?}
DRY -->|yes, tasks delete| FETCH["GET /tasks/:id\n(real API call)"]
FETCH --> DRYJSON{--json?}
DRYJSON -->|yes| OUTJSON1["JSON: { dry_run, would_delete }"]
DRYJSON -->|no| OUTTXT1["Text: 'Would delete task ...'"]
DRY -->|yes, agents rotate| DRYJSON2{--json?}
DRYJSON2 -->|yes| OUTJSON2["JSON: { dry_run, agent_id, action }"]
DRYJSON2 -->|no| OUTTXT2["Text: 'Would rotate key for agent ...'"]
DRY -->|yes, reset| OUTTXT3["Text only: list of paths\n(no --json support)"]
DRY -->|no| YES{"--yes / --force?"}
YES -->|no| PROMPT["Interactive confirm()"]
PROMPT -->|cancelled| EXIT["Exit"]
PROMPT -->|confirmed| ACTION
YES -->|yes| ACTION["Execute API call / filesystem op"]
ACTION --> JSON{--json?}
JSON -->|yes| OUTJSON3["Structured JSON output"]
JSON -->|no| OUTTXT4["Human-readable text output"]
Reviews (1): Last reviewed commit: "feat: make CLI agent-friendly (--yes, --..." | Re-trigger Greptile |
| if (opts.dryRun) { | ||
| const task = await apiCall<Task>("GET", `/tasks/${id}`); | ||
| if (opts.json) { | ||
| console.log(JSON.stringify({ dry_run: true, would_delete: task }, null, 2)); | ||
| return; | ||
| } | ||
| console.log(`Would delete task ${id}: ${task.content}`); | ||
| return; |
There was a problem hiding this comment.
--dry-run still makes a real network call
tasks delete --dry-run fetches GET /tasks/{id} before exiting, so it still makes a live API request. This is inconsistent with the agents rotate --dry-run path, which makes no API call and simply echoes the action from the CLI argument.
Both approaches are defensible, but the inconsistency is worth noting: an agent using --dry-run to avoid side effects may not expect a network hop. Consider either (a) aligning the two dry-run paths, or (b) documenting this in the help text (e.g. "Preview without deleting — still reads the task from the API").
| if (opts.dryRun) { | ||
| const hasConfig = node_fs.existsSync(configDir); | ||
| console.log("Dry run — the following would be removed:"); | ||
| console.log(` - API key from secure storage (if stored)`); | ||
| if (hasConfig) { | ||
| console.log(` - ${configDir}`); | ||
| } else { | ||
| console.log(` - ${configDir} (not found)`); | ||
| } | ||
| return; |
There was a problem hiding this comment.
--dry-run has no --json flag on reset
Every other destructive command in this PR (tasks delete, agents rotate) supports --dry-run --json together so agents can machine-parse the preview output. The reset command only emits human-readable text on dry-run and has no --json flag at all.
Since the PR goal is agent-friendliness, consider adding --json to reset and emitting something like:
{ "dry_run": true, "would_remove": ["api_key", "/home/user/.delega"] }so that agents consuming delega reset --dry-run --json get structured output consistent with the other commands.
| if (opts.json) { | ||
| console.log(JSON.stringify({ id, api_key: result.api_key }, null, 2)); | ||
| return; | ||
| } |
There was a problem hiding this comment.
JSON output ignores
result.id from API response
The type was updated to { id: string; api_key: string } to reflect that the server now returns an id field, but the JSON output still hard-codes the id from the CLI argument rather than using result.id. In practice these are always the same value, but for consistency with the declared return type it's cleaner to use the server-confirmed value directly. Consider spreading result or using result.id instead of id from the outer scope.
…son, result.id) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Makes the Delega CLI fully scriptable and agent-friendly, inspired by Eric Zakariasson's "Building CLIs for Agents".
--yes/-yflag ontasks deleteandagents rotateto skip interactiveconfirm()prompts — previously a blocker for non-interactive/agent usage--jsonflag added totasks complete,tasks delete,tasks delegate, andagents rotate— these commands previously only printed human-readable text--helpoutput viaaddHelpText("after", ...)— agents can pattern-match off real invocations--dry-runflag on destructive commands (tasks delete,agents rotate,reset) — preview what would happen without executingAll existing interactive behavior is preserved as the default. No breaking changes.
Test plan
npm run buildpasses (verified locally)delega tasks delete <id> --yesskips confirmationdelega agents rotate <id> --yesskips confirmationdelega tasks delete <id>still prompts interactively (no regression)delega tasks complete <id> --jsonreturns JSONdelega tasks delete <id> --json --yesreturns{"id":"...","deleted":true}delega tasks delegate <tid> <aid> --content "x" --jsonreturns subtask JSONdelega agents rotate <id> --json --yesreturns{"id":"...","api_key":"..."}delega tasks list --helpshows examples sectiondelega tasks delete --dry-run <id>previews without deletingdelega agents rotate --dry-run <id>previews without rotatingdelega reset --dry-runpreviews without cleaning🤖 Generated with Claude Code