Skip to content

feat(create-sanity): bundle init logic into single file#759

Draft
rexxars wants to merge 35 commits intobundled-createfrom
feat/bundled-create-sanity
Draft

feat(create-sanity): bundle init logic into single file#759
rexxars wants to merge 35 commits intobundled-createfrom
feat/bundled-create-sanity

Conversation

@rexxars
Copy link
Copy Markdown
Member

@rexxars rexxars commented Mar 23, 2026

Description

Note

Part 3/4 of the ongoing work to make create-sanity faster by bundling the init logic

This mostly completes the work - the remaining part is the telemetry integration and an optional but wanted step at reducing the amount of dependencies we rely on for the init step.

The bundling script has a few hacks that would be nice to get rid of over time, but not the end of the world.

What to review

Testing

@claude
Copy link
Copy Markdown

claude bot commented Mar 23, 2026

Claude finished @mttdnt's task in 7m 12s —— View job


Review

  • Gather context (CLAUDE.md, diff)
  • Review changed files
  • Check changeset
  • Post findings

Issues

1. util.deprecate() breaks instanceof checks (high severity)

The barrel exports in packages/@sanity/cli-core/src/_exports/index.ts wrap the error classes with util.deprecate(), but this breaks instanceof checks across the codebase.

util.deprecate(Cls, msg) returns a wrapper function whose .prototype is a different object from Cls.prototype. When the wrapper is invoked with new, Node.js uses Reflect.construct(Cls, args, wrapper), so the created instance inherits from wrapper.prototype, not Cls.prototype. This means:

const instance = new RealClass()
instance instanceof DeprecatedWrapper // FALSE — prototype chains don't overlap

The real classes are thrown internally by findProjectRoot.ts (L36) and SanityCommand.ts (L170, L181) using the direct imports. But the catch sites in @sanity/cli hold the deprecated wrapper from the barrel:

  • packages/@sanity/cli/src/commands/debug.tsif (!(err instanceof ProjectRootNotFoundError)) throw err → will always re-throw, breaking sanity debug in non-project directories
  • packages/@sanity/cli/src/commands/media/deploy-aspect.ts — same issue
  • packages/@sanity/cli/src/commands/documents/validate.ts — same issue
  • packages/@sanity/cli/src/prompts/promptForProject.tsNonInteractiveError catch in SanityCommand.ts will fail for errors thrown by this file

Fix: Use a plain re-export with a JSDoc deprecation tag instead of wrapping with util.deprecate:

/** @deprecated Import from `@sanity/cli-core/errors` */
export {NonInteractiveError} from '../errors/NonInteractiveError.js'

This preserves the prototype chain for instanceof while signalling the new import path to consumers.


2. Bundle import failure in CI

The bundle stats comment shows:

Import time: ❌ TypeError: Cannot add property upath, object is not extensible

A CJS module in the bundle is trying to mutate its exports at runtime after the rollup commonjs() plugin converted it to ESM (where the namespace object is sealed). The upath module or a dependency using it is the offender. This needs to be resolved before the bundle is usable — consider adding an alias or namedExports entry in the commonjs() plugin config, or replacing the offending dep with an ESM alternative.


3. Swallowed error context in dataset import (initStudio.ts:L149)

} catch {
  output.warn(
    'Sample dataset import failed. Your studio will work fine without it.\n' + ...
  )
}

Using a bare catch discards the actual error. If the sanity binary isn't found after install or the subprocess fails with a non-zero exit for a non-obvious reason, there's no diagnostic. Consider at least:

} catch (err) {
  output.warn(...)
  // log raw error in debug mode or append to message
}

Changeset

The changeset is present (pr-759.md) and the bump type (minor) is appropriate for new exports and the bundled CLI entry. The summary "bundle init logic into single file" is accurate but omits the addition of CLIError/CLIWarning to @sanity/cli-core and the removal of fromCreate. Those are API surface changes worth calling out for library consumers.


Minor observations (no action required)

  • The double-parse in parseArgs.ts (lenient for --help, strict for validation) is slightly wasteful but harmless since printHelp() exits before the strict parse on --help.
  • --env validation moved from oclif's parse callback (exit 2) to flagsToInitOptions (exit 3 via InitError). This is a minor exit-code change for invalid --env values on the oclif path but is intentional given the shared validation.
  • toOclifFlags in flagAdapter.ts silently drops the env parse callback (the flag's oclif-only validation hook). The validation is correctly replicated in flagsToInitOptions, so this is fine.

@rexxars rexxars force-pushed the feat/bundled-create-sanity branch from f51850a to 020c660 Compare March 23, 2026 22:43
@socket-security
Copy link
Copy Markdown

socket-security bot commented Mar 23, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​esbuild@​0.25.12911007393100
Addednpm/​clean-stack@​6.0.010010010081100
Addednpm/​wrap-ansi@​10.0.01001009384100
Addednpm/​rollup-plugin-visualizer@​7.0.19910010089100

View full report

@rexxars rexxars force-pushed the feat/bundled-create-sanity branch from 895b6fa to e6848b3 Compare March 23, 2026 23:05
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 23, 2026

Coverage Delta

File Statements
packages/@sanity/cli-core/src/_exports/index.ts 100.0% (new)
packages/@sanity/cli-core/src/errors/CLIError.ts 72.7% (new)
packages/@sanity/cli-core/src/errors/CLIWarning.ts 100.0% (new)
packages/@sanity/cli-core/src/errors/NonInteractiveError.ts 100.0% (±0%)
packages/@sanity/cli-core/src/errors/ProjectRootNotFoundError.ts 100.0% (±0%)
packages/@sanity/cli-core/src/services/apiClient.ts 100.0% (±0%)
packages/@sanity/cli-core/src/util/getCliTelemetry.ts 100.0% (±0%)
packages/@sanity/cli-core/src/ux/errors.ts 65.1% (new)
packages/@sanity/cli-core/src/ux/output.ts 50.0% (new)
packages/@sanity/cli/src/SanityHelp.ts 60.0% (- 10.4%)
packages/@sanity/cli/src/actions/init/bootstrapTemplate.ts 0.0% (±0%)
packages/@sanity/cli/src/actions/init/env/createOrAppendEnvVars.ts 0.0% (±0%)
packages/@sanity/cli/src/actions/init/flags.ts 100.0% (new)
packages/@sanity/cli/src/actions/init/flagsToInitOptions.ts 100.0% (new)
packages/@sanity/cli/src/actions/init/initAction.ts 94.8% (new)
packages/@sanity/cli/src/actions/init/initApp.ts 96.0% (new)
packages/@sanity/cli/src/actions/init/initError.ts 100.0% (new)
packages/@sanity/cli/src/actions/init/initHelpers.ts 100.0% (new)
packages/@sanity/cli/src/actions/init/initNextJs.ts 86.7% (new)
packages/@sanity/cli/src/actions/init/initStudio.ts 85.1% (new)
packages/@sanity/cli/src/actions/init/scaffoldTemplate.ts 88.0% (new)
packages/@sanity/cli/src/actions/mcp/setupMCP.ts 100.0% (±0%)
packages/@sanity/cli/src/commands/init.ts 100.0% (+ 7.4%)
packages/@sanity/cli/src/prompts/promptForDefaultConfig.ts 100.0% (±0%)
packages/@sanity/cli/src/telemetry/init.telemetry.ts 100.0% (±0%)
packages/@sanity/cli/src/util/flagAdapter.ts 91.7% (new)
packages/create-sanity/rollup.config.ts 0.0% (new)
packages/create-sanity/src/createCommand.ts 0.0% (new)
packages/create-sanity/src/help.ts 0.0% (new)
packages/create-sanity/src/index.ts 0.0% (new)
packages/create-sanity/src/noopTelemetry.ts 0.0% (new)
packages/create-sanity/src/parseArgs.ts 0.0% (new)

Comparing 32 changed files against main @ 56f2c0ad9debf4324b7f736ba2f19a2421f4eb7a

Overall Coverage

Metric Coverage
Statements 81.6% (- 1.4%)
Branches 71.1% (- 1.6%)
Functions 82.0% (- 1.2%)
Lines 82.1% (- 1.3%)

@rexxars rexxars force-pushed the feat/bundled-create-sanity branch 3 times, most recently from 3d2e1e9 to a27419e Compare March 24, 2026 18:27
@binoy14 binoy14 force-pushed the feat/bundled-create-sanity branch from c2b174f to 9efab2a Compare March 30, 2026 20:02
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 30, 2026

Bundle Stats — An error occurred while calculating bundle sizes.

Error details
From https://github.com/sanity-io/cli
 * branch            a2692060a2d77701523f03cd6c4e3c743702dd7b -> FETCH_HEAD
Building baseline...

Attention:
Turborepo now collects completely anonymous telemetry regarding usage.
This information is used to shape the Turborepo roadmap and prioritize features.
You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
https://turborepo.dev/docs/telemetry

Measuring baseline for packages/@sanity/cli
Found 1 exports and 1 bin entries
Measuring internal sizes...
Bundling @sanity/cli...
"fsevents" is imported by "node_modules/.pnpm/rollup@4.59.0/node_modules/rollup/dist/es/shared/node-entry.js", but could not be resolved – treating it as an external dependency.
Bundling bin:sanity...
Benchmarking import @sanity/cli (1/2)...
Benchmarking import bin:sanity (2/2)...
Measuring baseline for packages/@sanity/cli-core
Found 1 exports and 0 bin entries
Measuring internal sizes...
Bundling @sanity/cli-core...
Benchmarking import @sanity/cli-core (1/1)...
From https://github.com/sanity-io/cli
 * branch            2c0b60471cb9f92bf842453b79c8dc109bd4db54 -> FETCH_HEAD
Building head...
Measuring current for packages/@sanity/cli
Found 1 exports and 1 bin entries
Measuring internal sizes...
Bundling @sanity/cli...
"fsevents" is imported by "node_modules/.pnpm/rollup@4.59.0/node_modules/rollup/dist/es/shared/node-entry.js", but could not be resolved – treating it as an external dependency.
Bundling bin:sanity...
Benchmarking import @sanity/cli (1/2)...
Benchmarking import bin:sanity (2/2)...
Measuring current for packages/@sanity/cli-core
Found 1 exports and 0 bin entries
Measuring internal sizes...
Bundling @sanity/cli-core...
Benchmarking import @sanity/cli-core (1/1)...
Found 1 exports and 1 bin entries
Measuring internal sizes...
Bundling @sanity/cli...
"fsevents" is imported by "node_modules/.pnpm/rollup@4.59.0/node_modules/rollup/dist/es/shared/node-entry.js", but could not be resolved – treating it as an external dependency.
Bundling bin:sanity...
Benchmarking import @sanity/cli (1/2)...
Benchmarking import bin:sanity (2/2)...
Reading baseline from stdin...
Comparing against npm @sanity/cli@6.3.0...
Installing @sanity/cli@6.3.0 into temp directory...
Error: Failed to install @sanity/cli@6.3.0 from npm: spawnSync npm ETIMEDOUT

@binoy14 binoy14 force-pushed the feat/bundled-create-sanity branch from 9efab2a to 0ff423a Compare March 30, 2026 20:10
@binoy14 binoy14 force-pushed the feat/bundled-create-sanity branch from 0ff423a to b7a94b2 Compare March 30, 2026 21:55
Copy link
Copy Markdown
Contributor

binoy14 commented Mar 30, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

📦 Bundle Stats — @sanity/cli

Compared against bundled-create (d82d20e5)

@sanity/cli

Metric Value vs bundled-create (d82d20e)
Internal (raw) 2.1 KB -
Internal (gzip) 799 B -
Bundled (raw) 1.54 MB -9.40 MB, -86.0%
Bundled (gzip) 394.7 KB -1.67 MB, -81.2%
Import time 856ms +44ms, +5.4%

bin:sanity

Metric Value vs bundled-create (d82d20e)
Internal (raw) 975 B -
Internal (gzip) 460 B -
Bundled (raw) 9.84 MB -
Bundled (gzip) 1.77 MB -
Import time 1.97s +32ms, +1.6%

🗺️ 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 bundled-create (d82d20e5)

Metric Value vs bundled-create (d82d20e)
Internal (raw) 98.0 KB +4.9 KB, +5.3%
Internal (gzip) 23.3 KB +1.4 KB, +6.4%
Bundled (raw) 21.65 MB +35.6 KB, +0.2%
Bundled (gzip) 3.43 MB +8.5 KB, +0.2%
Import time 808ms +27ms, +3.4%

🗺️ 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 bundled-create (d82d20e5)

Metric Value vs bundled-create (d82d20e)
Internal (raw) 2.37 MB +2.37 MB, +254497.4%
Internal (gzip) 555.3 KB +554.8 KB, +112049.7%
Bundled (raw) 2.37 MB +2.37 MB, +248141.6%
Bundled (gzip) 555.3 KB +554.8 KB, +110520.0%
Import time ❌ TypeError: Cannot add property upath, object is not extensible -
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 1, 2026

Coverage Delta

File Statements
packages/@sanity/cli-core/src/_exports/index.ts 100.0% (new)
packages/@sanity/cli-core/src/errors/CLIError.ts 72.7% (new)
packages/@sanity/cli-core/src/errors/CLIWarning.ts 100.0% (new)
packages/@sanity/cli-core/src/errors/NonInteractiveError.ts 100.0% (±0%)
packages/@sanity/cli-core/src/errors/ProjectRootNotFoundError.ts 100.0% (±0%)
packages/@sanity/cli-core/src/services/apiClient.ts 100.0% (±0%)
packages/@sanity/cli-core/src/telemetry/getCliTelemetry.ts 100.0% (±0%)
packages/@sanity/cli-core/src/ux/errors.ts 65.1% (new)
packages/@sanity/cli-core/src/ux/output.ts 50.0% (new)
packages/@sanity/cli/src/SanityHelp.ts 88.1% (+ 7.7%)
packages/@sanity/cli/src/actions/init/bootstrapTemplate.ts 0.0% (±0%)
packages/@sanity/cli/src/actions/init/env/createOrAppendEnvVars.ts 0.0% (±0%)
packages/@sanity/cli/src/actions/init/flags.ts 100.0% (new)
packages/@sanity/cli/src/actions/init/flagsToInitOptions.ts 100.0% (new)
packages/@sanity/cli/src/actions/init/initAction.ts 94.8% (new)
packages/@sanity/cli/src/actions/init/initApp.ts 96.0% (new)
packages/@sanity/cli/src/actions/init/initError.ts 100.0% (new)
packages/@sanity/cli/src/actions/init/initHelpers.ts 100.0% (new)
packages/@sanity/cli/src/actions/init/initNextJs.ts 86.7% (new)
packages/@sanity/cli/src/actions/init/initStudio.ts 85.1% (new)
packages/@sanity/cli/src/actions/init/scaffoldTemplate.ts 88.0% (new)
packages/@sanity/cli/src/actions/mcp/setupMCP.ts 100.0% (±0%)
packages/@sanity/cli/src/commands/init.ts 100.0% (+ 7.4%)
packages/@sanity/cli/src/prompts/promptForDefaultConfig.ts 100.0% (±0%)
packages/@sanity/cli/src/telemetry/init.telemetry.ts 100.0% (±0%)
packages/@sanity/cli/src/util/flagAdapter.ts 91.7% (new)
packages/create-sanity/rollup.config.ts 0.0% (new)
packages/create-sanity/src/createCommand.ts 0.0% (new)
packages/create-sanity/src/help.ts 0.0% (new)
packages/create-sanity/src/index.ts 0.0% (new)
packages/create-sanity/src/noopTelemetry.ts 0.0% (new)
packages/create-sanity/src/parseArgs.ts 0.0% (new)

Comparing 32 changed files against main @ 7af1594d79003801d6daeadeeb20508d184adb25

Overall Coverage

Metric Coverage
Statements 81.7% (- 1.4%)
Branches 71.4% (- 1.5%)
Functions 82.2% (- 1.1%)
Lines 82.2% (- 1.3%)

@binoy14 binoy14 force-pushed the feat/bundled-create-sanity branch from 009e2d9 to 16a082a Compare April 1, 2026 17:12
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Coverage Delta

File Statements
packages/@sanity/cli-core/src/_exports/index.ts 100.0% (new)
packages/@sanity/cli-core/src/errors/CLIError.ts 72.7% (new)
packages/@sanity/cli-core/src/errors/CLIWarning.ts 100.0% (new)
packages/@sanity/cli-core/src/errors/NonInteractiveError.ts 100.0% (±0%)
packages/@sanity/cli-core/src/errors/ProjectRootNotFoundError.ts 100.0% (±0%)
packages/@sanity/cli-core/src/telemetry/getCliTelemetry.ts 100.0% (±0%)
packages/@sanity/cli-core/src/ux/errors.ts 65.1% (new)
packages/@sanity/cli-core/src/ux/output.ts 50.0% (new)
packages/@sanity/cli/src/SanityHelp.ts 88.1% (+ 7.7%)
packages/@sanity/cli/src/actions/init/bootstrapTemplate.ts 0.0% (±0%)
packages/@sanity/cli/src/actions/init/env/createOrAppendEnvVars.ts 0.0% (±0%)
packages/@sanity/cli/src/actions/init/flags.ts 100.0% (new)
packages/@sanity/cli/src/actions/init/flagsToInitOptions.ts 100.0% (new)
packages/@sanity/cli/src/actions/init/initAction.ts 94.8% (new)
packages/@sanity/cli/src/actions/init/initApp.ts 96.0% (new)
packages/@sanity/cli/src/actions/init/initError.ts 100.0% (new)
packages/@sanity/cli/src/actions/init/initHelpers.ts 100.0% (new)
packages/@sanity/cli/src/actions/init/initNextJs.ts 86.7% (new)
packages/@sanity/cli/src/actions/init/initStudio.ts 85.1% (new)
packages/@sanity/cli/src/actions/init/scaffoldTemplate.ts 88.0% (new)
packages/@sanity/cli/src/actions/mcp/setupMCP.ts 100.0% (±0%)
packages/@sanity/cli/src/commands/init.ts 100.0% (+ 7.4%)
packages/@sanity/cli/src/prompts/promptForDefaultConfig.ts 100.0% (±0%)
packages/@sanity/cli/src/telemetry/init.telemetry.ts 100.0% (±0%)
packages/@sanity/cli/src/util/flagAdapter.ts 91.7% (new)
packages/create-sanity/rollup.config.ts 0.0% (new)
packages/create-sanity/src/createCommand.ts 0.0% (new)
packages/create-sanity/src/help.ts 0.0% (new)
packages/create-sanity/src/index.ts 0.0% (new)
packages/create-sanity/src/noopTelemetry.ts 0.0% (new)
packages/create-sanity/src/parseArgs.ts 0.0% (new)

Comparing 31 changed files against main @ ef5ed4565d33b83d67cd66c6b3c335516e5b1132

Overall Coverage

Metric Coverage
Statements 81.7% (- 1.4%)
Branches 71.3% (- 1.6%)
Functions 82.2% (- 1.1%)
Lines 82.2% (- 1.3%)

rexxars and others added 2 commits April 16, 2026 18:43
…rectly

Replaces the spawn-wrapper approach with a TypeScript entry point that
parses flags using @oclif/core/parser (reusing InitCommand.flags for
exact parity) and calls initAction() directly. Uses no-op telemetry stub.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Switch from esbuild to Rollup for the create-sanity standalone bundle
to enable better tree-shaking of barrel exports. Rollup resolves
@sanity/cli-core source directly via alias plugin so it can
tree-shake unused exports from the barrel.

Plugins: alias, node-resolve, commonjs, json, esbuild (transpile only).
Bundle size is ~13MB (same as esbuild - tree-shaking improvements
will come in subsequent tasks with stub removal).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
rexxars and others added 27 commits April 16, 2026 18:43
Tests run against the built dist/index.js bundle and cover:
- --help output with flag listing
- Package manager detection (npm/pnpm/yarn) in help text
- Hidden flags not shown in help
- -h shorthand
- --help precedence over other flags
- Invalid flag produces clean error (no stack trace)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove unused devDeps: @oclif/core, tsx
- Add debug as devDep (used in rollup.config.ts alias)
- Remove unused InitFlagName type export
- Add knip ignore for @sanity/cli (imported via relative source paths)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace dynamic import of ImportDatasetCommand with spawning the
project's own sanity binary via execa. The dynamic import pulled the
entire oclif command tree into the create-sanity bundle because Rollup
inlines all dynamic imports.

The scaffolded project always has sanity as a dependency, so spawning
its binary for dataset import works in both standalone and oclif contexts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The function is 4 lines - no need for a separate package.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace custom detectPackageManager with the shared
getRunningPackageManager from @sanity/cli-core/package-manager.
Adds bun support for help text (`bun create sanity@latest`).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
create-sanity now handles --help itself via parseArgs, so it never
delegates to `sanity init --help`. The --from-create flag, the
SanityHelp.replaceInitWithCreateCommand rewriting, and the fromCreate
option in InitOptions are all unused. Remove them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
npm requires `--` to forward flags to the create script (e.g.
`npm create sanity@latest -- --template moviedb`). Other package
managers don't need it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move flagsToInitOptions, InitCommandFlags, InitCommandArgs, and the
narrowing helpers out of types.ts into flagsToInitOptions.ts. types.ts
now only contains type definitions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add fs.access check before spawning the sanity binary for dataset
import. Gives a clear error message instead of a raw ENOENT if
dependencies weren't installed correctly.

Also fix misleading vitest config comment.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use execa preferLocal instead of manual .bin path (Windows compat)
- Fix exit:0 being silently discarded in CLIError (0 || undefined bug)
- Remove duplicate --env validation from InitCommand (flagsToInitOptions
  is the canonical location, shared with create-sanity)
- Remove unused overrides parameter from toOclifFlags

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

parseArgs doesn't support oclif features like aliases, option
validation, or exclusive constraints. Add post-parse handling:

- Register flag aliases (e.g. --project-id) as separate parseArgs
  options, then resolve them back to canonical names
- Validate string flags with `options` against allowed values
  (--package-manager, --visibility)
- Check exclusive constraints and error if conflicting flags are passed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move all parseArgs logic (option building, alias resolution, negation
merging, option/exclusive validation, help printing) out of index.ts
into a dedicated parseArgs.ts module.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace ImportDatasetCommand mock with execa mock
- Update assertion to match new call signature (binary name, args, options)
- Fix env validation exit code expectation (now InitError exit:1, not oclif exit:2)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Establish consistent exit code semantics:
- 1: init action runtime failure (auth, missing deps, etc)
- 2: flag parsing/validation error (unknown flag, invalid option value,
  exclusive constraint violation)
- 3: domain-specific flag validation (e.g. --env must start with .env)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add pretest script so `pnpm test` builds the bundle before running
- Wrap execa call in initStudio with try/catch so dataset import
  failures produce a clean InitError instead of dumping ExecaError
- Add explicit default:false to bare, dataset-default, no-git flags
  so parseArgs always populates them, matching InitCommandFlags types

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use helpLabel when defined (e.g. --[no-]git)
- Show --[no-] prefix for allowNo boolean flags
- Wrap long descriptions to terminal width
- Show --help in the options list
- Error when both a flag and its alias are passed (--project + --project-id)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On Windows, environment variables are case-insensitive but process.env
preserves the original casing. When overriding npm_config_user_agent
in tests, the original key (potentially different casing) wasn't being
removed, so the override was ineffective.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rewrite printHelp to match oclif's help formatting:
- Terminal width detection: OCLIF_COLUMNS env > TTY width > 80 fallback,
  clamped to minimum 40
- Use wrap-ansi with {hard: true} for description wrapping
- Dynamic left column width based on widest flag label
- Automatic multiline format (flag on own line, description below) when
  any description wraps to >4 lines at current terminal width
- Wrap first, then indent (matching oclif's ordering)

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

Move mcpMode computation into flagsToInitOptions so the identical logic
in init.ts and create-sanity/index.ts cannot diverge. The function now
takes an `interactive` boolean and derives both `isUnattended` and
`mcpMode` internally.

Add deprecation warnings in parseArgs.ts so that create-sanity users
see feedback when using --reconfigure, --create-project, or --quickstart
(oclif handles this automatically for `sanity init`, but the standalone
path was silent).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove oclif type dependency from Output interface (cli-core/types.ts)
- Replace process.exit() in parseArgs validation with FlagValidationError
- Add explicit return type on warn adapter in create-sanity entry point
- Extract shared INIT_DESCRIPTION constant to deduplicate help text
- Suppress @iarna/toml eval warning in Rollup config

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@mttdnt mttdnt force-pushed the feat/bundled-create-sanity branch from 00daf50 to bc02ced Compare April 16, 2026 23: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.

2 participants