Hey! I’ve been using the Gemini CLI lately, but I got a bit spooked by how easy it is to accidentally leak API keys. I realised my standard setup had some flaws:
- Storing keys in a
.envfile is risky because they can be easily exfiltrated. - Passing keys via the command line exposes the plaintext secret to forensic artefacts, like the PowerShell
PSReadlinehistory file. - If you run AI agents without sandboxing, a prompt injection attack could force the model to execute malicious commands on your host system.
So, this is my personal setup I now use for running the Gemini CLI on Windows. It’s my way of keeping keys safe in an encrypted vault whilst I develop locally.
- Auto-Provisioning: Prompts you securely for your API key the first time you run it and stores it natively in an encrypted OS vault.
- History Safe: Uses a secure password prompt so your API key never touches your terminal command history.
- Global Access: Runs from any directory.
- Sandboxed: Runs the CLI in
--sandboxmode by default via a container engine to protect your host file system. - Process Isolated: Injects the API key exclusively into the isolated environment block of the child CLI process, ensuring zero forensic residue in your parent terminal memory.
⚠️ A Note on YOLO Mode: Please don't use the--yoloflag with this setup (or ever, really). YOLO mode bypasses tool call approval prompts and can lead to unauthorised shell execution. Let the sandbox do its job!
Regardless of which runner option you choose below, your system needs the core AI tools and the container sandbox installed first.
1. Install Node.js & The CLI
The Gemini CLI is a Node application. Download and install Node from nodejs.org, then install the CLI globally:
npm install -g @google/gemini-cli2. Set up the Sandbox
Because we forcefully append the --sandbox flag for security, you need a container engine to create the disposable environment where the AI executes code.
- Download and install Rancher Desktop (a free alternative to Docker Desktop).
- During setup, choose
dockerd (moby)as the container engine. - Verify it's working: Open your terminal and run
docker ps. If it returns column headers without an error, your sandbox engine is ready!
This approach uses a cross-platform Python architecture to interface directly with the Windows Credential Manager. It completely avoids modifying your terminal profile and requires zero Microsoft PowerShell modules.
You don't even need Python installed to run this!
- Go to the Releases tab of this repository.
- Download
gemini-safe-windows.exe. - Drop the executable into a folder that is in your system's
PATH(e.g.,C:\Scripts\). - Open a terminal and run
gemini-safe-windows "your prompt here".
If you prefer running the raw script:
- Ensure Python 3 is installed.
- Clone this repository and install the requirements:
pip install -r requirements.txt
- Set up a macro in your Command Prompt using
doskeyso you can run it from anywhere:doskey gemini-safe=python "C:\path\to\gemini-safe.py" $*
If you don't want to use Python and prefer living entirely in PowerShell 7+, you can use Microsoft's SecretStore module.
(Note: Windows PowerShell 5.1 is not recommended for this setup; please use PowerShell 7+).
Open PowerShell and run this once to install the modules and register your local vault:
Install-Module Microsoft.PowerShell.SecretManagement, Microsoft.PowerShell.SecretStore -Repository PSGallery -Force
Register-SecretVault -Name LocalVault -ModuleName Microsoft.PowerShell.SecretStore -DefaultVaultNow we drop the smart wrapper script into your PowerShell profile.
1. Open your profile:
notepad $PROFILE(If Notepad says the file doesn't exist, run New-Item -ItemType File -Path $PROFILE -Force and try again).
2. Paste this function at the bottom of the file and save:
function Start-GeminiSafe {
<#
.SYNOPSIS
A safe wrapper for the Gemini CLI that auto-prompts for API keys, uses SecretStore, and enforces sandboxing.
#>
[CmdletBinding()]
param(
[Parameter(ValueFromRemainingArguments=$true)]
[string[]]$GeminiArgs
)
$secretName = "GEMINI_API_KEY"
$secretExists = Get-SecretInfo -Name $secretName -ErrorAction SilentlyContinue
if (-not $secretExists) {
Write-Host "No Gemini API Key found in your vault. Let's save it." -ForegroundColor Cyan
$KeyPrompt = Get-Credential -UserName "gemini" -Message "Paste your Gemini API Key in the Password field"
$secretMeta = @{
Description = "Google Gemini CLI API Key"
AddedDate = (Get-Date).ToString("yyyy-MM-dd")
Environment = "Local Dev"
}
Set-Secret -Name $secretName -Secret $KeyPrompt.Password -Metadata $secretMeta
Write-Host "Key saved to vault!" -ForegroundColor Green
}
try {
$secureKey = Get-Secret -Name $secretName -AsPlainText
} catch {
Write-Error "Failed to retrieve GEMINI_API_KEY from the secret store."
return
}
if (-not $secureKey) { return }
try {
Write-Host "Starting Gemini CLI safely in Sandbox mode..." -ForegroundColor Green
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = if ($IsWindows) { "gemini.cmd" } else { "gemini" }
$psi.Arguments = "$($GeminiArgs -join ' ') --sandbox"
$psi.UseShellExecute = $false
$psi.Environment["GEMINI_API_KEY"] = $secureKey
$process = [System.Diagnostics.Process]::Start($psi)
$process.WaitForExit()
} catch {
Write-Error "Failed to execute the Gemini CLI process: $_"
} finally {
$secureKey = $null
[System.GC]::Collect()
}
}3. Reload your profile:
. $PROFILE4. Run it!
Start-GeminiSafe "Write a python script to reverse a string"While this setup is a massive improvement over plaintext .env files, nothing is 100% bulletproof:
- Child Processes: When you inject an environment variable into a process, any child processes it spawns inherit it. If the AI executes a shell script inside the sandbox, that script technically has access to your API key in its environment.
- Crash Dumps: If your container engine or the CLI crashes, system error logs or debugging tools will sometimes take a "snapshot" of your environment variables. Be careful if you ever share crash dumps or logs publicly.
The underlying logic of both scripts works perfectly on macOS. However, getting the prerequisites installed looks a little different.
- Node.js: Use Homebrew to avoid permission errors with global npm packages:
brew install node. - Container Engine: macOS developers heavily favour Colima over Rancher Desktop. It's a lightweight CLI container runtime. Run
brew install colima docker, thencolima start. - PowerShell (Option 2 only): Macs default to
zsh. You'll need to install PS7 manually viabrew install --cask powershell. Typepwshto launch it. Your$PROFILElives at~/.config/powershell/Microsoft.PowerShell_profile.ps1.
Instead of the Windows Credential Manager, the script automatically talks to the Apple Keychain.
- Pre-compiled Binary: Download
gemini-safe-macosfrom Releases, move it to/usr/local/bin/, and runchmod +x /usr/local/bin/gemini-safe-macos. - Running from Source: To create your alias, open
nano ~/.zshrcand add:alias gemini-safe='python3 /Users/yourusername/path/to/gemini-safe.py'. Then runsource ~/.zshrc.