genbox 1.0.25 → 1.0.27

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/dist/api.js CHANGED
@@ -49,10 +49,26 @@ async function fetchApi(endpoint, options = {}) {
49
49
  if (token) {
50
50
  headers['Authorization'] = `Bearer ${token}`;
51
51
  }
52
- const response = await fetch(url, {
53
- ...options,
54
- headers,
55
- });
52
+ let response;
53
+ try {
54
+ response = await fetch(url, {
55
+ ...options,
56
+ headers,
57
+ });
58
+ }
59
+ catch (error) {
60
+ // Handle network-level errors (DNS, connection refused, timeout, etc.)
61
+ if (error.cause?.code === 'ECONNREFUSED') {
62
+ throw new Error(`Cannot connect to Genbox API at ${API_URL}. Is the server running?`);
63
+ }
64
+ if (error.cause?.code === 'ENOTFOUND') {
65
+ throw new Error(`Cannot resolve Genbox API host. Check your internet connection.`);
66
+ }
67
+ if (error.message?.includes('fetch failed')) {
68
+ throw new Error(`Cannot connect to Genbox API at ${API_URL}. Check your internet connection or try again later.`);
69
+ }
70
+ throw new Error(`Network error: ${error.message}`);
71
+ }
56
72
  if (!response.ok) {
57
73
  // Handle authentication errors with a friendly message
58
74
  if (response.status === 401) {
@@ -66,7 +66,9 @@ function createShowCommand() {
66
66
  const configLoader = new config_loader_1.ConfigLoader();
67
67
  const loadResult = await configLoader.load();
68
68
  if (!loadResult.found || !loadResult.config) {
69
- console.log(chalk_1.default.red('No genbox.yaml found in current directory or parent directories'));
69
+ console.log(chalk_1.default.red('Not a genbox project'));
70
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
71
+ console.log(chalk_1.default.dim('Run "genbox init" to initialize a new project.'));
70
72
  process.exit(1);
71
73
  }
72
74
  const config = loadResult.config;
@@ -87,7 +89,8 @@ function createDiffCommand() {
87
89
  const configLoader = new config_loader_1.ConfigLoader();
88
90
  const loadResult = await configLoader.load();
89
91
  if (!loadResult.found || !loadResult.config) {
90
- console.log(chalk_1.default.red('No genbox.yaml found'));
92
+ console.log(chalk_1.default.red('Not a genbox project'));
93
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
91
94
  process.exit(1);
92
95
  }
93
96
  const config = loadResult.config;
@@ -196,11 +196,16 @@ exports.createCommand = new commander_1.Command('create')
196
196
  // Load configuration
197
197
  const configLoader = new config_loader_1.ConfigLoader();
198
198
  const loadResult = await configLoader.load();
199
+ if (!loadResult.config) {
200
+ console.log(chalk_1.default.red('Not a genbox project'));
201
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
202
+ console.log(chalk_1.default.dim('Run "genbox init" to initialize a new project.'));
203
+ return;
204
+ }
199
205
  const configVersion = (0, schema_v4_1.getConfigVersion)(loadResult.config);
200
- if (!loadResult.config || configVersion === 'unknown') {
201
- // Fall back to legacy v1/v2 handling
202
- const name = nameArg || await promptForName(options.yes);
203
- await createLegacy(name, options);
206
+ if (configVersion === 'unknown') {
207
+ console.log(chalk_1.default.red('Unknown config version'));
208
+ console.log(chalk_1.default.dim('Run "genbox init" to create a new configuration.'));
204
209
  return;
205
210
  }
206
211
  // Support both v3 and v4 configs
@@ -758,6 +763,14 @@ function buildPayload(resolved, config, publicKey, privateKey, configLoader) {
758
763
  gitToken: envVars.GIT_TOKEN,
759
764
  envVars: resolved.env,
760
765
  apps: resolved.apps.map(a => a.name),
766
+ appConfigs: resolved.apps.map(a => ({
767
+ name: a.name,
768
+ path: a.path.startsWith('/') ? a.path : `${resolved.repos[0]?.path || '/home/dev'}/${a.path}`,
769
+ type: a.type,
770
+ port: a.port,
771
+ framework: a.framework,
772
+ commands: a.commands,
773
+ })),
761
774
  infrastructure: resolved.infrastructure.map(i => ({
762
775
  name: i.name,
763
776
  type: i.type,
@@ -960,6 +960,26 @@ exports.initCommand = new commander_1.Command('init')
960
960
  console.log(chalk_1.default.dim(' Or use env var: CORS_ORIGINS=*.genbox.dev'));
961
961
  console.log('');
962
962
  console.log(chalk_1.default.red(' Without this, you will see CORS errors when accessing genbox environments.'));
963
+ // OAuth Configuration Instructions
964
+ console.log('');
965
+ console.log(chalk_1.default.yellow('=== OAuth Provider Configuration ==='));
966
+ console.log(chalk_1.default.white('If your app uses OAuth (Google, GitHub, etc.), add *.genbox.dev to allowed domains:'));
967
+ console.log('');
968
+ console.log(chalk_1.default.dim(' Google OAuth (console.cloud.google.com):'));
969
+ console.log(chalk_1.default.cyan(' Authorized JavaScript origins:'));
970
+ console.log(chalk_1.default.cyan(' https://*.genbox.dev'));
971
+ console.log(chalk_1.default.cyan(' Authorized redirect URIs:'));
972
+ console.log(chalk_1.default.cyan(' https://*.genbox.dev/api/auth/callback/google'));
973
+ console.log(chalk_1.default.cyan(' https://*.genbox.dev/auth/google/callback'));
974
+ console.log('');
975
+ console.log(chalk_1.default.dim(' GitHub OAuth (github.com/settings/developers):'));
976
+ console.log(chalk_1.default.cyan(' Authorization callback URL:'));
977
+ console.log(chalk_1.default.cyan(' https://*.genbox.dev/api/auth/callback/github'));
978
+ console.log('');
979
+ console.log(chalk_1.default.dim(' Other providers (Auth0, Clerk, etc.):'));
980
+ console.log(chalk_1.default.cyan(' Add *.genbox.dev to allowed callback URLs/origins'));
981
+ console.log('');
982
+ console.log(chalk_1.default.red(' Without this, OAuth flows will fail in genbox environments.'));
963
983
  }
964
984
  // Next steps
965
985
  console.log('');
@@ -967,14 +987,16 @@ exports.initCommand = new commander_1.Command('init')
967
987
  console.log(chalk_1.default.dim(` 1. Review and edit ${CONFIG_FILENAME}`));
968
988
  if (hasBackendApps && hasFrontendApps) {
969
989
  console.log(chalk_1.default.yellow(` 2. Add .genbox.dev to your backend CORS configuration`));
970
- console.log(chalk_1.default.dim(` 3. Update ${ENV_FILENAME} to use API URL variables where needed`));
971
- console.log(chalk_1.default.dim(` 4. Run 'genbox profiles' to see available profiles`));
972
- console.log(chalk_1.default.dim(` 5. Run 'genbox create <name> --profile <profile>' to create an environment`));
990
+ console.log(chalk_1.default.yellow(` 3. Add *.genbox.dev to OAuth providers (Google, GitHub, etc.) if using auth`));
991
+ console.log(chalk_1.default.dim(` 4. Update ${ENV_FILENAME} to use API URL variables where needed`));
992
+ console.log(chalk_1.default.dim(` 5. Run 'genbox profiles' to see available profiles`));
993
+ console.log(chalk_1.default.dim(` 6. Run 'genbox create <name> --profile <profile>' to create an environment`));
973
994
  }
974
995
  else {
975
996
  console.log(chalk_1.default.dim(` 2. Update ${ENV_FILENAME} to use API URL variables where needed`));
976
- console.log(chalk_1.default.dim(` 3. Run 'genbox profiles' to see available profiles`));
977
- console.log(chalk_1.default.dim(` 4. Run 'genbox create <name> --profile <profile>' to create an environment`));
997
+ console.log(chalk_1.default.dim(` 3. Add *.genbox.dev to OAuth providers if using auth`));
998
+ console.log(chalk_1.default.dim(` 4. Run 'genbox profiles' to see available profiles`));
999
+ console.log(chalk_1.default.dim(` 5. Run 'genbox create <name> --profile <profile>' to create an environment`));
978
1000
  }
979
1001
  }
980
1002
  catch (error) {
@@ -990,35 +1012,59 @@ exports.initCommand = new commander_1.Command('init')
990
1012
  * Create default profiles (sync version for non-interactive mode)
991
1013
  */
992
1014
  function createDefaultProfilesSync(scan, config) {
993
- return createProfilesFromScan(scan);
1015
+ const definedEnvs = Object.keys(config.environments || {});
1016
+ return createProfilesFromScan(scan, definedEnvs);
994
1017
  }
995
1018
  async function createDefaultProfiles(scan, config) {
996
- return createProfilesFromScan(scan);
1019
+ // Get defined environments to use in profiles
1020
+ const definedEnvs = Object.keys(config.environments || {});
1021
+ return createProfilesFromScan(scan, definedEnvs);
997
1022
  }
998
- function createProfilesFromScan(scan) {
1023
+ function createProfilesFromScan(scan, definedEnvironments = []) {
999
1024
  const profiles = {};
1000
1025
  const frontendApps = scan.apps.filter(a => a.type === 'frontend');
1001
1026
  const backendApps = scan.apps.filter(a => a.type === 'backend' || a.type === 'api');
1002
1027
  const hasApi = scan.apps.some(a => a.name === 'api' || a.type === 'backend');
1028
+ // Determine which environment to use for remote connections
1029
+ // Priority: staging > production > first defined
1030
+ const remoteEnv = definedEnvironments.includes('staging')
1031
+ ? 'staging'
1032
+ : definedEnvironments.includes('production')
1033
+ ? 'production'
1034
+ : definedEnvironments[0];
1003
1035
  // Quick UI profiles for each frontend (v4: use default_connection instead of connect_to)
1004
- for (const frontend of frontendApps.slice(0, 3)) {
1005
- profiles[`${frontend.name}-quick`] = {
1006
- description: `${frontend.name} only, connected to staging`,
1007
- size: 'small',
1008
- apps: [frontend.name],
1009
- default_connection: 'staging',
1010
- };
1036
+ // Only create if we have a remote environment defined
1037
+ if (remoteEnv) {
1038
+ for (const frontend of frontendApps.slice(0, 3)) {
1039
+ profiles[`${frontend.name}-quick`] = {
1040
+ description: `${frontend.name} only, connected to ${remoteEnv}`,
1041
+ size: 'small',
1042
+ apps: [frontend.name],
1043
+ default_connection: remoteEnv,
1044
+ };
1045
+ }
1046
+ }
1047
+ else {
1048
+ // No remote environment - create local-only profiles
1049
+ for (const frontend of frontendApps.slice(0, 3)) {
1050
+ profiles[`${frontend.name}-local`] = {
1051
+ description: `${frontend.name} with local API`,
1052
+ size: 'medium',
1053
+ apps: [frontend.name, ...(hasApi ? ['api'] : [])],
1054
+ };
1055
+ }
1011
1056
  }
1012
- // Full local development
1057
+ // Full local development (with DB copy from available environment)
1013
1058
  if (hasApi && frontendApps.length > 0) {
1014
1059
  const primaryFrontend = frontendApps[0];
1060
+ const dbSource = remoteEnv || 'staging'; // Use defined env or default
1015
1061
  profiles[`${primaryFrontend.name}-full`] = {
1016
1062
  description: `${primaryFrontend.name} + local API + DB copy`,
1017
1063
  size: 'large',
1018
1064
  apps: [primaryFrontend.name, 'api'],
1019
1065
  database: {
1020
- mode: 'copy',
1021
- source: 'staging',
1066
+ mode: remoteEnv ? 'copy' : 'local', // Only copy if we have a source
1067
+ ...(remoteEnv && { source: dbSource }),
1022
1068
  },
1023
1069
  };
1024
1070
  }
@@ -1033,24 +1079,25 @@ function createProfilesFromScan(scan) {
1033
1079
  },
1034
1080
  };
1035
1081
  }
1036
- // All frontends + staging (v4: use default_connection)
1037
- if (frontendApps.length > 1) {
1038
- profiles['frontends-staging'] = {
1039
- description: 'All frontends with staging backend',
1082
+ // All frontends + remote backend (only if remote env defined)
1083
+ if (frontendApps.length > 1 && remoteEnv) {
1084
+ profiles[`frontends-${remoteEnv}`] = {
1085
+ description: `All frontends with ${remoteEnv} backend`,
1040
1086
  size: 'medium',
1041
1087
  apps: frontendApps.map(a => a.name),
1042
- default_connection: 'staging',
1088
+ default_connection: remoteEnv,
1043
1089
  };
1044
1090
  }
1045
1091
  // Full stack
1046
1092
  if (scan.apps.length > 1) {
1093
+ const dbSource = remoteEnv || 'staging';
1047
1094
  profiles['full-stack'] = {
1048
- description: 'Everything local with DB copy',
1095
+ description: 'Everything local' + (remoteEnv ? ' with DB copy' : ''),
1049
1096
  size: 'xl',
1050
1097
  apps: scan.apps.filter(a => a.type !== 'library').map(a => a.name),
1051
1098
  database: {
1052
- mode: 'copy',
1053
- source: 'staging',
1099
+ mode: remoteEnv ? 'copy' : 'local',
1100
+ ...(remoteEnv && { source: dbSource }),
1054
1101
  },
1055
1102
  };
1056
1103
  }
@@ -71,7 +71,8 @@ exports.migrateCommand = new commander_1.Command('migrate')
71
71
  const configLoader = new config_loader_1.ConfigLoader();
72
72
  const loadResult = await configLoader.load(cwd);
73
73
  if (!loadResult.found || !loadResult.config) {
74
- console.log(chalk_1.default.red('No genbox.yaml found. Nothing to migrate.'));
74
+ console.log(chalk_1.default.red('Not a genbox project'));
75
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
75
76
  process.exit(1);
76
77
  }
77
78
  const config = loadResult.config;
@@ -213,7 +214,8 @@ exports.deprecationsCommand = new commander_1.Command('deprecations')
213
214
  const configLoader = new config_loader_1.ConfigLoader();
214
215
  const loadResult = await configLoader.load(cwd);
215
216
  if (!loadResult.found || !loadResult.config) {
216
- console.log(chalk_1.default.red('No genbox.yaml found.'));
217
+ console.log(chalk_1.default.red('Not a genbox project'));
218
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
217
219
  process.exit(1);
218
220
  }
219
221
  const deprecations = (0, migration_1.checkDeprecations)(loadResult.config);
@@ -53,8 +53,9 @@ exports.profilesCommand = new commander_1.Command('profiles')
53
53
  const configLoader = new config_loader_1.ConfigLoader();
54
54
  const loadResult = await configLoader.load();
55
55
  if (!loadResult.config) {
56
- console.log(chalk_1.default.yellow('No genbox.yaml found'));
57
- console.log(chalk_1.default.dim('Run "genbox init" to create a configuration'));
56
+ console.log(chalk_1.default.red('Not a genbox project'));
57
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
58
+ console.log(chalk_1.default.dim('Run "genbox init" to initialize a new project.'));
58
59
  return;
59
60
  }
60
61
  const version = (0, schema_v4_1.getConfigVersion)(loadResult.config);
@@ -113,12 +114,13 @@ exports.profilesCommand
113
114
  const configLoader = new config_loader_1.ConfigLoader();
114
115
  const loadResult = await configLoader.load();
115
116
  if (!loadResult.config) {
116
- console.log(chalk_1.default.yellow('No genbox.yaml found'));
117
+ console.log(chalk_1.default.red('Not a genbox project'));
118
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
117
119
  return;
118
120
  }
119
121
  const configVersion = (0, schema_v4_1.getConfigVersion)(loadResult.config);
120
122
  if (configVersion === 'unknown') {
121
- console.log(chalk_1.default.yellow('Unknown config version'));
123
+ console.log(chalk_1.default.red('Unknown config version'));
122
124
  return;
123
125
  }
124
126
  const config = loadResult.config;
@@ -196,12 +198,13 @@ exports.profilesCommand
196
198
  const configLoader = new config_loader_1.ConfigLoader();
197
199
  const loadResult = await configLoader.load();
198
200
  if (!loadResult.config) {
199
- console.log(chalk_1.default.yellow('No genbox.yaml found'));
201
+ console.log(chalk_1.default.red('Not a genbox project'));
202
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
200
203
  return;
201
204
  }
202
205
  const configVersion = (0, schema_v4_1.getConfigVersion)(loadResult.config);
203
206
  if (configVersion === 'unknown') {
204
- console.log(chalk_1.default.yellow('Unknown config version'));
207
+ console.log(chalk_1.default.red('Unknown config version'));
205
208
  return;
206
209
  }
207
210
  const config = loadResult.config;
@@ -318,12 +321,13 @@ exports.profilesCommand
318
321
  const configLoader = new config_loader_1.ConfigLoader();
319
322
  const loadResult = await configLoader.load();
320
323
  if (!loadResult.config) {
321
- console.log(chalk_1.default.yellow('No genbox.yaml found'));
324
+ console.log(chalk_1.default.red('Not a genbox project'));
325
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
322
326
  return;
323
327
  }
324
328
  const configVersion = (0, schema_v4_1.getConfigVersion)(loadResult.config);
325
329
  if (configVersion === 'unknown') {
326
- console.log(chalk_1.default.yellow('Unknown config version'));
330
+ console.log(chalk_1.default.red('Unknown config version'));
327
331
  return;
328
332
  }
329
333
  const config = loadResult.config;
@@ -463,9 +463,15 @@ exports.rebuildCommand = new commander_1.Command('rebuild')
463
463
  // Load configuration
464
464
  const configLoader = new config_loader_1.ConfigLoader();
465
465
  const loadResult = await configLoader.load();
466
+ if (!loadResult.config) {
467
+ console.log(chalk_1.default.red('Not a genbox project'));
468
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
469
+ console.log(chalk_1.default.dim('Run "genbox init" to initialize a new project.'));
470
+ return;
471
+ }
466
472
  const configVersion = (0, schema_v4_1.getConfigVersion)(loadResult.config);
467
- if (!loadResult.config || configVersion === 'unknown') {
468
- console.error(chalk_1.default.red('No valid genbox.yaml configuration found'));
473
+ if (configVersion === 'unknown') {
474
+ console.log(chalk_1.default.red('Unknown config version'));
469
475
  return;
470
476
  }
471
477
  const config = loadResult.config;
@@ -77,7 +77,9 @@ exports.resolveCommand = new commander_1.Command('resolve')
77
77
  const configLoader = new config_loader_1.ConfigLoader();
78
78
  const loadResult = await configLoader.load(cwd);
79
79
  if (!loadResult.found || !loadResult.config) {
80
- console.log(chalk_1.default.red('No genbox.yaml found. Run "genbox init" first.'));
80
+ console.log(chalk_1.default.red('Not a genbox project'));
81
+ console.log(chalk_1.default.dim('No genbox.yaml found in current directory.'));
82
+ console.log(chalk_1.default.dim('Run "genbox init" to initialize a new project.'));
81
83
  process.exit(1);
82
84
  }
83
85
  let config = loadResult.config;
@@ -153,7 +153,7 @@ async function validateGenboxConfig(cwd) {
153
153
  if (!loadResult.found || !loadResult.config) {
154
154
  errors.push({
155
155
  path: 'genbox.yaml',
156
- message: 'No genbox.yaml found. Run "genbox init" first.',
156
+ message: 'Not a genbox project. No genbox.yaml found in current directory.',
157
157
  severity: 'error',
158
158
  });
159
159
  return { valid: false, errors, warnings };
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  /**
3
- * Multi-Level Configuration Loader
3
+ * Configuration Loader
4
4
  *
5
- * Resolution order (highest priority first):
6
- * 1. CLI flags
7
- * 2. User profiles (~/.genbox/profiles.yaml)
8
- * 3. Project config (./genbox.yaml)
9
- * 4. Workspace config (../genbox.yaml)
10
- * 5. User defaults (~/.genbox/config.json)
5
+ * Loads genbox.yaml from the CURRENT directory only.
6
+ * No parent directory lookup - each project is self-contained.
7
+ *
8
+ * Additional sources (merged with project config):
9
+ * - User profiles (~/.genbox/profiles.yaml)
10
+ * - User defaults (~/.genbox/config.json)
11
11
  */
12
12
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
13
  if (k2 === undefined) k2 = k;
@@ -92,21 +92,13 @@ class ConfigLoader {
92
92
  async load(cwd = process.cwd()) {
93
93
  const sources = [];
94
94
  const warnings = [];
95
- // 1. Find and load workspace config (parent directories)
96
- const workspaceConfig = this.findWorkspaceConfig(cwd);
97
- if (workspaceConfig) {
98
- sources.push(workspaceConfig);
99
- }
100
- // 2. Load project config (current directory or git root)
95
+ // Load project config from current directory ONLY
101
96
  const projectConfig = this.loadProjectConfig(cwd);
102
97
  if (projectConfig) {
103
98
  sources.push(projectConfig);
104
99
  }
105
- // 3. Load user config
100
+ // Load user config (for user-level defaults and profiles)
106
101
  const userConfig = this.loadUserConfig();
107
- // Determine if this is a workspace setup
108
- const isWorkspace = workspaceConfig !== null &&
109
- (projectConfig === null || workspaceConfig.path !== projectConfig.path);
110
102
  // Merge configurations
111
103
  const mergedConfig = this.mergeConfigs(sources, userConfig);
112
104
  // Validate
@@ -115,56 +107,17 @@ class ConfigLoader {
115
107
  warnings.push(...validation.errors.map(e => e.message));
116
108
  }
117
109
  warnings.push(...validation.warnings.map(w => w.message));
118
- // Determine root directory
119
- const root = workspaceConfig?.path
120
- ? path.dirname(workspaceConfig.path)
121
- : projectConfig?.path
122
- ? path.dirname(projectConfig.path)
123
- : cwd;
110
+ // Root is current directory
111
+ const root = projectConfig?.path ? path.dirname(projectConfig.path) : cwd;
124
112
  return {
125
113
  found: sources.length > 0,
126
114
  config: sources.length > 0 ? mergedConfig : null,
127
115
  sources,
128
116
  warnings,
129
- isWorkspace,
117
+ isWorkspace: false,
130
118
  root,
131
119
  };
132
120
  }
133
- /**
134
- * Find workspace config by searching parent directories
135
- */
136
- findWorkspaceConfig(startDir) {
137
- let currentDir = path.resolve(startDir);
138
- const root = path.parse(currentDir).root;
139
- // Go up to 5 levels max
140
- for (let i = 0; i < 5; i++) {
141
- const parentDir = path.dirname(currentDir);
142
- // Stop at filesystem root
143
- if (parentDir === currentDir || parentDir === root) {
144
- break;
145
- }
146
- const configPath = path.join(parentDir, CONFIG_FILENAME);
147
- if (fs.existsSync(configPath)) {
148
- try {
149
- const content = fs.readFileSync(configPath, 'utf8');
150
- const config = yaml.load(content);
151
- // Check if it's a workspace config (has structure: 'workspace' or multiple repos)
152
- if (config.project?.structure === 'workspace' || config.repos) {
153
- return {
154
- type: 'workspace',
155
- path: configPath,
156
- config,
157
- };
158
- }
159
- }
160
- catch (err) {
161
- console.warn(`Warning: Could not parse ${configPath}:`, err);
162
- }
163
- }
164
- currentDir = parentDir;
165
- }
166
- return null;
167
- }
168
121
  /**
169
122
  * Load project config from current directory
170
123
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genbox",
3
- "version": "1.0.25",
3
+ "version": "1.0.27",
4
4
  "description": "Genbox CLI - AI-Powered Development Environments",
5
5
  "main": "dist/index.js",
6
6
  "bin": {