feat(cli): treat --json as unattended mode#1420
Conversation
📦 Bundle Stats —
|
| Metric | Value | vs main (3848089) |
|---|---|---|
| Internal (raw) | 2.7 KB | - |
| Internal (gzip) | 1.0 KB | - |
| Bundled (raw) | 11.16 MB | - |
| Bundled (gzip) | 2.10 MB | - |
| Import time | 918ms | +20ms, +2.2% |
bin:sanity
| Metric | Value | vs main (3848089) |
|---|---|---|
| Internal (raw) | 782 B | - |
| Internal (gzip) | 423 B | - |
| Bundled (raw) | 9.87 MB | - |
| Bundled (gzip) | 1.78 MB | - |
| Import time | 2.33s | +3ms, +0.1% |
🗺️ View treemap · Artifacts
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
📦 Bundle Stats — @sanity/cli-core
Compared against main (38480893)
| Metric | Value | vs main (3848089) |
|---|---|---|
| Internal (raw) | 105.7 KB | +121 B, +0.1% |
| Internal (gzip) | 25.8 KB | +67 B, +0.3% |
| Bundled (raw) | 21.72 MB | +121 B, +0.0% |
| Bundled (gzip) | 3.46 MB | +56 B, +0.0% |
| Import time | 805ms | -5ms, -0.7% |
🗺️ View treemap · Artifacts
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
📦 Bundle Stats — create-sanity
Compared against main (38480893)
| Metric | Value | vs main (3848089) |
|---|---|---|
| Internal (raw) | 908 B | - |
| Internal (gzip) | 483 B | - |
| Bundled (raw) | 931 B | - |
| Bundled (gzip) | 491 B | - |
| Import time | ❌ ChildProcess denied: node | - |
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 013f630. Configure here.
Coverage Delta
Comparing 1 changed file against main @ Overall Coverage
|
013f630 to
6ee82bc
Compare
MCP setup switched to non-prompting `auto` only for --yes, so any other unattended run — a non-TTY, or --json once it implies unattended (#1420) — still stopped at the MCP prompt. Gate it on isUnattended() so a non-interactive init never blocks there.
6ee82bc to
a04fa3d
Compare
A command that emits machine-readable output can't stop at a prompt — the caller parsing its stdout has no way to answer. Fold --json into isUnattended() so every command that already respects unattended mode also skips prompts under --json.
a04fa3d to
d0ba803
Compare
snocorp
left a comment
There was a problem hiding this comment.
Looks good, just left one question about the test
| uri: '/projects/test-project/roles', | ||
| }).reply(200, mockRoles) | ||
|
|
||
| // --json is unattended, so the role defaults to viewer without a roles prompt |
There was a problem hiding this comment.
Should we assert that select/input is not called as well?
|
It might also be good to audit the use of |
I did that and apart from #1421 everything seems good. |

Description
A command that emits machine-readable output can't stop at a prompt — the caller parsing its stdout has no way to answer.
--jsonshould therefore behave like--yes: use defaults, error on missing input, never prompt.Rather than each command re-deriving this,
--jsonis folded intoSanityCommand.isUnattended(). Every command that already respects unattended mode now also skips prompts under--json.What to review
SanityCommand.isUnattended()now returns true for--jsonas well as--yes/non-TTY.--jsonflag inherit the change:init,projects create,tokens add(anddeploy, once its refactor lands). Notablytokens add --jsonnow uses the defaultviewerrole instead of prompting.Testing
tokens add's--jsonunit test was updated to reflect that the role now defaults instead of prompting (no roles fetch). Other affected commands' unit tests pass unchanged.Note
Medium Risk
Central CLI behavior change affects every command using
isUnattended()with--json, which may alter defaults (e.g. token role) for scripts that previously hung on prompts.Overview
SanityCommand.isUnattended()now treats--jsonlike--yesand non-TTY stdin: commands must not prompt and should use defaults or fail with a non-zero exit when input is missing. The docblock explains that machine-readable callers cannot answer interactive prompts.Any command that already branches on
isUnattended()and exposes--jsonpicks up this behavior centrally (e.g.tokens add --jsondefaults the role toviewerinstead of fetching roles and prompting).The
tokens add--jsontest was aligned with that: no roles API mock, and assertions thatselect/inputare never called. A changeset records a minor@sanity/cli-corerelease.Reviewed by Cursor Bugbot for commit 41138e8. Bugbot is set up for automated code reviews on this repo. Configure here.