Uh oh!
There was an error while loading. Please reload this page.
feat(cli): default output to JSON for coding agents - #5532
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:333917938d
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Uh oh!
There was an error while loading. Please reload this page.
Supabase CLI previewnpx --yes https://pkg.pr.new/supabase@5532Preview package for commit |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:6c907b6cdf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:c2f5e4c66b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
## Summary
Coding agents that run the CLI now get JSON output by default, so they
can parse structured results instead of scraping human-formatted tables.
I resolve the effective output format once at the TypeScript entrypoint
(both the legacy and next roots): an explicit `--output` /
`--output-format` always wins, otherwise a detected coding agent gets
`json` and everyone else keeps `text`. For Go-proxied commands this
flows down as `--output json` to the Go subprocess, which renders JSON
for the data-returning commands and ignores the flag elsewhere, so no Go
changes were needed.
## Changes
- Resolve output format from coding-agent detection in both CLI roots,
defaulting agents to `json` when no format is set explicitly.
- Add a shared `resolveAgentOutputFormat` helper (`explicit ?? (agent ?
json : text)`) reused by both roots, with unit tests.
- Make the `--output-format` global flag optional so an
explicitly-passed format is distinguishable from the default.
- Suppress the agent JSON default whenever the Go-compat `-o`/`--output`
flag is passed explicitly: `-o json|yaml|toml|env` already
short-circuits inside handlers, and `-o pretty` now keeps rendering the
human table on natively ported commands instead of being overridden to
JSON.
## Behavior notes
- Humans and CI keep their current output: production telemetry shows
~99.6% of CI invocations carry no coding-agent env signal, so they don't
flip.
- Error rendering follows the resolved format. In text mode errors stay
as red text on stderr, unchanged. In agent-default JSON mode handler
errors emit the existing structured envelope
(`{"_tag":"Error","error":{code,message}}`) on stdout with a non-zero
exit code, the same behavior `--output-format json` already had, so
agents get parseable failures instead of prose.
- Interactive prompts already refuse to block in JSON mode
(`NonInteractiveError`), so a detected agent cannot hang on a confirm
prompt.
- `--help` and `--version` render before the output layer engages and
stay text in both roots.
- `--agent yes|no` overrides detection in both directions for the
default-format decision.
## Linear
- fixes GROWTH-913
---------
Co-authored-by: Julien Goux <hi@jgoux.dev>…tudio E2E `Start supabase` flake) (#49198) <!-- ccr-slack-attribution --> _Requested by **Ivan Vasilov** · [Slack thread](https://supabase.slack.com/archives/C063LNYJJKS/p1787058646458219?thread_ts=1787058646.458219&cid=C063LNYJJKS)_ **Before:** the root `package.json` pins the Supabase CLI at `supabase: ^2.76.10`, and `pnpm-lock.yaml` resolves it to `2.76.14`. **After:** it pins `supabase: ^2.114.0`. This bumps the Supabase CLI that `pnpm run e2e:setup:cli` and `pnpm run setup:cli` shell out to, so local dev and the E2E workflows boot the local stack with a CLI from this month instead of one from ~38 minor releases ago. **How:** a one-line version change to the `supabase` devDependency in the root `package.json`. Nothing else in the repo changes — no workflow, config, or test changes. ###⚠️ This PR is incomplete: `pnpm-lock.yaml` still needs regenerating `pnpm-lock.yaml` is **not** updated in this PR, so `pnpm install --frozen-lockfile` will fail until someone runs: ```bash pnpm install --lockfile-only ``` and pushes the result to this branch. The lockfile could not be regenerated in the environment this PR was authored in: pnpm re-resolves `apps/studio`'s `"@std/path": "npm:@jsr/std__path@^1.0.8"` on every install, and `npm.jsr.io` is not reachable from there (`ERR_PNPM_FETCH_403`). Treat this PR as needing one extra commit before it can go green. ### Why `^2.114.0` and not `^2.115.0` `2.115.0` is the current `latest` on npm, but it was published only hours ago, and `pnpm-workspace.yaml` sets `minimumReleaseAge: 4320` (3 days) with `supabase` not in `minimumReleaseAgeExclude`. Pinning `2.115.0` today would fail the repo's own supply-chain check. `2.114.0` (2026-08-12) is the newest release that satisfies that policy. ## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Dependency bump. **Speculative** — this is an experiment, not a confirmed fix. ## What is the current behavior? The `Selfhosted Studio E2E Tests` workflow has been failing on `master` at the `Start supabase` step. Recent runs: - https://github.com/supabase/supabase/actions/runs/32092940311 - https://github.com/supabase/supabase/actions/runs/32131961447 In the Slack thread, Ivan Vasilov suggested trying a newer CLI and Alaister Young endorsed giving it a go. ## What is the new behavior? The workflow runs `supabase start` with CLI 2.114.0 instead of 2.76.14. The question this PR is trying to answer is simply **"does a newer CLI help this flake?"** It is not a diagnosis and not a claimed fix. If CI still fails at `Start supabase` on this branch, the bump can be kept or dropped on its own merits and the investigation continues elsewhere. ## Additional context **Verification status:** none locally. The bump was not exercised locally — this repo checkout has no `node_modules` (see the lockfile note above), so `pnpm typecheck`, `pnpm lint`, and `pnpm test:studio` were not run, and neither was `supabase start`. CI on this PR is the only signal. **Call-site compatibility check.** CLI 2.99/2.100 moved to a new TypeScript shell with a stricter argument parser: command-specific flags must now come *after* the subcommand. Both call sites in the root `package.json` already use that order, so no script changes are needed: ``` supabase stop --all --no-backup --workdir ./e2e/studio supabase start --exclude studio,mailpit --workdir ./e2e/studio ``` **Changelog entries between 2.76.14 and 2.114.0 that touch `supabase start` or local config.** Listed so reviewers know what changed in the range — **not** as a claim about what is failing in CI: - **2.112.0** — `supabase start` no longer hangs when analytics migrations fail; the analytics container exits and retries instead of booting against an unmigrated database ([#6093](supabase/cli#6093)). - **2.112.0** — `supabase start` reuses existing volumes instead of failing when they already exist ([#6037](supabase/cli#6037)); Kong reloads after `supabase db reset` ([#6017](supabase/cli#6017)); custom auth email templates survive `db reset` ([#6065](supabase/cli#6065)); `supabase start` works on SELinux-enforcing hosts ([#6000](supabase/cli#6000)). - **2.106.0 — behavior change worth watching.** `[api].auto_expose_new_tables` now resolves to `false` when unset, and local start/reset revokes default Data API privileges for newly created `public` tables, sequences, and functions ([#5524](supabase/cli#5524)). Neither `supabase/config.toml` nor `e2e/studio/supabase/config.toml` sets this key, so this default applies. If E2E specs create `public` objects and then read them through the Data API, they may need explicit `GRANT`s (the deprecated escape hatch is `auto_expose_new_tables = true`). - **2.106.0** — when the CLI detects a coding-agent environment, or `--agent yes` is passed, commands default to JSON output ([#5532](supabase/cli#5532)). `e2e:setup:cli` already passes `--output json` to `supabase status` explicitly, so this should be a no-op here. - **2.100.0** — stricter flag ordering, covered above. - **2.112.0** — `functions deploy` no longer forwards `NPM_AUTH_TOKEN` into Docker bundling ([#6005](supabase/cli#6005)). Not used by these workflows. - **2.107.0** — pg-delta is the default schema diff engine for `db diff` / `db pull` on new projects ([#5511](supabase/cli#5511)). - Many bundled Docker image bumps across the range (`supabase/postgres` 17.6.1.087 → later patches, `postgres-meta`, `vector` 0.28.1 → 0.53.0, Studio image), plus `fix(analytics): wait for logflare before starting vector` (2.84.3) and `fix: use correct docker.sock binding with vector` (2.84.7). Full comparison: supabase/cli@v2.76.14...v2.114.0 --- _Generated by [Claude Code](https://claude.ai/code/session_0143DrDMGnSSwuHebTPJv7ZY)_ --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
Summary
Coding agents that run the CLI now get JSON output by default, so they can parse structured results instead of scraping human-formatted tables. I resolve the effective output format once at the TypeScript entrypoint (both the legacy and next roots): an explicit
--output/--output-formatalways wins, otherwise a detected coding agent getsjsonand everyone else keepstext. For Go-proxied commands this flows down as--output jsonto the Go subprocess, which renders JSON for the data-returning commands and ignores the flag elsewhere, so no Go changes were needed.Changes
jsonwhen no format is set explicitly.resolveAgentOutputFormathelper (explicit ?? (agent ? json : text)) reused by both roots, with unit tests.--output-formatglobal flag optional so an explicitly-passed format is distinguishable from the default.-o/--outputflag is passed explicitly:-o json|yaml|toml|envalready short-circuits inside handlers, and-o prettynow keeps rendering the human table on natively ported commands instead of being overridden to JSON.Behavior notes
{"_tag":"Error","error":{code,message}}) on stdout with a non-zero exit code, the same behavior--output-format jsonalready had, so agents get parseable failures instead of prose.NonInteractiveError), so a detected agent cannot hang on a confirm prompt.--helpand--versionrender before the output layer engages and stay text in both roots.--agent yes|nooverrides detection in both directions for the default-format decision.Linear