Releases: justbuild-it/iriscale_voice
Release list
v0.1.32
Fix false Codex permission alerts during automatic approval review (#46). Voice now announces a permission wait only when the current turn records a human reviewer. Automatic review, bypass mode, and unverifiable reviewer metadata stay quiet. Stale blocked dashboard states and reminder text are cleared without treating automatic review as user presence. Claude permission and completion alerts retain their behavior.
Update
Windows Codex users:
irm https://raw.githubusercontent.com/justbuild-it/iriscale_voice/v0.1.32/install.ps1 | iexRequires Codex 0.154.0+. Fully restart Codex; review changed hooks if prompted. Existing v0.1.31 bridge installations need the updated runtime, while older installs also need the installer to migrate their bridge and hook configuration.
Claude Code plugin users:
claude plugin marketplace update iriscale
claude plugin update iriscale-voice@iriscale
Fully restart Claude Code and reopen the sessions dashboard after updating; an existing window continues running its previous version.
Validation and npm
All 11 CI checks passed on merge commit fb3274d (Actions run 34726063141). Tests cover Windows, macOS, Linux, automatic versus human approval review, stale-state cleanup, and normal-mode background hook behavior. The maintainer's live session stopped producing false permission alerts with this fix.
npm publication is coordinated with Puneet in #36. Until the registry is verified, use the pinned Windows installer above or the Claude marketplace update. This release supersedes v0.1.30 and v0.1.31 as the npm publication candidate.
The public pinned Windows installer was downloaded and verified against the tagged source. Its disposable-home smoke test passed, including permission-review filtering against the downloaded runtime, actual PowerShell hooks, named sessions, background-worker survival, and cleanup. The first local run exceeded the SessionEnd deadline; the unchanged repeat passed. Timing details and native verification follow-up are recorded in #36.
v0.1.31
Fix Windows Codex hooks timing out after 10 or 30 seconds even though their foreground work completed. Background notification watchers now run without keeping Codex's output connections open. The hook bridge preserves foreground results and lets notifications continue.
Updating
Windows Codex users must reapply the installer so the hook bridge and configuration are updated:
irm https://raw.githubusercontent.com/justbuild-it/iriscale_voice/v0.1.31/install.ps1 | iexRequires Codex 0.154.0+. Fully restart Codex and review/trust the changed hooks. Updating only the runtime is insufficient.
Claude Code plugin users:
claude plugin marketplace update iriscale
claude plugin update iriscale-voice@iriscale
Restart Claude Code after updating.
Validation and npm availability
All 11 CI jobs passed on release commit 61152b1, covering Windows, macOS, Linux, both Windows installers, and real background-watcher behavior. The maintainer reports no Hook failed message in a live prompt test of the fix.
npm publication is pending with Puneet in #36. At release time, npm latest remains 0.1.25; the GitHub installer above provides v0.1.31 now. Native macOS audio/Terminal verification remains tracked in #36.
Follow-up found during rollout
Automatic-review Codex sessions can announce a permission wait even though no user answer is needed. This is separate from the hook timeout fix in this release. PR #46 fixes the false alerts and blocked dashboard state; it is not included in v0.1.31. npm publication is held pending that fix and its subsequent verified release.
Public installer verification: the pinned installer matches the tagged source and passed the Windows disposable-home smoke test, including all five hooks through PowerShell, normal-mode background survival, named sessions, SessionEnd cleanup, and failure/timeout handling. The deliberately stalled-worker test needed a repeat because the first run reached the outer worker deadline rather than the expected inner runtime deadline; no assertions were relaxed.
v0.1.30
Codex fixes from #42:
- Fix Windows prompt-submit "Hook failed / hook exited with code 1" errors caused by invoking cmd-style commands through PowerShell.
- Use lifecycle hooks for completion so internal temporary Codex requests do not produce false voice alerts or dashboard rows.
- Remove an ended Codex session from the board when SessionEnd is received; preserve distinct real sessions sharing a folder.
Requires Codex 0.154.0 or newer. Reapply installation, restart Codex, and review all five hooks in /hooks.
Windows standalone upgrade (use the fresh installer, not the old v0.1.29 updater):
irm https://raw.githubusercontent.com/justbuild-it/iriscale_voice/v0.1.30/install.ps1 | iexClaude Code users: update the iriscale marketplace and iriscale-voice plugin, then restart Claude Code.
npm publication is tracked in #36. A GitHub release does not update npm users; verify @iriscale/voice@0.1.30 is published before using that npm version. Native macOS audio/Terminal verification remains tracked there as well.
v0.1.29
Audit fixes: #37.
Codex dashboard fixes: #38.
Fixed
- Preserve Windows Codex notification JSON through a native stdin bridge, so
unnamed sessions show their project folder instead of a collapsed Windows path.
Use the latest Codex title record on board refresh and identify unnamed Codex
hooks correctly. Reapply the Codex installation and restart Codex after updating. - Preserve Codex TOML settings across quoted brackets, comments, multiline values,
and quoted keys; reject uncertain boundaries before installing. Both npm and
PowerShell installers preserve mixed hook groups and restore displaced notifications. - Scrub quoted credential prefixes and API-key header values before speech, logs,
and session state; skip environment assignments in program-only announcements. - Keep reminder schedules through duplicate events; install Codex's
PostToolUse
resume hook to clear answered permissions after the tool finishes. - Make npx updates refresh the stable runtime at recorded agent homes. Protect
backup names against collisions and preserve Unicode Windows launcher paths. - Store scratch files in a private user configuration directory; reject symlinks and
directories owned by another user. Restart the board after upgrading. - Quote macOS Terminal launch paths, report speech/launch failures, and advertise
focus shortcuts only for supported rows. Add structural Codex installer diagnostics
without rejecting unrelated asynchronous hooks. - Correct package names and document Codex event limits. Add shared installer and
runtime regression coverage to CI and the prepublish checks.
Installation and testing
Reapply the Codex installation and restart Codex and the board; replacing the runtime alone does not update registered hooks. Review changed hooks in /hooks.
GitHub release commit: af30512ff6c72f4bdc8a7f196a92d13e4b7d8c8d. All CI checks passed on this exact commit.
npm publication is pending with Puneet in #36; do not assume npx @iriscale/voice@latest contains this release until the registry version is verified. The pinned GitHub PowerShell installer can be used now.
Live macOS/Codex verification remains tracked in #36. The recurring live UserPromptSubmit hook exit-code-1 report remains unresolved in #39; this release does not claim that error is fixed.
v0.1.28 — waits for your agents, and for your microphone
Fixed
- No "waiting for you" while background agents are still running. Claude Code's idle
timer does not look at background agents, so a minute after the main turn paused it
sent the idle notice and the plugin spoke it and moved the row to needs your review,
wiping the waiting for 2 agents note. The notice is now ignored while the row is
working (or scheduled) with work in flight; the row and its note stay put, and
"done" comes when the last agent lands and the real final turn ends. Permission
prompts and errors still speak.
Added
- Microphone awareness on Windows (
mic_aware, on;mic_wait, 30 s). Windows keeps
a per-app record of microphone use for its privacy indicator; while an app holds the
mic its stop time is zero. The speaker now waits while any app has the mic open
(dictation such as Wispr Flow or voice typing, a call) and, if the mic opens
mid-sentence, cancels the speech and says the line again once the mic closes - so the
plugin's words no longer land in your dictated prompt. Speech moved from an inline
PowerShell command to a smallspeak.ps1written next to the state; the hook path is
unchanged. macOS (CoreAudio) and Linux (PulseAudio/PipeWire) equivalents are on the
roadmap.
npm: not on npm yet.
npx @iriscale/voice@latestinstalls 0.1.25 until 0.1.28 is published (#32).
v0.1.27 — review-window sets the idle window for you; welcome-back lines spoken
Fixed
- Welcome-back summaries were silent. The line was launched with its stdin pointed at
/dev/null, which discarded the message being piped in, so the log showed an empty
WelcomeBackand nothing was said. Now spoken with its text.
Added
/iriscale-voice:review-window 10(CLI:iriscale-voice review-window [minutes|default]) sets
Claude Code's idle window - the time after a turn ends during which a keypress in that
session still marks it reviewed - without anyone editing JSON. Backssettings.jsonup,
edits it with node or python3 when present and a careful text edit otherwise, validates the
result, restores the backup if it ever came out invalid.statusrecommends it while the
60 s default is in effect.npx /voice install claude --applysets ten minutes
too, only when you have not chosen a value.
Changed
- The review window is visible and documented.
statussays how long after a turn ends
a keypress still counts as reviewed, and the board footer states it (reviewed = a key
pressed there within 60s of finishing). It is Claude Code'smessageIdleNotifThresholdMs;
the docs now recommend600000(ten minutes) because with the default a session you
return to after a couple of minutes can only be cleared by sending a prompt - Claude's
idle notice is one-shot, so typing later is invisible.
npm: not on npm yet.
npx @iriscale/voice@latestinstalls 0.1.25 until 0.1.27 is published (#32).
v0.1.26 — test suite isolates its temp state
Fixed
- The test suite no longer shares state with your live sessions. The script keeps its
turn clocks, cooldown files,last_promptand the board pid under$TMPDIR/iriscale-voice,
and the suite used the real one: alast_promptolder than ten minutes from your own
sessions madestampprint a welcome-back line inside a captured check (the traversal
test then failed with[: integer expression expected), and the suite left its
evil.startandbrd-*.lastfiles next to yours.TMPDIRnow points into the
suite's throwaway directory. CI never saw it - fresh runners have no history.
npm: not on npm yet.
npx @iriscale/voice@latestinstalls 0.1.25 until 0.1.26 is published (#32).
v0.1.25 — pick a voice, speak more clearly, no reminders for answered prompts
Added
/iriscale-voice:speaker(CLI:iriscale-voice speaker) — who does the talking.
Without an argument it shows the voices worth using and where clearer ones come from
(macOS: Manage Voices downloads an Enhanced/Premium variant; Windows: Speech
settings) — macOS installs about forty English voices and most are novelty toys (Boing,
Bubbles, Zarvox) or 1980s formant voices (Albert, Fred), so the default output is a
shortlist of the natural ones actually installed andspeaker --allprints every one.
A voice macOS lists twice (the plain entry and its Siri variant) is shown once. With a
name it sets the voice and speaks a sample so you hear the change at once; on macOS a
namesaydoes not know is refused instead of failing silently later.speaker default
restores the system voice, andvoicesis an alias for the list. Every line of the
list fits 80 columns, and its slash command answers in prose rather than pasting the
block: column-aligned terminal text does not wrap in a chat pane, so it scrolled
sideways and lost the ends of its longest lines (one ran to 106 characters). It closes
by writing the command out —/iriscale-voice:speaker "Samantha"— rather than
describing it.install clauderespells the commands it writes. Slash commands are authored in the
plugin's namespaced form, but outside the plugin they are flat files invoked with a
hyphen, so a command telling you to run/iriscale-voice:speakerwas pointing at
something that does not exist in that install. Command bodies are now rewritten to
/iriscale-voice-…as they are copied, next to the existing${CLAUDE_PLUGIN_ROOT}
substitution.pronouncesetting:word=spokenpairs for anything the synthesizer mangles —
pronounce=iriscale=eye riss scale,naro=nah row. Whole-word, any case, wins over the
built-in list, and still passes throughclean()so a value can never reach the shell.
Changed
- Announcements are easier to understand. The synthesizer now gets a version of each
line tuned for the ear while the log, board and repeat guard keep the plain text: a
short pause after the session name ("payments api, done" instead of one run-on
phrase), CamelCase tool names split (Ask User Question, Web Fetch), the two-character
hash Claude Code appends to auto-named sessions spelled out (iriscale voice 4 D rather
than "fourd"; real words such as cafe are left alone), and common CLI names said the
way people say them (N P X, E S lint, kube control, P S Q L, and then for
&&).IRISCALE_VOICE_DEBUG=1now prints both the plain line and the spoken form.
Fixed
- A renamed or dropped slash command lingered forever.
install claudeonly ever
wrote the commands it ships and never took back one it had shipped before, so a command
that changed name stayed in the picker calling a subcommand the script no longer has
(anduninstall claudeleft it behind too). Both now sweep everyiriscale-voice-*.md
in~/.claude/commandswhose body points at our script; a file of your own that happens
to share the prefix is left alone. - Voice names with parentheses were silently ignored. macOS lists its clearer voices
asEddy (English (US))and downloaded ones asSamantha (Enhanced), but thevoice
setting rejected any name containing(/)and fell back to the system default without
a word. Parentheses are now allowed (they are inert inside the quotedsayargument and
the single-quoted PowerShell string; quotes, backslashes, backticks and$are still
refused). - "still needs your answer" spoken after you had already answered. Answering a
permission prompt or anAskUserQuestionfires noUserPromptSubmit, so nothing told
the plugin the dialog was gone: the session stayed needs your answer until the turn
ended, and if Claude worked on for more than three minutes the reminder watcher spoke
"… still needs your answer, 3 minutes" over a session that was busy, not blocked. A
newPostToolUsehook (resume, the eighth hook) marks the session working the
moment the tool you were asked about runs: it movessince, which ends that turn's
watcher, clears the reminder schedule, and counts as you being present for
remind_pause. It fires on every tool call, so it is builtins-only and touches nothing
unless the session was actually blocked - aready/reviewrow keeps its review
lifecycle. A second prompt in the same turn now also restarts the 3/10-minute clock
instead of inheriting the first one's. Codex has no post-tool hook, so a Codex row
still clears on your next prompt or the turn's end. Plugin users get the hook on
update;install claude --applyusers re-run the installer.
npm: published as
@iriscale/voice@0.1.25, built from this tag (all 27 files verified identical).
v0.1.24 — npx installer for Codex and Claude Code
Added
npx @iriscale/voice@latest install codex --apply— a Codex installer for every OS.
macOS and Linux had no installer at all (README: "No installer yet"), and getting
iriscale-voiceonto a PATH meant cloning the repo. One command now installs the
script to a stable directory (~/.local/share/iriscale-voice, or
%LOCALAPPDATA%\Programs\iriscale-voice— the same rootinstall.ps1uses), puts it
on PATH, installs the$iriscale-voiceskill, and mergesnotifyplus the
UserPromptSubmit/PermissionRequesthooks into~/.codex/. It backs up every file
it edits, validates a pre-existinghooks.jsonbefore writing anything, is
idempotent, and is reversed exactly byiriscale-voice uninstall codex. Without
--applyit writes nothing and prints the configuration with your paths filled in.
Node is an install-time dependency only — hooks still call the same zero-dependency
POSIX script directly, andnpm installon its own touches no configuration. The
hooks hold absolute paths, so voice works whether or not the command is on your
PATH; when~/.local/binis not on it, the installer prints the exact line for
your shell. (docs/install/npm.md, #28)install claude --apply— Claude Code without the plugin. The same npx line
installs the seven hooks into~/.claude/settings.json, the skill, and the
slash commands, resolving${CLAUDE_PLUGIN_ROOT}to the stable path as it writes.
~/.claude/commands/takes flat files only — a subdirectory there is not a namespace,
only skills namespace by directory — so outside the plugin the commands are spelled
/iriscale-voice-statusrather than/iriscale-voice:status.iriscale-voice doctor claudereports what is installed and flags a duplicated hook (counted per matcher, so
the twoNotificationmatchers are not mistaken for one). The plugin stays the recommended route for Claude Code; running both
would speak twice — Claude Code deduplicates a handler across settings files but keeps a
plugin's copy separate — so the installer refuses unless--force, keying on
enabledPluginsin the settings files and on a real plugin manifest rather than on a
marketplace merely having been added. Both agents share one copy of the script — uninstalling one leaves it for
the other, and the last one out removes it.- Your own configuration survives. Codex allows a single top-level
notify, so ours
displaces any other — it is now remembered and restored on uninstall instead of leaving
you to dig it out of the backup. And a hook of your own that happens to call the CLI
(iriscale-voice say "build done") is no longer mistaken for one of ours and removed:
ownership is decided by the internal event argument our own entries always end with. - Hooks are appended, never replaced. Installing for either agent used to overwrite
the wholeUserPromptSubmitentry, discarding a hook of the user's own on the same
event. Our entries are now merged in beside existing ones and replaced individually on
re-install, and uninstall removes only ours. - Known divergence, unchanged:
install.ps1still replaces each Codex hook event
rather than appending, so the PowerShell route can still discard aUserPromptSubmit
hook of the user's own where the npm route now preserves it. Running the npm installer
over a PowerShell install is safe (it recognises those entries as ours and replaces
them without duplicating), so no one ends up speaking twice. Fixinginstall.ps1
itself needs a Windows machine to verify on and is deliberately left for a maintainer
who has one. package.jsonjoins the version guard: scriptVERSION, three manifests and the
package must agree, andtest/npm.shcovers both installers against throwaway
~/.codexand~/.claudedirectories.
npm: 0.1.24 was never published to npm. The first published version is 0.1.25, so
npx @iriscale/voice@latestworks; to run exactly 0.1.24, install from this tag.
v0.1.23 — passive review lifecycle and reminders
Added
- Passive review lifecycle. Nothing to click or acknowledge. Claude Code fires its
idle notice 60 s after a turn ends only if no key was pressed in that session (focus and
mouse do not count); the plugin already receives it. A READY Claude session that
outlives that window with no notice becomes reviewed; one that gets the notice
becomes needs your review. The board now says needs your answer (permission
prompt), needs your action (error), needs your review, ready, working,
scheduled, reviewed - and no longer greys a row out by the clock (board_ready_minutes
removed). - Reminders, few and merged. After the first announcement, a session that still needs
you is reminded on a schedule: answers at 3 and 10 minutes, review at 15, errors at
10 (remind_answer/remind_review/remind_action;verbose3,10,20 / 10,30 /
10;basicnever). Several due at once become one line ("still waiting: payments
needs your answer, billing ready for review"); a reminder is skipped, not deferred,
if you sent a prompt anywhere in the lastremind_pauseminutes (2); then silence. - Welcome back. After
welcome_backquiet minutes (10), your next prompt is preceded
by "while you were away: …" naming what waits. Off with0. - Events
RemindandWelcomeBack(on in standard and verbose) so quiet hours, mutes
and the cooldown apply to them too. A detached watcher per session-turn does the
timing; the hook path stays builtins-only.