Lumoswitch Docs
Agent setup

Gemini CLI setup

Gemini CLI is Google's open-source terminal coding agent. It can understand a project, edit files, run commands, and invoke tools. Its native Gemini protocol can send those requests through Lumoswitch.

The API configuration must enable Gemini output, and the target model must support the streaming responses and function calls used by Gemini CLI. The commands below target Bash or Zsh on macOS and Linux and require Node.js. Before continuing, confirm that node --version and gemini --version both return version numbers.

Choose a setup method

MethodBest forLocal writesStill active after exit?
One-time launchTesting a URL, Key, or modelDedicated Lumoswitch auth-mode fileKey and model do not persist
Persistent useEveryday terminal useNative configuration + optional launcher and auth-mode fileYes
IDE CompanionConnecting an editor to the current Gemini CLIReuses the current CLI processDepends on the CLI method

Gemini CLI has no standalone official coding desktop app. The official IDE Companion and ACP integrations connect to a Gemini CLI process, so start the CLI with this page's instructions before connecting it to an editor.

Prepare the connection values

PlaceholderValue
{{api_base_url}}The Gemini request URL shown by the API configuration; do not append /v1
{{access_key}}The API configuration's Access Key
{{model}}The client-facing model name shown by the API configuration
{{gemini_settings_json}}Generated Gemini CLI model and authentication settings JSON

Commands copied from the console already contain real values. Gemini's thinkingBudget and thinkingLevel vary by model generation, so the template does not guess a numeric budget from generic effort tiers; it emits only verified-safe model and authentication settings.

One-time launch

This command runs in a subshell, so the Access Key, URL, and model do not remain in the current terminal. Those connection values expire as soon as Gemini CLI exits.

(
  set -e
  LUMOSWITCH_GEMINI_SETTINGS="$(mktemp "${TMPDIR:-/tmp}/lumoswitch-gemini.XXXXXX")"
  trap 'rm -f "$LUMOSWITCH_GEMINI_SETTINGS"' EXIT
  printf '%s\n' '{{gemini_settings_json}}' > "$LUMOSWITCH_GEMINI_SETTINGS"
  chmod 600 "$LUMOSWITCH_GEMINI_SETTINGS"
  env \
    GEMINI_API_KEY="{{access_key}}" \
    GEMINI_MODEL="{{model}}" \
    GOOGLE_GEMINI_BASE_URL="{{api_base_url}}" \
    GEMINI_CLI_SYSTEM_SETTINGS_PATH="$LUMOSWITCH_GEMINI_SETTINGS" \
    gemini --model "{{model}}"
)

The generated authentication settings live in a 0600 temporary file and are removed when Gemini CLI exits. The command does not change ~/.gemini/settings.json or leave a Lumoswitch settings file in the user directory; the Access Key is never written to the temporary file.

Persistent use

Run the complete command during initial setup and whenever the Lumoswitch URL, Access Key, or model changes. It writes Gemini CLI-supported persistent settings and a dedicated auth-mode file, then saves an optional Lumoswitch maintenance launcher.

Persistent import stores the Access Key in an owner-only managed environment or Agent configuration file. Use it only on a trusted personal device.

set -e
LUMOSWITCH_ROOT="$HOME/.config/lumoswitch/agents/gemini-cli"
LUMOSWITCH_ENV="$LUMOSWITCH_ROOT/env.sh"
LUMOSWITCH_LAUNCHER="$HOME/.local/bin/lumoswitch-gemini-cli"
mkdir -p "$LUMOSWITCH_ROOT" "$(dirname "$LUMOSWITCH_LAUNCHER")"
umask 077

if [ -f "$LUMOSWITCH_LAUNCHER" ]; then
  LUMOSWITCH_BACKUP="$LUMOSWITCH_LAUNCHER.backup.$(date +%Y%m%d-%H%M%S)-$$"
  cp "$LUMOSWITCH_LAUNCHER" "$LUMOSWITCH_BACKUP"
  chmod 600 "$LUMOSWITCH_BACKUP"
fi

LUMOSWITCH_GEMINI_SETTINGS="$LUMOSWITCH_ROOT/settings.json"
printf '%s\n' '{{gemini_settings_json}}' > "$LUMOSWITCH_GEMINI_SETTINGS"

cat > "$LUMOSWITCH_ENV" <<'LUMOSWITCH_ENV_EOF'
export GEMINI_CLI_SYSTEM_SETTINGS_PATH="$HOME/.config/lumoswitch/agents/gemini-cli/settings.json"
export GEMINI_API_KEY="{{access_key}}"
export GEMINI_MODEL="{{model}}"
export GOOGLE_GEMINI_BASE_URL="{{api_base_url}}"
LUMOSWITCH_ENV_EOF

case "$SHELL" in
  */zsh) LUMOSWITCH_PROFILE="$HOME/.zshrc" ;;
  */bash) LUMOSWITCH_PROFILE="$HOME/.bashrc" ;;
  *) LUMOSWITCH_PROFILE="$HOME/.profile" ;;
esac
touch "$LUMOSWITCH_PROFILE"
LUMOSWITCH_PROFILE_MARKER='# Lumoswitch Agent: gemini-cli'
LUMOSWITCH_SOURCE_LINE='[ -f "$HOME/.config/lumoswitch/agents/gemini-cli/env.sh" ] && . "$HOME/.config/lumoswitch/agents/gemini-cli/env.sh"'
if ! grep -Fqx "$LUMOSWITCH_SOURCE_LINE" "$LUMOSWITCH_PROFILE"; then
  printf '\n%s\n%s\n' "$LUMOSWITCH_PROFILE_MARKER" "$LUMOSWITCH_SOURCE_LINE" >> "$LUMOSWITCH_PROFILE"
fi
printf '%s\n' "$LUMOSWITCH_PROFILE" > "$LUMOSWITCH_ROOT/profile-path"

cat > "$LUMOSWITCH_LAUNCHER" <<'LUMOSWITCH_LAUNCHER_EOF'
#!/usr/bin/env bash
set -e
LUMOSWITCH_ROOT="$HOME/.config/lumoswitch/agents/gemini-cli"
LUMOSWITCH_ENV="$LUMOSWITCH_ROOT/env.sh"
LUMOSWITCH_LAUNCHER="$HOME/.local/bin/lumoswitch-gemini-cli"

if [ "$1" = "--lumoswitch-clean" ]; then
  if [ -f "$LUMOSWITCH_ROOT/profile-path" ]; then
    LUMOSWITCH_PROFILE="$(cat "$LUMOSWITCH_ROOT/profile-path")"
    if [ -f "$LUMOSWITCH_PROFILE" ]; then
      LUMOSWITCH_PROFILE_MARKER='# Lumoswitch Agent: gemini-cli'
      LUMOSWITCH_SOURCE_LINE='[ -f "$HOME/.config/lumoswitch/agents/gemini-cli/env.sh" ] && . "$HOME/.config/lumoswitch/agents/gemini-cli/env.sh"'
      LUMOSWITCH_PROFILE_TMP="$LUMOSWITCH_PROFILE.lumoswitch.$$"
      awk -v marker="$LUMOSWITCH_PROFILE_MARKER" -v source="$LUMOSWITCH_SOURCE_LINE" '$0 != marker && $0 != source' "$LUMOSWITCH_PROFILE" > "$LUMOSWITCH_PROFILE_TMP"
      mv "$LUMOSWITCH_PROFILE_TMP" "$LUMOSWITCH_PROFILE"
    fi
  fi
  if [ -d "$LUMOSWITCH_ROOT" ]; then
    find "$LUMOSWITCH_ROOT" -depth \( -type f -o -type l \) -delete
    find "$LUMOSWITCH_ROOT" -depth -type d -exec rmdir {} \; 2>/dev/null || true
  fi
  find "$(dirname "$LUMOSWITCH_LAUNCHER")" -maxdepth 1 -type f -name 'lumoswitch-gemini-cli.backup.*' -delete
  rm -f "$LUMOSWITCH_LAUNCHER"
  printf '%s\n' 'Lumoswitch native setup and optional launcher removed. Open a new terminal to refresh the environment.'
  exit 0
fi

if [ -f "$LUMOSWITCH_ENV" ]; then . "$LUMOSWITCH_ENV"; fi
exec gemini "$@"
LUMOSWITCH_LAUNCHER_EOF

chmod 600 "$LUMOSWITCH_ENV"
find "$LUMOSWITCH_ROOT" -type f -exec chmod 600 {} \;
chmod 700 "$LUMOSWITCH_LAUNCHER"
. "$LUMOSWITCH_ENV"
printf '%s\n' 'Native Lumoswitch setup saved. Future command: gemini'
printf '%s\n' 'Optional maintenance launcher: ~/.local/bin/lumoswitch-gemini-cli'
gemini

For later sessions, run:

gemini

You can append normal Gemini CLI arguments. Before an update, the installer keeps unique timestamped copies of the old launcher and authentication settings with 0600 permissions. The native gemini command reads the installed settings directly; the optional launcher does the same.

Native Windows PowerShell import

These commands run natively in Windows PowerShell without WSL and use the same connection values as the macOS/Linux templates on this page.

One-time use on Windows

& {
  $ErrorActionPreference = 'Stop'
  $lumoswitchConfig = Join-Path ([IO.Path]::GetTempPath()) ('lumoswitch-' + [Guid]::NewGuid().ToString('N') + '.json')
  $lumoswitchConfigContent = @'
{{gemini_settings_json}}
'@
  [IO.File]::WriteAllText($lumoswitchConfig, $lumoswitchConfigContent, [Text.UTF8Encoding]::new($false))
  $lumoswitchEnvironmentNames = @('GEMINI_API_KEY', 'GEMINI_CLI_SYSTEM_SETTINGS_PATH', 'GEMINI_MODEL', 'GOOGLE_GEMINI_BASE_URL')
  $lumoswitchPreviousEnvironment = @{}
  foreach ($lumoswitchName in $lumoswitchEnvironmentNames) {
    $lumoswitchPreviousEnvironment[$lumoswitchName] = [Environment]::GetEnvironmentVariable($lumoswitchName, 'Process')
  }
  $lumoswitchExitCode = 0
  try {
    [Environment]::SetEnvironmentVariable('GEMINI_API_KEY', '{{access_key}}', 'Process')
    [Environment]::SetEnvironmentVariable('GEMINI_CLI_SYSTEM_SETTINGS_PATH', $lumoswitchConfig, 'Process')
    [Environment]::SetEnvironmentVariable('GEMINI_MODEL', '{{model}}', 'Process')
    [Environment]::SetEnvironmentVariable('GOOGLE_GEMINI_BASE_URL', '{{api_base_url}}', 'Process')
    $lumoswitchArguments = @('--model', '{{model}}')
    $lumoswitchExecutable = Get-Command 'gemini.cmd' -CommandType Application -ErrorAction SilentlyContinue
    if ($null -eq $lumoswitchExecutable) { $lumoswitchExecutable = Get-Command 'gemini' -CommandType Application -ErrorAction Stop }
    & $lumoswitchExecutable.Path @lumoswitchArguments
    if ($null -ne $LASTEXITCODE) { $lumoswitchExitCode = $LASTEXITCODE }
  } finally {
    foreach ($lumoswitchName in $lumoswitchEnvironmentNames) {
      [Environment]::SetEnvironmentVariable($lumoswitchName, $lumoswitchPreviousEnvironment[$lumoswitchName], 'Process')
    }
    Remove-Item -LiteralPath $lumoswitchConfig -Force -ErrorAction SilentlyContinue
  }
  if ($lumoswitchExitCode -ne 0) { throw 'gemini exited with code ' + $lumoswitchExitCode }
}

Persistent use on Windows

This command backs up existing Lumoswitch-owned files and restricts access to the configuration and launcher for the current user.

& {
  $ErrorActionPreference = 'Stop'
  $lumoswitchRoot = Join-Path $env:LOCALAPPDATA 'Lumoswitch\agents\gemini-cli'
  $lumoswitchLauncher = Join-Path $env:LOCALAPPDATA 'Lumoswitch\bin\lumoswitch-gemini-cli.ps1'
  $lumoswitchBackupSuffix = (Get-Date -Format 'yyyyMMdd-HHmmss') + '-' + $PID

  function Protect-LumoswitchFile([string] $Path) {
    $lumoswitchSid = [Security.Principal.WindowsIdentity]::GetCurrent().User.Value
    & icacls.exe $Path '/inheritance:r' '/grant:r' ('*' + $lumoswitchSid + ':(F)') '*S-1-5-18:(F)' '*S-1-5-32-544:(F)' | Out-Null
    if ($LASTEXITCODE -ne 0) { throw "Could not restrict access to $Path" }
  }

  function Install-LumoswitchFile([string] $Path, [string] $Content) {
    [IO.Directory]::CreateDirectory((Split-Path -Parent $Path)) | Out-Null
    if (Test-Path -LiteralPath $Path) {
      $lumoswitchItem = Get-Item -LiteralPath $Path -Force
      if ($lumoswitchItem.PSIsContainer -or ($lumoswitchItem.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
        throw "Lumoswitch refused to replace a directory or link: $Path"
      }
      $lumoswitchBackup = $Path + '.backup.' + $lumoswitchBackupSuffix
      Copy-Item -LiteralPath $Path -Destination $lumoswitchBackup
      Protect-LumoswitchFile $lumoswitchBackup
    }
    $lumoswitchTemporary = $Path + '.' + [Guid]::NewGuid().ToString('N') + '.tmp'
    try {
      [IO.File]::WriteAllText($lumoswitchTemporary, $Content, [Text.UTF8Encoding]::new($false))
      Move-Item -LiteralPath $lumoswitchTemporary -Destination $Path -Force
      Protect-LumoswitchFile $Path
    } finally {
      Remove-Item -LiteralPath $lumoswitchTemporary -Force -ErrorAction SilentlyContinue
    }
  }

  [IO.Directory]::CreateDirectory($lumoswitchRoot) | Out-Null
  $lumoswitchGeminiSettings = Join-Path $lumoswitchRoot 'settings.json'
  Install-LumoswitchFile $lumoswitchGeminiSettings '{{gemini_settings_json}}'

  $lumoswitchEnvironment = [ordered]@{}
  $lumoswitchEnvironment['GEMINI_CLI_SYSTEM_SETTINGS_PATH'] = (Join-Path $lumoswitchRoot 'settings.json')
  $lumoswitchEnvironment['GEMINI_API_KEY'] = '{{access_key}}'
  $lumoswitchEnvironment['GEMINI_MODEL'] = '{{model}}'
  $lumoswitchEnvironment['GOOGLE_GEMINI_BASE_URL'] = '{{api_base_url}}'
  foreach ($lumoswitchEntry in $lumoswitchEnvironment.GetEnumerator()) {
    [Environment]::SetEnvironmentVariable($lumoswitchEntry.Key, $lumoswitchEntry.Value, 'User')
    [Environment]::SetEnvironmentVariable($lumoswitchEntry.Key, $lumoswitchEntry.Value, 'Process')
  }

  $lumoswitchLauncherContent = @'
param([Parameter(ValueFromRemainingArguments = $true)][string[]] $AgentArgs)
$ErrorActionPreference = 'Stop'
$lumoswitchRoot = Join-Path $env:LOCALAPPDATA 'Lumoswitch\agents\gemini-cli'
$lumoswitchLauncher = Join-Path $env:LOCALAPPDATA 'Lumoswitch\bin\lumoswitch-gemini-cli.ps1'

function Remove-LumoswitchFile([string] $Path) {
  if (-not (Test-Path -LiteralPath $Path)) { return }
  $lumoswitchItem = Get-Item -LiteralPath $Path -Force
  if ($lumoswitchItem.PSIsContainer -or ($lumoswitchItem.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
    throw "Lumoswitch refused to remove a directory or link: $Path"
  }
  Remove-Item -LiteralPath $Path -Force
}

if ($AgentArgs.Count -gt 0 -and $AgentArgs[0] -eq '--lumoswitch-clean') {
  foreach ($lumoswitchName in @('GEMINI_CLI_SYSTEM_SETTINGS_PATH', 'GEMINI_API_KEY', 'GEMINI_MODEL', 'GOOGLE_GEMINI_BASE_URL')) {
    [Environment]::SetEnvironmentVariable($lumoswitchName, $null, 'User')
    [Environment]::SetEnvironmentVariable($lumoswitchName, $null, 'Process')
  }
  if (Test-Path -LiteralPath $lumoswitchRoot -PathType Container) {
    $lumoswitchRootItem = Get-Item -LiteralPath $lumoswitchRoot -Force
    if ($lumoswitchRootItem.Attributes -band [IO.FileAttributes]::ReparsePoint) { throw 'Lumoswitch refused to clean through a linked directory.' }
    foreach ($lumoswitchFile in @(Get-ChildItem -LiteralPath $lumoswitchRoot -File -Recurse -Force)) { Remove-LumoswitchFile $lumoswitchFile.FullName }
    foreach ($lumoswitchDirectory in @(Get-ChildItem -LiteralPath $lumoswitchRoot -Directory -Recurse -Force | Sort-Object FullName -Descending)) {
      if ($null -eq (Get-ChildItem -LiteralPath $lumoswitchDirectory.FullName -Force | Select-Object -First 1)) { Remove-Item -LiteralPath $lumoswitchDirectory.FullName -Force }
    }
    if ($null -eq (Get-ChildItem -LiteralPath $lumoswitchRoot -Force | Select-Object -First 1)) { Remove-Item -LiteralPath $lumoswitchRoot -Force }
  }
  $lumoswitchBin = Split-Path -Parent $lumoswitchLauncher
  if (Test-Path -LiteralPath $lumoswitchBin -PathType Container) {
    foreach ($lumoswitchBackup in @(Get-ChildItem -LiteralPath $lumoswitchBin -Filter 'lumoswitch-gemini-cli.ps1.backup.*' -File -Force)) { Remove-LumoswitchFile $lumoswitchBackup.FullName }
  }
  Remove-LumoswitchFile $lumoswitchLauncher
  Write-Host 'Lumoswitch native setup and optional launcher removed. Open a new terminal to refresh the environment.'
  exit 0
}

$lumoswitchEnvironment = [ordered]@{}
$lumoswitchEnvironment['GEMINI_CLI_SYSTEM_SETTINGS_PATH'] = (Join-Path $lumoswitchRoot 'settings.json')
$lumoswitchEnvironment['GEMINI_API_KEY'] = '{{access_key}}'
$lumoswitchEnvironment['GEMINI_MODEL'] = '{{model}}'
$lumoswitchEnvironment['GOOGLE_GEMINI_BASE_URL'] = '{{api_base_url}}'
foreach ($lumoswitchEntry in $lumoswitchEnvironment.GetEnumerator()) {
  [Environment]::SetEnvironmentVariable($lumoswitchEntry.Key, $lumoswitchEntry.Value, 'Process')
}
$lumoswitchExecutable = Get-Command 'gemini.cmd' -CommandType Application -ErrorAction SilentlyContinue
if ($null -eq $lumoswitchExecutable) { $lumoswitchExecutable = Get-Command 'gemini.exe' -CommandType Application -ErrorAction SilentlyContinue }
if ($null -eq $lumoswitchExecutable) { $lumoswitchExecutable = Get-Command 'gemini' -CommandType Application -ErrorAction Stop }
$lumoswitchArguments = @()
& $lumoswitchExecutable.Path @lumoswitchArguments @AgentArgs
if ($null -ne $LASTEXITCODE) { exit $LASTEXITCODE }
'@
  Install-LumoswitchFile $lumoswitchLauncher $lumoswitchLauncherContent
  Write-Host 'Native Lumoswitch setup saved. Future command: gemini'
  Write-Host 'Optional maintenance launcher:' $lumoswitchLauncher
  $lumoswitchExecutable = Get-Command 'gemini.cmd' -CommandType Application -ErrorAction SilentlyContinue
  if ($null -eq $lumoswitchExecutable) { $lumoswitchExecutable = Get-Command 'gemini.exe' -CommandType Application -ErrorAction SilentlyContinue }
  if ($null -eq $lumoswitchExecutable) { $lumoswitchExecutable = Get-Command 'gemini' -CommandType Application -ErrorAction Stop }
  $lumoswitchArguments = @()
  & $lumoswitchExecutable.Path @lumoswitchArguments
  if ($null -ne $LASTEXITCODE -and $LASTEXITCODE -ne 0) { throw 'gemini exited with code ' + $LASTEXITCODE }
}

The import writes the Agent-supported persistent configuration and starts gemini directly. The saved Lumoswitch maintenance script is not required to start the Agent; run it with --lumoswitch-clean when you need to restore or remove this setup.

Remove the CLI setup

Windows PowerShell

Exit every Lumoswitch session for this Agent, then run the command below. The optional maintenance launcher removes the managed native configuration, restores any preserved shared file, clears Lumoswitch user environment values, and removes itself.

& {
  $lumoswitchLauncher = Join-Path $env:LOCALAPPDATA 'Lumoswitch\bin\lumoswitch-gemini-cli.ps1'
  if (-not (Test-Path -LiteralPath $lumoswitchLauncher -PathType Leaf)) {
    throw 'The optional Lumoswitch maintenance launcher is missing. Run persistent import again before cleanup.'
  }
  & powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File $lumoswitchLauncher --lumoswitch-clean
}

macOS / Linux

This command removes the managed Gemini settings path, user environment hook, optional launcher, and backups. It does not remove ~/.gemini/settings.json, Google sign-in state, chat history, or other Gemini configuration.

"$HOME/.local/bin/lumoswitch-gemini-cli" --lumoswitch-clean

The one-time command sets variables inside a child shell, so nothing remains after it exits.

IDE Companion and other interfaces

  • VS Code-compatible editors: start Gemini CLI with this page's command, then run /ide enable in the CLI. The official Gemini CLI Companion reuses that running process and its Lumoswitch configuration.
  • “Gemini CLI: Run” in an editor: this command starts plain gemini, which uses Lumoswitch after the persistent environment is loaded. Restart the editor after importing so its terminal inherits the new environment.
  • ACP clients such as JetBrains and Zed: these connect to a CLI process, but the client controls the launch command. Point it to gemini after restarting the client; the optional launcher remains available only as a compatibility fallback.
  • Gemini web and regular Gemini apps: they currently expose no official custom-model endpoint contract, so this Lumoswitch setup does not apply.

Removing the launcher removes the persistent CLI entry point. Close already-running CLI and IDE sessions before expecting it to take effect. If an ACP client separately stored a launch command, remove that command in the client as well.

See Gemini CLI IDE integration, authentication, and the configuration reference.

Verify and troubleshoot

  • Google sign-in still appears: confirm that the dedicated auth-mode file was written successfully and is readable by the current user.
  • 404: this setup uses the native Gemini protocol; do not replace the Base URL with an OpenAI-compatible /v1 URL.
  • Function calls fail: the target model may support plain text but not native Gemini function calling.
  • The IDE uses its default provider: confirm the Companion is connected to the current Lumoswitch CLI process, not a separate plain gemini process started by the editor.
Maintainer publishing fields
  • Platform ID: gemini-cli
  • Display name: Gemini CLI
  • Downstream protocol: gemini
  • commandTemplate: copy the complete code block under "One-time launch"
  • Persistence strategy: native
  • persistentCommandTemplate: copy the complete code block under "Persistent use"
  • futureCommand: gemini
  • Display order: 50
  • Last verified: 2026-08-27

On this page