GitHub - moonklabs/sprintable-gemini: Sprintable channel + tools extension for Gemini CLI — real-time team chat via AfterAgent hooks, hosted MCP · GitHub
Skip to content

About

Sprintable channel + tools extension for Gemini CLI — real-time team chat via AfterAgent hooks, hosted MCP

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

6 Commits

Folders and files

Repository files navigation

sprintable-gemini

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.

Install

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.

What it does

  • SessionStart hook boots a detached background listener that consumes the Sprintable SSE stream (GET /api/v2/agent/stream) for this agent's conversations.
  • AfterAgent hook 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 actual gemini-cli source: continueRequest = [{text: continueReason}], capped at MAX_TURNS=100 per 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.

Settings

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):

Setting Env var Sensitive
Sprintable Agent API Key SPRINTABLE_API_KEY yes (OS keychain)
Sprintable API URL SPRINTABLE_API_URL no (defaults to https://app.sprintable.ai)

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.

Uninstall

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.)

Design notes (ground-truthed against gemini-cli's own source, not public docs)

  • 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 bundled gemini-cli package directly.
  • gemini -r <session_id> -p "<msg>" reliably re-fires AfterAgent on the resumed turn. This is the opposite of how codex exec resume behaves (codex's resume never re-fires its Stop hook, 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 sibling sprintable-codex plugin where it was the correct fix) caused a real, reproduced double-post, since AfterAgent's prompt_response and a would-be -o json capture 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 for gemini-extension.json at the clone root (confirmed by reading the install/clone code path); the URL parser itself rejects anything but exactly owner/repo (throws on extra path segments). That's why this extension lives in its own repository instead of a subdirectory of moonklabs/sprintable-agent-plugins alongside the codex and grok plugins.
  • No per-agent home directory override exists in Gemini CLI (~/.gemini is hardcoded — no GEMINI_HOME-equivalent env var, unlike Codex's CODEX_HOME or Grok's GROK_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. Use SPRINTABLE_STATE_DIR to 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.

Development / testing note

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.

About

Sprintable channel + tools extension for Gemini CLI — real-time team chat via AfterAgent hooks, hosted MCP

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages