feat: add Gemini API key onboarding

This commit is contained in:
Jonáš Jančařík
2026-01-08 14:44:40 +01:00
committed by Peter Steinberger
parent 340d5d03f2
commit 302d51fd40
9 changed files with 75 additions and 2 deletions

View File

@@ -165,8 +165,9 @@ Options:
- `--workspace <dir>`
- `--non-interactive`
- `--mode <local|remote>`
- `--auth-choice <oauth|claude-cli|openai-codex|codex-cli|antigravity|apiKey|minimax|skip>`
- `--auth-choice <oauth|claude-cli|openai-codex|codex-cli|antigravity|gemini-api-key|apiKey|minimax|skip>`
- `--anthropic-api-key <key>`
- `--gemini-api-key <key>`
- `--gateway-port <port>`
- `--gateway-bind <loopback|lan|tailnet|auto>`
- `--gateway-auth <off|token|password>`

View File

@@ -170,6 +170,17 @@ clawdbot onboard --non-interactive \
Add `--json` for a machinereadable summary.
Gemini example:
```bash
clawdbot onboard --non-interactive \
--mode local \
--auth-choice gemini-api-key \
--gemini-api-key "$GEMINI_API_KEY" \
--gateway-port 18789 \
--gateway-bind loopback
```
Add agent (noninteractive) example:
```bash

View File

@@ -232,9 +232,10 @@ export function buildProgram() {
.option("--mode <mode>", "Wizard mode: local|remote")
.option(
"--auth-choice <choice>",
"Auth: oauth|claude-cli|openai-codex|codex-cli|antigravity|apiKey|minimax|skip",
"Auth: oauth|claude-cli|openai-codex|codex-cli|antigravity|gemini-api-key|apiKey|minimax|skip",
)
.option("--anthropic-api-key <key>", "Anthropic API key")
.option("--gemini-api-key <key>", "Gemini API key")
.option("--gateway-port <port>", "Gateway port")
.option("--gateway-bind <mode>", "Gateway bind: loopback|lan|tailnet|auto")
.option("--gateway-auth <mode>", "Gateway auth: off|token|password")
@@ -263,11 +264,13 @@ export function buildProgram() {
| "openai-codex"
| "codex-cli"
| "antigravity"
| "gemini-api-key"
| "apiKey"
| "minimax"
| "skip"
| undefined,
anthropicApiKey: opts.anthropicApiKey as string | undefined,
geminiApiKey: opts.geminiApiKey as string | undefined,
gatewayPort:
typeof opts.gatewayPort === "string"
? Number.parseInt(opts.gatewayPort, 10)

View File

@@ -85,6 +85,7 @@ export function buildAuthChoiceOptions(params: {
value: "antigravity",
label: "Google Antigravity (Claude Opus 4.5, Gemini 3, etc.)",
});
options.push({ value: "gemini-api-key", label: "Google Gemini API key" });
options.push({ value: "apiKey", label: "Anthropic API key" });
options.push({ value: "minimax", label: "Minimax M2.1 (LM Studio)" });
if (params.includeSkip) {

View File

@@ -30,6 +30,7 @@ import {
applyMinimaxConfig,
applyMinimaxProviderConfig,
setAnthropicApiKey,
setGeminiApiKey,
writeOAuthCredentials,
} from "./onboard-auth.js";
import { openUrl } from "./onboard-helpers.js";
@@ -415,6 +416,17 @@ export async function applyAuthChoice(params: {
"OAuth help",
);
}
} else if (params.authChoice === "gemini-api-key") {
const key = await params.prompter.text({
message: "Enter Gemini API key",
validate: (value) => (value?.trim() ? undefined : "Required"),
});
await setGeminiApiKey(String(key).trim(), params.agentDir);
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "google:default",
provider: "google",
mode: "api_key",
});
} else if (params.authChoice === "apiKey") {
const key = await params.prompter.text({
message: "Enter Anthropic API key",

View File

@@ -55,6 +55,7 @@ import {
applyAuthProfileConfig,
applyMinimaxConfig,
setAnthropicApiKey,
setGeminiApiKey,
writeOAuthCredentials,
} from "./onboard-auth.js";
import {
@@ -300,6 +301,7 @@ async function promptAuthConfig(
| "openai-codex"
| "codex-cli"
| "antigravity"
| "gemini-api-key"
| "apiKey"
| "minimax"
| "skip";
@@ -513,6 +515,20 @@ async function promptAuthConfig(
runtime.error(String(err));
note("Trouble with OAuth? See https://docs.clawd.bot/start/faq", "OAuth");
}
} else if (authChoice === "gemini-api-key") {
const key = guardCancel(
await text({
message: "Enter Gemini API key",
validate: (value) => (value?.trim() ? undefined : "Required"),
}),
runtime,
);
await setGeminiApiKey(String(key).trim());
next = applyAuthProfileConfig(next, {
profileId: "google:default",
provider: "google",
mode: "api_key",
});
} else if (authChoice === "apiKey") {
const key = guardCancel(
await text({

View File

@@ -33,6 +33,19 @@ export async function setAnthropicApiKey(key: string, agentDir?: string) {
});
}
export async function setGeminiApiKey(key: string, agentDir?: string) {
// Write to the multi-agent path so gateway finds credentials on startup
upsertAuthProfile({
profileId: "google:default",
credential: {
type: "api_key",
provider: "google",
key,
},
agentDir: agentDir ?? resolveDefaultAgentDir(),
});
}
export function applyAuthProfileConfig(
cfg: ClawdbotConfig,
params: {

View File

@@ -28,6 +28,7 @@ import {
applyAuthProfileConfig,
applyMinimaxConfig,
setAnthropicApiKey,
setGeminiApiKey,
} from "./onboard-auth.js";
import {
applyWizardMetadata,
@@ -119,6 +120,19 @@ export async function runNonInteractiveOnboarding(
provider: "anthropic",
mode: "api_key",
});
} else if (authChoice === "gemini-api-key") {
const key = opts.geminiApiKey?.trim();
if (!key) {
runtime.error("Missing --gemini-api-key");
runtime.exit(1);
return;
}
await setGeminiApiKey(key);
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "google:default",
provider: "google",
mode: "api_key",
});
} else if (authChoice === "claude-cli") {
const store = ensureAuthProfileStore(undefined, {
allowKeychainPrompt: false,

View File

@@ -9,6 +9,7 @@ export type AuthChoice =
| "codex-cli"
| "antigravity"
| "apiKey"
| "gemini-api-key"
| "minimax"
| "skip";
export type GatewayAuthChoice = "off" | "token" | "password";
@@ -24,6 +25,7 @@ export type OnboardOptions = {
nonInteractive?: boolean;
authChoice?: AuthChoice;
anthropicApiKey?: string;
geminiApiKey?: string;
gatewayPort?: number;
gatewayBind?: GatewayBind;
gatewayAuth?: GatewayAuthChoice;