Skip to content

feat(cli): detect SvelteKit apps in a monorepo and offer a picker - #148

Merged
oekazuma merged 2 commits into
mainfrom
advisor/019-monorepo-app-picker
Jul 8, 2026
Merged

oekazuma merged 2 commits into
mainfrom
advisor/019-monorepo-app-picker

Conversation

@oekazuma

@oekazuma oekazuma commented Jul 8, 2026 •

Copy link
Copy Markdown
Owner

Summary

Implements plan plans/019-monorepo-app-picker.md (design doc included in this PR: docs/superpowers/specs/2026-07-08-monorepo-app-picker-design.md).

Running npx svelte-vitals at a monorepo root used to dead-end with exit 2, forcing users to know and type the app path (npx svelte-vitals ./apps/web). Now that dead end becomes a helpful path:

  • One SvelteKit app detected → a stderr notice (detected SvelteKit app at apps/web; analyzing it.) and the analysis just runs.
  • Multiple apps + interactive terminal → a @clack/prompts single-select picker (same style as the install wizard); cancel exits 0.
  • Multiple apps + non-TTY (CI, agents) → never prompts; exit 2 with the detected list and a pass one as a path hint.

Design decisions (maintainer-approved)

  • Failure-time trigger only. Discovery runs only when no path argument was given AND project detection failed — every currently-working invocation is untouched, and an explicit path that fails is still an immediate error (the user's stated target is never reinterpreted; resolveArgs now records explicitPath).
  • Detection is tool-agnostic: glob for svelte.config.{js,ts} (depth-capped at 4, ignoring node_modules/.svelte-kit/build/dist/.git), qualified by an adjacent src/routes — which also excludes SvelteKit component libraries with nothing to analyze. No workspace-manifest parsing.
  • After selection the chosen directory becomes the analysis cwd, so svelte-vitals.config.* loads from the selected app and --diff/--staged/--baseline keep working (their subdirectory handling shipped in fix(cli): make --diff/--staged work when the project is not at the git repo root #114/feat(cli): add --baseline <ref> to report only newly introduced findings #142). The cwd computation in run() is now hoisted to a single variable used everywhere.
  • The picker is injected into run() (RunOptions.selectApp) and wired to clack in bin.ts — keeping prompts out of the library entry point and making every branch unit-testable.
  • Ride-along fix: the old error message told users to "pass --config", a flag that doesn't exist; it now suggests passing a path.

Changes

  • packages/cli/src/discover-apps.ts (new), discovery/picker branch in run(), explicitPath in resolve-args.ts, clack wiring in bin.ts, message fix in providers/source/project.ts
  • New monorepo fixture (apps/web, apps/admin, packages/ui as the excluded library) and 12 new test cases across discover-apps, run-discover, and resolve-args tests; one pre-existing run.test.ts case now passes explicitPath: true to keep meaning "this exact directory is the target"
  • Docs: "Monorepos" section in the CLI guide (en/ja), one-line README pointer
  • Changeset: minor for svelte-vitals

Verification

  • pnpm typecheck, pnpm --filter svelte-vitals test (436 tests), pnpm lint — all green
  • Live checks with the built CLI: explicit path failure stays an immediate error with no discovery; running at the fixture monorepo root without a TTY prints the app list + hint and exits 2

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • svelte-vitals can now detect SvelteKit apps in a monorepo when run from the repository root without a path.
    • If one app is found, it runs automatically; if multiple are found, interactive terminals can choose which app to analyze.
  • Bug Fixes

    • Improved behavior for non-interactive environments by exiting with a clear message and guidance instead of prompting.
    • Kept explicitly provided app paths unchanged.
  • Documentation

    • Updated usage and CLI guides to explain monorepo support and selection behavior.

Running `npx svelte-vitals` at a monorepo root with no path argument used
to dead-end with exit 2 ("No SvelteKit project found"). Now, only when no
explicit path was given and detection fails, it globs for
svelte.config.{js,ts} + src/routes nearby: one match auto-continues with a
stderr notice, multiple matches prompt an interactive single-select (clack,
cancel = exit 0), and non-TTY environments get exit 2 with the app list and
a path hint instead of a prompt. An explicit path's failure is never
reinterpreted. Also fixes the "or pass --config" error text, which named a
flag that doesn't exist.

See docs/superpowers/specs/2026-07-08-monorepo-app-picker-design.md for the
full design.
@coderabbitai

coderabbitai Bot commented Jul 8, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@oekazuma, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 48 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ccb8b8f7-5771-45d0-95c7-ce6e00d68369

📥 Commits

Reviewing files that changed from the base of the PR and between 44c0384 and ed98207.

📒 Files selected for processing (2)
  • packages/cli/src/index.ts
  • packages/cli/test/run-discover.test.ts
📝 Walkthrough

Walkthrough

This PR adds monorepo SvelteKit app auto-detection to the svelte-vitals CLI. When run without an explicit path and project detection fails, it discovers candidate apps, auto-analyzes a sole match, prompts interactively for multiple matches in TTY, or exits with code 2 otherwise, with corresponding fixtures, tests, and docs.

Changes

Monorepo App Picker

Layer / File(s) Summary
Design spec and error message
docs/superpowers/specs/2026-07-08-monorepo-app-picker-design.md, packages/cli/src/providers/source/project.ts
Spec document defines discovery rules and picker flow; detectProject's error message is updated to suggest passing a path instead of --config.
App discovery implementation
packages/cli/src/discover-apps.ts, packages/cli/test/discover-apps.test.ts, packages/cli/test/fixtures/monorepo-project/...
discoverApps(cwd) globs svelte.config.{js,ts}, filters by src/routes presence, dedupes and sorts results; new fixtures and unit tests cover valid apps, excluded libraries, empty trees, and cwd exclusion.
explicitPath flag
packages/cli/src/resolve-args.ts, packages/cli/test/resolve-args.test.ts
resolveArgs() sets explicitPath based on positional argument presence, validated by new unit tests.
run() discovery/picker integration
packages/cli/src/index.ts
RunOptions adds explicitPath and selectApp; run() tracks a mutable cwd, discovers apps on ProjectError, auto-analyzes single matches, prompts for multiple matches, exits with code 2 or 0 accordingly, and reuses cwd for staged/baseline flows.
CLI picker wiring
packages/cli/src/bin.ts
Imports @clack/prompts, defines selectApp using p.select, and passes it into the run() call.
End-to-end tests
packages/cli/test/run-discover.test.ts, packages/cli/test/run.test.ts
New suites test TTY/non-TTY multi-app behavior, cancellation, explicitPath suppression, zero-app fallback, and single-app auto-analysis; existing test updated with explicitPath: true.
Docs and changeset
.changeset/monorepo-app-picker.md, README.md, docs/src/content/docs/guides/cli.md, docs/src/content/docs/ja/guides/cli.md
Documents monorepo detection, prompting, and exit codes across changeset, README, and English/Japanese CLI guides.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant run
  participant discoverApps
  participant selectApp
  participant analyzeProject
  User->>run: invoke CLI without path
  run->>analyzeProject: analyzeProject(cwd)
  analyzeProject-->>run: throws ProjectError
  run->>discoverApps: discoverApps(cwd)
  discoverApps-->>run: apps list
  alt one app found
    run->>analyzeProject: analyzeProject(join(cwd, app))
  else multiple apps and TTY
    run->>selectApp: selectApp(apps)
    selectApp-->>run: chosen app or null
    run->>analyzeProject: analyzeProject(join(cwd, chosen))
  else multiple apps non-interactive or zero found
    run-->>User: exit code 2 with message
  end
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main CLI change: monorepo app detection with an interactive picker.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/cli/src/index.ts`:
- Around line 249-260: The app selection prompt in index.ts is currently gated
only by stdout TTY, so selectApp can still run when stdin is not interactive and
hang or fail. Update the condition around the selectApp branch to require an
interactive stdin as well (using process.stdin.isTTY, or both stdin and stdout),
and keep the existing fallback/error path in the same control flow so
non-interactive shells skip the picker.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a5030158-2afa-49b8-8781-642c66dc57f0

📥 Commits

Reviewing files that changed from the base of the PR and between dad2cce and 44c0384.

📒 Files selected for processing (19)
  • .changeset/monorepo-app-picker.md
  • README.md
  • docs/src/content/docs/guides/cli.md
  • docs/src/content/docs/ja/guides/cli.md
  • docs/superpowers/specs/2026-07-08-monorepo-app-picker-design.md
  • packages/cli/src/bin.ts
  • packages/cli/src/discover-apps.ts
  • packages/cli/src/index.ts
  • packages/cli/src/providers/source/project.ts
  • packages/cli/src/resolve-args.ts
  • packages/cli/test/discover-apps.test.ts
  • packages/cli/test/fixtures/monorepo-project/apps/admin/src/routes/+page.svelte
  • packages/cli/test/fixtures/monorepo-project/apps/admin/svelte.config.js
  • packages/cli/test/fixtures/monorepo-project/apps/web/src/routes/+page.svelte
  • packages/cli/test/fixtures/monorepo-project/apps/web/svelte.config.js
  • packages/cli/test/fixtures/monorepo-project/packages/ui/svelte.config.js
  • packages/cli/test/resolve-args.test.ts
  • packages/cli/test/run-discover.test.ts
  • packages/cli/test/run.test.ts

Comment thread packages/cli/src/index.ts Outdated
…icker

@clack/prompts reads from stdin, so gating the picker only on stdout TTY
could hang the prompt when stdin is piped or redirected while stdout is a
terminal. Gate on both streams; a non-interactive stdin now takes the
existing non-TTY fallback (app list + path hint, exit 2).
@oekazuma
oekazuma merged commit 4c90f29 into main Jul 8, 2026
7 checks passed
@oekazuma
oekazuma deleted the advisor/019-monorepo-app-picker branch July 8, 2026 07:14
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.

1 participant