Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion packages/cli/src/cli/commands/project/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ function validateNonInteractiveFlags(command: Command): void {
const { path } = command.opts<CreateOptions>();

if (path && !command.args.length) {
command.error("Non-interactive mode requires all flags: --name, --path");
command.error(
"--path requires a project name argument. Usage: base44 create <name> --path <path>",
);
}
}

Expand Down Expand Up @@ -113,6 +115,8 @@ async function createInteractive(
async function createNonInteractive(
options: CreateOptions,
): Promise<RunCommandResult> {
log.info(`Creating a new project at ${resolve(options.path!)}`);

const template = await getTemplateById(
options.template ?? DEFAULT_TEMPLATE_ID,
);
Expand Down Expand Up @@ -290,8 +294,20 @@ export function getCreateCommand(context: CLIContext): Command {
)
.option("--deploy", "Build and deploy the site")
.option("--no-skills", "Skip AI agent skills installation")
.addHelpText(
"after",
`
Examples:
$ base44 create my-app Creates a base44 project at ./my-app
$ base44 create my-todo-app --template backend-and-client Creates a base44 backend-and-client project at ./my-todo-app
$ base44 create my-app --path ./projects/my-app --deploy Creates a base44 project at ./project/my-app and deploys it`,
)
.hook("preAction", validateNonInteractiveFlags)
.action(async (name: string | undefined, options: CreateOptions) => {
if (name && !options.path) {
options.path = `./${kebabCase(name)}`;
}

const isNonInteractive = !!(options.name ?? name) && !!options.path;

if (isNonInteractive) {
Expand Down
13 changes: 12 additions & 1 deletion packages/cli/tests/cli/create.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe("create command", () => {
const result = await t.run("create", "--path", "./my-project");

t.expectResult(result).toFail();
t.expectResult(result).toContain("Non-interactive mode requires all flags");
t.expectResult(result).toContain("--path requires a project name argument");
});

it("creates project in non-interactive mode", async () => {
Expand All @@ -36,6 +36,17 @@ describe("create command", () => {
t.expectResult(result).toContain("new-project-id");
});

it("infers path from name when --path is not provided", async () => {
await t.givenLoggedIn({ email: "test@example.com", name: "Test User" });
t.api.mockCreateApp({ id: "inferred-path-id", name: "My App" });

const result = await t.run("create", "My App", "--no-skills");

t.expectResult(result).toSucceed();
t.expectResult(result).toContain("Creating a new project at");
t.expectResult(result).toContain("Project created successfully");
});

it("creates project with custom template", async () => {
await t.givenLoggedIn({ email: "test@example.com", name: "Test User" });
t.api.mockCreateApp({
Expand Down
Loading