A fast, secure CLI tool for managing multiple Google Cloud Platform accounts with seamless switching of both gcloud configurations and ADC credentials.
Managing multiple GCP accounts is painful:
- You have to re-authenticate every time you switch accounts
- Application Default Credentials (ADC) are stored in a single file that gets overwritten
- Constantly running
gcloud auth application-default loginis tedious - Easy to accidentally run commands against the wrong project
gcpx saves separate ADC credentials for each account and swaps them automatically when switching. No more re-authentication!
| Feature | Description |
|---|---|
| Save | Store current gcloud + ADC + kubectl context as a named context |
| Switch | Instantly switch between contexts (gcloud + ADC + kubectl) |
| List | View all saved contexts with active indicator |
| Run | Execute commands with a specific context (isolated) |
| Login | Re-authenticate and auto-save credentials |
| Delete | Remove saved contexts |
| Completions | Shell completion for bash, zsh, fish, powershell |
| kubectl | Automatically saves and restores kubectl context |
| Smart skip | Skips switching if already on the requested context |
| Workspace config | Pin a project to a context via .gcpx.toml (discovered from cwd and parents) |
cargo install gcpxbrew tap andres-pcg/tap
brew install gcpxDownload the latest binary from the Releases page.
# Authenticate with your first account
gcloud auth login
gcloud auth application-default login
# Save it as a context
gcpx save work
# Authenticate with another account
gcloud config configurations create personal
gcloud auth login
gcloud auth application-default login
# Save it too
gcpx save personal# Switch between accounts instantly (no re-auth!)
gcpx switch work
gcpx switch personal
# Or use interactive mode
gcpx
# List all contexts
gcpx list
# Output:
# * work (active)
# personal
# Check current context
gcpx current
# Output: workYou can pin a project or workspace to a specific gcpx context so that:
- Interactive switch (
gcpxorgcpx switch) pre-selects that context in the menu. gcpx switch --workspaceswitches directly to the context defined for the current project (no menu).
Create a .gcpx.toml (or .gcpx.json) in the project root:
# .gcpx.toml
context = "work"gcpx discovers config by walking from the current working directory up through parent directories until it finds a config file or reaches your home directory. So from any subdirectory of the project, the same config applies.
Auto-switch when you cd (or open a terminal): Add a hook to your shell so that when you change directory (or when the prompt runs), gcpx switches to the workspace context automatically and silently. No need to run gcpx switch --workspace by hand.
| Shell | Add to your config |
|---|---|
| Zsh | chpwd() { gcpx switch --workspace --silent 2>/dev/null } (and run once when the shell starts: e.g. call it from .zshrc after defining it, or use a precmd that runs on first prompt) |
| Bash | PROMPT_COMMAND='gcpx switch --workspace --silent 2>/dev/null; '"$PROMPT_COMMAND" |
| Fish | function __gcpx_auto_switch; gcpx switch --workspace --silent 2>/dev/null; end; add_prompt __gcpx_auto_switch or run it in fish_prompt |
Example for Zsh:
# In ~/.zshrc
gcpx_auto_switch() { gcpx switch --workspace --silent 2>/dev/null }
autoload -U add-zsh-hook
add-zsh-hook chpwd gcpx_auto_switch
add-zsh-hook precmd gcpx_auto_switchExample for Bash:
# In ~/.bashrc
PROMPT_COMMAND="gcpx switch --workspace --silent 2>/dev/null; ${PROMPT_COMMAND:-true}"Optional: to avoid running gcpx on every prompt when you stay in the same directory, only run when the directory changes (e.g. in Zsh, guard with if [[ "$(pwd)" != "$GCPX_LAST_CWD" ]]; then ...; GCPX_LAST_CWD=$(pwd); fi).
When there’s no .gcpx.toml in the path, the command does nothing (and stderr is discarded), so it’s safe to use everywhere.
Important: The config we use is the one in the current working directory (or the nearest parent that has a .gcpx.toml). So if you open your IDE with a parent folder (e.g. MINED) as the workspace root, the terminal starts in MINED and gcpx will use MINED/.gcpx.toml if it exists — not athenea/.gcpx.toml. To use the config in a subfolder, either open that folder as the workspace root, or cd into it (the hook will then run and use that folder’s config).
When streaming or sharing your screen, use the -q or --quiet flag to hide sensitive details like account email, project ID, and kubectl context:
# Normal output shows details
gcpx switch work
# Output:
# Switched to 'work' successfully!
# account: you@company.com
# project: my-secret-project
# kubectl: gke_my-cluster
# Quiet mode hides sensitive info
gcpx switch work -q
# Output:
# Switched to 'work' successfully!
# Also works with save and login
gcpx save my-context --quiet
gcpx login work -qRun a command with a different context without switching globally:
# Run gcloud command with 'personal' context
gcpx run personal gcloud compute instances list
# Run terraform with specific context
gcpx run work terraform apply# Opens browser for auth, then auto-saves
gcpx login work# Delete just the saved credentials
gcpx delete old-project
# Also delete the gcloud configuration
gcpx delete old-project --gcloud-configShow the active GCP context in your shell prompt to always know which account you're using.
If you use Powerlevel10k, add a custom segment:
- Edit
~/.p10k.zshand addgcpxto your prompt elements (inside the anonymous function, around line 40-80):
typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(
# ... other elements ...
gcpx # gcpx context
gcloud # google cloud cli
# ... other elements ...
)- Add this function at the END of the file, but BEFORE the options restoration lines. Look for the closing
}of the anonymous function and add the function AFTER it:
} # <-- This closes the anonymous function (around line 1700+)
################################[ gcpx: GCP context from gcpx ]################################
# Custom segment for gcpx - MUST be placed OUTSIDE the anonymous function
function prompt_gcpx() {
local ctx=$(~/.cargo/bin/gcpx current 2>/dev/null)
if [[ -n "$ctx" && "$ctx" != "none" ]]; then
p10k segment -f 33 -i '☁' -t "$ctx"
fi
}
# Restore original shell options (REQUIRED - do not remove these lines!)
(( ${#p10k_config_opts} )) && setopt ${p10k_config_opts[@]}
'builtin' 'unset' 'p10k_config_opts'Warning: The last two lines that restore shell options are CRITICAL. If they are missing, aliases and other shell features will stop working.
- Reload:
source ~/.p10k.zsh
Add to your ~/.zshrc after Oh-My-Zsh is loaded:
# GCP context in prompt
gcpx_prompt_info() {
local ctx=$(gcpx current 2>/dev/null)
if [[ -n "$ctx" && "$ctx" != "none" ]]; then
echo "%{$fg[cyan]%}☁ $ctx%{$reset_color%} "
fi
}
# Prepend to your existing prompt
PROMPT='$(gcpx_prompt_info)'$PROMPTIf you use Starship, add to ~/.config/starship.toml:
[custom.gcpx]
command = "gcpx current 2>/dev/null"
when = "gcpx current 2>/dev/null"
format = "[$output]($style) "
style = "bold cyan"
symbol = "☁ "Add to your ~/.bashrc:
gcpx_prompt() {
local ctx=$(gcpx current 2>/dev/null)
if [ -n "$ctx" ] && [ "$ctx" != "none" ]; then
echo "($ctx) "
fi
}
PS1='$(gcpx_prompt)\u@\h:\w\$ 'Add to ~/.config/fish/config.fish:
function fish_prompt
set -l ctx (gcpx current 2>/dev/null)
if test -n "$ctx" -a "$ctx" != "none"
set_color cyan
echo -n "☁ $ctx "
set_color normal
end
# ... rest of your prompt
endGenerate completions for your shell:
# Bash
gcpx completions bash > /etc/bash_completion.d/gcpx
# Zsh
gcpx completions zsh > "${fpath[1]}/_gcpx"
# Fish
gcpx completions fish > ~/.config/fish/completions/gcpx.fish
# PowerShell
gcpx completions powershell > gcpx.ps1gcpx stores credentials and metadata in ~/.config/gcpx/:
~/.config/gcpx/
.current # Tracks active context name
work/
adc.json # Saved ADC credentials (0600 permissions)
metadata.json # gcloud config, account, project, kubectl context
personal/
adc.json
metadata.json
When you gcpx save <name>:
- Captures your current gcloud config name, account, and project
- Captures your current kubectl context (if kubectl is installed)
- Copies ADC credentials to the context directory
- Saves metadata so switching works even if context name differs from gcloud config
When you gcpx switch <name>:
- Checks if already on the requested context (skips if so - saves time!)
- Reads metadata to get the correct gcloud configuration name
- Activates that gcloud configuration
- Restores the saved ADC credentials
- Switches kubectl context (if one was saved)
- Updates the
.currenttracking file
| Platform | Status | Notes |
|---|---|---|
| macOS (Apple Silicon) | Tested | Primary development platform |
| macOS (Intel) | Built | Smoke tested in CI |
| Linux (x86_64) | Built | Smoke tested in CI |
| Linux (ARM64) | Built | Cross-compiled, not runtime tested |
| Linux (musl) | Built | Cross-compiled, not runtime tested |
| Windows (x86_64) | Built | Smoke tested in CI |
Binaries are provided for all platforms above. If you encounter issues on any platform, please open an issue.
- Credential files are stored with
0600permissions (owner read/write only) - No credentials are transmitted over the network
- Credentials stay in your home directory
# Clone the repo
git clone https://github.com/andres-pcg/gcpx.git
cd gcpx
# Build
cargo build
# Run tests
cargo test -- --test-threads=1
# Run clippy
cargo clippy
# Format code
cargo fmtMIT License - see LICENSE for details.
Contributions are welcome! Please feel free to submit a Pull Request.