Skip to content

feat(nextjs): Add --non-interactive flag for headless CLI operation#1183

Open
codyde wants to merge 12 commits intomasterfrom
feature/headless-mode
Open

feat(nextjs): Add --non-interactive flag for headless CLI operation#1183
codyde wants to merge 12 commits intomasterfrom
feature/headless-mode

Conversation

@codyde
Copy link
Contributor

@codyde codyde commented Jan 8, 2026

Summary

Adds support for fully headless/automated Sentry setup without browser authentication. This enables CI/CD pipelines and AI agents to scaffold Sentry configuration with environment variable placeholders that can be populated later.

New CLI Flags

Flag Description
--skip-auth Skip Sentry authentication, use env var placeholders
--tracing Enable performance/tracing monitoring
--replay Enable Session Replay
--logs Enable Sentry Logs
--tunnel-route Enable tunnel route for ad-blocker circumvention
--mcp-cursor Add MCP config for Cursor
--mcp-vscode Add MCP config for VS Code
--mcp-claude Add MCP config for Claude Code
--mcp-opencode Add MCP config for OpenCode
--mcp-jetbrains Show MCP config for JetBrains IDEs

Example Usage

npx @sentry/wizard -i nextjs \
  --skip-auth \
  --tracing \
  --replay \
  --logs \
  --mcp-opencode \
  --ignore-git-changes

Behavior in --skip-auth Mode

  • Config files use process.env.SENTRY_DSN / process.env.NEXT_PUBLIC_SENTRY_DSN
  • next.config.js uses process.env.SENTRY_ORG and process.env.SENTRY_PROJECT
  • Creates .env.example documenting all required environment variables
  • MCP configs use base URL (mcp.sentry.dev/mcp) without project scope
  • Skips: example page creation, CI setup prompts, turbopack warning
  • Feature flags default to false (must be explicitly enabled)

Generated .env.example

# Sentry Configuration
SENTRY_DSN=
NEXT_PUBLIC_SENTRY_DSN=
SENTRY_ORG=
SENTRY_PROJECT=
SENTRY_AUTH_TOKEN=

Use Cases

  1. AI Agent Setup: Agents can run the wizard headlessly and populate env vars programmatically
  2. CI/CD Scaffolding: Set up Sentry structure in pipelines without interactive prompts
  3. Template Projects: Create project templates with Sentry pre-configured for env vars

Testing

  • yarn build passes
  • yarn lint passes
  • yarn test passes
  • Manual testing with --skip-auth flag in test Next.js project

Add support for fully headless/automated Sentry setup without browser
authentication. This enables CI/CD pipelines and AI agents to scaffold
Sentry configuration with environment variable placeholders.

New CLI flags:
- --skip-auth: Skip authentication, use env var placeholders
- --tracing: Enable performance monitoring
- --replay: Enable Session Replay
- --logs: Enable Sentry Logs
- --tunnel-route: Enable tunnel route
- --mcp-cursor/vscode/claude/opencode/jetbrains: Add MCP configs

In skip-auth mode:
- Config files use process.env.SENTRY_DSN / NEXT_PUBLIC_SENTRY_DSN
- next.config uses process.env.SENTRY_ORG / SENTRY_PROJECT
- Creates .env.example documenting required variables
- MCP configs use base URL without project scope
- Skips example page, CI setup, and turbopack warning
@github-actions
Copy link

github-actions bot commented Jan 8, 2026

Semver Impact of This PR

🟡 Minor (new features)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

Cloudflare

  • Support wrapping workers main file by JPeer264 in #1156
  • Enable update of the wrangler file by JPeer264 in #1149
  • Add a basic skeleton for cloudflare by JPeer264 in #1147

Mcp

  • Add multi-select support for MCP configuration by cursor in #1153
  • Add OpenCode as MCP server provider option by codyde in #1154

Other

  • (nextjs) Add --skip-auth flag for headless CLI operation by codyde in #1183

Bug Fixes 🐛

  • (next) Remove Turbopack outro warning by logaretm in #1173
  • (react-router) Avoid force-running npx react-router reveal by Lms24 in #1181

Build / dependencies / internal 🔧

Deps

  • Update tmp from 0.0.33 to 0.2.4 by Lms24 in #1176
  • Update brace-expansion to 2.0.2 and 1.1.12 by Lms24 in #1175
  • Bump js-yaml from 4.1.0 to 4.1.1 by dependabot in #1114
  • Bump vite from 6.3.6 to 6.4.1 in /e2e-tests/test-applications/cloudflare-wrangler-sourcemaps-test-app by dependabot in #1112
  • Bump devalue from 4.3.3 to 5.6.1 in /e2e-tests/test-applications/cloudflare-wrangler-sourcemaps-test-app by dependabot in #1172

Test

  • Clean up e2e test utils by Lms24 in #1182
  • Update vite to 7.3.0 in pnpm-workspace-test-app by Lms24 in #1174
  • Unstale lock file in pnpm-workspace-test-app by Lms24 in #1170
  • Update @vitest/coverage-v8 to bump glob to 10.5.0 by Lms24 in #1169
  • Update @angular/common and related dependencies by Lms24 in #1168
  • Update @cloudflare/vitest-pool-workers dependencies by Lms24 in #1167

Other

  • (publish) Use fully automatic changelog generation by Lms24 in #1138
  • Remove duplications for SDKs that do not support spotlight by JPeer264 in #1151
  • Wrong changelog category for last update by JPeer264 in #1150

Other

  • test(e2e): Migrate React-native and Expo e2e tests to use clifty by Lms24 in #1179
  • test(e2e): Migrate Flutter e2e tests to use clifty by Lms24 in #1180
  • test(e2e): Migrate Nuxt e2e tests to use clifty by Lms24 in #1178
  • test(e2e): Migrate Angular e2e tests to clifty by Lms24 in #1165

🤖 This preview updates automatically when you update the PR.

Copy link
Member

@Lms24 Lms24 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for opening this PR! I think adding a non-blocking execution flow makes sense. Both for agents as well as humans :) However, I would ask that we take one of these two routes but not mix things up:

  1. We add a --agentMode CLI flag which fully automates every step to make it non-blocking. It can work in conjuction with other high-level CLI flags like --tracing for high-level options but it can be used to skip over multiple steps or change wizard behaviour however otherwise necessary
  2. We add specific flags for each step. For example --auth=false (or --skip-auth) controls authentication and the related code injection steps requiring dsns, project/org data etc (like right now). But in addition, --example-page=false skips the example page, --tunnelRoute decides whether to set tunnelRoute, --setup-ci for (not) skipping CI setup, etc.

I would personally prefer 2 because this allows to make the wizard non-blocking for non-agentic use, too. For example, we could use it in docs to customize the wizard code snippet more based on the selected features on the setup page. Same in the in-product onboarding.

I just want to avoid that a flag like --skip-auth does more than its name implies.
Likewise, I'd slightly prefer "enable" naming over "skip". So users set --example-page=false instead of --skip-example-page. This more resembles the default behaviour of the wizard in the interactive mode. Though happy to hear counter arguments here :)

WDYT?


// Determine tunnel route setting
let tunnelRoute: boolean;
if (skipAuth) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m: is there a reason we only apply the --tunnelRoute argument on if --skip-auth is set? I'd tend towards treating these flags independently of each other

Comment on lines 425 to 427
let shouldCreateExamplePage = false;
if (!skipAuth) {
shouldCreateExamplePage = await askShouldCreateExamplePage();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m: I'd rather have this be its own flag. Nothing about --skip-auth suggests that it skips example page creation.

Instead, I suggest we do something like this:

const shouldCreateExamplePage = options.examplePage ?? await askShouldCreateExamplePage();

Comment on lines 481 to 482
// Skip turbopack warning in skip-auth mode
if (!skipAuth) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m: I don't think we should skip this but rather just log the warning instead if the clack.select prompt that halts the wizard execution. My thinking is that this might even be valuable information for agents.

Comment on lines 502 to 503
// Skip CI setup in skip-auth mode
if (!skipAuth) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m: same here. I think a log message that users/agents need to configure CI after the wizard finished instead of the prompt, is better than entirely skipping this step, no?

@Lms24
Copy link
Member

Lms24 commented Jan 8, 2026

Also, please add an e2e test that covers the agentic setup flow so that we have a good picture of what kind of file output we expect from this flow.

@Lms24
Copy link
Member

Lms24 commented Jan 8, 2026

Oh yea, speaking of --help, the e2e test needs adjustments for whatever options we settle on.

Address PR review feedback:

1. Revert CHANGELOG.md - use PR description instead
2. Simplify to single NEXT_PUBLIC_SENTRY_DSN env var (works for both
   server and client)
3. Consolidate MCP flags into single --mcp array option:
   --mcp cursor,vscode or --mcp cursor --mcp vscode
4. Make all flags work independently (not tied to --skip-auth):
   - --tracing, --replay, --logs: use flag if set, prompt otherwise
   - --tunnel-route: use flag if set, prompt otherwise
   - --example-page: use flag if set, prompt otherwise (defaults to
     false in skip-auth mode)
5. Turbopack warning: log as warning in skip-auth mode instead of skip
6. CI setup: show helpful log message in skip-auth mode instead of skip
Copy link
Member

@Lms24 Lms24 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes! After thinking about this for a while, I think something like a --non-interactive or --headless flag, would make sense and could even replace --skip-auth. My thinking here:

  • --skip-auth does not imply that prompts/warnings/steps requiring input are skipped
  • --headless/--non-interactive (feel free to suggest other names) suggest skipping prompts and as a consequence authentication (at least to a point I guess xD)

WDYT?

@codyde codyde changed the title feat(nextjs): Add --skip-auth flag for headless CLI operation feat(nextjs): Add --non-interactive flag for headless CLI operation Jan 23, 2026
- Add [NextJS only] prefix to all new CLI flag descriptions
- Change chalk.dim to chalk.cyan for env vars in outro message
- Update help-message.test.ts with new flag descriptions
- Add checkFileDoesNotExist/checkFileDoesNotContain to eslint assertion functions
- Fix and expand e2e tests for non-interactive mode:
  - Fix .env.example assertion (empty placeholders, not 'your-auth-token')
  - Fix config file checks (instrumentation-client.ts, not sentry.client.config.ts)
  - Add assertions for env var usage in config files
  - Add test suite for MCP configuration with base URL
  - Add test suite for minimal mode (no feature flags)
- Fix help-message test snapshot for mcp flag line wrapping
- Add package-lock.json creation in non-interactive tests to auto-detect npm
- Fix tunnel route to default to false in non-interactive mode (avoid prompt)
- Remove special case for 'all flags provided'
- Build featuresToPrompt array first, then check length
- Only log features when some were provided via CLI
The package-lock.json we create for npm detection shows as untracked,
causing the git dirty check prompt which hangs in non-interactive mode.
In non-interactive mode, features not provided via CLI flags should
default to false instead of prompting the user. This was causing the
wizard to hang waiting for input in headless environments.
OpenCode uses opencode.json at project root, not .opencode/mcp.json
The npm install timeout needs to be on the 'Adding MCP configurations'
expectation since that's the first output after npm install completes.
@codyde codyde marked this pull request as ready for review February 3, 2026 06:13
Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.


Sentry.init({
dsn: "${dsn}",${integrationsOptions}${performanceOptions}${logsOptions}${replayOptions}
dsn: ${dsnValue},${integrationsOptions}${performanceOptions}${logsOptions}${replayOptions}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy-paste snippet missing useEnvVars parameter propagation

Medium Severity

The getInstrumentationClientHookCopyPasteSnippet function doesn't accept or propagate the new useEnvVars parameter when calling getInstrumentationClientFileContents. In non-interactive mode when an instrumentation-client file already exists (or creation fails), the copy-paste instructions will incorrectly show dsn: "" instead of dsn: process.env.NEXT_PUBLIC_SENTRY_DSN. The callers in nextjs-wizard.ts at lines 926 and 942 also need to pass useEnvVars to this function.

Additional Locations (2)

Fix in Cursor Fix in Web

},
spotlight,
options,
useEnvVars,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wizard hangs in non-interactive mode on existing files

High Severity

Multiple interactive prompts in the wizard are not guarded by nonInteractive checks. When a project has existing _error pages, global-error pages, instrumentation files, or root layout files, the wizard calls clack.confirm or showCopyPasteInstructions which block waiting for user input. In non-interactive mode, this causes the wizard to hang indefinitely. The affected prompts include: underscore error page confirmation (lines 265, 293), global error page confirmation (line 365), root layout instructions (line 414), and instrumentation hook instructions (lines 827, 836, 924, 935).

Additional Locations (2)

Fix in Cursor Fix in Web

Copy link
Member

@Lms24 Lms24 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine and --non-interactive sounds like a good choice. Thanks for making the hanges!

All good from my end! Before we merge this, I'd be curious on the new sentry CLI's perspective, given it's also designed for agentic use (cc @betegon). Ideally, we can scope the individual arguments to the respective wizard flows, similarly to what I sketched out in #1200, once the new CLI calls the wizard. Anyway, not a blocker to merge this into the current wizard from my PoV.

Comment on lines +52 to +53
// Create package-lock.json so npm is auto-detected (avoids package manager prompt)
createPackageLockForNpm(projectDir);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should be able to bypass package manager selection with the --inon-interactive flag. Otherwise the non-interactive mode might hang here. Probably fine to fall back to npm here in case the detection fails.

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