Add `--json` output mode to every `func` subcommand, including errors
- Dominant language
- Go
- Stars
- 365
- Forks
- 223
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 25
Description
## Summary
Every `func` subcommand should support a `--json` flag that emits structured output suitable for machine consumption. Errors must also be returned as JSON when `--json` is set, not as human-formatted strings.
## Motivation
Today the only structured signal callers (MCP server, scripts, IDEs, CI, future Console plugin) can extract from `func` is the exit code plus stdout/stderr text. This forces every consumer to either substring-match output (brittle — see #3753 for a worked example of why this fails) or invent its own taxonomy by guessing at `func`'s intent. The result is a contract that's secretly the consumer's job to maintain, even though the producer (`func`) is the only code that actually knows what happened.
Putting structured output behind a `--json` flag fixes this for every consumer at once. Same pattern as `kubectl -o json`, `gh --json`, `aws --output json` — users already expect it from modern CLIs.
## Scope
- Every existing `func` subcommand accepts `--json`.
- On success: command-specific structured payload (e.g., `func list --json` returns the function list; `func describe --json` returns the deployed-function spec; `func deploy --json` returns the resulting service URL/image/etc).
- **On failure: a structured error object** (this is the part most consumers actually need), with at minimum:
- `category` (e.g. `REGISTRY_ERROR`, `CLUSTER_ERROR`, `BUILD_ERROR`, `VALIDATION_ERROR`, `AUTH_ERROR`, `READONLY_ERROR`, `TIMEOUT_ERROR`, `UNKNOWN_ERROR`)
- `code` (stable string identifier; finer-grained than category)
- `retryable` / `transient` boolean
- `message` (human-readable summary)
- `hint` (suggested remediation)
- `context` (resource name, namespace, registry, etc. — whatever's relevant to the failure)
- Default output (no flag) stays exactly as it is. `--json` is opt-in.
## Open design questions (decide before implementing)
1. **Envelope shape.** Suggested: `{"status": "ok"|"error", "data": ..., "error": {...}}` so callers can dispatch with one key.
2. **Stream choice.** All JSON to stdout (recommended — `status` carries success/failure, no need to merge streams) vs error JSON to stderr.
3. **Streaming commands** (`func logs`, `func deploy --verbose`): pick NDJSON (one event per line) or explicitly mark `--json` unsupported for these. "Explicit and unsupported" beats "clever and surprising."
4. **Schema versioning.** Either an `apiVersion` field in the envelope, or document that v1 evolves additively only and breaking changes require `--json=v2`. Pin early.
5. **Internal refactor.** Errors emitted from underlying code paths need to carry enough context to be rendered as JSON. Typed errors at the failure site, translated at the CLI boundary.
## Related
- #3750 — original ask for structured MCP error categories (consumer-side workaround).
- #3753 — attempt to do classification in the MCP server via substring matching. Rejected because the classification belongs in `func`, not in MCP.
## Non-goals
- Localization of error messages (separate concern).
- Replacing the existing human-readable output (this is additive).
Contributor guide
Assessment
This issue has not been assessed yet.