roger-roger
v0.1.14
Published
Bring yourself back to the conversation: your coding agents reach you by Slack, a sound or a spoken line when they finish, get stuck, or need a decision, and you answer from your phone.
Maintainers
Readme
roger-roger
An agent skill that brings you back to the conversation when you've walked away from the screen with a Slack message, a ding, a spoken line (Gemini 3.1 Flash TTS), or any combination. It can also ask you to choose between options with Slack buttons while the agent waits.
It works with any agent that supports Agent Skills, such as Claude Code, Codex, Cursor, and others.
Install
One command, in any shell on Windows, macOS or Linux:
npx roger-roger@latest installIt asks a few questions in the terminal and does the rest. First it offers to put the roger-roger command on your PATH (npm install -g), then it links the skill into every agent's skills folder it finds (Claude Code, Codex, OpenCode, Cursor, Gemini CLI, Copilot, and ~/.agents/skills), registers with Herdr as a plugin when it's installed, connects Slack, lets you hear the sounds and the voices before you choose, and installs the terminal-question hooks and the tray icon. Once it's on your PATH, roger-roger install runs the same setup again whenever you want to change something.
If you'd rather install first and set up after, that works too: npm install -g roger-roger, then roger-roger install.
To take it off again, npx roger-roger@latest uninstall (or roger-roger uninstall): it lists what it finds, you tick what should go, and it removes the hooks, the skill links, the Herdr plugin, the daemon and the tray, your settings and tokens, and the global command. The Slack CLI is offered too, unticked. roger-roger help shows every command, and roger-roger help notify one command's flags.
Other ways in:
- skills.sh:
npx skills add code-red-app/roger-rogercopies the skill alone. The agent runs it asnode <skill-dir>/scripts/roger-roger.mjsand, on first use, asks you to runnpx roger-roger install. - Herdr:
herdr plugin install code-red-app/roger-roger/skills/roger-roger. The daemon starts with Herdr, snooze becomes an action you can bind to a key, and roger-roger setup opens as a popup pane.
Needs Node 18 or newer (22 for questions with buttons).
Slack
There's nothing to configure by hand. roger-roger install connects Slack using Slack's official Slack CLI:
- It installs the CLI if it's missing, after asking you.
- It logs the CLI in: you paste a
/slackauthticket …command into Slack, approve, and type the code Slack shows. - It creates and installs a roger-roger app in your workspace from
skills/roger-roger/slack/manifest.json(Socket Mode, interactivity, DMs to the bot;chat:write,im:write,im:history,files:read,files:write,reactions:write). The CLI hands the app's tokens over, and they are kept in~/.roger-roger/slack.json.
Messages then arrive as DMs from the roger-roger bot. An agent can do the same steps one at a time with roger-roger slack-setup, if you'd rather not leave the conversation.
Manual setup instead: create an app from the same manifest at api.slack.com/apps, then set these environment variables. Tokens saved by the setup take priority when both exist.
| Variable | Needed for |
|---|---|
| SLACK_API_BOT_TOKEN | Slack. The bot token (xoxb-…), with files:read and files:write for attachments in either direction. SLACK_BOT_TOKEN also works. |
| ROGER_ROGER_SLACK_APP_TOKEN (or SLACK_APP_TOKEN) | Questions with buttons (ask). An app-level token (xapp-…) with connections:write. |
Speech
| Variable | Needed for |
|---|---|
| GEMINI_API_KEY | Gemini TTS. A key from Google AI Studio. GOOGLE_API_KEY also works. |
You can also paste the key into roger-roger install; it's kept in ~/.roger-roger/keys.json, readable by you only, and a variable set the ordinary way always wins over it. OpenAI and ElevenLabs voices work the same way (OPENAI_API_KEY, ELEVENLABS_API_KEY).
A missing key is not fatal. Speech falls back to the computer's built-in voice (SAPI on Windows, say on macOS, spd-say/espeak on Linux).
Setup
roger-roger install asks, in the terminal:
- which agents should have the skill (every one it finds is ticked)
- whether to tell your agents to always use it: a marked block in each agent's global instructions (
~/.claude/CLAUDE.md,~/.codex/AGENTS.md,~/.config/opencode/AGENTS.md,~/.gemini/GEMINI.md), which uninstall takes out again - whether to register with Herdr, if it's installed
- how to reach you: Slack, sound, speech, in any combination
- Slack: it connects it for you (see above), and where messages go (your DMs, or a channel)
- which sound to play: space plays the highlighted one
- who makes the voice (Gemini, OpenAI, ElevenLabs), the key if none is set, and which voice: space lets each introduce itself
- whether the spoken line should be a short summary or the full message
- when you want to be notified
- whether questions an agent asks in its own terminal should reach Slack too
- whether to put an icon in the system tray
It ends with a test notification. Your answers are saved to ~/.roger-roger/config.json. To change them, run it again, or just tell the agent ("only ping me when you're blocked", "use the Puck voice").
Questions from Slack
ask posts a question with one button per option, with the agent's recommended option in green (--recommend). Click one, or use Other… to type your own answer, and the agent gets it from wait.
- Reminders: if you haven't answered, you're reminded after 15 minutes by default, in Slack plus sound and speech (
setup --remind). - No answer: when a question runs out of time — 45 minutes by default — the recommended option is applied, and the message says so up front. Agents turn this off for risky decisions (
setup --on-expire nothingturns it off everywhere). - Nothing is lost if the agent stopped waiting: the answer is kept and handed over by the next command that agent runs, whatever it is. The message says which has happened — saved for 🌹 rose, then delivered to 🌹 rose — so you never have to guess whether it arrived.
There is no always-on service. ask starts a small watcher process, and one watcher serves every open question on the machine. It exits by itself a few seconds after the last question is answered, expires, or is cancelled. State lives in ~/.roger-roger/decisions/, and the watcher's log is ~/.roger-roger/daemon.log.
More
- Progress messages:
progress --message "Phase 2/4…"keeps one Slack message up to date during long work, and--donefinishes it. Its ⏸ Pause, ⏹ Stop and 📝 Note buttons let you steer the agent from your phone. The agent picks them up at its next check, and the message confirms once it has actually paused, stopped, or read your note. - Edit before use:
ask --draft "…"shows a commit message, PR text, or email with Use as is and ✏️ Edit. Edit opens it pre-filled, and the agent uses your version. - Summary card:
notify --summary --field "Tests=318 passed"ends a task with a card: key facts, how long it took, and every decision you made along the way.--actions "Open a PR|Run the full suite"adds follow-up buttons. - Talk to the bot: DM the roger-roger bot in Slack. A reply in a progress message's thread, or any DM while an agent is working, reaches that agent at its next check. A reply in a question's thread answers it. Anything else waits in an inbox for the next agent. 👀 means an agent has it, ✅ means an agent has answered it.
- Attachments:
--attach fileonnotifyandaskposts logs, diffs, or screenshots with the message. The bot needsfiles:write. - Send it a screenshot: files you attach in Slack come the other way too. They're downloaded to
~/.roger-roger/filesand the agent is handed the path, so "here's what it looks like" works as an instruction. Needsfiles:read, so an app created before this needsslack-setup createrun once more. - Multi-select:
ask --multishows checkboxes and a Submit button.--recommend "A|C"pre-ticks options. - Session label: a small
machine · agent · model · sessionline under each Slack message tells several agents apart (setup --session-label offhides it). - One voice at a time: several agents on one machine take turns at the speakers instead of talking over each other. A waiting announcement plays in full as soon as the one before it finishes.
- Works with any agent: Claude Code, Codex, OpenCode, or a plain shell script. A session is recognised by whatever id the agent publishes, or by the
--sessionname it passes, or by the terminal — no per-product support needed. - Every agent has a name: each session is given a colour nickname — 🌿 sage, 🌹 rose, 🍇 plum — shown on its Slack messages with a matching colour bar.
sessionslists who is running;sessions rename sage plumchanges one. - Named in Herdr too: an agent running in a Herdr pane gets its badge and a word or two of its work on the tab (
🍯 amber | build process) and its work on the agent (build-process-improvements), so the Herdr sidebar and the Slack messages name the same thing. Nothing to set up: the skill sees the pane it runs in and labels it on the first command, and again after a rename. As a Herdr plugin (roger-roger installregisters it, orherdr plugin install code-red-app/roger-roger/skills/roger-roger), the daemon starts with Herdr, snooze is an action, and the setup opens as a popup pane. - Talk to an agent: write "sage, rerun the tests" (or "hey sage rerun the tests", or "sage: ..."). With one agent running, a plain message goes to it. With several, but only one of them listening, it goes to that one and Slack says so, with a button to redirect it. With several, the bot asks which, with a button per agent — and remembers your answer for that thread.
- You can hear who it is: a spoken line starts with the agent's name — "Amber here.", "This is Rose.", "Jade speaking." — so three agents sharing one pair of speakers stay tellable apart (
setup --say-who off). - Reachable while idle: an agent that has finished can run
listenin the background instead of going quiet. It costs nothing to wait, and when you write, it wakes up and answers. Slack shows 👀 when an agent is listening and 💤 when your message is saved for one that isn't, so you always know which. - In the tray:
tray installputs an icon in the system tray, started with the daemon from then on (tray startstarts it straight away;setup --tray offstops it starting by itself) — every agent at a glance, a translucent panel on click, snooze on right-click, a Stop button while a voice is speaking (roger-roger hushfrom a terminal), and a log of who said what lately: every notification and question from the agents, and every message and answer from you, per agent or all together. It reads the same state the daemon already keeps and runs ordinary commands, so it can be closed, killed or never installed and nothing else changes. - Questions asked in the terminal: when the agent asks you something with its own question tool (Claude Code's question dialog, OpenCode's question tool, Codex's
request_user_input) or wants a plan approved, it's stuck until you answer and can't tell you itself.hooks installhooks into each of those agents it finds: once the question has gone unanswered for a little while, it arrives in Slack with its options, and when you answer in the terminal the message turns into your answer. Claude Code gets three hooks in~/.claude/settings.json; OpenCode a small plugin in~/.config/opencode/plugins/; Codex three hooks in~/.codex/hooks.json, which you trust once in Codex's/hooks. Claude Code knows when you've stopped typing; OpenCode and Codex don't, so they wait 20 seconds first (setup --terminal-wait).setup --permission-pings ondoes the same for ordinary permission prompts.hooks uninstalltakes it all out again. - Quiet hours:
setup --quiet-hours 22:00-08:00mutes sound and speech overnight. It's off by default.
Sounds
chime · ding · marimba · bubble · alert. They are generated by tools/make-sounds.mjs. Run npm run make-sounds to regenerate them.
How it runs
One daemon per machine does the work: it holds the Slack connection open (so a message you send is picked up immediately, whether or not an agent is waiting), owns the speakers, and is the only writer of the state under ~/.roger-roger. Agents run the CLI, which is thin — it hands the command to the daemon over a local socket (a named pipe on Windows) and prints the answer. The daemon starts on the first command and stays; roger-roger daemon status shows it, daemon stop ends it. Nothing listens on the network, and if the daemon can't start, commands fall back to running in the calling process.
CLI
The skill is a zero-dependency Node script. The npm package puts it on your PATH as roger-roger; from a skills.sh copy, run node skills/roger-roger/scripts/roger-roger.mjs instead.
roger-roger install
roger-roger status
roger-roger sessions
roger-roger daemon status
roger-roger play alert
roger-roger say "[positive] Hello there." --voice Puck
roger-roger preview-sounds
roger-roger preview-voices Puck Sulafat
roger-roger notify --kind done --message "Build finished" --say "The build is done." --attach build.log
roger-roger progress --message "Phase 2/4: migrating orders"
roger-roger control --wait 10m
roger-roger ask --question "Commit message OK?" --draft-file msg.txt --recommend 1
roger-roger ask --question "Deploy now?" --choices "Yes|Tomorrow|No" --recommend Yes --wait 10mDevelopment
npm testRequires Node 18+ (22+ for ask, which uses the built-in WebSocket).
CI runs the tests on Linux, macOS and Windows for every push and pull request. A release is a tag:
npm version minor # bumps package.json and herdr-plugin.toml together, commits, tags
git push --follow-tags # publishes to npm and creates the GitHub releaseThe release workflow needs one repository secret, NPM_TOKEN: an npm granular access token with publish rights on the package.
