base44 0.0.16 → 0.0.18

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.
Files changed (28) hide show
  1. package/README.md +58 -142
  2. package/bin/dev.js +12 -0
  3. package/bin/run.js +12 -0
  4. package/dist/{cli/index.js → index.js} +55 -15
  5. package/package.json +7 -8
  6. /package/dist/{cli/templates → templates}/backend-and-client/.nvmrc +0 -0
  7. /package/dist/{cli/templates → templates}/backend-and-client/README.md +0 -0
  8. /package/dist/{cli/templates → templates}/backend-and-client/base44/app.jsonc.ejs +0 -0
  9. /package/dist/{cli/templates → templates}/backend-and-client/base44/config.jsonc.ejs +0 -0
  10. /package/dist/{cli/templates → templates}/backend-and-client/base44/entities/task.jsonc +0 -0
  11. /package/dist/{cli/templates → templates}/backend-and-client/components.json +0 -0
  12. /package/dist/{cli/templates → templates}/backend-and-client/index.html +0 -0
  13. /package/dist/{cli/templates → templates}/backend-and-client/jsconfig.json +0 -0
  14. /package/dist/{cli/templates → templates}/backend-and-client/package.json +0 -0
  15. /package/dist/{cli/templates → templates}/backend-and-client/postcss.config.js +0 -0
  16. /package/dist/{cli/templates → templates}/backend-and-client/src/App.jsx +0 -0
  17. /package/dist/{cli/templates → templates}/backend-and-client/src/api/base44Client.js.ejs +0 -0
  18. /package/dist/{cli/templates → templates}/backend-and-client/src/components/Base44Logo.jsx +0 -0
  19. /package/dist/{cli/templates → templates}/backend-and-client/src/components/ui/button.jsx +0 -0
  20. /package/dist/{cli/templates → templates}/backend-and-client/src/components/ui/checkbox.jsx +0 -0
  21. /package/dist/{cli/templates → templates}/backend-and-client/src/components/ui/input.jsx +0 -0
  22. /package/dist/{cli/templates → templates}/backend-and-client/src/index.css +0 -0
  23. /package/dist/{cli/templates → templates}/backend-and-client/src/main.jsx +0 -0
  24. /package/dist/{cli/templates → templates}/backend-and-client/tailwind.config.js +0 -0
  25. /package/dist/{cli/templates → templates}/backend-and-client/vite.config.js +0 -0
  26. /package/dist/{cli/templates → templates}/backend-only/base44/app.jsonc.ejs +0 -0
  27. /package/dist/{cli/templates → templates}/backend-only/base44/config.jsonc.ejs +0 -0
  28. /package/dist/{cli/templates → templates}/templates.json +0 -0
package/README.md CHANGED
@@ -1,193 +1,109 @@
1
1
  # Base44 CLI
2
2
 
3
- A unified command-line interface for managing Base44 applications, entities, functions, deployments, and related services.
3
+ Command-line interface for building applications with [Base44's backend service](https://docs.base44.com/developers/backend/overview/introduction).
4
4
 
5
- **Zero dependencies** - installs in seconds with no dependency resolution.
5
+ Base44's backend service provides a managed backend for your applications, including data storage with entities, serverless functions, authentication, and hosting. The CLI lets you:
6
+
7
+ - **Create projects** from templates.
8
+ - **Sync** resources defined in local code with your Base44 backend.
9
+ - **Deploy sites** to Base44's hosting platform.
10
+
11
+ To get started, see the full list of commands below or check out the [documentation](https://docs.base44.com/developers/references/cli/get-started/overview).
6
12
 
7
13
  ## Installation
8
14
 
9
15
  ```bash
10
- # Using npm (globally)
11
16
  npm install -g base44
12
-
13
- # Or run directly with npx
14
- npx base44 <command>
15
17
  ```
16
18
 
17
- ## Quick Start
19
+ Or run commands directly with npx:
18
20
 
19
21
  ```bash
20
- # 1. Login to Base44
21
- base44 login
22
-
23
- # 2. Create a new project
24
- base44 create
25
-
26
- # 3. Deploy everything (entities, functions, and site)
27
- npm run build
28
- base44 deploy
22
+ npx base44 <command>
29
23
  ```
30
24
 
31
- ## Commands
32
-
33
- ### Authentication
25
+ Requires Node.js 20.19.0 or higher.
34
26
 
35
- | Command | Description |
36
- |---------|-------------|
37
- | `base44 login` | Authenticate with Base44 using device code flow |
38
- | `base44 whoami` | Display current authenticated user |
39
- | `base44 logout` | Logout from current device |
40
-
41
- ### Project Management
42
-
43
- | Command | Description |
44
- |---------|-------------|
45
- | `base44 create` | Create a new Base44 project from a template |
46
- | `base44 link` | Link a local project to Base44 (create new or link existing) |
47
- | `base44 dashboard` | Open the app dashboard in your browser |
48
-
49
- #### Link Command Options
50
-
51
- The `link` command supports both creating new projects and linking to existing ones:
27
+ ## Quick start
52
28
 
53
29
  ```bash
54
- # Interactive mode - choose to create new or link existing
55
- base44 link
56
-
57
- # Create a new project (non-interactive)
58
- base44 link --create --name "my-app" --description "My app description"
30
+ # Authenticate
31
+ base44 login
59
32
 
60
- # Link to an existing project by ID (non-interactive)
61
- base44 link --existing <app-id>
33
+ # Create a project
34
+ base44 create
62
35
  ```
63
36
 
64
- | Option | Description |
65
- |--------|-------------|
66
- | `-c, --create` | Create a new project (skip selection prompt) |
67
- | `-e, --existing <id>` | Link to an existing project by ID |
68
- | `-n, --name <name>` | Project name (required with --create) |
69
- | `-d, --description <desc>` | Project description (optional) |
37
+ The CLI will guide you through project setup. For step-by-step tutorials, see the quickstart guides:
70
38
 
71
- ### Deployment
72
-
73
- | Command | Description |
74
- |---------|-------------|
75
- | `base44 deploy` | Deploy all resources (entities, functions, and site) |
39
+ - [Backend only](https://docs.base44.com/developers/backend/quickstart/quickstart-backend-only) — for headless apps or custom frontends
40
+ - [React](https://docs.base44.com/developers/backend/quickstart/quickstart-with-react) — full-stack with Vite + React
76
41
 
77
- ### Entities
78
-
79
- | Command | Description |
80
- |---------|-------------|
81
- | `base44 entities push` | Push local entity schemas to Base44 |
82
-
83
- ### Functions
42
+ ## Commands
84
43
 
85
44
  | Command | Description |
86
- |---------|-------------|
87
- | `base44 functions deploy` | Deploy local functions to Base44 |
88
-
89
- ### Site
45
+ | ------- | ----------- |
46
+ | [`create`](https://docs.base44.com/developers/references/cli/commands/create) | Create a new Base44 project from a template |
47
+ | [`deploy`](https://docs.base44.com/developers/references/cli/commands/deploy) | Deploy resources and site to Base44 |
48
+ | [`link`](https://docs.base44.com/developers/references/cli/commands/link) | Link a local project to a project on Base44 |
49
+ | [`dashboard`](https://docs.base44.com/developers/references/cli/commands/dashboard) | Open the app dashboard in your browser |
50
+ | [`login`](https://docs.base44.com/developers/references/cli/commands/login) | Authenticate with Base44 |
51
+ | [`logout`](https://docs.base44.com/developers/references/cli/commands/logout) | Sign out and clear stored credentials |
52
+ | [`whoami`](https://docs.base44.com/developers/references/cli/commands/whoami) | Display the current authenticated user |
53
+ | [`entities push`](https://docs.base44.com/developers/references/cli/commands/entities-push) | Push local entity schemas to Base44 |
54
+ | [`functions deploy`](https://docs.base44.com/developers/references/cli/commands/functions-deploy) | Deploy local functions to Base44 |
55
+ | [`site deploy`](https://docs.base44.com/developers/references/cli/commands/site-deploy) | Deploy built site files to Base44 hosting |
90
56
 
91
- | Command | Description |
92
- |---------|-------------|
93
- | `base44 site deploy` | Deploy built site files to Base44 hosting |
94
57
 
95
- ## Configuration
58
+ <!--| [`eject`](https://docs.base44.com/developers/references/cli/commands/eject) | Create a Base44 backend project from an existing Base44 app | -->
96
59
 
97
- ### Project Configuration
60
+ ## AI Agent Skills
98
61
 
99
- Base44 projects are configured via a `config.jsonc` (or `config.json`) file in the `base44/` subdirectory:
62
+ When creating a project, you'll be prompted to install AI agent skills for your preferred coding assistants:
100
63
 
101
- ```jsonc
102
- // base44/config.jsonc
103
- {
104
- "name": "My Project",
105
- "entitiesDir": "./entities", // Default: ./entities
106
- "functionsDir": "./functions", // Default: ./functions
107
- "site": {
108
- "outputDirectory": "../dist" // Path to built site files
109
- }
110
- }
111
64
  ```
112
-
113
- ### App Configuration
114
-
115
- Your app ID is stored in a `.app.jsonc` file in the `base44/` directory. This file is created automatically when you run `base44 create` or `base44 link`:
116
-
117
- ```jsonc
118
- // base44/.app.jsonc
119
- {
120
- "id": "your-app-id"
121
- }
65
+ ◆ Add AI agent skills? (Select agents to configure)
66
+ │ ◼ Cursor
67
+ │ ◼ Claude Code
68
+
122
69
  ```
123
70
 
124
- ## Project Structure
71
+ This installs [base44/skills](https://github.com/base44/skills) which helps AI agents understand how to work with Base44 projects.
125
72
 
126
- A typical Base44 project has this structure:
127
-
128
- ```
129
- my-project/
130
- ├── base44/
131
- │ ├── config.jsonc # Project configuration
132
- │ ├── .app.jsonc # App ID (git-ignored)
133
- │ ├── entities/ # Entity schema files
134
- │ │ ├── user.jsonc
135
- │ │ └── product.jsonc
136
- │ └── functions/ # Backend functions
137
- │ └── my-function/
138
- │ ├── config.jsonc
139
- │ └── index.js
140
- ├── src/ # Your frontend code
141
- ├── dist/ # Built site files (for deployment)
142
- └── package.json
143
- ```
144
-
145
- ## Development
146
-
147
- ### Prerequisites
148
-
149
- - Node.js >= 20.19.0
150
- - npm
151
-
152
- ### Setup
73
+ **Non-interactive mode:**
153
74
 
154
75
  ```bash
155
- # Clone the repository
156
- git clone https://github.com/base44/cli.git
157
- cd cli
76
+ # Install skills for all supported agents
77
+ base44 create --name my-app --path ./my-app --skills
158
78
 
159
- # Install dependencies
160
- npm install
79
+ # Skip skills installation
80
+ base44 create --name my-app --path ./my-app
81
+ ```
161
82
 
162
- # Build
163
- npm run build
83
+ **Manual installation:**
164
84
 
165
- # Run in development mode
166
- npm run dev -- <command>
85
+ ```bash
86
+ npx add-skill base44/skills
167
87
  ```
168
88
 
169
- ### Available Scripts
89
+ ## Help
170
90
 
171
91
  ```bash
172
- npm run build # Build with tsdown
173
- npm run typecheck # Type check with tsc
174
- npm run dev # Run in development mode with tsx
175
- npm run lint # Lint with ESLint
176
- npm test # Run tests with Vitest
92
+ base44 --help
93
+ base44 <command> --help
177
94
  ```
178
95
 
179
- ### Running the Built CLI
96
+ ## Version
180
97
 
181
98
  ```bash
182
- # After building
183
- npm start -- <command>
184
-
185
- # Or directly
186
- ./dist/cli/index.js <command>
99
+ base44 --version
187
100
  ```
188
- ## Contributing
189
101
 
190
- See [AGENTS.md](./AGENTS.md) for development guidelines and architecture documentation.
102
+ ## Alpha
103
+
104
+ The CLI and Base44 backend service are currently in alpha. We're actively improving them based on user feedback. Share your thoughts and feature requests on our [GitHub Discussions](https://github.com/orgs/base44/discussions).
105
+
106
+ Found a bug? [Open an issue](https://github.com/base44/cli/issues).
191
107
 
192
108
  ## License
193
109
 
package/bin/dev.js ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env tsx
2
+ import { program, CLIExitError } from "../src/cli/index.ts";
3
+
4
+ try {
5
+ await program.parseAsync();
6
+ } catch (error) {
7
+ if (error instanceof CLIExitError) {
8
+ process.exit(error.code);
9
+ }
10
+ console.error(error);
11
+ process.exit(1);
12
+ }
package/bin/run.js ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ import { program, CLIExitError } from "../dist/index.js";
3
+
4
+ try {
5
+ await program.parseAsync();
6
+ } catch (error) {
7
+ if (error instanceof CLIExitError) {
8
+ process.exit(error.code);
9
+ }
10
+ console.error(error);
11
+ process.exit(1);
12
+ }
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env node
2
1
  import { createRequire } from "node:module";
3
2
  import { EventEmitter, addAbortListener, on, once, setMaxListeners } from "node:events";
4
3
  import childProcess, { ChildProcess, execFile, spawn, spawnSync } from "node:child_process";
@@ -16798,7 +16797,10 @@ async function createProject(projectName, description) {
16798
16797
  return { projectId: CreateProjectResponseSchema.parse(await response.json()).id };
16799
16798
  }
16800
16799
  async function listProjects() {
16801
- const response = await base44Client.get(`api/apps?sort=-updated_date&fields=id,name,user_description,is_managed_source_code`);
16800
+ const response = await base44Client.get(`api/apps`, { searchParams: {
16801
+ "sort": "-updated_date",
16802
+ "fields": "id,name,user_description,is_managed_source_code"
16803
+ } });
16802
16804
  return ProjectsResponseSchema.parse(await response.json());
16803
16805
  }
16804
16806
 
@@ -30583,6 +30585,21 @@ async function getUserInfo(accessToken) {
30583
30585
  return result.data;
30584
30586
  }
30585
30587
 
30588
+ //#endregion
30589
+ //#region src/cli/errors.ts
30590
+ /**
30591
+ * Error thrown to signal a controlled CLI exit with a specific exit code.
30592
+ * This allows proper error propagation without calling process.exit() directly,
30593
+ * making the code more testable and maintaining a single exit point.
30594
+ */
30595
+ var CLIExitError = class extends Error {
30596
+ constructor(code$1) {
30597
+ super(`CLI exited with code ${code$1}`);
30598
+ this.code = code$1;
30599
+ this.name = "CLIExitError";
30600
+ }
30601
+ };
30602
+
30586
30603
  //#endregion
30587
30604
  //#region node_modules/chalk/source/vendor/ansi-styles/index.js
30588
30605
  const ANSI_BACKGROUND_OFFSET = 10;
@@ -31149,7 +31166,7 @@ async function runCommand(commandFn, options) {
31149
31166
  } catch (e$1) {
31150
31167
  if (e$1 instanceof Error) M.error(e$1.stack ?? e$1.message);
31151
31168
  else M.error(String(e$1));
31152
- process.exit(1);
31169
+ throw new CLIExitError(1);
31153
31170
  }
31154
31171
  }
31155
31172
 
@@ -38090,6 +38107,7 @@ async function createInteractive(options) {
38090
38107
  description: result.description || void 0,
38091
38108
  projectPath: result.projectPath,
38092
38109
  deploy: options.deploy,
38110
+ skills: options.skills,
38093
38111
  isInteractive: true
38094
38112
  });
38095
38113
  }
@@ -38100,10 +38118,11 @@ async function createNonInteractive(options) {
38100
38118
  description: options.description,
38101
38119
  projectPath: options.path,
38102
38120
  deploy: options.deploy,
38121
+ skills: options.skills,
38103
38122
  isInteractive: false
38104
38123
  });
38105
38124
  }
38106
- async function executeCreate({ template, name: rawName, description, projectPath, deploy, isInteractive }) {
38125
+ async function executeCreate({ template, name: rawName, description, projectPath, deploy, skills, isInteractive }) {
38107
38126
  const name$1 = rawName.trim();
38108
38127
  const resolvedPath = resolve(projectPath);
38109
38128
  const { projectId } = await runTask("Setting up your project...", async () => {
@@ -38163,12 +38182,31 @@ async function executeCreate({ template, name: rawName, description, projectPath
38163
38182
  finalAppUrl = appUrl;
38164
38183
  }
38165
38184
  }
38185
+ let shouldAddSkills = false;
38186
+ if (isInteractive) {
38187
+ const result = await ye({ message: "Add AI agent skills?" });
38188
+ shouldAddSkills = !pD(result) && result;
38189
+ } else shouldAddSkills = !!skills;
38190
+ if (shouldAddSkills) await runTask("Installing AI agent skills...", async () => {
38191
+ await execa("npx", [
38192
+ "-y",
38193
+ "add-skill",
38194
+ "base44/skills",
38195
+ "-y"
38196
+ ], {
38197
+ cwd: resolvedPath,
38198
+ stdio: "inherit"
38199
+ });
38200
+ }, {
38201
+ successMessage: theme.colors.base44Orange("AI agent skills added successfully"),
38202
+ errorMessage: "Failed to add AI agent skills - you can add them later with: npx add-skill base44/skills"
38203
+ });
38166
38204
  M.message(`${theme.styles.header("Project")}: ${theme.colors.base44Orange(name$1)}`);
38167
38205
  M.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl(projectId))}`);
38168
38206
  if (finalAppUrl) M.message(`${theme.styles.header("Site")}: ${theme.colors.links(finalAppUrl)}`);
38169
38207
  return { outroMessage: "Your project is set up and ready to use" };
38170
38208
  }
38171
- const createCommand = new Command("create").description("Create a new Base44 project").option("-n, --name <name>", "Project name").option("-d, --description <description>", "Project description").option("-p, --path <path>", "Path where to create the project").option("-t, --template <id>", "Template ID (e.g., backend-only, backend-and-client)").option("--deploy", "Build and deploy the site").hook("preAction", validateNonInteractiveFlags$1).action(async (options) => {
38209
+ const createCommand = new Command("create").description("Create a new Base44 project").option("-n, --name <name>", "Project name").option("-d, --description <description>", "Project description").option("-p, --path <path>", "Path where to create the project").option("-t, --template <id>", "Template ID (e.g., backend-only, backend-and-client)").option("--deploy", "Build and deploy the site").option("--skills", "Add AI agent skills").hook("preAction", validateNonInteractiveFlags$1).action(async (options) => {
38172
38210
  await chooseCreate(options);
38173
38211
  });
38174
38212
 
@@ -38754,9 +38792,8 @@ const deployCommand = new Command("deploy").description("Deploy all project reso
38754
38792
  //#endregion
38755
38793
  //#region src/cli/commands/project/link.ts
38756
38794
  function validateNonInteractiveFlags(command) {
38757
- const { create: create$1, name: name$1, existing, projectId } = command.opts();
38758
- if (create$1 && existing) command.error("--create and --existing cannot be used together");
38759
- if (existing && !projectId) command.error("--projectId is required when using --existing");
38795
+ const { create: create$1, name: name$1, projectId } = command.opts();
38796
+ if (create$1 && projectId) command.error("--create and --projectId cannot be used together");
38760
38797
  if (create$1 && !name$1) command.error("--name is required when using --create");
38761
38798
  }
38762
38799
  async function promptForLinkAction() {
@@ -38820,14 +38857,18 @@ async function link(options) {
38820
38857
  if (!projectRoot) throw new Error("No Base44 project found. Run this command from a project directory with a config.jsonc file.");
38821
38858
  if (await appConfigExists(projectRoot.root)) throw new Error("Project is already linked. An .app.jsonc file with the appId already exists.");
38822
38859
  let finalProjectId;
38823
- const action = options.existing ? "choose" : options.create ? "create" : await promptForLinkAction();
38860
+ const action = options.projectId ? "choose" : options.create ? "create" : await promptForLinkAction();
38824
38861
  if (action === "choose") {
38825
38862
  const linkableProjects = (await runTask("Fetching projects...", async () => listProjects(), {
38826
38863
  successMessage: "Projects fetched",
38827
38864
  errorMessage: "Failed to fetch projects"
38828
38865
  })).filter((p$1) => p$1.isManagedSourceCode !== true);
38829
38866
  if (!linkableProjects.length) return { outroMessage: "No projects available for linking" };
38830
- const { id: projectId } = options.existing ? { id: options.projectId } : await promptForExistingProject(linkableProjects);
38867
+ let projectId;
38868
+ if (options.projectId) {
38869
+ if (!linkableProjects.find((p$1) => p$1.id === options.projectId)) throw new Error(`Project with ID "${options.projectId}" not found or not available for linking.`);
38870
+ projectId = options.projectId;
38871
+ } else projectId = (await promptForExistingProject(linkableProjects)).id;
38831
38872
  await runTask("Linking project...", async () => {
38832
38873
  await writeAppConfig(projectRoot.root, projectId);
38833
38874
  setAppConfig({
@@ -38861,7 +38902,7 @@ async function link(options) {
38861
38902
  M.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl(finalProjectId))}`);
38862
38903
  return { outroMessage: "Project linked" };
38863
38904
  }
38864
- const linkCommand = new Command("link").description("Link a local project to a Base44 project (create new or link existing)").option("-c, --create", "Create a new project (skip selection prompt)").option("-n, --name <name>", "Project name (required when --create is used)").option("-d, --description <description>", "Project description").option("-e, --existing", "Link to an existing project (skip selection prompt)").option("-p, --projectId <id>", "Project ID (required when --existing is used)").hook("preAction", validateNonInteractiveFlags).action(async (options) => {
38905
+ const linkCommand = new Command("link").description("Link a local project to a Base44 project (create new or link existing)").option("-c, --create", "Create a new project (skip selection prompt)").option("-n, --name <name>", "Project name (required when --create is used)").option("-d, --description <description>", "Project description").option("-p, --projectId <id>", "Project ID to link to an existing project (skips selection prompt)").hook("preAction", validateNonInteractiveFlags).action(async (options) => {
38865
38906
  await runCommand(() => link(options), {
38866
38907
  requireAuth: true,
38867
38908
  requireAppConfig: false
@@ -38891,10 +38932,10 @@ const siteDeployCommand = new Command("site").description("Manage site deploymen
38891
38932
 
38892
38933
  //#endregion
38893
38934
  //#region package.json
38894
- var version = "0.0.16";
38935
+ var version = "0.0.18";
38895
38936
 
38896
38937
  //#endregion
38897
- //#region src/cli/index.ts
38938
+ //#region src/cli/program.ts
38898
38939
  const program = new Command();
38899
38940
  program.name("base44").description("Base44 CLI - Unified interface for managing Base44 applications").version(version);
38900
38941
  program.configureHelp({ sortSubcommands: true });
@@ -38908,7 +38949,6 @@ program.addCommand(linkCommand);
38908
38949
  program.addCommand(entitiesPushCommand);
38909
38950
  program.addCommand(functionsDeployCommand);
38910
38951
  program.addCommand(siteDeployCommand);
38911
- program.parse();
38912
38952
 
38913
38953
  //#endregion
38914
- export { };
38954
+ export { CLIExitError, program };
package/package.json CHANGED
@@ -1,21 +1,20 @@
1
1
  {
2
2
  "name": "base44",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "description": "Base44 CLI - Unified interface for managing Base44 applications",
5
5
  "type": "module",
6
- "main": "./dist/cli/index.js",
7
- "bin": "./dist/cli/index.js",
8
- "exports": {
9
- ".": "./dist/cli/index.js"
6
+ "bin": {
7
+ "base44": "./bin/run.js"
10
8
  },
11
9
  "files": [
12
- "dist"
10
+ "dist",
11
+ "bin"
13
12
  ],
14
13
  "scripts": {
15
14
  "build": "tsdown",
16
15
  "typecheck": "tsc --noEmit",
17
- "dev": "tsx src/cli/index.ts",
18
- "start": "node dist/cli/index.js",
16
+ "dev": "./bin/dev.js",
17
+ "start": "./bin/run.js",
19
18
  "clean": "rm -rf dist",
20
19
  "lint": "eslint src",
21
20
  "test": "vitest run",