genbox 1.0.191 → 1.0.192

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.
@@ -654,6 +654,7 @@ exports.createCommand = new commander_1.Command('create')
654
654
  .option('--dry-run', 'Show what would be created without actually creating')
655
655
  .option('-r, --restore', 'Restore from backup (uses genbox name to find backup)')
656
656
  .option('--inject-claude-auth', 'Inject local Claude Code credentials for remote execution')
657
+ .option('--inject-gemini-auth', 'Inject local Gemini CLI credentials for remote execution')
657
658
  .action(async (nameArg, options) => {
658
659
  try {
659
660
  // Handle local genbox creation
@@ -1142,6 +1143,40 @@ exports.createCommand = new commander_1.Command('create')
1142
1143
  console.log(chalk_1.default.dim(' Claude Code will be installed with your credentials'));
1143
1144
  }
1144
1145
  }
1146
+ // Handle Gemini CLI credential injection
1147
+ // Check both CLI flag and genbox.yaml config
1148
+ const shouldInjectGeminiAuth = options.injectGeminiAuth || config.defaults?.inject_gemini_auth;
1149
+ if (shouldInjectGeminiAuth) {
1150
+ console.log('');
1151
+ console.log(chalk_1.default.blue('=== Gemini CLI Authentication ==='));
1152
+ const geminiCreds = (0, utils_1.getGeminiCredentials)();
1153
+ if (!geminiCreds.found) {
1154
+ console.log(chalk_1.default.yellow('⚠ Gemini CLI credentials not found'));
1155
+ console.log(chalk_1.default.dim(` ${geminiCreds.error}`));
1156
+ console.log('');
1157
+ console.log((0, utils_1.getGeminiAuthInstructions)());
1158
+ console.log('');
1159
+ if (!options.yes) {
1160
+ const continueWithoutGemini = await prompts.confirm({
1161
+ message: 'Continue without Gemini authentication?',
1162
+ default: false,
1163
+ });
1164
+ if (!continueWithoutGemini) {
1165
+ console.log(chalk_1.default.dim('Cancelled.'));
1166
+ return;
1167
+ }
1168
+ }
1169
+ else {
1170
+ console.log(chalk_1.default.dim('Continuing without Gemini authentication (use -y to skip prompts)'));
1171
+ }
1172
+ }
1173
+ else {
1174
+ payload.geminiCredentials = geminiCreds.credentials;
1175
+ payload.installGeminiCli = true; // Auto-enable Gemini CLI installation
1176
+ console.log(chalk_1.default.green(`✓ Gemini credentials found (${geminiCreds.source})`));
1177
+ console.log(chalk_1.default.dim(' Gemini CLI will be installed with your credentials'));
1178
+ }
1179
+ }
1145
1180
  // Create genbox
1146
1181
  const spinner = (0, ora_1.default)(`Creating Genbox '${name}'...`).start();
1147
1182
  try {
@@ -833,7 +833,24 @@ async function getProjectSettings(detected, existingEnvValues) {
833
833
  console.log(chalk_1.default.dim(' This enables running Claude prompts remotely with your subscription.'));
834
834
  }
835
835
  }
836
- return { projectName, serverSize, baseBranch, installClaudeCode, injectClaudeAuth };
836
+ // Gemini CLI installation
837
+ const installGeminiCli = await prompts.confirm({
838
+ message: 'Install Gemini CLI on genbox servers?',
839
+ default: false,
840
+ });
841
+ // Gemini CLI credential injection
842
+ let injectGeminiAuth = false;
843
+ if (installGeminiCli) {
844
+ injectGeminiAuth = await prompts.confirm({
845
+ message: 'Inject your Gemini credentials into genboxes for remote execution?',
846
+ default: true,
847
+ });
848
+ if (injectGeminiAuth) {
849
+ console.log(chalk_1.default.dim(' Your local Gemini credentials will be injected when creating genboxes.'));
850
+ console.log(chalk_1.default.dim(' This enables running Gemini prompts remotely with your authentication.'));
851
+ }
852
+ }
853
+ return { projectName, serverSize, baseBranch, installClaudeCode, injectClaudeAuth, installGeminiCli, injectGeminiAuth };
837
854
  }
838
855
  // =============================================================================
839
856
  // Git Auth Setup
@@ -1489,6 +1506,12 @@ function generateConfig(detected, settings, repos, environments, profiles) {
1489
1506
  if (settings.injectClaudeAuth) {
1490
1507
  defaults.inject_claude_auth = true;
1491
1508
  }
1509
+ if (settings.installGeminiCli) {
1510
+ defaults.install_gemini_cli = true;
1511
+ }
1512
+ if (settings.injectGeminiAuth) {
1513
+ defaults.inject_gemini_auth = true;
1514
+ }
1492
1515
  // Map structure type
1493
1516
  const structureMap = {
1494
1517
  'single-app': 'single-app',
@@ -2255,6 +2278,8 @@ exports.initCommand = new commander_1.Command('init')
2255
2278
  baseBranch: detected.git?.branch || 'main',
2256
2279
  installClaudeCode: true,
2257
2280
  injectClaudeAuth: true,
2281
+ installGeminiCli: false,
2282
+ injectGeminiAuth: false,
2258
2283
  };
2259
2284
  const { repos, envVars: gitEnvVars } = await setupGitAuth(detected, settings.projectName, existingEnvValues);
2260
2285
  const environments = {};
@@ -12,6 +12,7 @@ const prompts_1 = require("@inquirer/prompts");
12
12
  const ora_1 = __importDefault(require("ora"));
13
13
  const api_1 = require("../api");
14
14
  const claude_auth_1 = require("../utils/claude-auth");
15
+ const gemini_auth_1 = require("../utils/gemini-auth");
15
16
  exports.setupCommand = new commander_1.Command('setup')
16
17
  .description('Configure user preferences (AI credentials, GitHub, defaults)')
17
18
  .option('--show', 'Show current configuration')
@@ -80,8 +81,30 @@ exports.setupCommand = new commander_1.Command('setup')
80
81
  console.log(chalk_1.default.dim(`Claude CLI: not found (${claudeCreds.error})`));
81
82
  console.log(chalk_1.default.dim(' Run "claude" to authenticate Claude Code first.'));
82
83
  }
83
- // TODO: Add Gemini and OpenAI credential detection when their CLIs are supported
84
- console.log(chalk_1.default.dim('\nGemini/OpenAI: Coming soon'));
84
+ // Gemini CLI
85
+ const geminiCreds = (0, gemini_auth_1.getGeminiCredentials)();
86
+ if (geminiCreds.found) {
87
+ const geminiStatus = current.geminiCredentials
88
+ ? chalk_1.default.green('configured')
89
+ : chalk_1.default.yellow('not synced');
90
+ console.log(`Gemini CLI: ${chalk_1.default.green('found locally')} | Server: ${geminiStatus}`);
91
+ const syncGemini = await (0, confirm_1.default)({
92
+ message: current.geminiCredentials
93
+ ? 'Update Gemini credentials on server?'
94
+ : 'Sync Gemini credentials to server?',
95
+ default: !current.geminiCredentials,
96
+ });
97
+ if (syncGemini) {
98
+ updates.geminiCredentials = geminiCreds.credentials;
99
+ console.log(chalk_1.default.green(' ✓ Gemini credentials will be synced'));
100
+ }
101
+ }
102
+ else {
103
+ console.log(chalk_1.default.dim(`Gemini CLI: not found (${geminiCreds.error})`));
104
+ console.log(chalk_1.default.dim(' Run "gemini" to authenticate Gemini CLI first.'));
105
+ }
106
+ // TODO: Add OpenAI credential detection when their CLI is supported
107
+ console.log(chalk_1.default.dim('\nOpenAI: Coming soon'));
85
108
  }
86
109
  // GitHub Token
87
110
  if (configureGithub) {
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ /**
3
+ * Gemini CLI Authentication Utilities
4
+ *
5
+ * Handles extraction of Gemini CLI credentials from:
6
+ * - ~/.gemini/oauth_creds.json (OAuth credentials from Google login)
7
+ * - GEMINI_API_KEY environment variable
8
+ *
9
+ * These credentials can be injected into genboxes to enable
10
+ * remote Gemini CLI execution using the user's authentication.
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.getGeminiCredentials = getGeminiCredentials;
47
+ exports.getGeminiAuthInstructions = getGeminiAuthInstructions;
48
+ const fs = __importStar(require("fs"));
49
+ const path = __importStar(require("path"));
50
+ const os = __importStar(require("os"));
51
+ /**
52
+ * Get Gemini CLI credentials from the appropriate source.
53
+ *
54
+ * Priority:
55
+ * 1. ~/.gemini/oauth_creds.json (Google OAuth login)
56
+ * 2. GEMINI_API_KEY environment variable
57
+ */
58
+ function getGeminiCredentials() {
59
+ // Try OAuth credentials file first (from `gemini` login)
60
+ const oauthResult = getCredentialsFromOAuthFile();
61
+ if (oauthResult.found) {
62
+ return oauthResult;
63
+ }
64
+ // Fallback to API key environment variable
65
+ const apiKey = process.env.GEMINI_API_KEY;
66
+ if (apiKey) {
67
+ return {
68
+ credentials: apiKey,
69
+ source: 'apikey',
70
+ found: true,
71
+ };
72
+ }
73
+ // Nothing found
74
+ return oauthResult; // Return the file result which has the error message
75
+ }
76
+ /**
77
+ * Extract credentials from ~/.gemini/oauth_creds.json
78
+ */
79
+ function getCredentialsFromOAuthFile() {
80
+ const credentialsPath = path.join(os.homedir(), '.gemini', 'oauth_creds.json');
81
+ if (!fs.existsSync(credentialsPath)) {
82
+ return {
83
+ credentials: '',
84
+ source: 'oauth',
85
+ found: false,
86
+ error: `Gemini credentials file not found at ${credentialsPath}. Run 'gemini' to authenticate first.`,
87
+ };
88
+ }
89
+ try {
90
+ const content = fs.readFileSync(credentialsPath, 'utf-8');
91
+ // Validate it's valid JSON with expected fields
92
+ const parsed = JSON.parse(content);
93
+ if (!parsed.access_token && !parsed.refresh_token) {
94
+ return {
95
+ credentials: '',
96
+ source: 'oauth',
97
+ found: false,
98
+ error: 'Gemini credentials file exists but appears invalid (missing tokens).',
99
+ };
100
+ }
101
+ return {
102
+ credentials: content,
103
+ source: 'oauth',
104
+ found: true,
105
+ };
106
+ }
107
+ catch (err) {
108
+ return {
109
+ credentials: '',
110
+ source: 'oauth',
111
+ found: false,
112
+ error: `Failed to read Gemini credentials: ${err.message}`,
113
+ };
114
+ }
115
+ }
116
+ /**
117
+ * Get instructions for authenticating Gemini CLI
118
+ */
119
+ function getGeminiAuthInstructions() {
120
+ return `To authenticate Gemini CLI:
121
+ 1. Install Gemini CLI: npm install -g @anthropic-ai/gemini-cli
122
+ 2. Run 'gemini' in your terminal
123
+ 3. Follow the browser authentication flow
124
+ 4. Your credentials will be stored in ~/.gemini/oauth_creds.json
125
+
126
+ Alternative: Set GEMINI_API_KEY environment variable with your API key.`;
127
+ }
@@ -23,4 +23,5 @@ __exportStar(require("./env-parser"), exports);
23
23
  __exportStar(require("./git-utils"), exports);
24
24
  __exportStar(require("./branch-prompt"), exports);
25
25
  __exportStar(require("./claude-auth"), exports);
26
+ __exportStar(require("./gemini-auth"), exports);
26
27
  __exportStar(require("./logo"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genbox",
3
- "version": "1.0.191",
3
+ "version": "1.0.192",
4
4
  "description": "Genbox CLI - AI-Powered Development Environments",
5
5
  "main": "dist/index.js",
6
6
  "bin": {