Reach your private Google Cloud services from your laptop, without the hassle.

zsh
$ bqto connect --service cloudsql --project my-project --instance orders-db
checking auth…
resolving endpoint…
checking firewall…
finding zones…
finding subnet…
creating bastion from debian-13-trixie-v20261014…
bastion bqto-7c92cdf1 is in us-east1-b
opening tunnel…
ready: 127.0.0.1:15432 → 10.10.1.19:5432 (instance orders-db), bastion bqto-7c92cdf1, expires at 14:24 (in 30m)
^C
deleting bastion…
bastion bqto-7c92cdf1 is being deleted (about 2 minutes)
How it works

Laptop, IAP, bastion, service.

  1. Your laptop127.0.0.1:15432
  2. IAPGoogle's front door
  3. Bastionin your project
  4. Private service10.10.1.19:5432
  1. A bastion starts

    bqto creates a small VM with no external IP in your project, in the service's network.

  2. IAP checks you

    The tunnel goes through IAP, which checks your own IAM roles on every connection. No SSH keys to hand out.

  3. You use the local port

    Point psql or your app at 127.0.0.1. When you stop, bqto deletes the bastion.

Use cases

Works where you work.

Your coding agent FREE

Give Claude Code or another agent the bqto skill and ask in plain words.

You:Count the orders in orders-db. It's the Cloud SQL instance in my-project.

Agent:

Checked bqto, gcloud and psql, the instance, its databases and users. PGPASSWORD is set.

Run this command?

bqto connect --no-input --duration 15m \
  --project my-project --service cloudsql \
  --instance orders-db -- sh -c 'psql \
  "host=$PGHOST port=$PGPORT user=postgres dbname=postgres sslmode=require" \
  -At -c "select count(*) from orders"'

You:Yes

Agent:

There are 5 orders in public.orders, the only orders table, in the postgres database on orders-db.

The temporary bastion has been deleted.

1m 40s, bastion included.

CI/CD FREE

A step in your workflow opens the tunnel, runs your migration and closes it. No service account key and no runner inside the VPC.

jobs:
  migrate:
    runs-on: ubuntu-24.04
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v7
        with:
          persist-credentials: false
      - uses: google-github-actions/auth@v3
        with:
          workload_identity_provider: ${{ vars.WIF_PROVIDER }}
          service_account: ${{ vars.WIF_SA }}
      - uses: google-github-actions/setup-gcloud@v3
      - uses: pilef-co/bqto-action@v1
        env:
          PGPASSWORD: ${{ secrets.DB_PASSWORD }}
        with:
          project: my-project
          instance: sql-main
          run: ./migrate up

Mac app PRO BETA

A switch in your menu bar for each saved profile. Turn it on, copy the port and turn it off to delete the bastion.

The bqto menu in the macOS menu bar lists saved profiles. Switching on the orders-db profile shows bqto's progress while it creates the bastion and opens the tunnel, then ready, 127.0.0.1:15432 and the time left. The pointer copies the address, and psql typed in Terminal connects to it. Switching the profile off shows "Ending: bqto is deleting the bastion", then "Gone, nothing to patch tomorrow."

Get started

Install bqto on macOS and Linux.

$ curl -fsSL https://raw.githubusercontent.com/pilef-co/bqto/main/install.sh | sh

Downloads the newest release for your Mac or Linux machine, checks its SHA-256 and puts bqto in /usr/local/bin, asking for your password only when that folder is not yours. No Go needed.

Then connect

Sign in twice with the same Google account, then run bqto. With no flags, it asks for the project, the service and the instance.

$ gcloud auth login && gcloud auth application-default login
$ bqto connect

What you need

  • The Google Cloud CLI, version 550.0.0 or later.
  • A firewall rule that allows tcp:22 from 35.235.240.0/20 into the service's VPC. bqto checks for it and never creates it.
  • The IAM roles to find the service, create the bastion and open the tunnel. The README lists them.
Free and Pro

What you can reach.

bqto FREE

  • Cloud SQL with read replicas
  • AlloyDB with read pools
  • Memorystore for Redis Basic and Standard
  • Memorystore for Valkey
  • Terminal, coding agents and the GitHub Action

bqto Pro PRO

Everything in the free bqto, plus:

  • Cloud Run internal services, through a SOCKS5 proxy or a local web proxy (--web) that adds your identity token
  • Managed Kafka
  • Redis and Valkey clusters
  • Profiles and stacks save a connection once and open it by name next time
  • --endpoint any private IP and port, such as an internal load balancer or a Private Service Connect endpoint
  • Bastion settings Spot, subnet, machine type and image
  • The Mac app
  • Cloud Run, Kafka, profiles and stacks in the GitHub Action

We give the Google account you sign up with access to download bqto Pro from Artifact Registry. After the beta's last day, it keeps working as the free bqto.

Pro beta

Get early access to bqto Pro.

Usually your work email. A personal Gmail works too.

If you want bqto Pro in CI.

Which bqto Pro features do you want to use?
Company size
Your role

Your answers reach Pilef through Google Forms. This site has no tracking and no cookies.

Questions.

What if I forget to close a session?

Every bastion has a time limit set in Compute Engine itself (--duration, 30 minutes by default). When it runs out, Google Cloud deletes the VM, even if your laptop is asleep or offline.

What does a session cost?

A session is one e2-micro VM with a 10 GB disk while it runs. In us-central1, that is about half a cent for 30 minutes. IAP TCP forwarding is free. bqto itself is free. You pay only for the VM and its disk.

Does bqto store my credentials?

No. bqto uses your gcloud login and your IAM roles. It never stores the private IP either: it looks it up on every connect.

Do I still need a database password?

Yes. bqto only opens the network path. You log in to the database as usual, with its password or an IAM token.

Is bqto made by Google?

No. Pilef makes bqto, and it's not affiliated with Google.