Skip to content

fix(cli): replace preferred-pm with local implementation#984

Merged
binoy14 merged 8 commits intomainfrom
replace-preffered-pm
Apr 23, 2026
Merged

fix(cli): replace preferred-pm with local implementation#984
binoy14 merged 8 commits intomainfrom
replace-preffered-pm

Conversation

@binoy14
Copy link
Copy Markdown
Contributor

@binoy14 binoy14 commented Apr 20, 2026

Description

Replaces the preferred-pm npm dependency with a local implementation to fix compatibility with yarn v1 on Node 20. The preferred-pm@5.0.0 package requires node >=22.13, which breaks yarn v1 Classic since it enforces engine checks by default.

See #983 for context on the yarn v1 + Node 20 incompatibility.

Changes:

  • Remove preferred-pm dependency from @sanity/cli
  • Add local preferredPm module that detects package managers via lock files, workspace configurations, and node_modules markers
  • Convert from async to sync detection (no behavioral change — the original library only did sync filesystem checks behind an async API)
  • Fix workspace detection for paths nested inside a package (e.g. packages/child/src)
  • Fix .modules.yaml parsing to handle both YAML and JSON formats

What to review

  • packages/@sanity/cli/src/util/packageManager/preferredPm.ts — the local implementation
  • packages/@sanity/cli/src/util/packageManager/__tests__/preferredPm.test.ts — unit tests (22 cases)
  • packages/@sanity/cli/src/util/packageManager/packageManagerChoice.ts — updated import and usage

Testing

Unit tests cover: lock file detection (all 6 lock file types), parent directory pnpm-lock walk-up, workspace root detection (yarn/npm/pnpm/bun workspaces, subdirectory paths, non-matching paths, workspaces.packages format), node_modules marker detection (YAML and JSON .modules.yaml formats), and empty directory fallback.

pnpm test packages/@sanity/cli/src/util/packageManager/__tests__/preferredPm.test.ts

Note

Medium Risk
Changes CLI package-manager auto-detection logic and removes a third-party dependency, which can affect dependency installation/upgrade flows across different workspace layouts. Risk is mitigated by extensive new unit tests, but behavior differences in edge cases are still possible.

Overview
Fixes Yarn v1 on Node 20 by removing the preferred-pm dependency (and its Node 22+ engine requirement) and switching getPackageManagerChoice to use a new in-repo preferredPm implementation.

The new detector infers the preferred package manager from lockfiles, pnpm lock/workspace files in parent directories, workspace root package.json globs, and node_modules markers (including more tolerant .modules.yaml parsing), with a comprehensive new vitest suite to cover these cases.

Reviewed by Cursor Bugbot for commit a000164. Bugbot is set up for automated code reviews on this repo. Configure here.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@claude
Copy link
Copy Markdown

claude Bot commented Apr 20, 2026

Claude finished @binoy14's task in 5m 10s —— View job


Review

  • Read changed files
  • Analyze implementation for bugs/logic errors
  • Check test coverage
  • Verify changeset

Previously reported infinite loop (b809ca7) is fixed — the current HEAD has no continue in detectFromWorkspaceRoot, so dir always advances. ✓

preferredPm.ts:83?? 'yarn' fallback assumes workspaces implies yarn

return detectFromLockFile(dir) ?? 'yarn'

Any directory with a workspaces field and no lock file returns 'yarn', even for npm workspaces. npm has supported workspaces since v7. A fresh checkout of an npm monorepo (before npm install is run) will be incorrectly detected as yarn. This is inherited from the original preferred-pm behavior, but it's worth knowing it exists. Fix this →

preferredPm.ts:66-95matchDir logic is correct but opaque

The packageDir === dir ? resolvedPkgPath : packageDir branch serves two different purposes:

  • When dir === resolvedPkgPath === packageDir (starting path is a package root): relativePath === '' triggers an immediate match — correct for workspace roots.
  • When findNearestPackageDir returns the workspace root itself (no intermediate package.json): the raw resolvedPkgPath is used for glob matching rather than packageDir.

Both paths work correctly for all test cases but the intent is non-obvious. A comment on that line would help future readers.

preferredPm.ts:54-64findNearestPackageDir never checks filesystem root

while (dir !== root) { ... }
return startDir

The loop exits before checking root/package.json. In practice this is fine, but it's inconsistent with findUp which does check root. Not a real bug.

Test coverage is thorough — 22 cases including the nested workspace walk-up, malformed JSON, YAML/JSON .modules.yaml parsing, and permission errors. The malformed package.json test requested in review is present at line 139. ✓

Changesetpatch bump is correct. Summary "Fix package manager detection failing with yarn v1 on Node 20." is concise and user-facing. ✓

picomatch is already a direct dependency at ^4.0.4 — no new dep introduced. ✓

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 20, 2026

📦 Bundle Stats — @sanity/cli

Compared against main (39834eef)

@sanity/cli

Metric Value vs main (39834ee)
Internal (raw) 2.1 KB -
Internal (gzip) 799 B -
Bundled (raw) 10.94 MB -
Bundled (gzip) 2.05 MB -
Import time 870ms +16ms, +1.9%

bin:sanity

Metric Value vs main (39834ee)
Internal (raw) 975 B -
Internal (gzip) 460 B -
Bundled (raw) 9.84 MB -
Bundled (gzip) 1.77 MB -
Import time 2.05s +56ms, +2.8%

🗺️ View treemap · Artifacts

Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

📦 Bundle Stats — @sanity/cli-core

Compared against main (39834eef)

Metric Value vs main (39834ee)
Internal (raw) 93.8 KB -
Internal (gzip) 21.9 KB -
Bundled (raw) 21.62 MB -
Bundled (gzip) 3.42 MB -
Import time 823ms +10ms, +1.3%

🗺️ View treemap · Artifacts

Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

📦 Bundle Stats — create-sanity

Compared against main (39834eef)

Metric Value vs main (39834ee)
Internal (raw) 976 B -
Internal (gzip) 507 B -
Bundled (raw) 50.7 KB -
Bundled (gzip) 12.6 KB -
Import time ❌ ChildProcess denied: node -
Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 20, 2026

Coverage Delta

File Statements
packages/@sanity/cli/src/util/packageManager/packageManagerChoice.ts 42.9% (±0%)
packages/@sanity/cli/src/util/packageManager/preferredPm.ts 93.0% (new)

Comparing 2 changed files against main @ 2fd358fc52ed3e2c3b89e45796e4a6044e03cd4c

Overall Coverage

Metric Coverage
Statements 84.0% (+ 0.1%)
Branches 73.8% (+ 0.1%)
Functions 84.0% (+ 0.1%)
Lines 84.5% (+ 0.1%)

binoy14 and others added 3 commits April 20, 2026 23:04
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ndows

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@binoy14 binoy14 marked this pull request as ready for review April 21, 2026 19:50
@binoy14 binoy14 requested a review from a team as a code owner April 21, 2026 19:50
@binoy14 binoy14 requested review from mariuslundgard and mttdnt and removed request for a team April 21, 2026 19:50
Comment thread packages/@sanity/cli/src/util/packageManager/preferredPm.ts Outdated
… match

When a nested package.json has a workspaces field whose globs don't
match the target path, continue traversing parent directories instead
of returning null. Also simplify error handling in detectFromNodeModules
to swallow all read errors for best-effort detection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@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 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b809ca7. Configure here.

Comment thread packages/@sanity/cli/src/util/packageManager/preferredPm.ts Outdated
binoy14 and others added 2 commits April 21, 2026 16:40
The continue statement skipped dir = path.dirname(dir) at the bottom
of the while loop, causing an infinite loop when a workspace's globs
didn't match the target path. Removing it lets the code fall through
to the directory advancement naturally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
chmod doesn't enforce read permissions on Windows, so the file remains
readable and the test returns 'pnpm' instead of falling through to 'npm'.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
mttdnt
mttdnt previously approved these changes Apr 22, 2026
Copy link
Copy Markdown
Contributor

@mttdnt mttdnt left a comment

Choose a reason for hiding this comment

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

LGTM, seems close enough to the npm packages, just a couple nits

import picomatch from 'picomatch'

import {toForwardSlashes} from '../toForwardSlashes.js'
import {type PackageManager} from './packageManagerChoice.js'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

should this be in a separate types file just to avoid the circular import

})
})

describe('workspace root detection', () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In this block maybe add a test for a malformed package.json in detectFromWorkspaceRoot

Address PR review feedback: inline DetectablePackageManager type to
break circular dependency between preferredPm and packageManagerChoice,
and add test covering malformed package.json handling in workspace
walk-up.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@binoy14 binoy14 merged commit 154e361 into main Apr 23, 2026
53 checks passed
@binoy14 binoy14 deleted the replace-preffered-pm branch April 23, 2026 14:31
gu-stav added a commit that referenced this pull request Apr 24, 2026
* fix(cli): replace preferred-pm with local implementation (#984)

* fix(cli): replace preferred-pm with local implementation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): address review feedback for preferredPm

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): detect pnpm-workspace.yaml in parent directory walk-up

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): normalize path separators for workspace glob matching on windows

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): continue workspace walk-up when inner workspace globs don't match

When a nested package.json has a workspaces field whose globs don't
match the target path, continue traversing parent directories instead
of returning null. Also simplify error handling in detectFromNodeModules
to swallow all read errors for best-effort detection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): remove continue that caused infinite loop in workspace walk-up

The continue statement skipped dir = path.dirname(dir) at the bottom
of the while loop, causing an infinite loop when a workspace's globs
didn't match the target path. Removing it lets the code fall through
to the directory advancement naturally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): skip chmod-based permission test on Windows

chmod doesn't enforce read permissions on Windows, so the file remains
readable and the test returns 'pnpm' instead of falling through to 'npm'.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): remove circular import and add malformed package.json test

Address PR review feedback: inline DetectablePackageManager type to
break circular dependency between preferredPm and packageManagerChoice,
and add test covering malformed package.json handling in workspace
walk-up.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* ci: split e2e workflow into PR and scheduled runs (#995)

Move registry-mode e2e tests and Slack failure notifications into a
dedicated hourly scheduled workflow. The PR/push workflow now only runs
in pack mode. Post-release dispatch in release.yml updated to target
the new scheduled workflow with `latest` instead of a specific version.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(cli): replace default namespace imports with named imports (#993)

Use named imports for semver, nock, and typescript to resolve 167
import-x/no-named-as-default-member lint warnings. Also replace one
`as any` with a proper type cast.

CJS modules (json5, dotenv, tar-fs, tar-stream) are left unchanged
since they don't support named ESM imports at runtime.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): default to TypeScript in unattended mode for sanity init (#1004)

* fix(cli): default to TypeScript in unattended mode for sanity init

When running sanity init in unattended mode (non-interactive terminal or
--yes flag), the CLI now defaults to TypeScript when --typescript or
--no-typescript is not explicitly provided, matching the interactive
prompt default.

Uses the existing flagOrDefault/shouldPrompt helpers already used by
initNextJs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update auto-generated changeset for PR #1004

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>

* refactor(cli): extract init command into framework-agnostic initAction (#999)

* refactor(cli): extract init command body into framework-agnostic initAction

Moves ~1100 lines of logic out of the oclif InitCommand into
actions/init/initAction.ts, leaving init.ts as a thin wrapper that
maps oclif flags → InitOptions and catches InitError.

Flow files (initApp, initStudio, initNextJs, scaffoldTemplate) now
accept `options: InitOptions` instead of individual flag params,
and throw InitError directly instead of receiving an `error` callback.

Zero test assertion changes — all 14 init test files pass as-is.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(cli): clean up init telemetry types

- Make `visibility` optional in `CreateOrSelectDatasetStep` (can be
  undefined in unattended mode)
- Remove dead `ConfigureAppProjectStep` interface (no trace.log call
  exists for it)
- Remove unnecessary `as 'private' | 'public'` cast now that the
  type accepts undefined

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR review feedback — restore telemetry, fix env path, add tests

- Restore configureAppProject trace calls dropped during extraction
  (thread `trace` param into promptForAppTemplateSetup)
- Replace `throw new InitError('', 0)` with plain `return` on --env path
  (it's a normal success path, not an error)
- Remove exitCode===0 special-case from command wrapper
- Add ConfigureAppProjectStep to telemetry union type
- Port 4 new test files from #845: flagsToInitOptions, initAction,
  initError, init.command
- Update 2 existing tests: --env path no longer throws

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(cli): close remaining oclif decoupling gaps in init flow files

- bootstrapTemplate: make overwriteFiles/useTypeScript optional
- initHelpers: use InitContext['output'] instead of Output
- initNextJs: throw InitError instead of output.error(), pass options directly
- initStudio: dynamic import for ImportDatasetCommand, use workDir over process.cwd()
- initApp: use workDir over process.cwd()
- scaffoldTemplate: remove as boolean casts and unnecessary try/catch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR review feedback — clean up test names, static import, tighten useTypeScript type

- Rename describe blocks to simpler names (mcpMode resolution, error handling)
- Use static import for InitError instead of dynamic import
- Make useTypeScript a required boolean since flagOrDefault always returns boolean

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: update selectTemplate tests for refactored options signature

Tests from #1004 used the old flat-argument signature; wrap in options
object to match the current selectTemplate interface.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(cli): split initAction.ts into plan/ and project/ modules

Extract helper functions from the 1175-line initAction.ts into
one-function-per-file modules under plan/ and project/ subdirectories.
initAction.ts now contains only the main orchestrator, flag validation,
and auth — down to ~300 lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: forward datasetDefault to app template dataset creation

The refactor from class methods to standalone functions dropped
the implicit this.flags['dataset-default'] read that getOrCreateDataset
relied on. Thread datasetDefault through getProjectDetails →
promptForAppTemplateSetup → getOrCreateDataset so --dataset-default
applies to app templates again.

Adds a regression test exercising the app template + --dataset-default
code path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Binoy Patel <me@binoy.io>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: Matthew Dent <mttdnt@gmail.com>
gu-stav added a commit that referenced this pull request Apr 24, 2026
* fix(cli): replace preferred-pm with local implementation (#984)

* fix(cli): replace preferred-pm with local implementation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): address review feedback for preferredPm

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): detect pnpm-workspace.yaml in parent directory walk-up

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): normalize path separators for workspace glob matching on windows

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): continue workspace walk-up when inner workspace globs don't match

When a nested package.json has a workspaces field whose globs don't
match the target path, continue traversing parent directories instead
of returning null. Also simplify error handling in detectFromNodeModules
to swallow all read errors for best-effort detection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): remove continue that caused infinite loop in workspace walk-up

The continue statement skipped dir = path.dirname(dir) at the bottom
of the while loop, causing an infinite loop when a workspace's globs
didn't match the target path. Removing it lets the code fall through
to the directory advancement naturally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): skip chmod-based permission test on Windows

chmod doesn't enforce read permissions on Windows, so the file remains
readable and the test returns 'pnpm' instead of falling through to 'npm'.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): remove circular import and add malformed package.json test

Address PR review feedback: inline DetectablePackageManager type to
break circular dependency between preferredPm and packageManagerChoice,
and add test covering malformed package.json handling in workspace
walk-up.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* ci: split e2e workflow into PR and scheduled runs (#995)

Move registry-mode e2e tests and Slack failure notifications into a
dedicated hourly scheduled workflow. The PR/push workflow now only runs
in pack mode. Post-release dispatch in release.yml updated to target
the new scheduled workflow with `latest` instead of a specific version.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(cli): replace default namespace imports with named imports (#993)

Use named imports for semver, nock, and typescript to resolve 167
import-x/no-named-as-default-member lint warnings. Also replace one
`as any` with a proper type cast.

CJS modules (json5, dotenv, tar-fs, tar-stream) are left unchanged
since they don't support named ESM imports at runtime.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): default to TypeScript in unattended mode for sanity init (#1004)

* fix(cli): default to TypeScript in unattended mode for sanity init

When running sanity init in unattended mode (non-interactive terminal or
--yes flag), the CLI now defaults to TypeScript when --typescript or
--no-typescript is not explicitly provided, matching the interactive
prompt default.

Uses the existing flagOrDefault/shouldPrompt helpers already used by
initNextJs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update auto-generated changeset for PR #1004

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>

* refactor(cli): extract init command into framework-agnostic initAction (#999)

* refactor(cli): extract init command body into framework-agnostic initAction

Moves ~1100 lines of logic out of the oclif InitCommand into
actions/init/initAction.ts, leaving init.ts as a thin wrapper that
maps oclif flags → InitOptions and catches InitError.

Flow files (initApp, initStudio, initNextJs, scaffoldTemplate) now
accept `options: InitOptions` instead of individual flag params,
and throw InitError directly instead of receiving an `error` callback.

Zero test assertion changes — all 14 init test files pass as-is.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(cli): clean up init telemetry types

- Make `visibility` optional in `CreateOrSelectDatasetStep` (can be
  undefined in unattended mode)
- Remove dead `ConfigureAppProjectStep` interface (no trace.log call
  exists for it)
- Remove unnecessary `as 'private' | 'public'` cast now that the
  type accepts undefined

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR review feedback — restore telemetry, fix env path, add tests

- Restore configureAppProject trace calls dropped during extraction
  (thread `trace` param into promptForAppTemplateSetup)
- Replace `throw new InitError('', 0)` with plain `return` on --env path
  (it's a normal success path, not an error)
- Remove exitCode===0 special-case from command wrapper
- Add ConfigureAppProjectStep to telemetry union type
- Port 4 new test files from #845: flagsToInitOptions, initAction,
  initError, init.command
- Update 2 existing tests: --env path no longer throws

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(cli): close remaining oclif decoupling gaps in init flow files

- bootstrapTemplate: make overwriteFiles/useTypeScript optional
- initHelpers: use InitContext['output'] instead of Output
- initNextJs: throw InitError instead of output.error(), pass options directly
- initStudio: dynamic import for ImportDatasetCommand, use workDir over process.cwd()
- initApp: use workDir over process.cwd()
- scaffoldTemplate: remove as boolean casts and unnecessary try/catch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR review feedback — clean up test names, static import, tighten useTypeScript type

- Rename describe blocks to simpler names (mcpMode resolution, error handling)
- Use static import for InitError instead of dynamic import
- Make useTypeScript a required boolean since flagOrDefault always returns boolean

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: update selectTemplate tests for refactored options signature

Tests from #1004 used the old flat-argument signature; wrap in options
object to match the current selectTemplate interface.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(cli): split initAction.ts into plan/ and project/ modules

Extract helper functions from the 1175-line initAction.ts into
one-function-per-file modules under plan/ and project/ subdirectories.
initAction.ts now contains only the main orchestrator, flag validation,
and auth — down to ~300 lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: forward datasetDefault to app template dataset creation

The refactor from class methods to standalone functions dropped
the implicit this.flags['dataset-default'] read that getOrCreateDataset
relied on. Thread datasetDefault through getProjectDetails →
promptForAppTemplateSetup → getOrCreateDataset so --dataset-default
applies to app templates again.

Adds a regression test exercising the app template + --dataset-default
code path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Binoy Patel <me@binoy.io>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com>
Co-authored-by: Matthew Dent <mttdnt@gmail.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