assistant-ui 0.0.90 → 0.0.92

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,141 +1,65 @@
1
1
  # `assistant-ui` CLI
2
2
 
3
- The `assistant-ui` CLI for adding components and dependencies to your project.
3
+ [![npm version](https://img.shields.io/npm/v/assistant-ui)](https://www.npmjs.com/package/assistant-ui)
4
+ [![npm downloads](https://img.shields.io/npm/dm/assistant-ui)](https://www.npmjs.com/package/assistant-ui)
5
+ [![GitHub stars](https://img.shields.io/github/stars/assistant-ui/assistant-ui)](https://github.com/assistant-ui/assistant-ui)
4
6
 
5
- ## Usage
7
+ Command-line tool for adding shadcn-style components to your project, scaffolding a new app, and keeping your assistant-ui packages up to date.
6
8
 
7
- Use the `init` command to initialize assistant-ui in an existing project.
9
+ ## Installation
8
10
 
9
- The `init` command installs dependencies, adds components, and configures your project for assistant-ui.
11
+ Run via your package manager of choice; nothing to install globally:
10
12
 
11
13
  ```bash
12
- npx assistant-ui@latest init
13
- npx assistant-ui@latest init --yes # non-interactive / CI / agent mode
14
+ npx assistant-ui@latest <command>
15
+ pnpm dlx assistant-ui@latest <command>
16
+ yarn dlx assistant-ui@latest <command>
17
+ bunx assistant-ui@latest <command>
14
18
  ```
15
19
 
16
- If no existing project is found (no `package.json`), `init` forwards to `create`.
17
- Passing `--preset` to `init` also forwards to `create` for compatibility.
18
-
19
- ## create
20
-
21
- Use the `create` command to scaffold a new Next.js project with assistant-ui.
22
-
23
- The `create` command scaffolds a project from assistant-ui starter templates or examples.
20
+ ## Common tasks
24
21
 
25
22
  ```bash
23
+ # scaffold a new Next.js project
26
24
  npx assistant-ui@latest create my-app
27
- ```
28
25
 
29
- You can choose from multiple templates:
26
+ # scaffold a minimal project
27
+ npx assistant-ui@latest create my-app --template minimal
30
28
 
31
- ```bash
32
- # Default template with Vercel AI SDK
33
- npx assistant-ui@latest create my-app
34
-
35
- # Minimal starter
36
- npx assistant-ui@latest create my-app -t minimal
37
-
38
- # With Assistant Cloud for persistence
39
- npx assistant-ui@latest create my-app -t cloud
29
+ # scaffold from a feature example
30
+ npx assistant-ui@latest create my-app --example with-ai-sdk-v6
40
31
 
41
- # With Assistant Cloud + Clerk auth
42
- npx assistant-ui@latest create my-app -t cloud-clerk
32
+ # scaffold an Expo / React Native project
33
+ npx assistant-ui@latest create my-app --native
43
34
 
44
- # With LangGraph starter template
45
- npx assistant-ui@latest create my-app -t langgraph
35
+ # scaffold a React Ink terminal project
36
+ npx assistant-ui@latest create my-app --ink
46
37
 
47
- # With MCP starter template
48
- npx assistant-ui@latest create my-app -t mcp
49
-
50
- # With playground preset configuration
51
- npx assistant-ui@latest create my-app --preset "https://www.assistant-ui.com/playground/init?preset=chatgpt"
52
- ```
53
-
54
- ## add
55
-
56
- Use the `add` command to add components to your project.
57
-
58
- The `add` command adds a component to your project and installs all required dependencies.
59
-
60
- ```bash
61
- npx assistant-ui@latest add [component]
62
- ```
38
+ # add assistant-ui to an existing project
39
+ npx assistant-ui@latest init
63
40
 
64
- ### Example
41
+ # initialize non-interactively for CI or agent flows
42
+ npx assistant-ui@latest init --yes
65
43
 
66
- ```bash
44
+ # add a component
67
45
  npx assistant-ui@latest add thread
68
- ```
69
-
70
- You can also add multiple components at once:
71
46
 
72
- ```bash
73
- npx assistant-ui@latest add thread thread-list assistant-modal
74
- ```
75
-
76
- ## update
77
-
78
- Use the `update` command to update all assistant-ui packages to their latest versions.
79
-
80
- ```bash
47
+ # update all @assistant-ui/* and assistant-* packages
81
48
  npx assistant-ui@latest update
82
- ```
83
-
84
- ## upgrade
85
-
86
- Use the `upgrade` command to automatically migrate your codebase when upgrading to a new major version.
87
49
 
88
- The `upgrade` command runs codemods to transform your code and prompts to install new dependencies.
89
-
90
- ```bash
50
+ # run codemods after a major version bump
91
51
  npx assistant-ui@latest upgrade
92
- ```
93
-
94
- ## info
95
-
96
- Use the `info` command to print your environment and package versions for bug reports.
97
52
 
98
- ```bash
53
+ # print env + version info for a bug report
99
54
  npx assistant-ui info
100
55
  ```
101
56
 
102
- This command collects and prints:
103
- - OS, Node.js version, package manager, and framework
104
- - All installed `@assistant-ui/*` and `assistant-*` package versions
105
- - Key ecosystem dependency versions (React, Next.js, AI SDK, etc.)
106
- - Peer dependency warnings if any mismatches are detected
107
-
108
- **Example output:**
57
+ `init` falls back to `create` when no `package.json` is found, so a single command works for both new and existing projects. Use `init --yes` for CI and agent flows where prompts are not available.
109
58
 
110
- ```
111
- Environment:
112
- OS: macOS 15.3 (arm64)
113
- Node.js: v22.14.0
114
- Package Manager: pnpm 10.32.1
115
- Framework: Next.js 15.3.1
116
-
117
- Packages:
118
- @assistant-ui/react 0.12.15
119
- @assistant-ui/react-ai-sdk 1.3.12
120
- @assistant-ui/react-markdown 0.3.8
121
- assistant-stream 0.2.14
122
-
123
- Ecosystem:
124
- react 19.1.0
125
- react-dom 19.1.0
126
- next 15.3.1
127
- ai 6.0.120
128
- ```
129
-
130
- The output includes a copy-pasteable markdown block that you can paste directly into a bug report.
59
+ ## Templates
131
60
 
132
- **Options:**
133
- - `-c, --cwd <cwd>` - the working directory. defaults to the current directory.
61
+ `create` scaffolds from named templates: `default` (AI SDK), `minimal`, `cloud`, `cloud-clerk`, `langgraph`, `mcp`. Pass `-t <name>`, pass `--example <name>` for examples such as `with-ai-sdk-v6`, use `--native` for Expo / React Native, use `--ink` for React Ink, or pass `--preset <url>` to scaffold from an `assistant-ui.com` playground link.
134
62
 
135
63
  ## Documentation
136
64
 
137
- Visit https://assistant-ui.com/docs/cli to view the full documentation.
138
-
139
- ## License
140
-
141
- Licensed under the [MIT license](https://github.com/assistant-ui/assistant-ui/blob/main/LICENSE).
65
+ Full command reference, flags, and template details at [assistant-ui.com/docs/cli](https://www.assistant-ui.com/docs/cli).
@@ -1,3 +1,16 @@
1
1
  import { Command } from "commander";
2
+ import { type PackageManagerName } from "../lib/create-project.js";
3
+ export interface AddComponentsPlan {
4
+ command: string;
5
+ args: string[];
6
+ }
7
+ export declare function createAddComponentsPlan(params: {
8
+ components: string[];
9
+ packageManager: PackageManagerName;
10
+ yes?: boolean;
11
+ overwrite?: boolean;
12
+ cwd?: string;
13
+ path?: string;
14
+ }): AddComponentsPlan;
2
15
  export declare const add: Command;
3
16
  //# sourceMappingURL=add.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,GAAG,SAuDZ,CAAC"}
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAIL,KAAK,kBAAkB,EACxB,iCAA8B;AAK/B,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAC9C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,cAAc,EAAE,kBAAkB,CAAC;IACnC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,iBAAiB,CAmBpB;AAED,eAAO,MAAM,GAAG,SAqDZ,CAAC"}
@@ -1,8 +1,30 @@
1
1
  import { Command } from "commander";
2
- import { spawn } from "cross-spawn";
3
2
  import { logger } from "../lib/utils/logger.js";
4
3
  import { hasConfig } from "../lib/utils/config.js";
4
+ import { dlxCommand, resolvePackageManager, resolvePackageManagerForCwd, } from "../lib/create-project.js";
5
+ import { runSpawn, SpawnExitError } from "../lib/run-spawn.js";
5
6
  const REGISTRY_BASE_URL = "https://r.assistant-ui.com";
7
+ export function createAddComponentsPlan(params) {
8
+ const componentsToAdd = params.components.map((c) => {
9
+ if (!/^[a-zA-Z0-9-/]+$/.test(c)) {
10
+ throw new Error(`Invalid component name: ${c}`);
11
+ }
12
+ return `${REGISTRY_BASE_URL}/${encodeURIComponent(c)}.json`;
13
+ });
14
+ const [command, dlxArgs] = dlxCommand(params.packageManager);
15
+ const args = [...dlxArgs, "shadcn@latest", "add", ...componentsToAdd];
16
+ // For npm, dlxArgs may already include `--yes` for npx auto-install.
17
+ // This flag is for shadcn's own confirmation prompt.
18
+ if (params.yes)
19
+ args.push("--yes");
20
+ if (params.overwrite)
21
+ args.push("--overwrite");
22
+ if (params.cwd)
23
+ args.push("--cwd", params.cwd);
24
+ if (params.path)
25
+ args.push("--path", params.path);
26
+ return { command, args };
27
+ }
6
28
  export const add = new Command()
7
29
  .name("add")
8
30
  .description("add a component to your project")
@@ -11,44 +33,38 @@ export const add = new Command()
11
33
  .option("-o, --overwrite", "overwrite existing files.", false)
12
34
  .option("-c, --cwd <cwd>", "the working directory. defaults to the current directory.", process.cwd())
13
35
  .option("-p, --path <path>", "the path to add the component to.")
14
- .action((components, opts) => {
36
+ .option("--use-npm", "explicitly use npm")
37
+ .option("--use-pnpm", "explicitly use pnpm")
38
+ .option("--use-yarn", "explicitly use yarn")
39
+ .option("--use-bun", "explicitly use bun")
40
+ .action(async (components, opts) => {
15
41
  // Check if project is initialized
16
42
  if (!hasConfig(opts.cwd)) {
17
43
  logger.warn("It looks like you haven't initialized your project yet. Run 'assistant-ui init' first.");
18
44
  logger.break();
19
45
  }
20
- const componentsToAdd = components.map((c) => {
21
- if (!/^[a-zA-Z0-9-/]+$/.test(c)) {
22
- throw new Error(`Invalid component name: ${c}`);
23
- }
24
- return `${REGISTRY_BASE_URL}/${encodeURIComponent(c)}.json`;
25
- });
26
46
  logger.step(`Adding ${components.length} component(s)...`);
27
- const args = [`shadcn@latest`, "add", ...componentsToAdd];
28
- if (opts.yes)
29
- args.push("--yes");
30
- if (opts.overwrite)
31
- args.push("--overwrite");
32
- if (opts.cwd)
33
- args.push("--cwd", opts.cwd);
34
- if (opts.path)
35
- args.push("--path", opts.path);
36
- const child = spawn("npx", args, {
37
- stdio: "inherit",
38
- shell: true,
39
- });
40
- child.on("error", (error) => {
41
- logger.error(`Failed to add components: ${error.message}`);
42
- process.exit(1);
47
+ const packageManager = await resolvePackageManagerForCwd(opts.cwd, resolvePackageManager(opts));
48
+ const { command, args } = createAddComponentsPlan({
49
+ components,
50
+ packageManager,
51
+ yes: opts.yes,
52
+ overwrite: opts.overwrite,
53
+ cwd: opts.cwd,
54
+ path: opts.path,
43
55
  });
44
- child.on("close", (code) => {
45
- if (code !== 0) {
46
- logger.error(`Process exited with code ${code}`);
47
- process.exit(code || 1);
48
- }
49
- else {
50
- logger.success("Components added successfully!");
56
+ try {
57
+ await runSpawn(command, args, opts.cwd);
58
+ }
59
+ catch (error) {
60
+ if (error instanceof SpawnExitError) {
61
+ logger.error(`Process exited with code ${error.code}`);
62
+ process.exit(error.code);
51
63
  }
52
- });
64
+ const message = error instanceof Error ? error.message : String(error);
65
+ logger.error(`Failed to add components: ${message}`);
66
+ process.exit(1);
67
+ }
68
+ logger.success("Components added successfully!");
53
69
  });
54
70
  //# sourceMappingURL=add.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  import { Command } from "commander";
2
2
  import * as p from "@clack/prompts";
3
- import { type PackageManagerName } from "../lib/create-project.js";
4
3
  export interface ProjectMetadata {
5
4
  name: string;
6
5
  label: string;
@@ -21,12 +20,19 @@ export declare function resolveCreateProjectDirectory(params: {
21
20
  projectDirectory?: string;
22
21
  stdinIsTTY?: boolean;
23
22
  }): string | undefined;
24
- export declare function resolvePackageManager(opts: {
25
- useNpm?: boolean;
26
- usePnpm?: boolean;
27
- useYarn?: boolean;
28
- useBun?: boolean;
29
- }): PackageManagerName | undefined;
30
23
  export declare function resolvePresetUrl(preset: string): string;
24
+ export interface ScaffoldSelectorOptions {
25
+ template?: string;
26
+ example?: string;
27
+ preset?: string;
28
+ native?: boolean;
29
+ ink?: boolean;
30
+ }
31
+ export interface ResolvedScaffoldSelector {
32
+ template?: string;
33
+ example?: string;
34
+ preset?: string;
35
+ }
36
+ export declare function resolveScaffoldSelector(opts: ScaffoldSelectorOptions): ResolvedScaffoldSelector;
31
37
  export declare const create: Command;
32
38
  //# sourceMappingURL=create.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AAEpC,OAAO,EAML,KAAK,kBAAkB,EACxB,iCAA8B;AAE/B,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,gBAAgB,EAAE,eAAe,EA2N7C,CAAC;AAmBF,wBAAsB,cAAc,CAAC,MAAM,EAAE;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC;CAC9B,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAyElC;AAiCD,wBAAgB,6BAA6B,CAAC,MAAM,EAAE;IACpD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG,MAAM,GAAG,SAAS,CAMrB;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,kBAAkB,GAAG,SAAS,CAMjC;AAKD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED,eAAO,MAAM,MAAM,SAsOf,CAAC"}
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAI5C,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AAapC,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,gBAAgB,EAAE,eAAe,EA2N7C,CAAC;AAmBF,wBAAsB,cAAc,CAAC,MAAM,EAAE;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC;CAC9B,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAyElC;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE;IACpD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG,MAAM,GAAG,SAAS,CAMrB;AAKD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAYD,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,uBAAuB,GAC5B,wBAAwB,CAkC1B;AAED,eAAO,MAAM,MAAM,SAmPf,CAAC"}
@@ -1,11 +1,11 @@
1
- import { Command } from "commander";
1
+ import { Command, Option } from "commander";
2
2
  import chalk from "chalk";
3
- import { spawn } from "cross-spawn";
4
3
  import fs from "node:fs";
5
4
  import path from "node:path";
6
5
  import * as p from "@clack/prompts";
7
6
  import { logger } from "../lib/utils/logger.js";
8
- import { dlxCommand, downloadProject, resolveLatestReleaseRef, resolvePackageManagerName, transformProject, } from "../lib/create-project.js";
7
+ import { dlxCommand, downloadProject, resolveLatestReleaseRef, resolvePackageManager, resolvePackageManagerForCwd, scaffoldProject, transformProject, } from "../lib/create-project.js";
8
+ import { runSpawn, SpawnExitError } from "../lib/run-spawn.js";
9
9
  export const PROJECT_METADATA = [
10
10
  // Templates
11
11
  {
@@ -14,7 +14,7 @@ export const PROJECT_METADATA = [
14
14
  description: "Default template with Vercel AI SDK",
15
15
  category: "template",
16
16
  path: "templates/default",
17
- hasLocalComponents: true,
17
+ hasLocalComponents: false,
18
18
  },
19
19
  {
20
20
  name: "minimal",
@@ -30,7 +30,7 @@ export const PROJECT_METADATA = [
30
30
  description: "Cloud-backed persistence starter",
31
31
  category: "template",
32
32
  path: "templates/cloud",
33
- hasLocalComponents: true,
33
+ hasLocalComponents: false,
34
34
  },
35
35
  {
36
36
  name: "cloud-clerk",
@@ -38,7 +38,7 @@ export const PROJECT_METADATA = [
38
38
  description: "Cloud-backed starter with Clerk auth",
39
39
  category: "template",
40
40
  path: "templates/cloud-clerk",
41
- hasLocalComponents: true,
41
+ hasLocalComponents: false,
42
42
  },
43
43
  {
44
44
  name: "langgraph",
@@ -46,15 +46,15 @@ export const PROJECT_METADATA = [
46
46
  description: "LangGraph starter template",
47
47
  category: "template",
48
48
  path: "templates/langgraph",
49
- hasLocalComponents: true,
49
+ hasLocalComponents: false,
50
50
  },
51
51
  {
52
52
  name: "mcp",
53
53
  label: "MCP",
54
- description: "MCP starter template",
54
+ description: "MCP tools + MCP Apps renderer starter",
55
55
  category: "template",
56
56
  path: "templates/mcp",
57
- hasLocalComponents: true,
57
+ hasLocalComponents: false,
58
58
  },
59
59
  // Examples
60
60
  {
@@ -238,7 +238,7 @@ const templateNames = PROJECT_METADATA.filter((m) => m.category === "template").
238
238
  const exampleNames = PROJECT_METADATA.filter((m) => m.category === "example").map((m) => m.name);
239
239
  export async function resolveProject(params) {
240
240
  const { template, example, stdinIsTTY = process.stdin.isTTY, select = p.select, isCancel = p.isCancel, } = params;
241
- if (template) {
241
+ if (template !== undefined) {
242
242
  const meta = PROJECT_METADATA.find((m) => m.name === template && m.category === "template");
243
243
  if (!meta) {
244
244
  logger.error(`Unknown template: ${template}`);
@@ -247,7 +247,7 @@ export async function resolveProject(params) {
247
247
  }
248
248
  return meta;
249
249
  }
250
- if (example) {
250
+ if (example !== undefined) {
251
251
  const meta = PROJECT_METADATA.find((m) => m.name === example && m.category === "example");
252
252
  if (!meta) {
253
253
  logger.error(`Unknown example: ${example}`);
@@ -294,30 +294,6 @@ export async function resolveProject(params) {
294
294
  }
295
295
  return meta;
296
296
  }
297
- class SpawnExitError extends Error {
298
- code;
299
- constructor(code) {
300
- super(`Process exited with code ${code}`);
301
- this.code = code;
302
- }
303
- }
304
- async function runSpawn(command, args, cwd) {
305
- return new Promise((resolve, reject) => {
306
- const child = spawn(command, args, {
307
- stdio: "inherit",
308
- cwd,
309
- });
310
- child.on("error", (error) => reject(error));
311
- child.on("close", (code) => {
312
- if (code !== 0) {
313
- reject(new SpawnExitError(code || 1));
314
- }
315
- else {
316
- resolve();
317
- }
318
- });
319
- });
320
- }
321
297
  export function resolveCreateProjectDirectory(params) {
322
298
  const { projectDirectory, stdinIsTTY = process.stdin.isTTY } = params;
323
299
  if (projectDirectory)
@@ -326,17 +302,6 @@ export function resolveCreateProjectDirectory(params) {
326
302
  return "my-aui-app";
327
303
  return undefined;
328
304
  }
329
- export function resolvePackageManager(opts) {
330
- if (opts.useNpm)
331
- return "npm";
332
- if (opts.usePnpm)
333
- return "pnpm";
334
- if (opts.useYarn)
335
- return "yarn";
336
- if (opts.useBun)
337
- return "bun";
338
- return undefined;
339
- }
340
305
  const PLAYGROUND_PRESET_BASE_URL = "https://www.assistant-ui.com/playground/init";
341
306
  export function resolvePresetUrl(preset) {
342
307
  if (preset.startsWith("http://") || preset.startsWith("https://")) {
@@ -344,6 +309,44 @@ export function resolvePresetUrl(preset) {
344
309
  }
345
310
  return `${PLAYGROUND_PRESET_BASE_URL}?preset=${encodeURIComponent(preset)}`;
346
311
  }
312
+ const scaffoldSelectorHelp = "Choose one scaffold selector: --template <name>, --example <name>, --native, or --ink. --preset <name-or-url> can be used with --template or by itself.";
313
+ function getPresetConflict(opts) {
314
+ if (opts.example !== undefined)
315
+ return "--example";
316
+ if (opts.native)
317
+ return "--native";
318
+ if (opts.ink)
319
+ return "--ink";
320
+ return undefined;
321
+ }
322
+ export function resolveScaffoldSelector(opts) {
323
+ const hasPreset = opts.preset !== undefined;
324
+ const presetConflict = getPresetConflict(opts);
325
+ const selectors = [
326
+ opts.template !== undefined ? "--template" : undefined,
327
+ opts.example !== undefined ? "--example" : undefined,
328
+ opts.native ? "--native" : undefined,
329
+ opts.ink ? "--ink" : undefined,
330
+ ].filter((selector) => selector !== undefined);
331
+ if (selectors.length > 1) {
332
+ throw new Error(`Only one scaffold selector can be provided (${selectors.join(", ")}). ${scaffoldSelectorHelp}`);
333
+ }
334
+ if (hasPreset && presetConflict) {
335
+ throw new Error(`Cannot use --preset with ${presetConflict}. ${scaffoldSelectorHelp}`);
336
+ }
337
+ if (opts.native)
338
+ return { example: "with-expo" };
339
+ if (opts.ink)
340
+ return { example: "with-react-ink" };
341
+ if (opts.preset !== undefined && opts.template === undefined) {
342
+ return { template: "default", preset: opts.preset };
343
+ }
344
+ return {
345
+ ...(opts.template !== undefined && { template: opts.template }),
346
+ ...(opts.example !== undefined && { example: opts.example }),
347
+ ...(hasPreset && { preset: opts.preset }),
348
+ };
349
+ }
347
350
  export const create = new Command()
348
351
  .name("create")
349
352
  .description("create a new project")
@@ -359,23 +362,24 @@ export const create = new Command()
359
362
  .option("--native", "create an Expo / React Native project")
360
363
  .option("--ink", "create a React Ink terminal project")
361
364
  .option("--skip-install", "skip installing packages")
365
+ .addOption(new Option("--debug-source-root <path>", "copy templates/examples from a local assistant-ui repo root").hideHelp())
362
366
  .action(async (projectDirectory, opts) => {
363
- if (opts.native) {
364
- opts.example = "with-expo";
365
- }
366
- if (opts.ink) {
367
- opts.example = "with-react-ink";
368
- }
369
- if (opts.example && opts.preset) {
370
- logger.error("Cannot use --preset with --example.");
371
- process.exit(1);
367
+ let scaffoldSelector;
368
+ try {
369
+ scaffoldSelector = resolveScaffoldSelector(opts);
372
370
  }
373
- if (opts.template && opts.example) {
374
- logger.error("Cannot use both --template and --example.");
371
+ catch (error) {
372
+ const message = error instanceof Error ? error.message : String(error);
373
+ logger.error(message);
375
374
  process.exit(1);
376
375
  }
376
+ const localSourceRoot = opts.debugSourceRoot
377
+ ? path.resolve(opts.debugSourceRoot)
378
+ : undefined;
377
379
  // Start release ref resolution early (runs during user prompts)
378
- const refPromise = resolveLatestReleaseRef();
380
+ const refPromise = localSourceRoot
381
+ ? Promise.resolve(undefined)
382
+ : resolveLatestReleaseRef();
379
383
  // 1. Resolve project directory
380
384
  let resolvedProjectDirectory = resolveCreateProjectDirectory({
381
385
  projectDirectory,
@@ -427,17 +431,14 @@ export const create = new Command()
427
431
  }
428
432
  }
429
433
  // 2. Resolve scaffold target
430
- const project = await resolveProject({
431
- template: opts.template,
432
- example: opts.example,
433
- });
434
+ const project = await resolveProject(scaffoldSelector);
434
435
  if (!project) {
435
436
  p.cancel("Project creation cancelled.");
436
437
  process.exit(0);
437
438
  }
438
439
  logger.info(`Creating project from ${project.category}: ${project.label}`);
439
440
  logger.break();
440
- const pm = await resolvePackageManagerName(absoluteProjectDir, resolvePackageManager(opts));
441
+ const pm = await resolvePackageManagerForCwd(path.dirname(absoluteProjectDir), resolvePackageManager(opts));
441
442
  // Clean up partial project directory on unexpected exit (e.g. Ctrl+C)
442
443
  const cleanupOnExit = () => {
443
444
  fs.rmSync(absoluteProjectDir, { recursive: true, force: true });
@@ -445,17 +446,28 @@ export const create = new Command()
445
446
  process.once("exit", cleanupOnExit);
446
447
  try {
447
448
  // 3. Resolve latest release ref (started before prompts)
448
- logger.step("Resolving latest release...");
449
+ if (!localSourceRoot) {
450
+ logger.step("Resolving latest release...");
451
+ }
449
452
  const ref = await refPromise;
450
- if (!ref) {
453
+ if (!localSourceRoot && !ref) {
451
454
  logger.warn("Could not resolve latest release, downloading from HEAD");
452
455
  }
453
- // 4. Download project
454
- logger.step("Downloading project...");
456
+ // 4. Scaffold project
457
+ logger.step(localSourceRoot
458
+ ? `Copying project from local source: ${localSourceRoot}`
459
+ : "Downloading project...");
455
460
  try {
456
- await downloadProject(project.path, absoluteProjectDir, ref);
461
+ const source = localSourceRoot
462
+ ? { kind: "local", rootDir: localSourceRoot }
463
+ : {
464
+ kind: "github",
465
+ ref,
466
+ };
467
+ await scaffoldProject(project.path, absoluteProjectDir, source);
457
468
  // If the template didn't exist at the release tag, retry from HEAD
458
- if (ref &&
469
+ if (!localSourceRoot &&
470
+ ref &&
459
471
  !fs.existsSync(path.join(absoluteProjectDir, "package.json"))) {
460
472
  fs.rmSync(absoluteProjectDir, { recursive: true, force: true });
461
473
  logger.warn("Template not found at release tag, downloading from HEAD");
@@ -474,8 +486,8 @@ export const create = new Command()
474
486
  throw err;
475
487
  }
476
488
  // 6. Apply preset if provided
477
- if (opts.preset) {
478
- const presetUrl = resolvePresetUrl(opts.preset);
489
+ if (scaffoldSelector.preset) {
490
+ const presetUrl = resolvePresetUrl(scaffoldSelector.preset);
479
491
  logger.info("Applying preset configuration...");
480
492
  logger.break();
481
493
  const [dlxCmd, dlxArgs] = dlxCommand(pm);