Astilba Create: Released documentation for the deterministic create-astilba CLI and its four supported recipe v2 contracts. # Create > Generate a verified TypeScript project from one maintained Astilba recipe. Astilba Create generates a complete TypeScript project from a small catalog of maintained recipes. It writes the application starting point, pinned toolchain, verification scripts, GitHub workflows, repository guidance, and an ownership manifest in one deterministic operation. `create-astilba` 0.3.0 is available on npm. Its supported public interface is the command-line tool: ```sh npm create astilba@latest ``` ## Choose your next step [Section titled “Choose your next step”](#choose-your-next-step) | Goal | Start here | | ------------------------------------------------ | ------------------------------------------------------------------ | | Decide whether Create fits | [Overview](/docs/create/overview/) | | Assemble a paste-ready command | [Configure a project](https://astilba.com/create/new/) | | Generate and verify a project | [Create your first project](/docs/create/quickstart/) | | Compare the four maintained starting points | [Choose a recipe](/docs/create/recipes/) | | Run Create in CI or an agent workflow | [Automate project creation](/docs/create/automation/) | | Understand its failure and filesystem boundaries | [Deterministic generation](/docs/create/deterministic-generation/) | | Interpret `.astilba/project.json` | [Project manifest](/docs/create/project-manifest/) | | Look up every option and default | [CLI reference](/docs/create/cli-reference/) | | Check the exact supported release surface | [Release and support](/docs/create/release-and-support/) | If this is your first visit, use the configurator or quickstart. If you are integrating Create into automation, read the automation guide and deterministic-generation model together. # Overview > Understand what Astilba Create generates, what it guarantees, and where its responsibility ends. Astilba Create turns a named recipe and a small set of project metadata into an independent TypeScript repository. Use it when you want a maintained starting point with build, test, lint, dependency, security, and repository conventions already connected. The current release is `create-astilba` 0.3.0. It supports four recipe v2 contracts: * `typescript-library` * `react-vite-spa` * `astro-static-site` * `cloudflare-worker-service` Run the interactive command to begin: ```sh npm create astilba@latest ``` Or [configure a paste-ready command](https://astilba.com/create/new/) from the same released catalog. ## Decide whether Create fits [Section titled “Decide whether Create fits”](#decide-whether-create-fits) | You want to… | Fit | | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | | Start one of the four supported TypeScript project kinds | This is the intended use case. | | Reproduce a project from explicit inputs in automation | Use non-interactive flags with `--json` and, when appropriate, `--dry-run`. | | Begin with exact dependencies and verification workflows | Every recipe pins its toolchain, packages, and GitHub Actions. | | Create a repository with no template ancestry | Git initialization creates a fresh `main` branch and does not copy Astilba’s commit history. | | Add arbitrary framework, database, authentication, or deployment combinations | Not yet. Create supports complete named recipes, not an unverified feature matrix. | | Merge generated files into an existing directory | Not supported. The destination must not already exist. | | Update or repair an existing generated project | Not in 0.3.0. `doctor` and migration tooling are future work. | | Import a programmatic generator API | Not supported. The npm package exports its CLI and package metadata, not its internal TypeScript modules. | ## Start from a complete recipe [Section titled “Start from a complete recipe”](#start-from-a-complete-recipe) Each recipe supplies project code and the engineering foundation around it: * exact Node.js, pnpm, dependency, and GitHub Action versions; * strict TypeScript; * Ultracite with Oxfmt and Oxlint; * Vitest and Knip; * a frozen-lockfile verification matrix; * Actionlint, Zizmor, OSV-Scanner, PR-title, CodeQL, and dependency-review workflows; * Renovate with a three-day minimum release age; * issue forms, pull-request, security, contribution, and repository-setting guidance; and * `.astilba/project.json`, which records recipe and file ownership evidence. The generated workflow files do not configure GitHub repository settings for you. After you publish the repository, follow its generated `docs/repository-settings.md` checklist. ## Understand the guarantees and costs [Section titled “Understand the guarantees and costs”](#understand-the-guarantees-and-costs) | Guarantee | Cost or boundary | | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | The same Create version, recipe, and metadata produce the same planned project files. | Change the generator version, recipe version, or inputs and the plan may change. Fresh `.git` metadata is not part of the byte-for-byte file contract. | | Generation does not merge through collisions. | The destination must be absent; generated output paths must be unique and portable. | | A partial staging tree is never presented as a complete project. | Create stages beside the destination and publishes only after file, link, mode, and optional Git initialization succeed. | | Ambient Git configuration cannot inject hooks or templates. | Git initialization runs with isolated global, system, template, and `GIT_*` settings. | | Generated application code becomes yours immediately. | Create records seeded files but does not claim permission to overwrite them later. | | Recipe maintenance covers the complete project contract. | The catalog stays deliberately small; optional capabilities are added only with their development and verification paths. | Dependency installation happens after the complete project tree is published. If `pnpm install` fails, Create preserves the generated project and tells you to resolve the package-manager error and run the install again. ## Choose a path [Section titled “Choose a path”](#choose-a-path) | You want to… | Continue with | | -------------------------------------------- | ------------------------------------------------------------------ | | Assemble a command from the released catalog | [Configure a project](https://astilba.com/create/new/) | | Generate a project interactively | [Create your first project](/docs/create/quickstart/) | | Select the right maintained starting point | [Choose a recipe](/docs/create/recipes/) | | Run without prompts | [Automate project creation](/docs/create/automation/) | | Audit filesystem and failure behavior | [Deterministic generation](/docs/create/deterministic-generation/) | | Understand future migration evidence | [Project manifest](/docs/create/project-manifest/) | | Confirm what 0.3.0 supports | [Release and support](/docs/create/release-and-support/) | # Create your first project > Generate, verify, and prepare a new Astilba project for GitHub. Create a project interactively, run its complete local verification command, then apply the generated repository settings after you publish it. ## Check the prerequisites [Section titled “Check the prerequisites”](#check-the-prerequisites) Use Node.js 22.18.0 or later. Generated projects pin pnpm 11.10.0. Create initializes Git on a fresh `main` branch by default, so use a Git version that supports `git init --initial-branch` or choose `--no-git`. Dependency installation uses an installed `pnpm` only when its version is exactly 11.10.0. Otherwise, Create asks Corepack for `pnpm@11.10.0`. ## Run the questionnaire [Section titled “Run the questionnaire”](#run-the-questionnaire) From the parent directory where the new project should live, run: ```sh npm create astilba@latest ``` The questionnaire asks for: 1. one supported recipe; 2. a portable relative destination such as `my-project`; 3. a short project description; 4. the GitHub owner; 5. whether to customize the inferred project, package, and repository names; 6. whether to initialize Git; 7. whether to install dependencies; and 8. whether to create the project, change a detail, or cancel. The directory name supplies the default project name, package name, and GitHub repository name. Keep the customization prompt at **no** to accept all three together, or choose **yes** to edit them individually. Before writing, Create validates every resolved value and shows the complete project summary. You can change one detail and return to the review without restarting the questionnaire. `--yes` skips this final review action only; it does not answer missing questions. The interactive flow defaults both Git initialization and dependency installation to **yes**. Create reports planning, generation, and optional dependency installation as separate phases. Its completion message states whether dependencies were installed and gives the next verification step. ## Finish and verify the generated project [Section titled “Finish and verify the generated project”](#finish-and-verify-the-generated-project) If Create installed dependencies, enter the new directory and run its complete verification script: ```sh cd my-project pnpm verify ``` If you declined dependency installation or installation failed, install the generated project’s pinned dependencies first: ```sh cd my-project pnpm install --frozen-lockfile pnpm verify ``` Every recipe checks formatting and lint rules, TypeScript, tests, unused files and dependencies, and its production build. The TypeScript library recipe also validates the packed package with Publint and Are the Types Wrong. ## Review what Create owns [Section titled “Review what Create owns”](#review-what-create-owns) Open `.astilba/project.json` before your first commit. It records: * the generator and recipe versions; * managed files and their SHA-256 digests; * seeded application files that become user-owned immediately; * individually owned `package.json` fields; and * the `CLAUDE.md` symbolic link and its target. The manifest is evidence for future fail-closed migrations. Create 0.3.0 does not include an updater, and the manifest does not prevent you from changing any generated file. ## Make the first commit [Section titled “Make the first commit”](#make-the-first-commit) When Git initialization is enabled, Create produces a fresh repository on `main` without an initial commit. Review the tree, then commit it yourself: ```sh git status git add . git commit -m "chore: establish project" ``` The repository has no shared commit ancestry with Astilba Create. ## Configure GitHub after publishing [Section titled “Configure GitHub after publishing”](#configure-github-after-publishing) Push the repository to the owner and repository name you supplied, then follow `docs/repository-settings.md`. Generated files cannot turn on branch protection, merge settings, private-vulnerability reporting, a Renovate installation, or an npm publishing environment. In particular: * allow squash merging and enable automatic merging; * configure the required verification checks on `main`; * install or grant repository access to Renovate; * keep the default workflow token read-only; and * for public packages, design and configure the publication workflow, protected environment, and npm trusted publishing. Create does not generate that release path. CodeQL and dependency review are designed for public repositories. Their generated workflows skip the relevant jobs when the repository is private. ## Continue from the generated README [Section titled “Continue from the generated README”](#continue-from-the-generated-readme) The new README contains recipe-specific development commands. Use [Choose a recipe](/docs/create/recipes/) to compare the initial files and verification behavior, or [CLI reference](/docs/create/cli-reference/) when you need to rerun creation with explicit metadata. # Choose a recipe > Compare the four versioned project recipes supported by Astilba Create 0.3.0. Choose the recipe whose complete runtime and verification contract matches your project. Create does not expose its internal profiles as a mix-and-match feature selector. All four recipes are version `2` in the project manifest. ## Compare the recipes [Section titled “Compare the recipes”](#compare-the-recipes) | Recipe | Starting point | Package posture | Recipe-specific verification | | --------------------------- | ----------------------------------------------- | ------------------- | -------------------------------------------------------------------------------------------------------------------- | | `typescript-library` | ESM TypeScript package with declarations | Public package | TypeScript build, tests, Publint, and Are the Types Wrong against the packed package | | `react-vite-spa` | Client-rendered React application built by Vite | Private application | TypeScript, Vitest, and a Vite production build | | `astro-static-site` | Statically rendered Astro site | Private application | Astro type checking, Vitest smoke test, and a static production build | | `cloudflare-worker-service` | TypeScript service for Cloudflare Workers | Private service | Generated Workers types, worker-pool tests, three TypeScript configurations, and a dry-run Wrangler deployment build | ## Shared foundation [Section titled “Shared foundation”](#shared-foundation) Every recipe includes: ```text .astilba/project.json .github/ISSUE_TEMPLATE/ .github/workflows/ .editorconfig .gitattributes .gitignore .node-version .npmrc AGENTS.md CLAUDE.md -> AGENTS.md CONTRIBUTING.md LICENSE README.md SECURITY.md docs/repository-settings.md knip.json oxfmt.config.ts oxlint.config.ts package.json pnpm-lock.yaml pnpm-workspace.yaml renovate.json tsconfig.json vitest.config.ts ``` The dependency, toolchain, action, and container references are exact pins. Renovate holds new releases for at least three days and uses conservative automerge rules. The verification workflow runs with a frozen lockfile on Node.js 22.18.0 and 24.18.0 in Create 0.3.0. ## TypeScript library [Section titled “TypeScript library”](#typescript-library) Choose `typescript-library` for a publishable ESM package: ```sh npm create astilba@latest -- my-library \ --recipe typescript-library \ --description "A useful TypeScript library." \ --github-owner example \ --package-name @example/my-library ``` The recipe adds: ```text src/index.ts tests/index.test.ts tsconfig.build.json ``` Its package export includes ESM JavaScript and declarations. `pnpm verify` builds the package and checks the packed public surface with Publint and Are the Types Wrong. ## React and Vite application [Section titled “React and Vite application”](#react-and-vite-application) Choose `react-vite-spa` for a client-rendered single-page application: ```sh npm create astilba@latest -- my-app \ --recipe react-vite-spa \ --description "A useful web application." \ --github-owner example ``` The recipe adds: ```text index.html src/app.tsx src/main.tsx src/project.json tests/project.test.ts vite.config.ts ``` The package is private. It supplies development, build, preview, test, and verification scripts, but no hosting provider or deployment automation. ## Astro static site [Section titled “Astro static site”](#astro-static-site) Choose `astro-static-site` for a statically rendered Astro site: ```sh npm create astilba@latest -- my-site \ --recipe astro-static-site \ --description "A useful static site." \ --github-owner example ``` The recipe adds: ```text astro.config.mjs src/pages/index.astro tests/smoke.test.ts ``` The package is private. `pnpm build` creates the static site, but the recipe does not choose or configure a hosting provider. ## Cloudflare Worker service [Section titled “Cloudflare Worker service”](#cloudflare-worker-service) Choose `cloudflare-worker-service` for a TypeScript service that runs on Cloudflare Workers: ```sh npm create astilba@latest -- my-worker \ --recipe cloudflare-worker-service \ --description "A useful Worker service." \ --github-owner example ``` The Worker project name must contain at most 63 lowercase letters, digits, or hyphens and cannot start or end with a hyphen. Create applies this stricter recipe rule to an explicit `--project-name` and to the name inferred from the destination. The recipe adds: ```text src/index.ts tests/index.test.ts tests/tsconfig.json tsconfig.config.json vitest.config.ts wrangler.jsonc ``` The package is private. Its build generates binding types and runs `wrangler deploy --dry-run`; only `pnpm deploy` performs a deployment. Review `wrangler.jsonc` and authenticate Wrangler before using that command. ## Know what is not a recipe option [Section titled “Know what is not a recipe option”](#know-what-is-not-a-recipe-option) Create 0.3.0 does not offer switches for Panda CSS, browser testing, monitoring, authentication, databases, framework deployment, or other optional systems. It also does not advertise arbitrary combinations of the internal project profiles. Add project-specific capabilities after generation and verify them in your repository. A capability becomes part of Create only when Astilba can maintain its complete development, CI, deployment, and verification contract. # Automate project creation > Run Astilba Create without prompts and consume its versioned JSON result safely. Supply every required input explicitly, request JSON output, and use the process exit code as the success boundary. ## Run without prompts [Section titled “Run without prompts”](#run-without-prompts) A non-interactive run requires a destination, recipe, description, and GitHub owner: ```sh npx --yes create-astilba@latest my-project \ --recipe react-vite-spa \ --description "A useful application." \ --github-owner example \ --package-name @example/my-project \ --no-install \ --json ``` `--json` never prompts, even when the terminal is interactive. It does not make missing inputs optional. Use the direct `npx` form whenever a machine will parse standard output. npm’s `create` wrapper writes its own lifecycle lines around the command, while `create-astilba` itself keeps standard output to the single JSON result. The destination name supplies these defaults: | Field | Default | | ----------------------- | -------------------------------- | | `--project-name` | normalized destination basename | | `--package-name` | normalized destination basename | | `--github-repo` | normalized destination basename | | Git initialization | enabled | | Dependency installation | disabled in non-interactive mode | Use `--install` when the workflow should run `pnpm install` after generation. Use `--no-git` when Git is intentionally unavailable. ## Plan without writing [Section titled “Plan without writing”](#plan-without-writing) Add `--dry-run` to resolve inputs and construct the complete generation plan without creating the destination, initializing Git, or installing dependencies: ```sh npx --yes create-astilba@latest my-project \ --recipe astro-static-site \ --description "A useful static site." \ --github-owner example \ --dry-run \ --json ``` The result uses `"action":"plan"` and `"installed":false`. A successful write uses `"action":"create"`. The JSON plan lists every regular-file and symbolic-link path in deterministic order. It does not return file contents or modes. A dry run validates metadata, the portable destination argument, recipe rules, generated paths, collisions, and link targets. It does not inspect the destination filesystem or exercise parent-directory preparation, Git, symbolic-link creation, or dependency installation. Run actual creation in the target environment to check that the destination is absent, any existing parent ancestry contains no symbolic links, missing parent directories can be created, and those external operations are available. ## Consume JSON output [Section titled “Consume JSON output”](#consume-json-output) Successful creation writes one JSON object to standard output: ```json { "action": "create", "destination": "/absolute/path/to/my-project", "files": [".astilba/project.json", ".editorconfig", "package.json"], "installed": false, "ok": true, "recipe": "react-vite-spa", "schemaVersion": 1, "symlinks": ["CLAUDE.md"] } ``` The actual `files` array contains every planned regular file in deterministic path order. The shortened array above only illustrates the response shape. On an ordinary error with `--json`, Create writes this shape to standard output and exits with status `1`: ```json { "destination": "/absolute/path/to/my-project", "error": { "code": "INSTALLATION_FAILED", "message": "The actionable error message.", "phase": "installation" }, "ok": false, "projectCreated": true, "schemaVersion": 1 } ``` `destination` is present when Create resolved one. `error.code` is one of `CANCELLED`, `GENERATION_FAILED`, `INSTALLATION_FAILED`, `INVALID_INPUT`, `PACKAGE_MANAGER_UNAVAILABLE`, or `UNEXPECTED_ERROR`. `CANCELLED` is the status-130 exception; the other codes use status `1`. `error.phase` is `input`, `generation`, `installation`, or `unknown`. Without `--json`, ordinary errors go to standard error with an `Error:` prefix. Cancellation and process interruption exit with status `130` in every output mode. Always check both `schemaVersion` and `ok` before reading other fields. Branch on `error.code`, `error.phase`, and `projectCreated`; treat `error.message` as human-readable context. ## Discover the released recipes [Section titled “Discover the released recipes”](#discover-the-released-recipes) Read the versioned recipe catalog when automation needs to offer or validate the released choices: ```sh npx --yes create-astilba@latest --catalog --json ``` This command does not prompt or write project files. Check `schemaVersion`, `generator.version`, and `ok` before reading `recipes`. Each recipe entry exposes its stable ID, recipe version, label, and description. The npm package includes the strict catalog schema at `schemas/catalog-v1.json`. Use the catalog as discovery metadata, not as a dependency or generated-file manifest. It deliberately excludes internal profiles, package pins, and implementation details. ## Distinguish generation from installation [Section titled “Distinguish generation from installation”](#distinguish-generation-from-installation) Create publishes the complete project tree before it runs dependency installation. This gives automation two distinct failure boundaries: 1. If generation fails, Create does not present the destination as complete. A rare failed publication rollback preserves `.astilba-create-incomplete`. 2. If installation fails, the project remains at the destination and the command exits with an error explaining how to rerun `pnpm install`. Choose `--no-install` when your workflow wants to inspect, archive, or enter the generated tree before resolving dependencies. It is also the default outside the interactive questionnaire. CLI output schema version 1 deliberately remains unchanged in Create 0.3.0. It reports whether the project was created, but it does not expose the internal distinction between an unchanged destination and an incomplete publication: both have `projectCreated: false`. When automatic recovery must be unambiguous, use `--no-install`, branch on the structured error fields, and never accept a destination that contains `.astilba-create-incomplete`. ## Pin when reproducibility requires it [Section titled “Pin when reproducibility requires it”](#pin-when-reproducibility-requires-it) `@latest` selects the npm release current at execution time. If an automation contract must stay on one generator release, invoke that exact package version: ```sh npx --yes create-astilba@0.3.0 my-project \ --recipe typescript-library \ --description "A useful library." \ --github-owner example \ --no-install \ --json ``` The generated manifest records the selected generator and recipe versions. Commit it with the project. ## Inspect catalog, help, and version as JSON [Section titled “Inspect catalog, help, and version as JSON”](#inspect-catalog-help-and-version-as-json) The informational commands support machine-readable output: ```sh npx --yes create-astilba@latest --catalog --json npx --yes create-astilba@latest --help --json npx --yes create-astilba@latest --version --json ``` Catalog returns `command`, `generator`, `ok`, `recipes`, and its own `schemaVersion`. Help returns `command`, `ok`, `schemaVersion`, and `usage`. Version returns `command`, `ok`, `schemaVersion`, and `version`. See [CLI reference](/docs/create/cli-reference/) for every option and validation rule, and [Deterministic generation](/docs/create/deterministic-generation/) for the filesystem transaction boundary. # Deterministic generation > Understand Astilba Create's planning, validation, staging, publication, and failure boundaries. Create plans and validates the complete project before it publishes a destination. It rejects ambiguous merges and portable-path hazards instead of guessing how to resolve them. ## Follow the generation sequence [Section titled “Follow the generation sequence”](#follow-the-generation-sequence) For one generator version, recipe version, and validated metadata, Create follows this sequence: 1. resolve exactly one named recipe and its required internal profiles; 2. validate project metadata and every output declaration; 3. reject file, directory, case-insensitive, and symbolic-link collisions; 4. construct the deterministic manifest and sorted project plan; 5. write files and links into a temporary sibling directory; 6. apply file and directory modes; 7. optionally initialize an isolated Git repository; 8. publish the complete top-level tree into a new destination; and 9. optionally install dependencies in the published project. `--dry-run` stops after planning and returns the file and link paths without writing anything. It validates the plan, not the target filesystem or external operations. ## Know what deterministic means [Section titled “Know what deterministic means”](#know-what-deterministic-means) The same Create version, recipe, and metadata produce the same planned regular-file bytes, path order, file modes, and symbolic-link targets. The manifest digests are therefore stable for the same plan. Fresh `.git` internals and an installed `node_modules` tree are outside that byte-for-byte contract. Git still receives a stable structural guarantee: Create starts a new repository on `main`, without template history or an initial commit. Recipe identifiers and recipe versions are permanent contract coordinates. Updating a recipe requires a new version; it does not silently redefine the recorded v2 output. ## Reject unsafe destinations [Section titled “Reject unsafe destinations”](#reject-unsafe-destinations) The command-line destination must be a normalized portable relative path. Create rejects: * absolute POSIX or Windows paths; * `.` or `..` path segments and traversal; * backslashes; * `.git` segments; * Windows device names such as `CON` or `NUL`; * trailing spaces or periods; * control or formatting characters; * non-ASCII path segments; and * characters that are not portable to Windows. During actual creation, the resolved destination must not already exist. Create makes missing parent directories one segment at a time and rejects symbolic links or non-directory entries in the existing ancestry. Dry runs skip this filesystem preparation and its checks. These rules are stricter than the host filesystem because a generated repository should remain portable when checked out elsewhere. ## Reject ambiguous output plans [Section titled “Reject ambiguous output plans”](#reject-ambiguous-output-plans) Before writing, Create rejects: * two declarations for the same path; * paths that differ only by letter case; * a regular file used as another output’s parent directory; * a profile dependency cycle or conflict; * a symbolic link that collides with another output; * a symbolic link whose target is not a planned regular file; and * any recipe output beneath the reserved `.astilba` manifest directory. Create does not have a generic “merge on collision” rule. Each named recipe must resolve to one internally consistent project. ## Publish only a complete tree [Section titled “Publish only a complete tree”](#publish-only-a-complete-tree) Create stages output in a temporary directory beside the destination. File writing, link creation, permission changes, and optional Git initialization happen there. Publication creates the destination with an incomplete marker, moves the staged top-level entries, then removes the marker only after every move succeeds. If a move fails, Create attempts to roll all moved entries back: * when rollback succeeds, it removes the marker and tries to remove the now-empty destination; * when any rollback also fails, it preserves the incomplete marker so the directory cannot be mistaken for a successful project. Create never recursively deletes a destination that another process may have changed. Cleanup failures cannot replace the publication result: an incomplete destination remains reported as incomplete, while a failure to remove an already empty staging directory does not turn a complete project into a failed generation. Human recovery output names the relevant outcome. If the incomplete marker remains, inspect the destination and either recover or remove it before running Create again. On Windows, `CLAUDE.md` requires symbolic-link permission. Enable Developer Mode or use an elevated shell. If the link cannot be created, staging fails before publication. ## Isolate Git initialization [Section titled “Isolate Git initialization”](#isolate-git-initialization) Git initialization removes ambient `GIT_*` variables and disables global and system configuration. It also supplies an empty temporary template directory. This prevents a developer’s hooks, templates, aliases, or global defaults from modifying the generated repository. Create verifies that `.git` is a real directory and that `HEAD` points to `refs/heads/main`. ## Treat installation as a separate phase [Section titled “Treat installation as a separate phase”](#treat-installation-as-a-separate-phase) Dependency installation is deliberately outside atomic generation: * Create uses an installed `pnpm` only when its version exactly matches the generated project’s pinned version. * Otherwise, it asks Corepack for that exact pnpm version before installing. * A package-manager failure leaves the generated project intact and reports that installation must be retried. This boundary avoids deleting a valid project because a registry, network, lifecycle script, or local package-manager configuration failed. ## Do not use Create as an updater [Section titled “Do not use Create as an updater”](#do-not-use-create-as-an-updater) Create 0.3.0 only creates a destination that does not exist. It does not regenerate over an existing repository, merge a newer recipe, run `doctor`, or update a default branch. The [project manifest](/docs/create/project-manifest/) records enough ownership evidence for future explicit migrations, but no migration command is shipped in this release. # Project manifest > Interpret the version, recipe, digest, field, and symbolic-link evidence in .astilba/project.json. Every generated project includes `.astilba/project.json`. Commit it with the repository: it records which Create and recipe versions produced the tree and what kind of ownership each generated output had at creation time. The manifest conforms to [the public Create v1 JSON Schema](https://astilba.com/schemas/create/v1.json). ## Read the top-level contract [Section titled “Read the top-level contract”](#read-the-top-level-contract) An abridged manifest looks like this: ```jsonc { "$schema": "https://astilba.com/schemas/create/v1.json", "features": [], "generator": { "name": "create-astilba", "version": "0.3.0" }, "ownership": { "managed": [ { "path": ".editorconfig", "sha256": "a 64-character lowercase hexadecimal digest" } ], "metadata": ".astilba/project.json", "seeded": ["README.md", "src/index.ts", "tests/index.test.ts"], "structured": [ { "fields": [ { "pointer": "/scripts/build", "sha256": "a 64-character lowercase hexadecimal digest" } ], "path": "package.json" } ], "symlinks": [ { "path": "CLAUDE.md", "target": "AGENTS.md" } ] }, "recipe": { "id": "typescript-library", "version": 2 }, "schemaVersion": 1 } ``` The example shortens the ownership arrays and replaces real digests with descriptions. Generated manifests contain the complete arrays and real SHA-256 values. ## Distinguish the versions [Section titled “Distinguish the versions”](#distinguish-the-versions) | Field | Meaning | | ------------------- | ------------------------------------------------------------------------------------ | | `schemaVersion` | Structure of the manifest itself. Version 1 is documented by the public schema. | | `generator.version` | Exact `create-astilba` package version that produced the project. | | `recipe.id` | Permanent identifier for the selected maintained recipe. | | `recipe.version` | Version of that recipe’s output contract. All recipes in Create 0.3.0 use version 2. | | `features` | Reserved feature list. It is empty in the current schema and release. | A new generator release does not necessarily imply a new manifest schema or recipe version. Each coordinate changes only when its own contract changes. ## Interpret ownership [Section titled “Interpret ownership”](#interpret-ownership) ### Managed files [Section titled “Managed files”](#managed-files) `ownership.managed` records each generator-owned configuration file with the SHA-256 digest of its UTF-8 content at generation time. The digest is evidence, not enforcement. You may edit a managed file. Future migration tooling would have to compare the recorded digest and fail closed when your content no longer matches an expected starting state. ### Metadata [Section titled “Metadata”](#metadata) `ownership.metadata` identifies `.astilba/project.json` itself. The manifest does not hash itself because that would create a recursive digest. ### Seeded files [Section titled “Seeded files”](#seeded-files) `ownership.seeded` lists application and documentation starting points that become user-owned immediately. Examples include `README.md`, source files, and tests. Future generator tooling must not assume that these files still resemble their generated form. ### Structured fields [Section titled “Structured fields”](#structured-fields) `ownership.structured` divides a JSON file into independently tracked fields. In 0.3.0, that file is `package.json`. Each `pointer` is an RFC 6901 JSON Pointer. Its digest covers the JSON serialization of that field’s original value, not the bytes of the entire file. This allows a future migration to reason about one script or dependency without claiming ownership of unrelated package metadata. ### Symbolic links [Section titled “Symbolic links”](#symbolic-links) `ownership.symlinks` records the link path and its planned target. Generated projects make `AGENTS.md` canonical and link `CLAUDE.md` to it. The target is recorded as a portable project-relative path. On Windows, creating the link requires Developer Mode or elevated privileges. ## Use the manifest today [Section titled “Use the manifest today”](#use-the-manifest-today) Create 0.3.0 does not include an update, migration, or `doctor` command. Today the manifest helps you: * identify the exact generator and recipe contract; * audit which files began as managed configuration or user-owned seeds; * verify original managed content against its digest; and * preserve future migration evidence when you commit the generated project. Do not interpret the manifest as permission for a future tool to overwrite changed files. The intended update model is explicit, authored, and fail-closed. # CLI reference > Look up Astilba Create commands, inputs, defaults, validation rules, output, and exit behavior. The supported public interface of `create-astilba` 0.3.0 is its command-line tool. ## Usage [Section titled “Usage”](#usage) ```text npm create astilba@latest npm create astilba@latest -- --recipe [options] npm create astilba@latest -- --catalog npx --yes create-astilba@latest --catalog --json ``` Use the first form for the interactive questionnaire. In the other npm forms, `--` tells npm to forward the remaining arguments to Create. Use the direct `npx` form whenever standard output must contain only the JSON object; npm’s `create` wrapper adds its own lifecycle lines. ## Recipes [Section titled “Recipes”](#recipes) | Identifier | Starting point | | --------------------------- | ------------------------------------------ | | `typescript-library` | ESM TypeScript library | | `react-vite-spa` | Client-rendered React and Vite application | | `astro-static-site` | Statically rendered Astro site | | `cloudflare-worker-service` | Cloudflare Worker service | Recipe identifiers are stable. See [Choose a recipe](/docs/create/recipes/) for generated files and verification behavior. ## Options [Section titled “Options”](#options) | Option | Short | Meaning | | ---------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `--catalog` | — | List the released recipes without starting the questionnaire or writing project files. Add `--json` for versioned machine-readable output. | | `--description ` | — | Project description. Required outside the interactive questionnaire. | | `--github-owner ` | — | GitHub account that will own the repository. Required outside the interactive questionnaire. | | `--github-repo ` | — | GitHub repository name. Defaults to the normalized destination basename. | | `--package-name ` | — | npm package name. Defaults to the normalized destination basename. | | `--project-name ` | — | Project name. Defaults to the normalized destination basename. | | `--recipe ` | `-r` | Stable recipe identifier. Required outside the interactive questionnaire. | | `--git` / `--no-git` | — | Enable or disable fresh Git initialization. Defaults to enabled. | | `--install` / `--no-install` | — | Enable or disable dependency installation. Questionnaire default: enabled. Prompt-free default: disabled. | | `--dry-run` | — | Validate inputs and construct the generation plan without writing, initializing Git, or installing. JSON output returns the planned file and link paths, not their contents or modes. | | `--json` | — | Emit versioned machine-readable output. This mode never prompts. Invoke `create-astilba` directly through `npx` when a machine will parse standard output. | | `--yes` | `-y` | Skip the final interactive confirmation. It does not supply missing required inputs. | | `--version` | `-v` | Print the installed Create version. | | `--help` | `-h` | Print usage, recipes, and options. | Provide at most one destination directory. ## Prompt-free requirements [Section titled “Prompt-free requirements”](#prompt-free-requirements) Create skips the questionnaire when standard input or output is not a terminal, when you pass `--json`, or when you provide every required input explicitly. A prompt-free run requires: * one destination; * `--recipe`; * `--description`; and * `--github-owner`. Create infers project, package, and repository names from the destination when you omit their explicit options. The inference lowercases the destination basename, replaces runs of non-alphanumeric characters with `-`, trims leading and trailing hyphens, and limits the result to 63 characters. The result must include at least one letter or digit. ## Metadata validation [Section titled “Metadata validation”](#metadata-validation) | Input | Validation | | ----------------- | ---------------------------------------------------------------------------------------------------------------------- | | Description | 1–280 characters; no leading or trailing whitespace; no control or formatting characters | | GitHub owner | 1–39 characters; letters, digits, and internal hyphens; must begin and end with a letter or digit | | GitHub repository | 1–100 characters; letters, digits, dots, underscores, and hyphens; must begin and end with a letter or digit | | Package name | 1–214 characters; supported lowercase npm package name, optionally scoped | | Project name | 1–100 characters; lowercase letters, digits, dots, underscores, and hyphens; must begin and end with a letter or digit | Create validates explicit and inferred values before planning output. The `cloudflare-worker-service` recipe further restricts the project name to at most 63 lowercase letters, digits, or hyphens, with no leading or trailing hyphen. This applies whether the value comes from `--project-name` or the destination basename. ## Destination validation [Section titled “Destination validation”](#destination-validation) The destination argument must be a normalized portable relative path. It cannot contain traversal, backslashes, `.git`, Windows device names, control or formatting characters, non-ASCII path segments, trailing spaces or periods, or Windows-forbidden filename characters. For actual creation, the destination must not exist. Create makes missing parent directories, while rejecting symbolic links or non-directory entries in the existing ancestry. `--dry-run` validates the destination argument and generated output plan, but it does not inspect the destination filesystem. It therefore does not prove that the destination is absent, existing parent ancestry is safe, missing parents can be created, Git or link creation will work, or dependency installation is available. See [Deterministic generation](/docs/create/deterministic-generation/) for output collision checks, staging, rollback, and the incomplete marker. ## Human-readable output [Section titled “Human-readable output”](#human-readable-output) Interactive terminals report planning, generation, and optional dependency installation as separate phases. A successful non-TTY run without `--json` prints the same final state and next step without terminal animation: ```text Created React + Vite application at /absolute/path/to/my-project. Dependencies were not installed. Next: open /absolute/path/to/my-project, run pnpm install --frozen-lockfile, then run pnpm verify. ``` A dry run begins with `Planned`. A successful install instead reports `Dependencies installed` and directs you to `pnpm verify`. Ordinary errors print to standard error as `Error: ` and exit with status `1`. Recovery text distinguishes these filesystem outcomes: * no generated files were committed to the destination; * publication is incomplete and the `.astilba-create-incomplete` marker remains; or * the project was created, but installation or terminal reporting needs attention. Cancellation and process interruption exit with status `130` in every output mode. If cancellation arrives after publication, recovery output still says that the project exists and whether dependency installation needs to be completed. ## JSON output [Section titled “JSON output”](#json-output) `--json` writes one JSON object to standard output. Invoke the package directly to keep npm wrapper output out of that stream: ```sh npx --yes create-astilba@latest my-project \ --recipe react-vite-spa \ --description "A useful application." \ --github-owner example \ --no-install \ --json ``` Successful plan or creation: | Field | Type | Meaning | | --------------- | ---------------------- | ------------------------------------------------------ | | `action` | `"plan"` or `"create"` | Whether `--dry-run` stopped before writing | | `destination` | string | Absolute resolved destination | | `files` | string array | Every planned regular-file path in deterministic order | | `installed` | boolean | Whether dependency installation completed | | `ok` | `true` | Success discriminator | | `recipe` | string | Selected recipe identifier | | `schemaVersion` | `1` | CLI output schema version | | `symlinks` | string array | Every planned symbolic-link path | Error: | Field | Type | Meaning | | ---------------- | ---------------- | --------------------------------------------------- | | `destination` | string, optional | Absolute resolved destination when one is available | | `error.code` | string | Stable failure category | | `error.message` | string | Human-readable actionable error | | `error.phase` | string | `input`, `generation`, `installation`, or `unknown` | | `ok` | `false` | Error discriminator | | `projectCreated` | boolean | Whether a complete project was published | | `schemaVersion` | `1` | CLI output schema version | `error.code` is one of `CANCELLED`, `GENERATION_FAILED`, `INSTALLATION_FAILED`, `INVALID_INPUT`, `PACKAGE_MANAGER_UNAVAILABLE`, or `UNEXPECTED_ERROR`. `CANCELLED` maps to status `130`; the other codes map to status `1`. When `projectCreated` is `false`, inspect a resolved destination for `.astilba-create-incomplete` before treating it as unchanged. ## Recipe catalog output [Section titled “Recipe catalog output”](#recipe-catalog-output) Use the catalog when an interface or automation needs to discover released recipe IDs without duplicating a list: ```sh npx --yes create-astilba@latest --catalog --json ``` The command does not start the questionnaire or write project files. It emits one newline-terminated JSON object with: | Field | Type | Meaning | | ------------------- | ------------------ | ------------------------------------------------------------ | | `command` | `"catalog"` | Catalog result discriminator | | `generator.name` | `"create-astilba"` | Package that owns the catalog | | `generator.version` | string | Exact installed Create version | | `ok` | `true` | Success discriminator | | `recipes` | array | Stable recipe IDs, recipe versions, labels, and descriptions | | `schemaVersion` | `1` | Catalog output schema version | The catalog deliberately omits internal profiles, dependency lists, and implementation details. Its schema version is independent from the generator version and recipe versions. The schema ships in the npm package at `schemas/catalog-v1.json`. `--help --json` returns `command`, `ok`, `schemaVersion`, and `usage`. `--version --json` returns `command`, `ok`, `schemaVersion`, and `version`. ## Exit status [Section titled “Exit status”](#exit-status) | Status | Meaning | | ------ | ---------------------------------------------------------------------------------------- | | `0` | Help, version, catalog, plan, creation, and any requested install completed successfully | | `1` | Input, planning, generation, Git, dependency-installation, or terminal-reporting error | | `130` | The operation was cancelled or interrupted | For a complete automated example, see [Automate project creation](/docs/create/automation/). # Release and support > Check the exact package, runtime, recipe, platform, and verification surface supported by Astilba Create 0.3.0. `create-astilba` 0.3.0 is published on npm from the public [`astilbahq/create`](https://github.com/astilbahq/create) repository. The source release is tagged [`v0.3.0`](https://github.com/astilbahq/create/tree/v0.3.0). ## Supported public surface [Section titled “Supported public surface”](#supported-public-surface) | Surface | 0.3.0 status | | --------------------------------------- | ---------------------------------------------------------------------- | | Interactive CLI | Recipe-first questionnaire with validated review and per-field editing | | Non-interactive CLI | Released | | Versioned recipe catalog | Schema version 1 through `--catalog --json` | | Versioned JSON output | Schema version 1 | | `--dry-run` planning | Released | | `typescript-library` | Recipe version 2 | | `react-vite-spa` | Recipe version 2 | | `astro-static-site` | Recipe version 2 | | `cloudflare-worker-service` | Recipe version 2 | | Project manifest | Schema version 1 | | Programmatic TypeScript API | Not exported by the npm package | | Update, migration, or `doctor` commands | Not shipped | | Arbitrary recipe composition | Not supported | The npm export map exposes package metadata only. Internal generator modules in the source repository are implementation details and are not a supported import path. Create 0.3.0 adds a versioned, non-interactive recipe catalog and its strict JSON Schema. All released recipe IDs, recipe versions, lockfiles, and output fingerprints remain unchanged from 0.2.0. Planning, generation, and optional dependency installation remain separate interactive phases. Human success and recovery output distinguishes a failure that committed no generated files, an incomplete publication with its marker, and a complete project whose installation or terminal reporting needs attention. The non-interactive creation flags, exit codes, and creation JSON schema version remain compatible with 0.1.2. ## Runtime requirements [Section titled “Runtime requirements”](#runtime-requirements) | Requirement | Supported value | | --------------------------------- | ------------------------ | | Create CLI runtime | Node.js 22.18.0 or later | | Generated project package manager | pnpm 11.10.0 | You invoke Create through npm, but generated projects use pnpm. With `--install`, Create uses the `pnpm` executable only when it reports version 11.10.0. Otherwise, Create asks Corepack for `pnpm@11.10.0`. Generated verification runs on the minimum Node.js release and the current supported major recorded by Create. In 0.3.0, those lanes are Node.js 22.18.0 and 24.18.0. ## Platform boundary [Section titled “Platform boundary”](#platform-boundary) Generated paths are restricted to a portable ASCII subset and checked for Windows device names and case-insensitive collisions. Every recipe creates `CLAUDE.md` as a symbolic link to `AGENTS.md`. Windows therefore requires Developer Mode or an elevated shell. If the filesystem refuses the link, Create stops in staging and does not publish a partial project. Before cloning a generated repository on Windows, enable symbolic-link support and configure Git to preserve symbolic links. ## Release evidence [Section titled “Release evidence”](#release-evidence) The Create repository verifies more than its own unit tests: * `pnpm verify` runs Ultracite, TypeScript, Vitest, Knip, and the package build; * `pnpm test:consumers` generates, installs, and runs `pnpm verify` in every recipe as an independent project; * `pnpm test:package` packs the actual npm tarball, verifies its contents and executable, installs it in a clean temporary consumer, generates all four recipes with JSON output, checks each manifest’s schema URL and recipe identity, and verifies each project; * the on-demand published-package acceptance workflow installs an exact npm version on Linux, macOS, and Windows, follows the public CLI path, checks its catalog and side-effect-free dry run, verifies the generated manifest and agent-instruction link, and runs the generated project’s own verification; * CI repeats recipe consumers on the supported Node.js lanes; * a Windows packed-CLI smoke test exercises symbolic-link creation; * Actionlint and Zizmor audit the emitted GitHub workflows; and * OSV-Scanner, CodeQL, and dependency review run against the Create source repository. The packed npm artifact contains the license, README, package metadata, compiled `dist` files, the public project-manifest and catalog schemas, and the recipe contract metadata and canonical lockfiles needed to verify generation. ## Publication evidence [Section titled “Publication evidence”](#publication-evidence) The [`v0.3.0` GitHub Release](https://github.com/astilbahq/create/releases/tag/v0.3.0) ran the checked-in release workflow. It verified that the release tag pointed to `main` and matched the package version, rebuilt and checked the package, and published through a protected GitHub environment with npm trusted publishing. The [`create-astilba@0.3.0` npm record](https://www.npmjs.com/package/create-astilba/v/0.3.0) includes a provenance attestation that identifies the public source repository and GitHub Actions release workflow. After publication, the [`create-astilba@0.3.0` acceptance run](https://github.com/astilbahq/create/actions/runs/30172510973) passed its Linux Astro, macOS TypeScript library, and Windows Cloudflare Workers journeys against the exact public package. These representative cross-platform journeys complement the complete recipe matrix in the ordinary source and packed-package tests; they do not claim every recipe-and-platform combination. ## Responsibility after generation [Section titled “Responsibility after generation”](#responsibility-after-generation) Create verifies the generated repository files, but it cannot apply hosted settings. You must follow the generated `docs/repository-settings.md` after pushing to GitHub. You also own product-specific work after generation: * choose and configure deployment infrastructure; * provision secrets and external services; * replace seeded example code; * decide repository visibility and publishing policy; and * keep project-specific capabilities tested. The Worker recipe includes Wrangler development, type-generation, dry-run build, and deployment commands. The Astro and React recipes deliberately do not choose a hosting provider. The library recipe supplies package checks but does not publish for you. ## Deliberate omissions [Section titled “Deliberate omissions”](#deliberate-omissions) Create 0.3.0 does not include optional Panda CSS, monitoring, browser testing, authentication, databases, or general deployment automation. These are not hidden flags or parked public recipes. Future repair and update tooling is intended to use explicit authored migrations and the manifest’s ownership evidence. It will not regenerate over an existing repository or silently mutate a default branch. Report generator defects or recipe regressions in the public [Create issue tracker](https://github.com/astilbahq/create/issues).