A Gemini CLI extension that provides an interactive speech-based prompt mechanism and reads Gemini's responses aloud using macOS text-to-speech.
TellMe Gemini enhances the Gemini CLI by hooking into the agent lifecycle:
- Interactive Prompt (BeforeAgent Hook) — When you prefix your prompt with a dot (
.), a Java Swing dialog box pops up for you to type your input. It then reads your prompt aloud ("You said: ...") and passes it to Gemini. If you prefix the prompts with..then it will not use the dialog box and will use the input from the prompt. - Speech Response (AfterAgent Hook) — After Gemini finishes responding to a spoken prompt (prefixed with
.or..or suffixed with..), the extension reads Gemini's response aloud ("I say: ...") using the native macOSsaycommand in the background.
- macOS (uses
/usr/bin/sayfor text-to-speech) - Node.js
- Java runtime (for the input dialog)
- Gemini CLI with extension support
git clone https://github.com/sandipchitale/tellme-gemini
cd tellme-gemini
gemini extensions link .gemini extensions disable tellme-geminigemini extensions enable tellme-geminigemini extensions uninstall tellme-gemini- You provide a prompt to the Gemini CLI starting with a
.or..(e.g.,.). - The
BeforeAgenthook executestellme.mjs. - It detects the
.prefix and launches a Java Swing input dialog ("Wassup? (try dictation)"). If you prefix the prompts with..then it will not use the dialog box and will use the input from the prompt. - You enter your actual prompt and click "OK" (if using
.). - It uses the macOS
/usr/bin/saycommand to speak your input aloud in the background: "You said: {input}.". On Linux it uses/usr/bin/espeak. - It sends the input to the Gemini CLI as
additionalContextto be used for the agent. If you cancel the dialog, it gracefully denies the execution, halting the agent.
- After Gemini generates a response, the
AfterAgenthook triggers. - It checks if the original prompt started with
.or ended with... - If it did, it retrieves the generated response from the hook payload (
prompt_response). - It uses
/usr/bin/sayto speak the response aloud: "I say: {response}". On Linux it uses/usr/bin/espeak. - The
sayprocess is spawned detached so the Gemini CLI can continue immediately without waiting for the speech to finish.
If the voice output is too long and you want to stop it do at the prompt:
!killall /usr/bin/say
ESCAPEtellme-gemini/
├── hooks/
│ └── hooks.json # Hook configuration mapping BeforeAgent/AfterAgent to tellme.mjs
├── scripts/
│ └── tellme.java # Java Swing input dialog (single-file source program)
├── gemini-extension.json # Gemini Extension metadata
├── package.json # Project metadata (no dependencies)
├── tellme.mjs # Main hook handler logic (plain JavaScript, Node.js built-ins only)
└── README.md # This file
tellme.mjs— The main script executed by the hooks. It reads the JSON event payload fromstdinand checkshook_event_nameto route logic to theBeforeAgentorAfterAgenthandlers. Uses only Node.js built-in modules (child_process,fs).scripts/tellme.java— A single-file Java source program that displays a Swing dialog for user input. Runs directly viajava tellme.javawithout needing compilation.hooks/hooks.json— Registersi-sayfor theBeforeAgenthook andtell-mefor theAfterAgenthook. Both point to thetellme.mjsscript.
Sandip Chitale
MIT