From 7adf74d0d669c0700a27119aba09975d5fab29a4 Mon Sep 17 00:00:00 2001 From: Ikuo Degawa Date: Wed, 24 Jun 2026 16:29:40 +0900 Subject: [PATCH 1/2] Repurpose gps as GCP project switcher Switch gps from gcloud-configuration switching to per-shell project override via CLOUDSDK_CORE_PROJECT, mirroring the aps (AWS_PROFILE) pattern. Prompt indicator switches from to . Co-authored-by: Claude Opus 4.7 --- .bash_profile | 4 ---- .functions | 57 +++++++++++++++++++------------------------- AIRULES.md | 2 +- claude/settings.json | 1 + 4 files changed, 27 insertions(+), 37 deletions(-) diff --git a/.bash_profile b/.bash_profile index 1f07d3d..237d09e 100644 --- a/.bash_profile +++ b/.bash_profile @@ -89,10 +89,6 @@ if [ -f ~/.aws/current_profile ]; then fi export CLOUDSDK_CONFIG="$XDG_CONFIG_HOME/gcloud" -if [ -f "$CLOUDSDK_CONFIG/active_config" ]; then - GC_ACTIVE_CONFIG="$(cat "$CLOUDSDK_CONFIG/active_config")" - export GC_ACTIVE_CONFIG -fi export COLIMA_HOME="$XDG_CONFIG_HOME/colima" diff --git a/.functions b/.functions index 9002732..7f27f55 100644 --- a/.functions +++ b/.functions @@ -9,8 +9,8 @@ prompt_aws() { } prompt_gc() { - if [[ -n "${GC_ACTIVE_CONFIG}" && "${GC_ACTIVE_CONFIG}" != "none" ]]; then - GC_PROMPT=" " + if [[ -n "${CLOUDSDK_CORE_PROJECT}" ]]; then + GC_PROMPT=" " else GC_PROMPT="" fi @@ -201,65 +201,58 @@ if [ ! "$(command -v gps)" ]; then cat << 'EOF' Usage: gps [OPTIONS] [QUERY] -Google Cloud Profile Switcher - Switch between gcloud configurations interactively +Google Cloud Project Switcher - Switch between GCP projects interactively. +Sets CLOUDSDK_CORE_PROJECT for the current shell (per-shell, not persisted). OPTIONS: --help, -h Show this help message - --clear Clear the current gcloud configuration (set to "none") - --list List all configurations (current one marked with *) + --clear Clear the current GCP project (unset CLOUDSDK_CORE_PROJECT) + --list List all projects (current one marked with *) ARGUMENTS: - QUERY Filter configurations by query string (optional) + QUERY Filter projects by query string (optional) EXAMPLES: - gps # Interactive configuration selection with fzf - gps prod # Filter configurations containing "prod" - gps --list # List all available configurations - gps --clear # Clear current configuration + gps # Interactive project selection with fzf + gps prod # Filter projects containing "prod" + gps --list # List all available projects + gps --clear # Clear current project EOF return fi - DUMMY_CONFIG_NAME="none" - if [ ! "$(gcloud config configurations list --format='value(name)' | grep "^${DUMMY_CONFIG_NAME}$")" ]; then - gcloud config configurations create "$DUMMY_CONFIG_NAME" - fi - if [ "$query" = "--clear" ]; then - export GC_ACTIVE_CONFIG="$DUMMY_CONFIG_NAME" - gcloud config configurations activate "$DUMMY_CONFIG_NAME" - echo "Google Cloud configuration cleared." + unset CLOUDSDK_CORE_PROJECT + echo "GCP project cleared." return fi if [ "$query" = "--list" ]; then - # List all configurations with current one marked with * - current_config="${GC_ACTIVE_CONFIG:-$(cat "${CLOUDSDK_CONFIG:-${XDG_CONFIG_HOME:-$HOME/.config}/gcloud}/active_config" 2>/dev/null || echo "")}" - gcloud config configurations list --format='value(name)' | while read -r config; do - if [ "$config" = "$current_config" ]; then - echo "* $config" + current_project="${CLOUDSDK_CORE_PROJECT:-}" + gcloud projects list --format='value(projectId)' --sort-by=projectId | while read -r project; do + if [ "$project" = "$current_project" ]; then + echo "* $project" else - echo " $config" + echo " $project" fi done return fi - config="" + project="" if [ -n "$query" ]; then - config="$(gcloud config configurations list --format='value(name)' | grep -v "^${DUMMY_CONFIG_NAME}$" | fzf --filter "$query" | head -n 1)" + project="$(gcloud projects list --format='value(projectId)' --sort-by=projectId | fzf --filter "$query" | head -n 1)" else - config="$(gcloud config configurations list --format='value(name)' | grep -v "^${DUMMY_CONFIG_NAME}$" | fzf)" + project="$(gcloud projects list --format='value(projectId)' --sort-by=projectId | fzf)" fi - if [ -z "$config" ]; then - echo "No profiles are selected." + if [ -z "$project" ]; then + echo "No projects are selected." return fi - gcloud config configurations activate "$config" - export GC_ACTIVE_CONFIG="$(cat "${CLOUDSDK_CONFIG:-${XDG_CONFIG_HOME:-$HOME/.config}/gcloud}/active_config")" - echo "Google Cloud config set: $config" + export CLOUDSDK_CORE_PROJECT="$project" + echo "GCP project set: $project" } fi diff --git a/AIRULES.md b/AIRULES.md index 7ee8097..478e243 100644 --- a/AIRULES.md +++ b/AIRULES.md @@ -94,7 +94,7 @@ 1. シェルコマンド内でコマンド置換(`$()`、バッククォート)を使わない - 複数行テキストはシングルクォートで渡す。本文にシングルクォートが含まれる場合のみ heredoc にフォールバック 1. AWS CLI を実行する際は必ず `AWS_PROFILE= aws ...` の形式で環境変数をコマンドの先頭に付与する。使用する profile は必ずユーザーに確認してから実行すること - - GCP の権限切り替えは `gps` コマンドを使用する +1. gcloud / bq / gsutil を実行する際は必ず `CLOUDSDK_CORE_PROJECT= gcloud ...` の形式で環境変数をコマンドの先頭に付与する。使用する project は必ずユーザーに確認してから実行すること。project 切替は `gps` コマンドを使う 1. プロジェクトと無関係のファイルは `ikuwowfiles/` 以下に置く(グローバル gitignore 対象) 1. コード・ファイル内の検索は `git grep` を第一選択とする - Bash の `find` コマンドではなく Glob/Grep/Read ツールを優先する。`find` は専用ツールでは実現できない場合(パーミッション・タイムスタンプ条件等)に限定する diff --git a/claude/settings.json b/claude/settings.json index fd0d613..a321bc3 100644 --- a/claude/settings.json +++ b/claude/settings.json @@ -52,6 +52,7 @@ "Bash(aps --help *)", "Bash(gps --list *)", "Bash(gps --help *)", + "Bash(gcloud projects list*)", "Bash(dog --help *)", "Bash(date *)", "Bash(aws sts get-caller-identity *)", From ad6832b0325f75634222daeaddc282afa9ebec49 Mon Sep 17 00:00:00 2001 From: Ikuo Degawa Date: Wed, 24 Jun 2026 16:36:49 +0900 Subject: [PATCH 2/2] Address review findings on gps refactor - Capture gcloud projects list output before piping so failures (auth, network) propagate as exit 1 with a clear message instead of the misleading "No projects are selected." or empty --list output. - Drop the redundant Bash(gcloud projects list*) allow rule; the existing Bash(gcloud * list *) on line 89 already covers it. - Generalize the AIRULES.md GCP rule example to so the prefix template matches the scope the rule declares (verified bq and gsutil honor CLOUDSDK_CORE_PROJECT empirically). Co-authored-by: Claude Opus 4.7 --- .functions | 11 ++++++++--- AIRULES.md | 2 +- claude/settings.json | 1 - 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.functions b/.functions index 7f27f55..2ef6272 100644 --- a/.functions +++ b/.functions @@ -227,9 +227,14 @@ EOF return fi + if ! projects="$(gcloud projects list --format='value(projectId)' --sort-by=projectId)"; then + echo "gps: failed to list GCP projects" >&2 + return 1 + fi + if [ "$query" = "--list" ]; then current_project="${CLOUDSDK_CORE_PROJECT:-}" - gcloud projects list --format='value(projectId)' --sort-by=projectId | while read -r project; do + echo "$projects" | while read -r project; do if [ "$project" = "$current_project" ]; then echo "* $project" else @@ -241,9 +246,9 @@ EOF project="" if [ -n "$query" ]; then - project="$(gcloud projects list --format='value(projectId)' --sort-by=projectId | fzf --filter "$query" | head -n 1)" + project="$(echo "$projects" | fzf --filter "$query" | head -n 1)" else - project="$(gcloud projects list --format='value(projectId)' --sort-by=projectId | fzf)" + project="$(echo "$projects" | fzf)" fi if [ -z "$project" ]; then diff --git a/AIRULES.md b/AIRULES.md index 478e243..6af347d 100644 --- a/AIRULES.md +++ b/AIRULES.md @@ -94,7 +94,7 @@ 1. シェルコマンド内でコマンド置換(`$()`、バッククォート)を使わない - 複数行テキストはシングルクォートで渡す。本文にシングルクォートが含まれる場合のみ heredoc にフォールバック 1. AWS CLI を実行する際は必ず `AWS_PROFILE= aws ...` の形式で環境変数をコマンドの先頭に付与する。使用する profile は必ずユーザーに確認してから実行すること -1. gcloud / bq / gsutil を実行する際は必ず `CLOUDSDK_CORE_PROJECT= gcloud ...` の形式で環境変数をコマンドの先頭に付与する。使用する project は必ずユーザーに確認してから実行すること。project 切替は `gps` コマンドを使う +1. gcloud / bq / gsutil を実行する際は必ず `CLOUDSDK_CORE_PROJECT= ...` の形式で環境変数をコマンドの先頭に付与する。使用する project は必ずユーザーに確認してから実行すること。project 切替は `gps` コマンドを使う 1. プロジェクトと無関係のファイルは `ikuwowfiles/` 以下に置く(グローバル gitignore 対象) 1. コード・ファイル内の検索は `git grep` を第一選択とする - Bash の `find` コマンドではなく Glob/Grep/Read ツールを優先する。`find` は専用ツールでは実現できない場合(パーミッション・タイムスタンプ条件等)に限定する diff --git a/claude/settings.json b/claude/settings.json index a321bc3..fd0d613 100644 --- a/claude/settings.json +++ b/claude/settings.json @@ -52,7 +52,6 @@ "Bash(aps --help *)", "Bash(gps --list *)", "Bash(gps --help *)", - "Bash(gcloud projects list*)", "Bash(dog --help *)", "Bash(date *)", "Bash(aws sts get-caller-identity *)",