{"slug": "gspot-gcloud-auth-monitoring-for-long-running-coding-agents", "title": "Gspot: Gcloud auth monitoring for long-running coding agents", "summary": "G-Spot, a new lightweight cross-platform system tray application for macOS, Windows, and Linux, continuously monitors Google Cloud SDK authentication, tracks active GCP project configurations, inspects billing, and prevents AI coding agents such as Gemini, Claude Code, Cursor, Copilot, and LangChain from timing out due to expired OAuth or Application Default Credentials (ADC). The app features dynamic icon coloring based on credential status, proactive desktop notifications, one-click re-authentication, and an instant project switcher, aiming to keep long-running coding agents authenticated and productive.", "body_md": "\"Hard to find, but keeps everything running smoothly.\"\n\nG-Spot is a lightweight, cross-platform system tray application for macOS, Windows, and Linux that continuously monitors Google Cloud SDK authentication, tracks active GCP project configurations, inspects billing, and prevents AI coding agents (Gemini, Claude Code, Cursor, Copilot, LangChain, etc.) from timing out due to expired OAuth or Application Default Credentials (ADC).\n\n**Dynamic GCP-Inspired Generic Cloud Icon System (Pillow ImageDraw):**- Programmatically rendered in Python using Pillow without using official trademarked logos.\n- Dynamically colored based on credential status using Google's signature color palette:\n**Solid Green (** Both User (`#34A853`\n\n):`gcloud auth`\n\n) and ADC (`application-default`\n\n) tokens are active.**Solid Yellow (** Partial authentication (only one set of tokens is active).`#FBBC05`\n\n):**Solid Red (** Both tokens are expired, missing, or disconnected.`#EA4335`\n\n):**Solid Blue (** Initializing / actively refreshing.`#4285F4`\n\n):**Solid Gray (** Offline — no network reachable, so credential status is unknown. Distinguished from Red deliberately: a red icon on a plane is a false alarm, and false alarms train you to ignore the icon.`#80868B`\n\n):\n\n**Dynamic Tooltips:** Hover displays`G-Spot: Active`\n\n,`G-Spot: Partial Auth`\n\n,`G-Spot: Expired`\n\n, or`G-Spot: Offline (no network)`\n\nalongside the active project ID (e.g.`G-Spot: Active (my-project-id)`\n\n).**Identity & Token Expiry Header:** Shows the authenticated Google account email and remaining token lifetime (e.g.,`Account: dev@company.com (~48m left)`\n\n).**Proactive Desktop Notifications & Interactive Modal Popups:**- Fires native OS desktop notification banners whenever authentication drops from Green to Yellow/Red —\n**and on the first check after launch**, since opening your laptop to a session that died overnight is the most common way this bites you. - Stays quiet when the cause is simply no network: G-Spot will not ask you to re-authenticate against a server it can't reach.\n- Automatically pops up an\n**Interactive System Modal Alert Dialog** with a 1-click`[Re-Authenticate Now]`\n\naction button when authentication is lost, immediately opening the terminal login flow. - Toggleable via\n`Popup on Auth Loss: [ON/OFF]`\n\nwith an instant preview action`Test Auth Loss Popup Now`\n\n.\n\n- Fires native OS desktop notification banners whenever authentication drops from Green to Yellow/Red —\n**One-Click Re-Authentication:**\"Connect All (User + ADC)\" launches your native terminal emulator (`Terminal.app`\n\non macOS, Command Prompt / PowerShell on Windows, or standard Linux emulators) to run`gcloud auth login && gcloud auth application-default login`\n\ninteractively.**Instant Project Switcher:** View recent projects and switch your active`gcloud`\n\nproject directly from the tray context menu without opening a shell.**Cloud Console Launcher:** Quick-jump directly to the Cloud Console dashboard for the currently active project.\n\nTo keep the primary tray menu lightweight and clutter-free, pro-developer utilities are housed in the **Developer & Agent Tools** submenu:\n\n**Copy Agent Env Vars (Export):** Copies standard shell export statements directly to the system clipboard:\n\n```\nexport GOOGLE_CLOUD_PROJECT=\"active-project-id\"\nexport CLOUDSDK_CORE_PROJECT=\"active-project-id\"\nexport GOOGLE_APPLICATION_CREDENTIALS=\"/path/to/application_default_credentials.json\"\nexport VERTEX_AI_PROJECT=\"active-project-id\"\n```\n\n**Run Agent Health Doctor:** Runs a diagnostic scan verifying physical ADC file paths, token expiry, network reachability, and detecting any conflicting environment variables (`GOOGLE_APPLICATION_CREDENTIALS`\n\n,`CLOUDSDK_AUTH_ACCESS_TOKEN`\n\n). The full report is copied to your clipboard — a nine-field diagnostic doesn't fit in a notification banner.**Switch SDK Profile / Config:** Submenu to list and activate named`gcloud`\n\nconfiguration profiles (`default`\n\n,`staging`\n\n,`production`\n\n).**Billing & Spend Snapshot:** Real-time visibility into project billing account linkage and status, with automatic fallback when missing billing IAM permissions.**Auto-Renew Tokens:** Toggleable background watcher that performs a real non-interactive refresh (via`gcloud config config-helper --min-expiry`\n\n) when fewer than 10 minutes remain. If the refresh does not extend the token, the underlying session has expired and G-Spot says so rather than reporting a success it didn't achieve.**Session Policy:** Direct links to the settings that actually govern how long your credentials live. Token lifetime is**not** a local setting — session length for Google Cloud (which covers the`gcloud`\n\nCLI and ADC, not just the web console) is a Google Workspace admin policy, configurable between 1 and 24 hours by someone holding the Security Settings privilege. G-Spot detects whether your active account belongs to a Workspace domain and either links you to the right admin page or explains why no such policy exists for a personal account.\n\n[Google Cloud SDK (](https://cloud.google.com/sdk/docs/install)installed and initialized.`gcloud`\n\n)\n\n- Download\nfrom the`GSPOT.exe`\n\n[latest GitHub Release](https://github.com/Somnora/GSPOT/releases)or find it directly in.`windows/GSPOT.exe`\n\n- Double-click\nto launch.`GSPOT.exe`\n\n- G-Spot will appear in your Windows notification area / taskbar tray (bottom-right near the clock, or inside the\n`^`\n\noverflow menu). - Both\n**left-click** and**right-click** open the status menu and quick switcher.\n\n- Download\n`G-Spot-1.0.0.dmg`\n\nfrom the[latest GitHub Release](https://github.com/Somnora/GSPOT/releases). - Open the\n`.dmg`\n\nand drag**G-Spot.app** into your**Applications** folder. - Launch\n**G-Spot** from Launchpad or Spotlight.\n\nNote:On first launch macOS may show a Gatekeeper warning since the app is not notarized. Right-click the app →Open→Opento bypass.\n\nRequires **Python 3.9+**.\n\n```\n# 1. Clone the repository\ngit clone https://github.com/Somnora/GSPOT.git && cd GSPOT\n\n# 2. Create and activate a virtual environment\npython3 -m venv .venv\nsource .venv/bin/activate    # On Windows: .venv\\Scripts\\activate\n\n# 3. Install dependencies\npip install -r requirements.txt\n\n# 4. Launch G-Spot\npython main.py\npip install pyinstaller\n.\\windows\\build_windows.bat\n# Output: dist\\GSPOT.exe and windows\\GSPOT.exe\npip install pyinstaller\npython macos/generate_icns.py   # Generate macOS .icns app icon\npyinstaller macos/G-Spot.spec --noconfirm --clean\nbash macos/build_dmg.sh         # Output: dist/G-Spot-1.0.0.dmg\npython main.py --help\n# Options:\n#   -i, --interval SECONDS   Polling check interval in seconds (default: 300 / 5 minutes)\n#   --debug                  Enable verbose debug logging\n#   -v, --version            Display version information\n#\n# Headless mode (no tray, no display required):\n#   --status                 Print current status and exit 0\n#   --json                   With --status, print JSON instead of one line\n#   --check                  Exit 0 if at least --min-minutes remain, else 1\n#   --renew                  Force a non-interactive refresh; exit 0 on success\n#   --min-minutes N          Minutes required (--check: 30, --renew: 55)\n```\n\n`--status`\n\n, `--check`\n\nand `--renew`\n\nrun without a tray and without a display. They\nnever import `pystray`\n\n, so they work over SSH, in a container, or in CI where\nimporting a GUI toolkit would raise.\n\nThe failure this tool exists to prevent is starting a long agent run on a token that dies halfway through. Gate the run instead of being notified about it:\n\n```\npython main.py --check --min-minutes 30 || python main.py --renew\n```\n\nExit 0 means you have at least 30 minutes and can safely start. Exit 1 means the\ncredential could not be brought up to that mark and only an interactive\n`gcloud auth login`\n\nwill help.\n\n``` bash\n$ python main.py --status\nGREEN | you@example.com | my-project | ~42m left | user=ok adc=ok\n\n$ python main.py --status --json\n{\n  \"state\": \"green\",\n  \"account\": \"you@example.com\",\n  \"project\": \"my-project\",\n  \"token_expiry_minutes\": 42,\n  \"adc_valid\": true,\n  \"user_valid\": true,\n  \"network_reachable\": true\n}\n```\n\n`state`\n\nis one of `green`\n\n, `yellow`\n\n, `red`\n\n, `offline`\n\n, `searching`\n\n. JSON goes to\nstdout and diagnostics to stderr, so `--status --json 2>/dev/null`\n\nis safe to\npipe straight into `jq`\n\n. `--status`\n\nalways exits 0 — it reports, it does not gate.\n\n`network_reachable`\n\nis only actively probed when every auth check has already\nfailed, so `true`\n\nmeans \"not proven unreachable\" rather than \"just pinged\".\n\n| Command | 0 | 1 |\n|---|---|---|\n`--status` |\nalways | — |\n`--check` |\nat least `--min-minutes` remain |\ntoo little time, expired, offline, unknown expiry, or no gcloud |\n`--renew` |\nrefreshed, or already above `--min-minutes` |\nrefresh could not extend the credential |\n\n`--check`\n\nfails closed: anything it cannot positively verify is a failure, since\na false pass costs you a dead agent run. Partial auth (one of user/ADC missing)\nstill exits 0 if there is enough time, but prints a warning to stderr.\n\n`--renew`\n\nexits 0 when the token was already comfortable and gcloud declined to\nrefresh it — that is the normal case in the one-liner above, not an error.\n\nTo have G-Spot run automatically in the background on system boot without showing a terminal window:\n\n- Create a LaunchAgent plist file at\n`~/Library/LaunchAgents/com.user.gspot.plist`\n\n:\n\n```\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n    <key>Label</key>\n    <string>com.user.gspot</string>\n    <key>ProgramArguments</key>\n    <array>\n        <string>/Users/YOUR_USERNAME/Desktop/G_Spot/.venv/bin/python</string>\n        <string>/Users/YOUR_USERNAME/Desktop/G_Spot/main.py</string>\n    </array>\n    <key>RunAtLoad</key>\n    <true/>\n    <key>KeepAlive</key>\n    <true/>\n    <key>StandardOutPath</key>\n    <string>/tmp/gspot.log</string>\n    <key>StandardErrorPath</key>\n    <string>/tmp/gspot.err</string>\n</dict>\n</plist>\n```\n\n- Load and start the service:\n\n```\nlaunchctl load ~/Library/LaunchAgents/com.user.gspot.plist\n```\n\n- Press\n`Win + R`\n\n, type`shell:startup`\n\n, and hit**Enter**. - Right-click in the folder ->\n**New**->** Shortcut**. - For location, enter:\n\n```\n\"C:\\path\\to\\G_Spot\\.venv\\Scripts\\pythonw.exe\" \"C:\\path\\to\\G_Spot\\main.py\"\n```\n\n*(Using*`pythonw.exe`\n\nruns Python without opening a Command Prompt window). - Click\n**Next**, name it`G-Spot`\n\n, and click**Finish**.\n\n- Open\n**Task Scheduler**->** Create Basic Task**. - Trigger:\n**When I log on**. - Action:\n**Start a program**. - Program:\n`C:\\path\\to\\G_Spot\\.venv\\Scripts\\pythonw.exe`\n\n- Arguments:\n`main.py`\n\n- Start in:\n`C:\\path\\to\\G_Spot`\n\nCreate `~/.config/autostart/gspot.desktop`\n\n:\n\n```\n[Desktop Entry]\nType=Application\nName=G-Spot\nComment=Google Status, Project, & Optimization Tool\nExec=/path/to/G_Spot/.venv/bin/python /path/to/G_Spot/main.py\nHidden=false\nNoDisplay=false\nX-GNOME-Autostart-enabled=true\n```\n\n- Create\n`~/.config/systemd/user/gspot.service`\n\n:\n\n```\n[Unit]\nDescription=G-Spot Background Tray Service\nAfter=graphical-session.target\n\n[Service]\nType=simple\nWorkingDirectory=/path/to/G_Spot\nExecStart=/path/to/G_Spot/.venv/bin/python main.py\nRestart=always\nRestartSec=5\n\n[Install]\nWantedBy=default.target\n```\n\n- Enable and start:\n\n```\nsystemctl --user daemon-reload\nsystemctl --user enable --now gspot.service\nG-Spot/\n├── .github/\n│   └── workflows/\n│       └── release.yml         # CI: Build .app, package .dmg, publish GitHub Release on tag\n├── assets/\n│   ├── icons/                  # Monotone SVG icons (active, degraded, expired, actions)\n│   ├── preview/                # Pre-rendered PNG previews of each icon state\n│   └── icon.icns               # macOS app icon bundle (generated by scripts/generate_icns.py)\n├── gspot/\n│   ├── __init__.py             # Package metadata & tagline\n│   ├── app.py                  # Pystray tray application loop & streamlined menu hierarchy\n│   ├── clipboard.py            # Cross-platform clipboard copy helper (pbcopy / clip / xclip)\n│   ├── config.py               # State enums (GREEN/YELLOW/RED), polling constants, status dataclass\n│   ├── gcloud.py               # Subprocess wrappers for auth, ADC, projects, configs, diagnostics\n│   ├── headless.py             # --status / --check / --renew CLI; imports no GUI dependencies\n│   ├── icons.py                # High-DPI 8x supersampled Pillow dynamic tray icon generator\n│   ├── notifications.py        # Desktop alert dispatcher + interactive modal popups\n│   ├── settings.py             # Persisted user preferences (~/.config/gspot/config.json)\n│   └── terminal.py             # Native interactive terminal launcher for re-authentication\n├── scripts/\n│   ├── generate_icns.py        # Renders app icon into macOS .iconset → .icns\n│   └── build_dmg.sh            # Packages G-Spot.app into a distributable .dmg installer\n├── tests/\n│   ├── __init__.py\n│   ├── test_auth_lifecycle.py  # 40 tests for state transitions, offline handling, auto-renew\n│   ├── test_gcloud.py          # 25 tests for gcloud wrappers, billing, and the health doctor\n│   ├── test_headless.py        # 22 tests for headless exit codes and display independence\n│   └── test_settings.py        # 12 tests for preference persistence and corrupt-file fallback\n├── main.py                     # CLI entrypoint; dispatches headless mode before loading the tray\n├── G-Spot.spec                 # PyInstaller build specification\n├── requirements.txt            # Dependencies (pystray, Pillow, plyer)\n└── README.md\n```\n\nPreferences you set from the tray menu (auto-renew, popup alerts, check interval) persist to:\n\n| Platform | Path |\n|---|---|\n| macOS / Linux | `~/.config/gspot/config.json` (respects `XDG_CONFIG_HOME` ) |\n| Windows | `%APPDATA%\\gspot\\config.json` |\n\nThe file is written atomically and is safe to edit by hand; out-of-range or malformed values fall\nback to defaults rather than preventing startup. `--interval`\n\noverrides the saved value for a\nsingle run without rewriting it.\n\nG-Spot cannot extend how long your credentials last, and neither can any other local tool. Access\ntokens live about an hour and refresh transparently; what actually kills a long agent run is the\n**session** behind them expiring. That session length is set by a Google Workspace administrator\n(Admin console → Security → Access and data control → Google Cloud session control), ranges from\n1 to 24 hours, and applies to the `gcloud`\n\nCLI and ADC just as much as to the web console. There\nis no gcloud flag or config property that changes it.\n\nWhat G-Spot does instead: refresh while refreshing still works, tell you clearly when it stops\nworking, and put the relevant admin page one click away under **Developer & Agent Tools → Session\nPolicy**. Personal `@gmail.com`\n\naccounts have no Workspace org and therefore no such policy — the\nmenu says so rather than linking you to a page you'd get denied on.\n\n```\nsource .venv/bin/activate\npython -m unittest discover -s tests -v\n```\n\nThe suite mocks every `gcloud`\n\ninvocation and network call, so it runs without a Google Cloud SDK\ninstallation and without touching your real credentials.\n\nMIT License. Built to keep AI agents authenticated and uninterrupted.", "url": "https://wpnews.pro/news/gspot-gcloud-auth-monitoring-for-long-running-coding-agents", "canonical_source": "https://github.com/Somnora/GSPOT", "published_at": "2026-08-23 00:28:44+00:00", "updated_at": "2026-08-23 00:43:33.929449+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools"], "entities": ["Google Cloud SDK", "G-Spot", "Gemini", "Claude Code", "Cursor", "Copilot", "LangChain"], "alternates": {"html": "https://wpnews.pro/news/gspot-gcloud-auth-monitoring-for-long-running-coding-agents", "markdown": "https://wpnews.pro/news/gspot-gcloud-auth-monitoring-for-long-running-coding-agents.md", "text": "https://wpnews.pro/news/gspot-gcloud-auth-monitoring-for-long-running-coding-agents.txt", "jsonld": "https://wpnews.pro/news/gspot-gcloud-auth-monitoring-for-long-running-coding-agents.jsonld"}}