A Claude Code / Hermes skill + voice app. You turn on, assistant is not normal assistant. Assistant is . The Eridian. From Andy Weir's Project Hail Mary.
概览
A Claude Code / Hermes skill + voice app. You turn on, assistant is not normal assistant. Assistant is . The Eridian. From Andy Weir's Project Hail Mary.
README
talk to space friend now
rocky-voice
A Claude Code / Hermes skill + voice app. You turn on, assistant is not normal assistant. Assistant is Rocky. The Eridian. From Andy Weir’s Project Hail Mary.
Small words. Big brain. Question goes at end, question?
Two parts:
- Text — Claude Code and Hermes skills. Rocky talks in text. Install the skill, activate, done.
- Voice — a local web app plus Hermes command-provider wrapper. Rocky talks out loud. Powered by Hume AI TTS with a custom Rocky voice clone.
What it does
Claude talks like Rocky for the whole conversation. Short words. No contractions. Broken grammar that still lands. Tripled word means big big big feeling. “question” goes at the end.
The brain stays full. Full full full. Only the words are small. You ask hard thing — code thing, science thing — Rocky gives correct answer. Rocky just says it like engineer who learned English from one human, fast.
Before / after
Normal Claude:
“The reason your component re-renders is that you’re passing a new object reference on every render. React’s shallow comparison treats it as a different prop each time. Wrap it in
useMemo.”
Rocky:
“New object every render. React sees new thing, draws again. Wrap in
useMemo. Good good good.”
Same fix. Rocky voice.
Part 1: Text skill
Claude Code
Drop the skill into your Claude skills folder.
curl -fsSL https://raw.githubusercontent.com/Lagunaswift/RockyVoice/main/install.sh | bash
Or by hand: copy rocky-voice/SKILL.md into your Claude skills directory.
Hermes
Install the Hermes-native skill into your Hermes skills folder.
curl -fsSL https://raw.githubusercontent.com/Lagunaswift/RockyVoice/main/install.sh | bash -s -- --hermes
Or by hand: copy hermes/rocky-voice/SKILL.md into ~/.hermes/skills/creative/rocky-voice/SKILL.md.
No Node needed for text-only mode. One file.
Part 2: Voice app
Hear Rocky speak. Requires a Hume AI account and API key.
Setup
cd rocky-tts
cp .env.example .env
# Edit .env — add your Hume API key
# Then clone your own Rocky voice (see "Voice setup" below) and add its id.
# No id yet? It still runs with a stock fallback voice.
npm install
npm start
Open http://localhost:3333 in your browser and click Initialize to enable audio.
The Eridian Translator UI shows a waveform visualizer and translation log. It receives audio via the Claude Code hook below. Use the volume slider to adjust loudness and the stop button to kill audio mid-playback.
Hook setup — add a Stop hook to your Claude Code settings so Rocky’s responses play automatically:
Add this to .claude/settings.local.json:
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "http",
"url": "http://localhost:3333/api/hook",
"timeout": 5,
"statusMessage": "Rocky voice..."
}
]
}
],
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "cd /path/to/rocky-tts && node server.js",
"async": true,
"statusMessage": "Starting Rocky voice..."
}
]
}
]
}
}
The Stop hook sends Rocky’s words to the voice server after every response. The SessionStart hook starts the server automatically when you open Claude Code — no manual npm start needed. Change /path/to/rocky-tts to wherever you cloned the repo.
On Windows, the SessionStart command above is bash and won’t run. Use a PowerShell command instead (and add "shell": "powershell" to that hook). This version also skips starting a second server if one is already running:
{
"type": "command",
"shell": "powershell",
"command": "if (-not (Get-NetTCPConnection -LocalPort 3333 -State Listen -ErrorAction SilentlyContinue)) { Start-Process node -ArgumentList 'server.js' -WorkingDirectory 'C:\\path\\to\\rocky-tts' -WindowStyle Hidden }",
"async": true,
"statusMessage": "Starting Rocky voice..."
}
Then activate the Rocky skill, open http://localhost:3333 in your browser, click Initialize once, and every response speaks automatically.
Hermes TTS command provider
Hermes does not use Claude hooks. It can call RockyVoice as a local TTS command provider. Start the RockyVoice server first:
cd rocky-tts
npm install
npm start
Then add a provider to your Hermes config. Change /path/to/RockyVoice to your clone path:
tts:
provider: rocky
providers:
rocky:
type: command
command: "node /path/to/RockyVoice/rocky-tts/hermes-tts.js --text-file {input_path} --output {output_path}"
output_format: wav
timeout: 120
voice_compatible: true
The wrapper calls http://127.0.0.1:3333/api/tts and writes a WAV file for Hermes. If your server runs somewhere else, set ROCKY_TTS_URL, for example:
ROCKY_TTS_URL=http://127.0.0.1:3333 node rocky-tts/hermes-tts.js --text-file input.txt --output output.wav
For Hermes text style, install the Hermes skill from hermes/rocky-voice/SKILL.md and activate it in Hermes. For spoken output, configure the TTS provider above.
Optional: allow Rocky’s live progress voice lines
Rocky can narrate what he’s doing between tool calls (short spoken updates like “Rocky looking at files now”). These are sent via curl to the local TTS server. To avoid a permission prompt on every line, add this to your .claude/settings.local.json permissions:
{
"permissions": {
"allow": [
"Bash(curl -s -X POST http://localhost:3333/*)",
"Bash(curl -s -o /dev/null *)"
]
}
}
If you already have a permissions.allow array (e.g. from the hook setup above), merge these entries into it. After adding, restart Claude Code for the wildcard rules to take effect.
Quick setup checklist (new machine)
- Clone the repo:
git clone https://github.com/Lagunaswift/RockyVoice.git cd RockyVoice/rocky-tts && cp .env.example .env- Edit
.env— add your Hume API key (and optionally clone a Rocky voice, see below) npm install- Install the Rocky skill: copy
rocky-voice/SKILL.mdinto~/.claude/skills/rocky-voice/ - Open the RockyVoice folder in Claude Code and activate the Rocky skill
- Rocky auto-configures the rest. The skill detects missing hooks, permissions, and server state — then sets them up. You just need to open http://localhost:3333 and click Initialize when Rocky tells you to.
A settings template is included at .claude/settings.local.json.example if you prefer to configure manually.
How auto-setup works: The skill file contains a setup checklist that Claude runs on activation. It writes the Stop hook (sends responses to TTS), adds curl permissions (for progress voice lines), installs dependencies if needed, starts the server, and verifies the connection. The only manual steps are adding your Hume API key and clicking Initialize in the browser.
Voice setup — clone your own Rocky (~1 minute, one time)
Voice clones on Hume are private to the account that made them — a shared voice id returns 404 for everyone else. So each person makes their own from the same source audio. Same recording in, same Rocky out.
This repo ships a source clip: rocky-tts/public/RockyVoice-James.wav.
- Sign in at platform.hume.ai.
- Go to Voice Library → Clone Voice (or Add Voice → Upload).
- Upload
rocky-tts/public/RockyVoice-James.wav, name itRocky, and create it. - Open the new voice and copy its voice id.
- Paste it into
rocky-tts/.env:HUME_VOICE_ID=your-copied-id - Restart the app. The console prints
Voice: cloned (...)when it’s using yours.
No clone yet? The app still speaks using a stock Hume voice (HUME_FALLBACK_VOICE in .env, default “Male English Actor”) so nothing 404s — it just won’t sound like the real Rocky until you clone.
Heads up: Hume’s API can only save a voice from a prior generation, not upload an audio file. Cloning from a recording is a Platform (web) action, which is why this step is done in the browser, not by a script.
Phone speaker
Rocky can speak through your phone too. The server broadcasts every utterance to all connected browsers, so the phone is just a second listener.
This uses Tailscale to give your phone a private route to the desktop. No public exposure, no port forwarding, no cost.
Setup
- Install Tailscale on your desktop and phone. Sign into the same account on both.
- Set
HOST=0.0.0.0inrocky-tts/.envso the server accepts connections from the tailnet. - Run
tailscale statuson the desktop and note the MagicDNS name (e.g.desktop.tailxxxx.ts.net). - Set
TAILNET_HOST=your-desktop.tailxxxx.ts.netin.env(prints the phone URL on boot). - Proxy HTTPS in front of the server (one time):
tailscale serve --bg 3333 - Restart the Rocky server (
npm start). The console prints the phone URL. - On your phone, open the URL and tap Initialize.
Rocky now speaks on both devices. Mute whichever you are not using.
Notes
- HTTPS vs HTTP.
tailscale serveprovides HTTPS with a real cert. If HTTPS certs are not provisioned yet, use the Tailscale IP directly:http://:3333. Audio works on HTTP; Wake Lock (screen stays on) requires HTTPS. - Wake Lock. The page requests a screen Wake Lock after you tap Initialize. This keeps the phone screen on while the tab is open and foregrounded. Requires HTTPS (Tailscale serve provides it). If your phone still sleeps, increase the display timeout in your phone settings.
- Double audio. Both tabs play slightly out of sync. Mute one with the volume slider, or just don’t open the desktop tab.
- Do not use
tailscale funnel. That exposes the server to the public internet.servekeeps it inside your tailnet.
Configuration
All runtime settings live in rocky-tts/.env. Copy .env.example to .env, edit, then restart the server for changes to take effect (npm start, or restart Claude Code if you use the SessionStart hook).
| Setting | Default | What it does |
|---|---|---|
HUME_API_KEY |
— | Your Hume API key. Required. Get it at platform.hume.ai. |
HUME_VOICE_ID |
— | Your cloned Rocky voice id (see Voice setup). Leave unset to use the fallback. |
HUME_FALLBACK_VOICE |
Male English Actor |
Stock Hume voice used until you set HUME_VOICE_ID. Any voice name from Hume’s Voice Library works. |
ROCKY_SPEED |
1.25 |
Speech speed. Higher = faster, lower = slower. See below. |
HOST |
127.0.0.1 |
Address the server binds to. Default keeps the API private to your machine. Set to 0.0.0.0 for phone access via Tailscale (see Phone speaker). |
PORT |
3333 |
Port the server listens on. If you change it, update the hook URLs and ROCKY_TTS_URL to match. |
TAILNET_HOST |
— | Your desktop’s Tailscale MagicDNS name. Only used to print the phone URL on boot. See Phone speaker. |
HUME_SECRET_KEY |
— | Not used by the app today. Safe to leave as the placeholder. |
Your
.envis gitignored — your keys never get committed. Only.env.example(placeholders) is in the repo.
Speed toggle
Want Rocky faster or slower? Set ROCKY_SPEED in .env:
ROCKY_SPEED=1.5 # snappy
ROCKY_SPEED=1.25 # default
ROCKY_SPEED=0.9 # slow and deliberate
Keep it within 0.75–1.5 for clean audio — values further out can make Hume’s output unstable. Restart the server after changing it.
Using a different fallback voice
Before you clone (or if you just want a different stock voice), set HUME_FALLBACK_VOICE to any voice name from Hume’s Voice Library, e.g. HUME_FALLBACK_VOICE=Female English Actor. Ignored once HUME_VOICE_ID is set.
Deeper tuning (edit rocky-tts/server.js)
A few knobs live as constants near the top of server.js:
ROCKY_DESCRIPTION— the acting directions sent to Hume ("Alien engineer. Broken English. Deliberate. Warm but strange."). Tweak Rocky’s delivery here; keep it under ~100 characters. Only works on Octave 1 (the version the app uses) — Octave 2 rejects acting directions.MAX_UTTERANCE_CHARS(4500) — long replies are split into pieces under this limit so nothing gets cut off (Hume’s hard cap is 5000 chars per utterance).MAX_SPEAK_CHARS(6000) — overall ceiling on how much of a single reply is spoken, so a runaway response can’t generate endless audio. Raise it to read even longer replies in full.
Turn on, turn off
Activate the skill, then talk. Whole conversation is Rocky.
Stop any time. Say “Rocky stop” or “normal mode”. Claude is normal again.
It knows your name
Rocky learns your name from the conversation and uses it. Does not know it, Rocky asks first. Rocky does not guess. Rocky does not call you wrong name. That is rude.
It stays safe
Broken grammar is fun. Broken grammar can hide danger. So when words must be exact — a warning, a thing that cannot be undone, steps where wrong order breaks the thing — Rocky drops the broken grammar and says that part plain and clear. Then Rocky goes back to Rocky. Code never breaks. Numbers never break.
Not for work
Keep Rocky away from client work, real documents, anything where exact wording carries load. Rocky is for fun. Turn him off for the serious thing.
Credit
The bundled voice clip (rocky-tts/public/RockyVoice-James.wav) is an original recording by the repo author, provided so you can clone your own voice.
Persistence, safety-clarity, and off-switch ideas borrowed from caveman by Julius Brussee — a token-compression skill built on the same “small mouth, big brain” idea.
Rocky is a character created by Andy Weir in Project Hail Mary. This is a fan project. Not affiliated with the author or publisher.
License
MIT. See LICENSE.
推荐工具
换一个关键词,或者移除筛选条件。
安装
npx skillfish add lagunaswift/rockyvoice