Skip to content

Repository files navigation

Hibiki

 _     _ _     _ _    _              .-----------.
| |   (_) |   (_) |  (_)          .-'   .-----.   '-.
| |__  _| |__  _| | ___          /   .--'     '--.   \
| '_ \| | '_ \| | |/ / |        /   /   .-----.   \   \
| | | | | |_) | |   <| |       /   /   /       \   \   \
|_| |_|_|_.__/|_|_|\_\_|      |   |   |   (O)   |   |   |

A macOS menu bar app that reads selected text aloud using OpenAI or ElevenLabs text-to-speech APIs. Built for agentic workflows, Hibiki supports global hotkeys, streaming audio playback, and a CLI (hibiki --text "Hello") so text from editors, browsers, and terminal sessions can be spoken instantly. Agent integration is a core feature: the repo includes ready-to-use skill and hook files so coding agents can trigger speech and spoken summaries directly from workflows. Hibiki also supports optional AI summarization and translation before playback, plus history and usage tracking.

Blog walkthrough: How I Built Hibiki

Read the Hibiki walkthrough blog post

Fork

This is a fork of RobertTLange/hibiki by Robert T. Lange. All original credit goes to the upstream author. This fork adds a floating "Speak" button that appears next to highlighted text in any app, so you can read a selection aloud with a single click instead of only via the global hotkey — a "Wispr Flow in reverse" for text-to-speech output.

What's new in this fork:

  • System-wide selection monitoring (Sources/Hibiki/Selection/) using the Accessibility API with a non-destructive read that never touches the clipboard.
  • A floating speak/stop pill positioned next to the selection, with multi-monitor clamping.
  • Settings to enable/disable the button, choose its position, set a minimum selection length, exclude specific apps, and launch at login.

Features

Feature Description
Floating Speak Button A pill appears next to highlighted text in any app; click to read it aloud (fork addition)
Agent Integration Built-in skill + hook templates for agent-driven spoken output
Global Hotkeys Option+F for TTS, Shift+Option+F for Summarize+TTS
Streaming Audio Audio plays as it's generated for fast response
TTS Providers OpenAI, ElevenLabs, or local Pocket TTS
AI Summarization Condense long texts before reading (GPT-5 Nano/Mini/5.2)
Translation Translate to English, Japanese, German, French, Spanish
CLI Tool hibiki --text "Hello" or hibiki --file-name README.md with --summarize and --translate flags
History & Stats Track past requests and API usage costs
Audio Player UI Visual waveform display with playback speed control (1.0x-2.5x)

Requirements

  • macOS 14.0 or later
  • OpenAI API key (required for summarization/translation and OpenAI TTS)
  • ElevenLabs API key (required if using ElevenLabs TTS provider)
  • uv (required for one-click managed Pocket TTS install)
  • Accessibility permission (to read selected text from other apps)

Installation

Build from source (recommended):

git clone https://github.com/RobertTLange/hibiki.git
cd hibiki
./build.sh
cp -R .build/Hibiki.app /Applications/Hibiki.app
open /Applications/Hibiki.app
sudo ln -sf /Applications/Hibiki.app/Contents/MacOS/hibiki-cli /usr/local/bin/hibiki

CLI binary path inside the app bundle: Hibiki.app/Contents/MacOS/hibiki-cli

Setup

  1. Launch Hibiki — appears as speaker icon in menu bar
  2. Grant Accessibility Permission — Settings → follow instructions
  3. Add API key(s) — OpenAI and/or ElevenLabs in Settings, or env vars OPENAI_API_KEY / ELEVENLABS_API_KEY
  4. Configure Hotkeys (optional) — defaults: Option+F (TTS), Shift+Option+F (Summarize+TTS)

Environment Variables (macOS menu bar apps)

If Hibiki is launched from Finder or open, it may not inherit terminal shell exports.
Set env vars through launchctl for GUI app visibility:

launchctl setenv OPENAI_API_KEY "sk-..."
launchctl setenv ELEVENLABS_API_KEY "..."
launchctl setenv POCKET_TTS_BASE_URL "http://127.0.0.1:8000"

Remove them later with launchctl unsetenv <NAME>.

Local Pocket TTS (managed)

  1. Open Settings → Configuration → Local Pocket TTS (Managed).
  2. Enable managed runtime.
  3. Click Install / Reinstall (uses uv to create a local venv and install pocket-tts).
  4. Click Start (or enable auto-start).
  5. Select provider Pocket TTS (Local) in the Text to Speech section.

Default managed endpoint: http://127.0.0.1:8000

Integration note: Hibiki uses a managed local Pocket TTS runtime (install/start/health checks in-app) and streams Pocket-generated WAV audio directly to the built-in player.

Official Pocket TTS repository: kyutai-labs/pocket-tts

Note: Pocket local mode is currently English-only in Hibiki.

CLI Usage

The Hibiki app must be running. Use hotkeys (Option+F, Shift+Option+F) for GUI-based TTS.

hibiki --text "Hello, world!"                        # Basic TTS
hibiki --file-name README.md                         # Read from file
hibiki --text "Long article..." --summarize          # Summarize + TTS
hibiki --file-name Sources/HibikiCLI/HibikiCLI.swift --summarize # Summarize file + TTS
hibiki --text "Long article..." --summarize --prompt "Summarize in 3 bullets." # Custom summary prompt
hibiki --text "Hello" --translate ja                 # Translate + TTS
hibiki --text "Article..." --summarize --translate fr # Full pipeline

Languages: en (English), ja (Japanese), de (German), fr (French), es (Spanish) Prompt override: --prompt replaces the default summarization prompt (requires --summarize). Input source: use exactly one of --text or --file-name. File decoding: --file-name expects UTF-8 text files. Markdown cleanup: .md / .markdown files get balanced cleanup (frontmatter/comments removed, headings/lists normalized, links simplified, code fences converted for speech). Input size limit: request URL payload must stay under ~32KB after encoding; very large files should be summarized or split.

Agent Integration

See skills/hibiki-tts/ for integration files.

Skill

Add Hibiki as a Claude Code skill so Claude can speak text aloud:

mkdir -p ~/.claude/skills/tts-hibiki
cp skills/hibiki-tts/SKILL.md ~/.claude/skills/tts-hibiki/SKILL.md

Install directly via npx:

TARGET_DIR="$HOME/.claude/skills/tts-hibiki" npx --yes zx -e 'const fs=require("node:fs/promises"),path=require("node:path");const target=process.env.TARGET_DIR;await fs.mkdir(target,{recursive:true});const res=await fetch("https://raw.githubusercontent.com/RobertTLange/hibiki/main/skills/hibiki-tts/SKILL.md");if(!res.ok)throw new Error(`Failed to download SKILL.md: ${res.status}`);await fs.writeFile(path.join(target,"SKILL.md"),await res.text(),"utf8")'

Hook

Automatically speak Claude's final response when a session ends:

cp skills/hibiki-tts/speak-summary.sh ~/.claude/hooks/
chmod +x ~/.claude/hooks/speak-summary.sh

Then merge skills/hibiki-tts/hooks.json into your ~/.claude/settings.json.

Security

  • Never commit API keys to this repo.
  • Prefer configuring keys inside Hibiki Settings.
  • For menu bar app launches, prefer launchctl setenv ... so Hibiki can read env vars.

Troubleshooting

Issue Solution
"No text selected" Ensure text is selected before pressing hotkey
"Accessibility permission not granted" Grant permission in System Settings
"No OpenAI API key configured" Add key in Settings, or run launchctl setenv OPENAI_API_KEY "sk-..."
"No ElevenLabs API key configured" Add key in Settings, or run launchctl setenv ELEVENLABS_API_KEY "..."
"uv was not found" Install uv and retry Pocket managed install
Chrome not capturing text Hibiki auto-falls back to clipboard (Cmd+C)

Debug logs available in Settings → Debug tab.

Architecture

Sources/
├── HibikiCLI/
│   └── HibikiCLI.swift          # CLI executable (argument parsing, URL scheme)
└── Hibiki/
    ├── HibikiApp.swift              # App entry point
    ├── AppDelegate.swift            # Menu bar setup, window management, URL handling
    ├── Selection/                   # Floating speak button (fork addition)
    │   ├── SelectionMonitor.swift       # System-wide selection detection (AX + polling)
    │   ├── SelectionHUDController.swift # Floating panel lifecycle + positioning
    │   └── SelectionHUDView.swift       # The speak/stop pill UI
    ├── Core/
    │   ├── AppState.swift           # Main application state
    │   ├── AccessibilityManager.swift   # Text selection via accessibility API
    │   ├── LaunchAtLogin.swift          # Launch-at-login via SMAppService (fork addition)
    │   ├── CLIRequestHandler.swift  # Handles CLI requests via URL scheme
    │   ├── PocketTTSRuntimeManager.swift # Managed local Pocket runtime install/start/health
    │   ├── PermissionManager.swift      # Permission checking
    │   ├── DebugLogger.swift        # In-app debug logging
    │   ├── HistoryManager.swift     # TTS history tracking
    │   ├── HistoryEntry.swift       # History data model
    │   ├── LLMService.swift         # OpenAI LLM API client (summarization/translation)
    │   ├── TextChunker.swift        # Long text chunking
    │   └── UsageStatistics.swift    # Usage tracking
    ├── Audio/
    │   ├── TTSService.swift         # OpenAI + ElevenLabs TTS API client
    │   ├── WAVStreamDecoder.swift   # Streaming WAV -> PCM decoder for local Pocket TTS
    │   ├── StreamingAudioPlayer.swift   # PCM audio playback
    │   └── AudioLevelMonitor.swift  # Audio level monitoring for waveform
    └── Views/
        ├── MainSettingsView.swift   # Tabbed settings window
        ├── MenuBarView.swift        # Menu bar popover
        ├── AudioPlayerPanel.swift   # Audio player with waveform
        ├── WaveformView.swift       # Waveform visualization
        └── Tabs/
            ├── ConfigurationTab.swift   # Provider, API keys, voice, hotkeys
            ├── DebugTab.swift           # Debug log viewer
            ├── HistoryTab.swift         # TTS history
            └── StatisticsTab.swift      # Usage statistics

About

macOS menu bar TTS with a floating Speak button for any app. Fork of RobertTLange/hibiki.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages