gcpctx
Directory-scoped Google Cloud service account impersonation contexts for terminals, IDEs, and coding agents.
What is gcpctx?
gcpctx automatically activates an isolated Google Cloud SDK and Application Default Credentials (ADC) environment when you enter a directory with a .gcpctx.toml file. Each profile maps to a GCP project and an impersonated service account. Activation exports a dedicated CLOUDSDK_CONFIG so your global ~/.config/gcloud is never mutated.
Why directory-scoped impersonation?
Developers and coding agents often inherit broad or wrong GCP credentials from the parent shell. gcpctx scopes authentication to the repository you are working in, with first-use approval and config-hash invalidation when trust-relevant settings change.
Installation
Choose one of these options:
| Method | Best for |
|---|---|
uvx |
Try without installing, CI one-offs, pinned versions |
pipx |
Daily CLI use on your machine |
| From source | Contributing or unreleased builds |
Run with uvx (no install)
uvx runs gcpctx in an ephemeral environment—no global install required.
# Latest from PyPI (when published)
uvx gcpctx --help
# Pin a version
uvx gcpctx@0.5.0 status
# Run from a local checkout (before publish)
uvx --from /path/to/gcpctx gcpctx --help
Typical workflow with uvx:
cd my-repo
uvx gcpctx create \
--project my-dev-project \
--service-account agent-dev@my-dev-project.iam.gserviceaccount.com
uvx gcpctx approve
eval "$(uvx gcpctx activate --shell zsh)"
uvx gcpctx status
uvx gcpctx doctor
Shell hooks from gcpctx install --shell zsh call gcpctx on your PATH. After choosing uvx, either add a shell alias (alias gcpctx='uvx gcpctx') or install with pipx / uv tool install for hook integration.
pipx
pipx install gcpctx
gcpctx --help
From source
git clone <repo-url> && cd gcpctx
uv sync
uv run gcpctx --help
# optional: uv tool install -e .
Quick start
# 1. Create project config
gcpctx create --project my-dev-project \
--service-account agent-dev@my-dev-project.iam.gserviceaccount.com
# 2. Approve and activate (zsh example)
gcpctx approve
eval "$(gcpctx activate --shell zsh)"
# 3. Verify
gcpctx status
gcloud config list
.gcpctx.toml example
version = 1
default_profile = "dev"
[profiles.dev]
project = "my-dev-project"
service_account = "agent-dev@my-dev-project.iam.gserviceaccount.com"
quota_project = "my-billing-project"
region = "asia-northeast1"
Examples
See examples/README.md for a manual integration demo that verifies google.auth.default() under gcpctx and chained service-account impersonation in Python (Terraform-backed IAM in examples/terraform/).
Shell integration
# Print snippet (review first)
gcpctx install --shell zsh # or: gcpctx install --shell bash
# Or append to your shell rc (check for existing '# >>> gcpctx hook >>>' first)
gcpctx install --shell zsh >> ~/.zshrc
exec $SHELL # reload shell
The hook runs gcpctx hook --shell zsh on every directory change. install and hook write shell code to stdout only; setup instructions go to stderr.
Manual activation without hooks:
eval "$(gcpctx activate --shell zsh)"
eval "$(gcpctx deactivate --shell zsh)" # restore prior env
Switch profile (after adding the gcpctx-switch wrapper from gcpctx install):
gcpctx-switch prod-readonly
IDE usage (VS Code, Cursor, JetBrains)
Integrated terminals inherit the parent shell environment. Subprocesses started by the IDE (build tasks, debuggers, test runners) see the same CLOUDSDK_CONFIG, ADC, and GCPCTX_* variables as your shell.
Recommended setup
- Add the shell hook to your rc file (
gcpctx install --shell zsh, then append or paste into~/.zshrc), or manuallyeval "$(gcpctx activate --shell zsh)"in your login shell. - Open the IDE from that shell (
cursor .,code .) so new integrated terminals start activated. - Confirm with
gcpctx statusin an integrated terminal.
Verify isolation
gcpctx status
gcpctx doctor
gcpctx doctor --json # machine-readable for scripts
Doctor checks that CLOUDSDK_CONFIG lives under ~/.cache/gcpctx/contexts/, gcloud project/impersonation match your profile, and ADC is initialized.
GOOGLE_APPLICATION_CREDENTIALS
In hook mode, GOOGLE_APPLICATION_CREDENTIALS is unset while active (previous value restored on deactivate) so ADC impersonation is not overridden. If you must keep a key file in non-interactive sessions, pass --allow-google-application-credentials to activate.
Coding agents (Cursor, Claude Code, Codex, Copilot)
Agents run in terminals or sandboxes that inherit environment variables. Use either shell activation (whole session) or gcpctx run (one process only).
Process-scoped launch (recommended for agents)
Run a command with per-project credentials without changing your parent shell:
gcpctx approve
gcpctx run -- claude
uvx gcpctx run -- codex ...
gcpctx run --profile dev -- gcloud storage ls
- Requires
.gcpctx.tomlin the current directory tree (exit 2 if missing). - Pre-approve for non-interactive terminals (
gcpctx approve). GOOGLE_APPLICATION_CREDENTIALSis unset in the child by default (same as hook mode).- Access tokens are short-lived; client libraries refresh ADC automatically (no gcpctx supervisor).
Shell activation (whole session)
-
Add
.gcpctx.tomlto the repo (gcpctx create). -
Approve once interactively, or pre-approve for automation:
gcpctx approve # remembered approval for this directory/profile
-
Activate in the shell that launches the agent:
eval "$(gcpctx activate --shell zsh)"
-
Agents and their subprocesses inherit isolated credentials.
Non-interactive / fail-closed
Without a matching approval, gcpctx activate exits with code 3 in non-interactive mode (typical agent terminals). Pre-run gcpctx approve in CI or document that users must activate interactively once.
Agent-friendly diagnostics
gcpctx doctor --json
gcpctx status --json
Use gcpctx status --json for activation fields (active, cloudsdk_config, approval, project, etc.).
Use gcpctx doctor --json for the compliance gate: versioned check results with id, severity, evidence, and structured remediation. See Doctor JSON contract.
When GOOGLE_APPLICATION_CREDENTIALS is required
Some tools insist on a key file path. Use --allow-google-application-credentials only when necessary; prefer impersonated ADC otherwise.
Security model (v0.3)
Security invariant
For any activated process, gcpctx guarantees that effective gcloud project, ADC context, impersonated service account, quota project, and credential-relevant environment variables match the approved profile and active policy, or activation fails closed.
See SECURITY.md for the enforcement map and Doctor JSON contract for machine-readable validation.
- POSIX only — Windows is unsupported (exit 10); the CLI fails closed until ACL checks land.
- First-use approval with remember + TTL (default 30 days); schema v2 binds gcloud path and fingerprint
- Config SHA-256 binding invalidates approval when project, service account, or config changes
- Immutable project identity —
CLOUDSDK_CORE_PROJECTalways matchesprofile.project(cannot set viaenv) - Isolated
CLOUDSDK_CONFIGunder~/.cache/gcpctx/contexts/ - Atomic, locked, symlink-safe writes for approvals and context state (
0600/0700) - gcloud binary trust validation (repo-local shadowing, world-writable parents, optional allowlist)
- Service account impersonation only (no long-lived key files in repo config)
GOOGLE_APPLICATION_CREDENTIALSunset by default in hook mode (restored on deactivate)- Optional
policy.tomlfor org-style allowlists and strict mode gcpctx doctor --strict --jsonfor CI/agent compliance gates- Append-only
audit.jsonlfor security events (no credential material)
See SECURITY.md and Architecture decision records (ADR-0003 through ADR-0009).
Upgrading to v0.3
Breaking: exit codes were remapped for automation. Notable changes from v0.2:
| Situation | v0.2 exit | v0.3 exit |
|---|---|---|
| Policy violation | 7 | 4 |
Unsafe filesystem (state_permissions) |
4 | 5 |
| gcloud trust / project / impersonation | 5 | 6 |
| ADC not initialized | 5 | 7 |
| IAM impersonation probe | 5 | 8 |
| Config schema error | 2 | 9 |
| Windows unsupported | 8 | 10 |
GOOGLE_APPLICATION_CREDENTIALS set |
6 | 4 |
Doctor --json shape changed: checks use id, status (pass/warn/fail), severity, evidence, and structured remediation. Top-level fields include version, status, profile, and context_id. See Doctor JSON contract.
CLI command renames
Commands were flattened and renamed (no backward-compatible aliases). Update shell rc files and scripts:
| Old | New |
|---|---|
init-project |
create |
init zsh / init bash |
install --shell zsh / install --shell bash |
hook eval |
hook --shell zsh / hook --shell bash |
profiles |
list |
use PROFILE / activate --profile NAME |
activate PROFILE or activate --profile NAME |
refresh |
reload |
clean --reinit |
reset |
config show / set-gcloud-path / unset-gcloud-path |
config / config PATH / config --unset (passing show prints a migration hint) |
gcpctx-use shell wrapper |
gcpctx-switch |
Re-run gcpctx install --shell zsh >> ~/.zshrc (or replace the # >>> gcpctx hook >>> block) after upgrading.
Upgrading from v0.1
- Remove any
[profiles.*.env] CLOUDSDK_CORE_PROJECTentries — useprofile.projectinstead. - Service account emails must use the same GCP project as
profile.project(e.g.agent@my-dev-project.iam.gserviceaccount.comforproject = "my-dev-project"). Cross-project impersonation is not supported in v0.2. - Re-run
gcpctx approveafter upgrade (approval schema v2 adds gcloud binding and expiry). - Pin gcloud per project if needed: add
gcloud_pathto.gcpctx.tomlor rungcpctx config "$(which gcloud)"in the repo (optional; pinning overrides PATH — rungcpctx config --unsetif you move or upgrade gcloud)
Policy file (optional)
~/.config/gcpctx/policy.toml or $GCPCTX_POLICY_PATH:
version = 1
[policy]
mode = "strict"
approval_ttl_days = 30
require_initialized_adc_for_hook = true
[allow]
projects = ["dev-*"]
[gcloud]
allowed_paths = ["/opt/google-cloud-sdk/bin/gcloud"]
Strict doctor
gcpctx doctor --strict --json
Non-zero exit when isolation, approval, ADC, IAM impersonation, or filesystem posture is unsafe. Exit codes are stable in v0.3 — see Doctor JSON contract.
Troubleshooting
| Symptom | Fix |
|---|---|
approval required in CI/agent |
Run gcpctx approve once, or activate interactively |
| Wrong project | gcpctx status; check .gcpctx.toml |
| Stale credentials | gcpctx reload; if that fails, gcpctx reset |
| Corrupt isolated ADC / clutter | gcpctx clean (project); gcpctx clean --all-contexts (all cache) |
| Reset remembered approvals | gcpctx clean --approvals or gcpctx revoke |
gcloud not found |
Install Google Cloud SDK |
| ADC issues | gcpctx doctor |
| IDE terminal not activated | Activate in parent shell before launching IDE, or use shell hooks |
Contributing
See CONTRIBUTING.md for developer setup, tests, and architecture notes.
Metadata
Release files for gcpctx 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| gcpctx-0.5.0.tar.gz | 173.8 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gcpctx-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 234.3 kB
Release files / gcpctx-0.5.0.tar.gz
| Download URL | gcpctx-0.5.0.tar.gz |
|---|---|
| Size | 173.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a156e72005976ebba7653877bfa8e4c233745f871b296dcb2b4861802bdf12e8
|
|
BLAKE2b-256 checksum How to use checksums |
0367d569af17b3e9ff622f2cec07e119ceb660788ada7604bb846739b6544d7a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 24, 2026.
Transparency logRelease files / gcpctx-0.5.0-py3-none-any.whl
| Download URL | gcpctx-0.5.0-py3-none-any.whl |
|---|---|
| Size | 60.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0630a9b89ba675ec0f1e9e87833b0368278f34596cb111c975cda6b612851061
|
|
BLAKE2b-256 checksum How to use checksums |
4640837b4ea6639a68c0134d65b2f1d9be60e6723e183b11d03f5d8dd67ad6d2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 24, 2026.
Transparency logSecurity for gcpctx 0.5.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for gcpctx-0.5.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 24, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.