Skip to content

CLI AI: Add --json flag for headless NDJSON output#3012

Open
wesleyfantinel wants to merge 17 commits intotrunkfrom
add/cli-studio-ai-json-flag
Open

CLI AI: Add --json flag for headless NDJSON output#3012
wesleyfantinel wants to merge 17 commits intotrunkfrom
add/cli-studio-ai-json-flag

Conversation

@wesleyfantinel
Copy link
Copy Markdown

@wesleyfantinel wesleyfantinel commented Apr 8, 2026

Related issues

How AI was used in this PR

Claude was used to brainstorm the design, write the implementation plan, and implement the changes. All code was reviewed and validated by the author.

Proposed Changes

  • Add --json flag and positional message argument to studio ai command for headless mode
  • Introduce AiOutputAdapter interface with AiChatUI implementing it directly (no wrapper class)
  • Add JsonAdapter that streams typed NDJSON events to stdout
  • Add --auto-approve as a separate CLI flag, independent of --json (defaults to true in JSON mode, overridable with --no-auto-approve)
  • In JSON mode, agent questions are emitted as question.asked events and the process exits after cleanup
  • Define NDJSON event schema: message, progress, info, error, question.asked, turn.started, turn.completed
  • Fix: running studio code "hello" in interactive mode now stays in the input loop after the first reply

Usage

# Single turn, streams NDJSON events to stdout
studio code  "create a theme for my site" --json

# JSON mode without auto-approving tools
studio code "update my theme" --json --no-auto-approve

# Interactive mode with initial message (stays in input loop)
studio code "hello, what can you do?"

# Validation: --json requires a message
studio code --json  # Error: --json requires an initial message argument

Files changed

File Change
apps/cli/ai/json-events.ts (new) NDJSON event types and emitEvent() helper
apps/cli/ai/output-adapter.ts (new) AiOutputAdapter interface and JsonAdapter
apps/cli/ai/agent.ts Add autoApprove field to AiAgentConfig, short-circuit canUseTool
apps/cli/ai/ui.ts AiChatUI implements AiOutputAdapter
apps/cli/commands/ai/index.ts Positional message, --json and --auto-approve flags, adapter pattern, single-turn path, initial message fix
apps/cli/commands/ai/sessions/resume.ts Use AiChatUI directly instead of removed InteractiveAdapter
apps/cli/commands/ai/tests/ai.test.ts Tests for JSON mode, auto-approve flag

Testing Instructions

  1. Build the CLI: npm run cli:build
  2. Run in JSON mode:
    node apps/cli/dist/cli/main.mjs code "hello, what can you do?" --json
  3. Verify NDJSON events are streamed to stdout (one JSON object per line)
  4. Verify turn.started is the first event and turn.completed is the last
  5. Run in interactive mode with initial message and verify it stays in the input loop after the first reply:
    node apps/cli/dist/cli/main.mjs code "hello"
  6. Run in interactive mode (no flags) and verify the TUI works as before:
    node apps/cli/dist/cli/main.mjs code
  7. Verify --json without a message shows an error:
    node apps/cli/dist/cli/main.mjs code --json
  8. Verify --no-auto-approve works with --json:
    node apps/cli/dist/cli/main.mjs code "hello" --json --no-auto-approve
  9. Run tests: npm test -- apps/cli/commands/ai/tests/ai.test.ts

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?

wesleyfantinel and others added 11 commits March 25, 2026 18:08
- Introduced `JsonAdapter` for emitting NDJSON events to stdout.
- Enhanced `runCommand` to support headless mode.
- Updated AI agent to handle `autoApprove` for non-interactive prompts.
- Added tests to validate NDJSON output behavior and error handling.
…andling, so that the type is conformant to zod
Make costUsd optional since only JsonAdapter provides it, guard
replaySessionHistory behind InteractiveAdapter instanceof check.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Integrate upstream trunk changes (activeSite/wpcomAccessToken for remote sites)
with branch changes (autoApprove/JSON mode). Add missing interface methods
(showOnboarding, showCapabilities, showSuccess, showProgress, setBusy) to
AiOutputAdapter and fix test config for JSON mode tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@wpmobilebot
Copy link
Copy Markdown
Collaborator

wpmobilebot commented Apr 8, 2026

📊 Performance Test Results

Comparing 9b57000 vs trunk

app-size

Metric trunk 9b57000 Diff Change
App Size (Mac) 1252.12 MB 1252.13 MB +0.00 MB ⚪ 0.0%

site-editor

Metric trunk 9b57000 Diff Change
load 1898 ms 1789 ms 109 ms 🟢 -5.7%

site-startup

Metric trunk 9b57000 Diff Change
siteCreation 8131 ms 9131 ms +1000 ms 🔴 12.3%
siteStartup 4171 ms 4169 ms 2 ms ⚪ 0.0%

Results are median values from multiple test runs.

Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff)

@wesleyfantinel wesleyfantinel requested a review from sejas April 8, 2026 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants