Fuzzy-search every Google Cloud project you have access to and jump straight to
it — Cloud Console, gcloud context switch, or clipboard — without leaving
Alfred.
Built for accounts with a lot of projects: results come from a local cache, so filtering stays instant no matter how many projects you can see.
gcp proj web
- macOS with Alfred 5 and the Powerpack (workflows are a Powerpack feature)
- Google Cloud CLI (
gcloud), already authenticated — rungcloud auth loginif you haven't - Python 3 — the system
/usr/bin/python3is fine; no third-party packages
- Download
GCP.alfredworkflowfrom the latest release. - Double-click it. Alfred shows an import dialog — click Import.
- Type
gcp projin Alfred. The first run builds the project cache, which takes a second or two; after that it is instant.
Updating works the same way — importing a newer version replaces the old one and keeps your configuration, cache, and favorites.
To build from source instead, see Development.
gcp proj <search> fuzzy-searches your projects. The proj prefix is
optional — gcp acme-prod works too. gcp on its own lists the subcommands.
| Subcommand | What it does |
|---|---|
gcp proj <search> |
Search all projects |
gcp fav |
Show only pinned favorites |
gcp refresh |
Rebuild the project cache now |
Press these on a highlighted result:
| Key | Action |
|---|---|
↩ |
Open the Cloud Console dashboard |
⌘↩ |
gcloud config set project <id> |
⌥↩ |
Copy the project ID |
⌃↩ |
Open IAM & Admin |
⇧↩ |
Open Logs Explorer |
⌘⌥↩ |
Open Billing |
⌃⌥↩ |
Pin / unpin as a favorite |
Your active gcloud project is marked ✓ active and floats to the top of an
unfiltered list. Alfred also learns which projects you pick, so the ones you use
most drift upward on their own.
Ranked best-first:
| Rank | Match | Example |
|---|---|---|
| 1 | Exact project ID | acme-prod-web-eu |
| 2 | Word initials | apwe → acme-prod-web-eu |
| 3 | Initials prefix | apw → acme-prod-web-eu |
| 4 | Substring (word boundaries score higher) | prod-web |
| 5 | Project name substring | matches the display name, not the ID |
| 6 | Loose subsequence | awe → acme-prod-web-eu |
Word initials are what make this usable when every project shares a suffix — typing the first letter of each hyphenated segment gets you there in four keystrokes.
⌃⌥↩ pins a project. Pins are marked ★ and sort above other matches — but
only among results that already match what you typed, so pinning something
never hijacks an unrelated search. On an unfiltered gcp proj they lead the
list in pin order, followed by your active project.
gcp fav shows only pinned projects. If a pinned project disappears from your
project list — deleted, or access revoked — it still appears there, flagged, so
you can unpin it.
Alfred → Workflows → GCP → Configure Workflow. Every field is optional.
| Setting | Default | Notes |
|---|---|---|
| Path to gcloud | auto-detect | Set this if gcloud lives somewhere unusual |
| Cache TTL (hours) | 12 |
How long the cached list stays fresh before a background refresh |
| Path to python3 | auto-detect | Set this to pin a specific interpreter |
Auto-detection checks, in order: ~/google-cloud-sdk/bin, Homebrew
(/opt/homebrew), then /usr/local. Alfred runs workflow scripts with a
minimal PATH, which is why absolute paths matter here.
gcloud projects list is a network call and far too slow to run on every
keystroke, so the project list is cached at:
~/Library/Application Support/Alfred/Workflow Data/com.derhally.gcp/
├── projects.json # the cached project list
└── favorites.json # your pins, in pin order
The cache is built on first use, then refreshed in the background once it is older than the TTL. Favorites are stored separately and survive every refresh.
Run gcp refresh after creating a project or gaining access to one, rather than
waiting for the TTL.
"Could not load projects" — the message shows gcloud's own error. Most
often it is expired credentials; run gcloud auth login.
"gcloud not found" — set Path to gcloud in Configure Workflow to the
output of which gcloud.
"python3 not found" — set Path to python3 to the output of which python3.
A project is missing — the cache is stale. Run gcp refresh. Note that only
ACTIVE projects are listed; projects pending deletion are excluded.
Nothing happens on ↩ — check Alfred's debug console (Workflows → GCP →
the bug icon) for the action script's output.
src/ is the source of truth. info.plist and icon.png are generated, so
edit the builder rather than the workflow in Alfred's UI.
python3 build.py # -> build/GCP/ and GCP.alfredworkflow
python3 tools/check_package.py # validate the package
open GCP.alfredworkflow # install or updateNothing beyond the Python standard library is required, on your machine or in CI.
| File | Role |
|---|---|
src/gcp_projects.py |
Script Filter — cache, matching, favorites, JSON output |
src/dispatch.sh |
Runs the chosen action |
src/refresh_cache.sh |
Rebuilds the cache; also safe to run from a terminal |
src/find_gcloud.sh, src/find_python.sh |
Locate binaries despite Alfred's minimal PATH |
build.py |
Generates info.plist + icon.png, packages the workflow |
tools/check_package.py |
Pre-ship checks on the built package |
version.txt |
Single source of truth for the version |
The workflow is three connected objects: a Script Filter, a Run Script action,
and a notification. Each result carries action and projectId workflow
variables, and each modifier overrides action — so one dispatcher handles
every key without extra wiring in the plist.
GCP.alfredworkflow is a build output and is not committed; releases carry it.
Releases are automated with
release-please, so commit
messages on main must follow
Conventional Commits:
| Prefix | Effect |
|---|---|
fix: |
patch bump — 1.1.0 → 1.1.1 |
feat: |
minor bump — 1.1.0 → 1.2.0 |
feat!: or a BREAKING CHANGE: footer |
major bump — 1.1.0 → 2.0.0 |
docs:, chore:, ci:, refactor: |
no release |
The flow:
- Push a conventional commit to
main. - Release-please opens (or updates) a release PR with the version bump and
generated
CHANGELOG.md. - Merge that PR. Release-please tags the release, then CI builds the package,
validates it, and attaches
GCP.alfredworkflowto it.
version.txt and .release-please-manifest.json are maintained by
release-please — bump them by merging its PR, not by hand. build.py reads
version.txt so the plist version always matches the release tag.
Every pull request runs the same build and validation, and uploads the package as a run artifact so a change can be test-imported before merge.
MIT — see LICENSE.