Skip to content

feat(cli): add --format=json to integration add (auto-provision)#15250

Merged
bhrigu123 merged 4 commits intomainfrom
feat/integration-add-json-output
Feb 25, 2026
Merged

feat(cli): add --format=json to integration add (auto-provision)#15250
bhrigu123 merged 4 commits intomainfrom
feat/integration-add-json-output

Conversation

@bhrigu123
Copy link
Copy Markdown
Contributor

@bhrigu123 bhrigu123 commented Feb 24, 2026

Summary

  • Adds --format=json support to vercel integration add for the auto-provision path (FF_AUTO_PROVISION_INSTALL=1)
  • On success, writes structured JSON to stdout with resource, integration, product, installation, billing plan, dashboard URL, SSO URLs, project connection status, and warnings
  • Refactors postProvisionSetup to return a PostProvisionSetupResult object instead of just an exit code

How agents use this (stream separation)

The Vercel CLI already separates streams per Unix convention:

  • stdout (fd 1): primary data — JSON result
  • stderr (fd 2): everything else — spinners, status messages, errors, prompts

When a human runs the command, they see both streams interleaved on the terminal. When an agent runs it, it captures them separately:

# Agent captures stdout (JSON) and stderr (diagnostics) separately
output=$(vercel integration add neon --format=json 2>/tmp/stderr.log)
exit_code=$?

if [ $exit_code -eq 0 ]; then
  echo "$output" | jq .resource.id    # parse JSON from stdout
else
  cat /tmp/stderr.log                  # read error details from stderr
fi

The agent determines success/failure from the exit code (0 = success, 1 = error), not by parsing output. Intermediate messages (spinners, "Installing...", "Provisioning...") go to stderr and don't interfere with the JSON on stdout.

Output contract

Exit code stdout stderr
0 JSON result progress/status messages
0 JSON with non-empty warnings array progress + warning messages (partial failure: resource provisioned but connect/env-pull failed)
1 (empty) error message

Example JSON output

{
  "resource": {
    "id": "res_xxx",
    "name": "neon-blue-river",
    "status": "available",
    "externalResourceId": "ext_xxx"
  },
  "integration": { "id": "int_xxx", "slug": "neon", "name": "Neon" },
  "product": { "id": "prod_xxx", "slug": "neon-postgres", "name": "Neon Postgres" },
  "installation": { "id": "inst_xxx" },
  "billingPlan": { "id": "plan_xxx", "name": "Free", "type": "subscription" },
  "dashboardUrl": "https://vercel.com/team/~/stores/integration/res_xxx",
  "ssoUrl": {
    "integration": "https://vercel.com/api/marketplace/sso?teamId=...&integrationConfigurationId=inst_xxx",
    "resource": "https://vercel.com/api/marketplace/sso?teamId=...&integrationConfigurationId=inst_xxx&resource_id=ext_xxx"
  },
  "project": { "id": "prj_xxx", "name": "my-app" },
  "environments": ["production", "preview", "development"],
  "envPulled": true,
  "warnings": []
}

All top-level keys are always present — billingPlan and project are null (not omitted) when absent.

Design decisions

  1. Errors to stderr, not stdout — consistent with Unix convention and all other integration subcommands (list, open, balance, remove, discover)
  2. Partial failures return exit code 0 with warnings — if the resource was provisioned (the primary action), that's success. Connection or env-pull failures are reported in the warnings array
  3. Terms acceptance works normally in JSON mode — terms browser flow writes to stderr, doesn't interfere with JSON on stdout
  4. Legacy path rejects --format — only the auto-provision code path supports JSON; the legacy flow errors with a clear message
  5. SSO URLs included — both integration-level and resource-level SSO links via buildSSOLink(), no extra API calls needed
  6. Shared env pull warning constantENV_PULL_FAILED_MESSAGE used by both postProvisionSetup and the JSON warnings builder

Test plan

  • --format=json outputs valid JSON to stdout on success (no project context)
  • JSON includes project: null when no project is linked
  • JSON includes project, environments, envPulled when connected to a project
  • JSON includes ssoUrl.integration and ssoUrl.resource
  • Partial failure: connect fails → JSON with warnings, exit code 0
  • Partial failure: env pull fails → JSON with warning, exit code 0
  • Pre-provisioning error → no JSON on stdout, exit code 1
  • Invalid --format=xml → error, exit code 1
  • Without --format, behavior unchanged (no JSON on stdout)
  • --format filtered from help when auto-provision FF is off
  • All 277 tests pass (including formatDynamicExamples coverage test)

🤖 Generated with Claude Code

…sion)

Enable coding agents and CI scripts to parse structured output from
`vercel integration add` when using the auto-provision flow.

JSON is written to stdout via client.stdout.write(), while all
intermediate messages (spinners, status, prompts) go to stderr via
output.log/error/spinner. This follows Unix stream separation
convention — agents read stdout for data and stderr for diagnostics.

Refactors postProvisionSetup to return a structured result object
(PostProvisionSetupResult) instead of just an exit code, so the JSON
output path has access to project, environments, and env-pull status.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bhrigu123 bhrigu123 requested review from a team as code owners February 24, 2026 23:52
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Feb 24, 2026

🦋 Changeset detected

Latest commit: f2a4848

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
vercel Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 24, 2026

📦 CLI Tarball Ready

The Vercel CLI tarball for this PR is now available!

Quick Test

You can test this PR's CLI directly by running:

npx https://vercel-frc1gkigf.vercel.sh/tarballs/vercel.tgz --help

Use in vercel.json

To use this CLI version in your project builds, add to your vercel.json:

{
  "build": {
    "env": {
      "VERCEL_CLI_VERSION": "vercel@https://vercel-frc1gkigf.vercel.sh/tarballs/vercel.tgz"
    }
  }
}

Python Runtime Wheel

A vercel-runtime wheel was also built for this PR.
To use in your Python project builds, also set this environment variable:

VERCEL_RUNTIME_PYTHON="vercel-runtime @ https://vercel-frc1gkigf.vercel.sh/tarballs/vercel_runtime-0.6.0.dev1771980297+f2a4848-py3-none-any.whl"

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 24, 2026

🧪 Unit Test Strategy

Comparing: f49e6aaf2a4848 (view diff)

Strategy: Affected packages only

✅ Only testing packages that have been modified or depend on modified packages.

Affected packages - 3 (8%)
  1. @vercel/fs-detectors
  2. @vercel/static-build
  3. vercel
Unaffected packages - 37 (93%)
  1. @vercel-internals/get-package-json
  2. @vercel/backends
  3. @vercel/build-utils
  4. @vercel/cervel
  5. @vercel/cli-auth
  6. @vercel/client
  7. @vercel/config
  8. @vercel/detect-agent
  9. @vercel/edge
  10. @vercel/elysia
  11. @vercel/error-utils
  12. @vercel/express
  13. @vercel/fastify
  14. @vercel/firewall
  15. @vercel/frameworks
  16. @vercel/functions
  17. @vercel/gatsby-plugin-vercel-builder
  18. @vercel/go
  19. @vercel/h3
  20. @vercel/hono
  21. @vercel/hydrogen
  22. @vercel/koa
  23. @vercel/nestjs
  24. @vercel/next
  25. @vercel/node
  26. @vercel/oidc
  27. @vercel/oidc-aws-credentials-provider
  28. @vercel/python
  29. @vercel/python-analysis
  30. @vercel/redwood
  31. @vercel/related-projects
  32. @vercel/remix-builder
  33. @vercel/routing-utils
  34. @vercel/ruby
  35. @vercel/rust
  36. @vercel/static-config
  37. examples

Results

  • Unit tests: Only affected packages will run unit tests
  • E2E tests: Running in parallel via E2E Tests workflow
  • Type checks: Only affected packages will run type checks

This comment is automatically generated based on the affected testing strategy

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The CI test ensures every addSubcommand option has a corresponding
dynamic example. Adding formatOption to command options requires a
matching entry in formatDynamicExamples().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Always include `project` field (null when absent) for stable contract
- Move formatOption to end of options array (consistent with other cmds)
- Extract env pull warning to shared ENV_PULL_FAILED_MESSAGE constant
- Filter --format from help when auto-provision FF is off
- Add ssoUrl.integration and ssoUrl.resource to JSON output via
  buildSSOLink() (no API calls, constructed from existing IDs)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bhrigu123 bhrigu123 merged commit f39fb1e into main Feb 25, 2026
178 checks passed
@bhrigu123 bhrigu123 deleted the feat/integration-add-json-output branch February 25, 2026 01:13
ricardo-agz pushed a commit that referenced this pull request Feb 25, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## vercel@50.24.0

### Minor Changes

- [dev] skip project setup for `vc dev` if `--local` or `-L` flag is
passed. ([#15239](#15239))

### Patch Changes

- feat(cli): add --format=json support to `integration add`
(auto-provision) ([#15250](#15250))

-   Updated dependencies \[]:
    -   @vercel/build-utils@13.5.0
    -   @vercel/next@4.15.34
    -   @vercel/redwood@2.4.9
    -   @vercel/rust@1.0.5
    -   @vercel/static-build@2.8.41

## @vercel/routing-utils@5.4.0

### Minor Changes

- Undeprecate `routes` schema and add aliases for `src`, `dest`, and
`status` ([#15010](#15010))

## @vercel/client@17.2.47

### Patch Changes

- Updated dependencies
\[[`0c961fce30d495620542066249dae447764d2eba`](0c961fc)]:
    -   @vercel/routing-utils@5.4.0
    -   @vercel/build-utils@13.5.0

## @vercel/config@0.0.34

### Patch Changes

- Undeprecate `routes` to match new routing-utils
([#15016](#15016))

- Updated dependencies
\[[`0c961fce30d495620542066249dae447764d2eba`](0c961fc)]:
    -   @vercel/routing-utils@5.4.0

## @vercel/fs-detectors@5.8.11

### Patch Changes

- [services] adds source information to detected services
([#15245](#15245))

- Updated dependencies
\[[`0c961fce30d495620542066249dae447764d2eba`](0c961fc)]:
    -   @vercel/routing-utils@5.4.0
    -   @vercel/frameworks@3.19.0


<!-- VADE_RISK_START -->
> [!NOTE]
> Low Risk Change
>
> This PR is an automated Changesets release that only updates version
numbers in package.json files and CHANGELOG.md files, with no code logic
changes.
> 
> - Version bumps across 5 packages (vercel, client, config,
fs-detectors, routing-utils)
> - Deletes consumed changeset markdown files
> - Updates CHANGELOG.md files with release notes
>
> <sup>Risk assessment for [commit
987df11](https://github.com/vercel/vercel/commit/987df111fedc0eb57c982038befca199bbf7e6fe).</sup>
<!-- VADE_RISK_END -->

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.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.

2 participants