Skip to content
Open
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: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,18 @@ The CLI will guide you through project setup. For step-by-step tutorials, see th

| Command | Description |
| ------- | ----------- |
| [`create`](https://docs.base44.com/developers/references/cli/commands/create) | Create a new Base44 project from a template |
| [`deploy`](https://docs.base44.com/developers/references/cli/commands/deploy) | Deploy resources and site to Base44 |
| [`link`](https://docs.base44.com/developers/references/cli/commands/link) | Link a local project to a project on Base44 |
| [`create`](https://docs.base44.com/developers/references/cli/commands/create) | Create a new Base44 project |
| [`deploy`](https://docs.base44.com/developers/references/cli/commands/deploy) | Deploy all project resources (entities, functions, agents, and site) |
| [`eject`](https://docs.base44.com/developers/references/cli/commands/eject) | Download the code for an existing Base44 project |
| [`link`](https://docs.base44.com/developers/references/cli/commands/link) | Link a local project to a Base44 project (create new or link existing) |
| [`status`](https://docs.base44.com/developers/references/cli/commands/status) | Show current project and authentication status |
| [`dashboard open`](https://docs.base44.com/developers/references/cli/commands/dashboard) | Open the app dashboard in your browser |
| [`login`](https://docs.base44.com/developers/references/cli/commands/login) | Authenticate with Base44 |
| [`logout`](https://docs.base44.com/developers/references/cli/commands/logout) | Sign out and clear stored credentials |
| [`whoami`](https://docs.base44.com/developers/references/cli/commands/whoami) | Display the current authenticated user |
| [`agents pull`](https://docs.base44.com/developers/references/cli/commands/agents-pull) | Pull agents from Base44 to local files |
| [`agents push`](https://docs.base44.com/developers/references/cli/commands/agents-push) | Push local agents to Base44 |
| [`entities push`](https://docs.base44.com/developers/references/cli/commands/entities-push) | Push local entity schemas to Base44 |
| [`logout`](https://docs.base44.com/developers/references/cli/commands/logout) | Logout from current device |
| [`whoami`](https://docs.base44.com/developers/references/cli/commands/whoami) | Display current authenticated user |
| [`agents pull`](https://docs.base44.com/developers/references/cli/commands/agents-pull) | Pull agents from Base44 to local files (replaces all local agent configs) |
| [`agents push`](https://docs.base44.com/developers/references/cli/commands/agents-push) | Push local agents to Base44 (replaces all remote agent configs) |
| [`entities push`](https://docs.base44.com/developers/references/cli/commands/entities-push) | Push local entities to Base44 |
| [`functions deploy`](https://docs.base44.com/developers/references/cli/commands/functions-deploy) | Deploy local functions to Base44 |
| [`site deploy`](https://docs.base44.com/developers/references/cli/commands/site-deploy) | Deploy built site files to Base44 hosting |
| [`site open`](https://docs.base44.com/developers/references/cli/commands/site-open) | Open the published site in your browser |
Expand Down
2 changes: 1 addition & 1 deletion src/cli/commands/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ async function devAction(options: DevOptions): Promise<RunCommandResult> {

export function getDevCommand(context: CLIContext): Command {
return new Command("dev")
.description("Start the development server")
.description("Start the local development server with hot reload")
.option("-p, --port <number>", "Port for the development server")
.action(async (options: DevOptions) => {
await runCommand(
Expand Down
29 changes: 29 additions & 0 deletions src/cli/commands/project/status.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Command } from "commander";
import { log } from "@clack/prompts";
import type { CLIContext } from "@/cli/types.js";
import { getDashboardUrl, runCommand, theme } from "@/cli/utils/index.js";
import type { RunCommandResult } from "@/cli/utils/runCommand.js";
import { readAuth } from "@/core/auth/index.js";
import { getAppConfig } from "@/core/project/index.js";

async function status(): Promise<RunCommandResult> {
const appConfig = getAppConfig();
const auth = await readAuth();

log.info(`${theme.styles.header("App ID")}: ${appConfig.id}`);
log.info(`${theme.styles.header("Project")}: ${appConfig.projectRoot}`);
log.info(`${theme.styles.header("User")}: ${theme.styles.bold(auth.email)}`);
log.info(
`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl(appConfig.id))}`,
);

return {};
}

export function getStatusCommand(context: CLIContext): Command {
return new Command("status")
.description("Show current project and authentication status")
.action(async () => {
await runCommand(status, { requireAuth: true }, context);
});
}
2 changes: 2 additions & 0 deletions src/cli/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { getTypesCommand } from "@/cli/commands/types/index.js";
import packageJson from "../../package.json";
import { getDevCommand } from "./commands/dev.js";
import { getEjectCommand } from "./commands/project/eject.js";
import { getStatusCommand } from "./commands/project/status.js";
import type { CLIContext } from "./types.js";

export function createProgram(context: CLIContext): Command {
Expand Down Expand Up @@ -41,6 +42,7 @@ export function createProgram(context: CLIContext): Command {
program.addCommand(getDeployCommand(context));
program.addCommand(getLinkCommand(context));
program.addCommand(getEjectCommand(context));
program.addCommand(getStatusCommand(context));

// Register entities commands
program.addCommand(getEntitiesPushCommand(context));
Expand Down
42 changes: 22 additions & 20 deletions src/cli/utils/runCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,28 +105,30 @@ export async function runCommand(
const { outroMessage } = await commandFn();
outro(outroMessage || "");
} catch (error) {
// Display error message
const errorMessage = error instanceof Error ? error.message : String(error);
log.error(errorMessage);

// Show stack trace if DEBUG mode
if (process.env.DEBUG === "1" && error instanceof Error && error.stack) {
log.error(theme.styles.dim(error.stack));
}
displayCommandError(error, context);
throw error;
}
}

// Display hints if this is a CLIError with hints
if (isCLIError(error)) {
const hints = theme.format.agentHints(error.hints);
if (hints) {
log.error(hints);
}
}
/**
* Display a structured error with optional debug stack trace, hints, and context.
* Extracted from runCommand's catch block to keep the main flow readable.
*/
function displayCommandError(error: unknown, context: CLIContext): void {
const errorMessage = error instanceof Error ? error.message : String(error);
log.error(errorMessage);

// Get error context and display in outro
const errorContext = context.errorReporter.getErrorContext();
outro(theme.format.errorContext(errorContext));
if (process.env.DEBUG === "1" && error instanceof Error && error.stack) {
log.error(theme.styles.dim(error.stack));
}

// Re-throw for runCLI to handle (error reporting, exit code)
throw error;
if (isCLIError(error)) {
const hints = theme.format.agentHints(error.hints);
if (hints) {
log.error(hints);
}
}

const errorContext = context.errorReporter.getErrorContext();
outro(theme.format.errorContext(errorContext));
}
Loading