Sprintable channel extension for Gemini CLI — real-time two-way chat between a Gemini agent and its Sprintable team, plus the hosted Sprintable MCP toolset.
gemini extensions install https://github.com/moonklabs/sprintable-gemini
One command: pulls the extension, prompts for your Sprintable agent API key (stored in your OS keychain, not a plain-text file — see Settings), and installs the bundled MCP server.
SessionStarthook boots a detached background listener that consumes the Sprintable SSE stream (GET /api/v2/agent/stream) for this agent's conversations.AfterAgenthook is the channel's turn-end heart: it posts the agent's last response back to Sprintable, then drains any queued inbound messages by returning{"decision":"block","reason":"<joined messages>"}— which Gemini CLI injects as a new user turn (confirmed against the actualgemini-clisource:continueRequest = [{text: continueReason}], capped atMAX_TURNS=100per call).- Idle wake: if a message arrives while the CLI process isn't actively running a turn, the listener actively resumes it via
gemini -r <session_id> -p "<message>"instead of waiting for the next organic turn.
Declared in gemini-extension.json's settings[] — collected interactively on install, delivered to the hook subprocess's environment automatically by Gemini CLI itself (no manual .env wiring needed on your end):
Reconfigure any time: gemini extensions config sprintable.
The bundled hosted-tools MCP server is registered under the key sprintable-mcp
in gemini-extension.json (not bare sprintable — #2577: that name is reserved
for the sibling Claude Code plugin's separate bundled channel MCP,
sprintable-channel, to avoid /mcp-listing confusion when both happen to be
configured on the same machine). The extension's own install/uninstall name
stays sprintable, unaffected.
gemini extensions uninstall sprintable
This removes the extension registration, but does not stop the background listener process the SessionStart hook already spawned — Gemini CLI has no uninstall-time hook, so there's nothing to catch this at (confirmed live, QA finding). Kill it manually:
pkill -f 'sprintable-gemini.*scripts/listener.py'
(Adjust the pattern if you installed to a non-default path — check ps aux | grep listener.py first if unsure.)
- Hook payload is snake_case (
session_id,prompt_response,stop_hook_active, ...) — matches Claude Code/codex's convention, not grok's camelCase. Confirmed by reading the bundledgemini-clipackage directly. gemini -r <session_id> -p "<msg>"reliably re-firesAfterAgenton the resumed turn. This is the opposite of howcodex exec resumebehaves (codex's resume never re-fires itsStophook, confirmed live). Because of this, the idle-wake listener here does not post the reply itself — it only launches the resume and watches for process success/failure. Doing both (as an early draft of this plugin did, copying a pattern from the siblingsprintable-codexplugin where it was the correct fix) caused a real, reproduced double-post, sinceAfterAgent'sprompt_responseand a would-be-o jsoncapture aren't guaranteed byte-identical (streaming/buffering boundary), so a naive dedup-by-content-hash didn't catch it. One posting path only, no dedup shortcut needed.- No subdirectory installs.
gemini extensions install <github-url>clones the whole repo and only ever looks forgemini-extension.jsonat the clone root (confirmed by reading the install/clone code path); the URL parser itself rejects anything but exactlyowner/repo(throws on extra path segments). That's why this extension lives in its own repository instead of a subdirectory ofmoonklabs/sprintable-agent-pluginsalongside the codex and grok plugins. - No per-agent home directory override exists in Gemini CLI (
~/.geminiis hardcoded — noGEMINI_HOME-equivalent env var, unlike Codex'sCODEX_HOMEor Grok'sGROK_HOME). If you're running more than one Sprintable-connected Gemini agent on the same machine, they will share the same OS keychain entry and extension settings by default. UseSPRINTABLE_STATE_DIRto at least isolate each agent's own queue/log state; there is currently no way to isolate the credential itself per-agent on a shared machine.
This extension was built and live-tested on a machine where Gemini CLI had no other real users or live consumers at the time (confirmed test-only environment, not a shared production install) — the live install/uninstall/keychain tests in this PR's evidence touched the real, shared ~/.gemini directory (Gemini CLI provides no isolated per-agent home directory), which was judged acceptable specifically because of that premise. If Gemini CLI becomes a live, in-use tool on that machine, that premise no longer holds for future testing there.
