gcloud — Google Cloud CLI in agentbox
The google-cloud-sdk (gcloud, gsutil, bq) is provisioned in the nix image
(flake.nix → basePackages), so gcloud is on $PATH in every shell. This skill
covers using it correctly in this container's constraints and the canonical GCP
deployment (the the target repository VPS behind IAP).
Environment constraints (read first)
/home/devuser is READ-ONLY. Only ~/workspace and ~/.config are writable.
gcloud's config/credential dir defaults to ~/.config/gcloud — writable, so
gcloud auth login and gcloud config work with no override.
- Auth is INTERACTIVE and operator-run. An agent cannot complete
gcloud auth login
(it opens a browser/entered code). Ask the operator to run it in the session with the
! prefix:! gcloud auth login
! gcloud config set project <PROJECT_ID>
After that, the agent's own gcloud calls reuse the stored credentials.
- Prefer impersonation over downloaded keys. Do not create/handle JSON service-account
key files. Use a deploy service account the operator can impersonate:
gcloud <cmd> --impersonate-service-account="<sa>@<project>.iam.gserviceaccount.com"
Verify access with:gcloud auth print-access-token --impersonate-service-account="<sa>@<project>…"
- Never commit credentials.
~/.config/gcloud, access tokens, and any key material
stay out of git. Application-default creds and tokens are runtime-only.
The canonical deployment — the target repository
- Project:
the target repository-503809 · Deploy SA (impersonate):
the target repository-deployer@the target repository-503809.iam.gserviceaccount.com
- Identity connector: the app validates Google IAP (
gcp-iap auth mode) — a
signed X-Goog-IAP-JWT-Assertion verified against Google's fixed JWKS. The deployment
puts the pod behind an IAP-gated external HTTPS load balancer.
- Full runbook: the
the target repository repo's docs/runbooks/gcp-vps-deploy.md — 10
idempotent phases (VPC + Cloud NAT egress, IAP-range firewall 130.211.0.0/22 +
35.191.0.0/16, GCE e2-standard-2/4 with no external IP, Secret Manager for
DB/cookie/model secrets, HTTPS LB + managed cert, IAP enable → derive the audience →
feed CAMPAIGNBUILDER_AUTH_AUD, e2e verify, snapshot backups).
- Least-privilege grant to ask the project owner for (impersonation, not a key):
roles/compute.admin, roles/iam.serviceAccountAdmin + roles/iam.serviceAccountUser,
roles/secretmanager.admin, roles/serviceusage.serviceUsageAdmin, and roles/iap.admin
for the full IAP path — all at project scope, no projectIamAdmin.
Common operations
# Identity / project
gcloud auth list # who am I
gcloud config get-value project
gcloud projects describe <PROJECT_ID> --format='value(projectNumber)'
# Enable APIs (idempotent)
gcloud services enable compute.googleapis.com iap.googleapis.com secretmanager.googleapis.com
# Compute Engine (check-before-create pattern — describe, then create)
gcloud compute instances describe <VM> --zone=<ZONE> --format='value(status)' \
|| gcloud compute instances create <VM> --zone=<ZONE> --machine-type=e2-standard-2 --no-address …
# Secret Manager (values via stdin — never a file on disk)
printf '%s' "$(openssl rand -base64 32)" | gcloud secrets create <name> --data-file=-
gcloud secrets versions access latest --secret=<name>
# IAP-brokered SSH (Google IAM, not host SSH) — this is authorised from agentbox
gcloud compute ssh <VM> --zone=<ZONE> --tunnel-through-iap --command '…'
# Derive the IAP audience for the app's gcp-iap auth mode
PN=$(gcloud projects describe <PROJECT_ID> --format='value(projectNumber)')
BID=$(gcloud compute backend-services describe <BACKEND> --global --format='value(id)')
echo "/projects/${PN}/global/backendServices/${BID}" # → CAMPAIGNBUILDER_AUTH_AUD
Execution contract for agents
- Check before create — every step is idempotent (
describe then create).
- Stop on failure — a half-built LB/firewall is worse than none; surface it.
- Resolve values, don't guess — the IAP audience is derived from the backend
service, never hard-coded.
- Secrets never to disk or git — stdin into Secret Manager; tokens are runtime-only.
- Surface interactive steps to the operator —
gcloud auth login, OAuth consent, and
the IAP brand are operator actions; provide the exact ! gcloud … line.
Notes
- Installed via
flake.nix basePackages (pkgs.google-cloud-sdk) — persistent across
rebuilds. (A prior userland bundle in ~/workspace/.tools predates this; the nix
package supersedes it once rebuilt.)
- Not an MCP server — this is a CLI skill (progressive disclosure): the front-matter
description is the discovery surface; this body is the on-demand detail.
- Related: the
the target repository repo (the app + the runbook), and the pod's gcp-iap
connector in control-plane/src/auth/verify.ts.
1---2name: gcloud3description: Google Cloud CLI (gcloud/gsutil/bq) for GCP operations from agentbox: Compute Engine VMs, Identity-Aware Proxy (IAP), Secret Manager, Cloud Run, Artifact Registry, Cloud NAT/firewall. Use when a task involves deploying to or operating Google Cloud — standing up a VM behind IAP, granting/impersonating a deploy service account, managing GCP secrets, or the the target repository VPS deployment. Installed via the nix flake (basePackages); auth is interactive (operator-run) and creds live in the writable ~/.config/gcloud.4---56# gcloud — Google Cloud CLI in agentbox78The `google-cloud-sdk` (gcloud, gsutil, bq) is provisioned in the nix image9(`flake.nix` → `basePackages`), so `gcloud` is on `$PATH` in every shell. This skill10covers using it correctly **in this container's constraints** and the canonical GCP11deployment (the `the target repository` VPS behind IAP).1213## Environment constraints (read first)1415- **`/home/devuser` is READ-ONLY.** Only `~/workspace` and `~/.config` are writable.16 gcloud's config/credential dir defaults to `~/.config/gcloud` — writable, so17 `gcloud auth login` and `gcloud config` work with no override.18- **Auth is INTERACTIVE and operator-run.** An agent cannot complete `gcloud auth login`19 (it opens a browser/entered code). Ask the operator to run it in the session with the20 `!` prefix:21 ```22 ! gcloud auth login23 ! gcloud config set project <PROJECT_ID>24 ```25 After that, the agent's own `gcloud` calls reuse the stored credentials.26- **Prefer impersonation over downloaded keys.** Do not create/handle JSON service-account27 key files. Use a deploy service account the operator can impersonate:28 ```29 gcloud <cmd> --impersonate-service-account="<sa>@<project>.iam.gserviceaccount.com"30 ```31 Verify access with:32 ```33 gcloud auth print-access-token --impersonate-service-account="<sa>@<project>…"34 ```35- **Never commit credentials.** `~/.config/gcloud`, access tokens, and any key material36 stay out of git. Application-default creds and tokens are runtime-only.3738## The canonical deployment — `the target repository`3940- **Project:** `the target repository-503809` · **Deploy SA (impersonate):**41 `the target repository-deployer@the target repository-503809.iam.gserviceaccount.com`42- **Identity connector:** the app validates Google **IAP** (`gcp-iap` auth mode) — a43 signed `X-Goog-IAP-JWT-Assertion` verified against Google's fixed JWKS. The deployment44 puts the pod behind an IAP-gated external HTTPS load balancer.45- **Full runbook:** the `the target repository` repo's `docs/runbooks/gcp-vps-deploy.md` — 1046 idempotent phases (VPC + Cloud NAT egress, IAP-range firewall `130.211.0.0/22` +47 `35.191.0.0/16`, GCE `e2-standard-2/4` with no external IP, Secret Manager for48 DB/cookie/model secrets, HTTPS LB + managed cert, IAP enable → derive the audience →49 feed `CAMPAIGNBUILDER_AUTH_AUD`, e2e verify, snapshot backups).50- **Least-privilege grant to ask the project owner for** (impersonation, not a key):51 `roles/compute.admin`, `roles/iam.serviceAccountAdmin` + `roles/iam.serviceAccountUser`,52 `roles/secretmanager.admin`, `roles/serviceusage.serviceUsageAdmin`, and `roles/iap.admin`53 for the full IAP path — all at **project scope**, no `projectIamAdmin`.5455## Common operations5657```bash58# Identity / project59gcloud auth list # who am I60gcloud config get-value project61gcloud projects describe <PROJECT_ID> --format='value(projectNumber)'6263# Enable APIs (idempotent)64gcloud services enable compute.googleapis.com iap.googleapis.com secretmanager.googleapis.com6566# Compute Engine (check-before-create pattern — describe, then create)67gcloud compute instances describe <VM> --zone=<ZONE> --format='value(status)' \68 || gcloud compute instances create <VM> --zone=<ZONE> --machine-type=e2-standard-2 --no-address …6970# Secret Manager (values via stdin — never a file on disk)71printf '%s' "$(openssl rand -base64 32)" | gcloud secrets create <name> --data-file=-72gcloud secrets versions access latest --secret=<name>7374# IAP-brokered SSH (Google IAM, not host SSH) — this is authorised from agentbox75gcloud compute ssh <VM> --zone=<ZONE> --tunnel-through-iap --command '…'7677# Derive the IAP audience for the app's gcp-iap auth mode78PN=$(gcloud projects describe <PROJECT_ID> --format='value(projectNumber)')79BID=$(gcloud compute backend-services describe <BACKEND> --global --format='value(id)')80echo "/projects/${PN}/global/backendServices/${BID}" # → CAMPAIGNBUILDER_AUTH_AUD81```8283## Execution contract for agents84851. **Check before create** — every step is idempotent (`describe` then `create`).862. **Stop on failure** — a half-built LB/firewall is worse than none; surface it.873. **Resolve values, don't guess** — the IAP audience is *derived* from the backend88 service, never hard-coded.894. **Secrets never to disk or git** — stdin into Secret Manager; tokens are runtime-only.905. **Surface interactive steps to the operator** — `gcloud auth login`, OAuth consent, and91 the IAP brand are operator actions; provide the exact `! gcloud …` line.9293## Notes9495- Installed via `flake.nix` `basePackages` (`pkgs.google-cloud-sdk`) — persistent across96 rebuilds. (A prior userland bundle in `~/workspace/.tools` predates this; the nix97 package supersedes it once rebuilt.)98- Not an MCP server — this is a CLI skill (progressive disclosure): the front-matter99 description is the discovery surface; this body is the on-demand detail.100- Related: the `the target repository` repo (the app + the runbook), and the pod's `gcp-iap`101 connector in `control-plane/src/auth/verify.ts`.