TellMe
A Claude Code plugin that provides an interactive speech-based prompt dialog and reads Claude's responses aloud using text-to-speech.
Overview
TellMe has two hooks that work together:
-
UserPromptSubmit Hook — intercepts prompts that start with . (dot). When detected, it displays an input dialog (macOS via osascript, Linux via Java) for the user to type or edit their input, speaks the input aloud ("You said: ..."), and forwards it as the prompt to Claude. If the user cancels the dialog, the prompt is blocked.
-
Stop Hook — triggers after Claude finishes a response. If the original prompt started with . or ended with .., it speaks Claude's response aloud with the format: "I say: {response}". The speech runs in a detached process so it doesn't block Claude Code.
Requirements
- macOS (10.x+) or Linux
- Node.js 23.6+
- Claude Code with plugin support
- Text-to-speech support:
/usr/bin/say (macOS) or espeak (Linux), or custom via TTS_COMMAND env var
Installation
-
Clone or copy this project:
git clone https://github.com/sandipchitale/tellme-claude.git
cd tellme-claude
-
Install dependencies:
npm install
-
Build the TypeScript:
npm run build
-
Install the plugin in Claude Code:
claude plugin install /path/to/tellme-claude
How It Works
UserPromptSubmit Hook
- The user types a prompt starting with
. (e.g., .tell me a joke)
- The hook strips the
. prefix:
- If the remaining text starts with
. again (e.g., ..tell me), use the text as-is without showing a dialog
- Otherwise, open a dialog box:
- macOS: Uses
osascript dialog titled "Yo" with message "Wassup? (try dictation)"
- Linux: Uses Java fallback (
scripts/tellme.java)
- The dialog shows the text as the default input

- The user can edit the text and click "GO", or click "Cancel"
- If confirmed, the plugin speaks "You said: {input}." aloud and forwards the text as the prompt
- If cancelled, the hook blocks the prompt with a "Cancelled." reason
Stop Hook
- Claude Code triggers the
Stop hook after finishing a response
- The hook handler reads the transcript file and extracts the last user prompt
- If the prompt started with
. or ended with .., it extracts the last assistant response
- It speaks the response aloud with the format: "I say: {response}" using the configured TTS command
- The TTS process is spawned detached so Claude Code continues immediately
Stopping Long Speech Output
If the voice output is too long and you want to stop it:
macOS:
!killall /usr/bin/say
Linux:
!killall espeak
Then press ESCAPE to return to prompt.
Project Structure
tellme-claude/
├── .claude-plugin/
│ ├── plugin.json # Plugin metadata (name: tellme-claude, v1.0.0)
│ └── marketplace.json # Marketplace/local dev config
├── hooks/
│ └── hooks.json # Hook event configuration (UserPromptSubmit + Stop)
├── scripts/
│ └── tellme.java # Java fallback for Linux dialog support
├── screenshots/
│ └── prompt-dialog-with-dictation.jpg # Example dialog screenshot
├── tellme.ts # Main hook handler (TypeScript source)
├── tellme.js # Compiled JS (generated by npm run build)
├── package.json # Dependencies and project config
├── tsconfig.json # TypeScript configuration (ES2022 target)
├── .gitignore
└── README.md
Key Implementation Details
tellme.ts — The main TypeScript source (ES2022 target), compiled to tellme.js via npm run build. It reads JSON from stdin, determines the hook event (UserPromptSubmit or Stop), and dispatches accordingly.
- For
UserPromptSubmit:
- On macOS: Opens a dialog with title "Yo" and message "Wassup? (try dictation)" using
osascript to let users confirm/edit input.
- On Linux: Uses Java fallback (
scripts/tellme.java) for dialog display.
- Supports double dots (
..) prefix to skip dialog and use text directly.
- Speaks "You said: {input}." before forwarding the prompt.
- For
Stop: Reads the transcript to check if the last prompt started with . or ended with .., then speaks the response with "I say: {response}". Uses child_process.spawn with detached: true so the voice doesn't block Claude Code.
- Cross-platform TTS: Uses
/usr/bin/say on macOS, /usr/bin/espeak on Linux. Configurable via TTS_COMMAND environment variable.
- Uses
child_process.execSync for dialogs and child_process.spawn for TTS.
hooks/hooks.json — Registers two hooks (UserPromptSubmit and Stop) that both run node ${CLAUDE_PLUGIN_ROOT}/tellme.js on every matcher (*).
Dependencies