diff --git a/.changeset/thick-baboons-confess.md b/.changeset/thick-baboons-confess.md
new file mode 100644
index 0000000000..7134284d0b
--- /dev/null
+++ b/.changeset/thick-baboons-confess.md
@@ -0,0 +1,5 @@
+---
+"assistant-ui": patch
+---
+
+feat: npx assistant-ui create
diff --git a/README.md b/README.md
index 3e5ed3a8d3..7f8132aaa8 100644
--- a/README.md
+++ b/README.md
@@ -10,30 +10,19 @@
- [Documentation](https://www.assistant-ui.com/docs/getting-started)
-## Minimal Example with Vercel AI SDK
+## Quick Start
+
+Step 1: Create a new project with `assistant-ui` pre-configured:
```sh
-npx assistant-ui@latest add modal
+npx assistant-ui@latest create my-app
+cd my-app
```
-```tsx
-"use client";
-
-import { useChat } from "@ai-sdk/react";
-import { AssistantRuntimeProvider } from "@assistant-ui/react";
-import { useVercelUseChatRuntime } from "@assistant-ui/react-ai-sdk";
-import { AssistantModal } from "@/components/ui/assistant-ui/assistant-modal";
-
-export default const MyApp = () => {
- const chat = useChat({
- api: "/api/chat" // your backend route
- });
- const runtime = useVercelUseChatRuntime(chat);
-
- return (
-
-
-
- );
-}
-```
+Step 2: Update the `.env` file with your OpenAI API key.
+
+Step 3: Run the app:
+
+```sh
+npm run dev
+```
\ No newline at end of file
diff --git a/apps/www/pages/docs/getting-started.mdx b/apps/www/pages/docs/getting-started.mdx
index 5872ed13e6..617531caa5 100644
--- a/apps/www/pages/docs/getting-started.mdx
+++ b/apps/www/pages/docs/getting-started.mdx
@@ -3,31 +3,42 @@ title: Getting Started
description: React Components for AI Chat
---
-import Image from "next/image";
-import architecture from "../../assets/docs/architecture.png";
+import { Steps } from "nextra/components";
-## Architecture
+## Start with a new project
-`assistant-ui` consists of two parts, **_Runtime_** and **_UI Components_**.
+
-
+### Create a new project
-The Runtime and UI Components each require independent setup and both must be set up.
+Create a new project with `assistant-ui` pre-configured:
-## Setup
+```sh
+npx assistant-ui@latest create my-app
+cd my-app
+```
-The recommended way to get started is with the following stack:
+### Add API key
-- NextJS
-- Vercel's `ai` package
-- `tailwindcss` for styling
-- `shadcn/ui` for UI components
+Add a new `.env` file to your project with your OpenAI API key:
-### Step 1: Setup Runtime
+```sh
+OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+```
+
+### Start the app
+
+```sh
+npm run dev
+```
+
+
+## Install in an existing app
+
+
+
+
+### Setup Runtime
You wrap your entire app in a `` component.
@@ -36,7 +47,7 @@ The `Runtime` takes care of LLM communication, tools, streaming, state managemen
Refer to [Picking a Runtime](/docs/runtimes/pick-a-runtime) to pick the right runtime for your use case.
-### Step 2: Setup UI Components
+### Setup UI Components
The easiest way to get started is with `shadcn/ui` + `tailwind` components.
@@ -45,3 +56,5 @@ Currently, two modes are supported:
- [``](/docs/ui/AssistantModal): a modal chat UI in the bottom right corner
- [``](/docs/ui/AssistantSidebar): a sidebar chat UI
- [``](/docs/ui/Thread): the raw chat UI
+
+
\ No newline at end of file
diff --git a/apps/www/pages/docs/index.mdx b/apps/www/pages/docs/index.mdx
index 1da6e9707b..4add3394a1 100644
--- a/apps/www/pages/docs/index.mdx
+++ b/apps/www/pages/docs/index.mdx
@@ -3,6 +3,9 @@ title: Introduction
description: React Components for AI Chat
---
+import Image from "next/image";
+import architecture from "../../assets/docs/architecture.png";
+
### Composable Primitives
Inspired by [radix-ui](https://www.radix-ui.com/primitives), composable primitives allow you to mix and match the subset of features that you need.
@@ -14,3 +17,15 @@ assistant-ui does not ship with any styling or CSS code. Instead, you start with
### Open and Extensible
You have access to the entire internal state of assistant-ui and can mix and match your own promitives with ours.
+
+### Architecture
+
+`assistant-ui` consists of two parts, **_Runtime_** and **_UI Components_**.
+
+
+
+The Runtime and UI Components each require independent setup and both must be set up.
\ No newline at end of file
diff --git a/packages/cli/src/commands/create.ts b/packages/cli/src/commands/create.ts
new file mode 100644
index 0000000000..22968b8d4e
--- /dev/null
+++ b/packages/cli/src/commands/create.ts
@@ -0,0 +1,68 @@
+import { Command } from "commander";
+import chalk from "chalk";
+import { spawn } from "child_process";
+
+export const create = new Command()
+ .name("create")
+ .description("create a new project")
+ .arguments("")
+ .usage(`${chalk.green("")} [options]`)
+ .option(
+ "--use-npm",
+ `
+
+ Explicitly tell the CLI to bootstrap the application using npm
+`,
+ )
+ .option(
+ "--use-pnpm",
+ `
+
+ Explicitly tell the CLI to bootstrap the application using pnpm
+`,
+ )
+ .option(
+ "--use-yarn",
+ `
+
+ Explicitly tell the CLI to bootstrap the application using Yarn
+`,
+ )
+ .option(
+ "--use-bun",
+ `
+
+ Explicitly tell the CLI to bootstrap the application using Bun
+`,
+ )
+ .option(
+ "--skip-install",
+ `
+
+ Explicitly tell the CLI to skip installing packages
+`,
+ )
+ .action(() => {
+ const child = spawn(
+ "npx",
+ [
+ `create-next-app@latest`,
+ ...process.argv.slice(3),
+ "-e",
+ "https://github.com/Yonom/assistant-ui-starter",
+ ],
+ {
+ stdio: "inherit",
+ },
+ );
+
+ child.on("error", (error) => {
+ console.error(`Error: ${error.message}`);
+ });
+
+ child.on("close", (code) => {
+ if (code !== 0) {
+ console.log(`other-package-script process exited with code ${code}`);
+ }
+ });
+ });
diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts
index 5940cfbb49..d1f1604616 100644
--- a/packages/cli/src/index.ts
+++ b/packages/cli/src/index.ts
@@ -4,12 +4,13 @@ import { add } from "@/src/commands/add";
import { Command } from "commander";
import { getPackageInfo } from "./utils/get-package-info";
+import { create } from "./commands/create";
process.on("SIGINT", () => process.exit(0));
process.on("SIGTERM", () => process.exit(0));
async function main() {
- const packageInfo = await getPackageInfo();
+ const packageInfo = getPackageInfo();
const program = new Command()
.name("assistant-ui")
@@ -21,6 +22,7 @@ async function main() {
);
program.addCommand(add);
+ program.addCommand(create);
program.parse();
}
diff --git a/packages/cli/src/utils/get-package-info.ts b/packages/cli/src/utils/get-package-info.ts
index cdcfdd7278..090c64343e 100644
--- a/packages/cli/src/utils/get-package-info.ts
+++ b/packages/cli/src/utils/get-package-info.ts
@@ -1,8 +1,12 @@
import path from "node:path";
import fs from "node:fs";
+import { fileURLToPath } from "node:url";
export function getPackageInfo() {
- const packageJsonPath = path.join("package.json");
+ // Convert the current module URL to a file path
+ const __filename = fileURLToPath(import.meta.url);
+ const __dirname = path.dirname(__filename);
+ const packageJsonPath = path.join(__dirname, "..", "package.json");
return JSON.parse(fs.readFileSync(packageJsonPath).toString("utf-8")) as {
version: string;