Skip to content

feat(cli): M8 — headless one-shot mode (-p / --print)#19

Merged
oratis merged 1 commit into
mainfrom
feat/m8-headless
May 28, 2026
Merged

feat(cli): M8 — headless one-shot mode (-p / --print)#19
oratis merged 1 commit into
mainfrom
feat/m8-headless

Conversation

@oratis

@oratis oratis commented May 28, 2026

Copy link
Copy Markdown
Owner

Summary

Removes the "Headless mode is wired in M8" stub at apps/cli/src/cli.ts:42 and ships the real thing.

  • apps/cli/src/headless.ts (NEW) — full bootstrap (settings, creds, tools, memory, skills, output style, MCP, hooks, sandbox, autoCompact) but runs a SINGLE turn instead of a readline loop. Three output formats:
    • text — plain deltas + minimal tool markers (default)
    • json — single final JSON object on stdout at exit (full transcript + usage + exitCode)
    • stream-json — NDJSON, one event per line, suitable for piping into another process
  • Approval callback returns false in headless (no human to ask). Use --mode dontAsk or --mode bypassPermissions (trust-gated) for auto-approval.
  • SIGINT/SIGTERM wired to AbortController → exit code 5.
  • 5 stable exit codes (documented in --help): 0 ok / 1 generic / 2 bad-input / 3 api-or-auth / 4 max-turns / 5 aborted.
  • cli.ts replaces the stub branch with a real runHeadless() call.

Test plan

  • pnpm -F deepcode-cli test43 passing (was 41; +2 in headless.test.ts)
  • pnpm -F deepcode-cli build — clean
  • Smoke: HOME=/tmp/empty node apps/cli/dist/cli.js -p "hi" → prints "No DeepSeek credentials.", exits 3 ✅
  • Smoke: same with --output-format json → same exit 3 ✅
  • docs/BEHAVIOR_PARITY.md updated — -p moves to ✅, output-format to 🟡 (full pieces still pending json-schema)

Notes

  • The test file is intentionally minimal (early-exit paths only) because mocking DeepSeekProvider from the host process is awkward without dep injection. Live end-to-end is exercised via docs/m1-validation.md against the real API.
  • json-schema and include-partial-messages remain parsed-only (M8-rest).

🤖 Generated with Claude Code

Removes the "Headless mode is wired in M8" stub and ships the real thing.

  · apps/cli/src/headless.ts (NEW, ~270 lines)
    - Mirrors the REPL bootstrap (settings + creds + tools + memory + skills +
      output style + MCP + hooks + sandbox + autoCompact) but runs a SINGLE
      conversation turn, no readline.
    - Three output formats:
      · text — plain deltas + tool markers (default)
      · json — single final JSON object on stdout
      · stream-json — NDJSON, one event per line
    - Approval callback returns `false` in headless (no human to ask);
      users wanting auto-yes pass --mode dontAsk or --mode bypassPermissions.
    - SIGINT/SIGTERM hook → AbortController → exit code 5.
    - 5 stable exit codes: 0 ok / 1 generic / 2 bad-input / 3 api-or-auth /
      4 max-turns / 5 aborted.

  · apps/cli/src/cli.ts — replaces the stub branch with a real runHeadless()
    call.

  · apps/cli/src/parse-args.ts help text — documents the exit codes and what
    each output-format means.

  · apps/cli/src/headless.test.ts (NEW) — 2 tests proving early-exit paths
    (returns 3 on missing creds + same behavior under --output-format json).
    Live end-to-end coverage is via docs/m1-validation.md (real API).

  · docs/BEHAVIOR_PARITY.md — `-p` headless and --output-format move from
    🔄 M8 to ✅ / 🟡 (json-schema + include-partial-messages still parsed only).

Tests: core unchanged (308 pass); cli 41 → 43 (+2 headless). Total 351.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@oratis oratis merged commit 31a05be into main May 28, 2026
1 of 2 checks passed
@oratis oratis deleted the feat/m8-headless branch May 28, 2026 05:22
oratis added a commit that referenced this pull request May 28, 2026
This session ("继续推进" from v2) added 5 PRs on top of #1-#16:
  · #17 M3c-rest tools (TodoWrite + WebFetch + WebSearch)
  · #18 M3.5 attack tests + security-model.md
  · #19 M8 headless mode (-p / --print)
  · #20 M5.2 plugin live wire-up
  · #21 system-reminder injector

Test count: 313 → 387 (+74).
Scope completion estimate: 65-70% → 72-78%.

Major remaining items: M6 Mac Electron (still 0%), M7 file panel (depends
on M6), and the M3c-rest/M8/M5.2 leftovers itemized in the body.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

1 participant