vibeaudio 0.25.2 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/package.json +1 -1
- package/src/cli.js +17 -0
- package/src/hooks.js +1 -1
package/README.md
CHANGED
|
@@ -300,7 +300,7 @@ Where an agent reports more than start and stop, VibeAudio listens for that too
|
|
|
300
300
|
| :--- | :--- |
|
|
301
301
|
| **Five agents tell you when they're waiting on you** | When a permission dialog opens the music stops rather than sounding busy while the agent is stuck on you, and it resumes once the thing you answered has run. Claude Code covers the terminal, desktop app and IDEs alike, plus MCP servers asking for input. Copilot CLI's own `PermissionRequest` fires before *every* permission check — dialog or not — so VibeAudio listens for its permission-prompt notification instead. Cursor and Grok have no such event that's been verified, so they keep playing through a prompt. |
|
|
302
302
|
| **Claude Code turns that never reach `Stop` still end the music** | An API error or rate limit ends the turn with `StopFailure` instead, which plays the failure chime. Interrupting (Esc, or the stop button in the desktop app) fires no hook at all, so the background player watches the session transcript for Claude Code's interrupt entry and stops silently within half a second — whether the agent was writing or running a tool. A prompt that another hook blocks (a token-saving proxy, say) never reaches `Stop` either, so the same watcher ends the music on Claude Code's "prompt blocked" entry — or never starts it, when the blocker was quicker than we were. Closing the session mid-turn stops it too — but only if that session started the music, so closing an idle terminal never silences another one. |
|
|
303
|
-
| **Codex asks you to trust the hook once** | Codex keeps a per-hook trust hash in `~/.codex/config.toml` and won't run a hook it hasn't been told to trust, so the install isn't live until you approve each one the first time
|
|
303
|
+
| **Codex asks you to trust the hook once** | Codex keeps a per-hook trust hash in `~/.codex/config.toml` and won't run a hook it hasn't been told to trust, so the install isn't live until you approve each one. The CLI asks the first time each fires; the Codex desktop app shows **Review hooks** in the composer, where **Allow all** approves them in one go. Both write the same records, so approving in one covers the other. |
|
|
304
304
|
| **Cursor and Antigravity say how a turn ended** | Cursor's stop event reports whether the turn completed, aborted or errored, and Antigravity's gives a termination reason, so an error plays the failure chime. Claude Code and Qwen Code send a separate `StopFailure` for an API error. The others send no verdict, so a turn there always ends on the success chime — VibeAudio won't invent a failure the agent never claimed. |
|
|
305
305
|
| <a id="antigravity-hooks"></a>**Antigravity never gets a pre-tool hook** | Its pre-tool hook has to approve or deny every tool call — one that answers nothing blocks the tool — so VibeAudio installs none, and `--reactive` does nothing there. It has no prompt event either: the start event fires before every model call, and VibeAudio starts the music on the first one of each prompt only. Its hooks live in `~/.gemini/config/hooks.json` under a name of their own, so your other named hooks there are never touched. Verified with the `agy` CLI; the desktop app reads the same file by Antigravity's own docs but hasn't been checked live. |
|
|
306
306
|
| **Upgraded, and a new feature isn't there?** | Hooks are written into your agent's config once, at install time, and an upgrade doesn't touch them. When a new version listens for more events (0.13.1 added Codex's `Interrupt` and `SessionEnd`), `vibe --doctor` and `vibe --status` name what's missing, and `vibe --install-hooks` adds it. |
|
|
@@ -334,6 +334,8 @@ Sessions with no id in their payload share a single slot, so they behave as one.
|
|
|
334
334
|
|
|
335
335
|
> **The Claude Code desktop app is covered too**, not just the terminal — both read the same `~/.claude/settings.json` (or `$CLAUDE_CONFIG_DIR/settings.json`). (The separate **Claude Desktop** chat app is a different product with no hooks; that one needs [MCP](#-everything-else-claude-desktop-vs-code-via-mcp).)
|
|
336
336
|
|
|
337
|
+
> **So is the Codex desktop app** (the Codex side of the ChatGPT app): it runs the same Codex engine on the same `~/.codex/hooks.json`, so `--install-hooks` covers it with nothing extra. Approve the hooks once from its **Review hooks** prompt. Its stop button ends the music silently, as Codex's `Interrupt` does in the CLI.
|
|
338
|
+
|
|
337
339
|
> **One player is shared.** Prompt two agents at once and the last prompt owns the music. One person, one set of speakers — deliberate, not a limitation being worked around.
|
|
338
340
|
|
|
339
341
|
### 🔔 Desktop banners: `vibe --notify`
|
|
@@ -878,6 +880,7 @@ The full order, highest first: **a flag** → **an environment variable** → **
|
|
|
878
880
|
| `--report [days]` | How long you waited on agents, and on which projects, from the local turn log | `7` days |
|
|
879
881
|
| `--card [--out <path>]` | With `--report`: the totals as a shareable image - PNG on macOS, SVG anywhere - saved to `~/.vibeaudio/card.png`, replaced each run | off |
|
|
880
882
|
| `--statusline` | The same state as one plain line for tmux or a shell prompt (`working ×2`, `waiting: api`); prints nothing when idle | — |
|
|
883
|
+
| `--why` | Why the music is playing or silent, as one plain line (the first line of `--status`) | — |
|
|
881
884
|
| `--state` | What every agent on the machine is doing, as one line of JSON: `idle`, `working`, `stuck` or `waiting` | — |
|
|
882
885
|
| `--events` | Stream agent state changes as JSON lines, starting with the current state, until stopped | — |
|
|
883
886
|
| `--dashboard` | Serve a read-only live view of every agent on this machine at `http://127.0.0.1:4747`, and open it. `--port <n>` and `--no-open` adjust it | — |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeaudio",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "Procedural focus music while your AI coding tools (Claude Code, Codex, Cursor, Grok, Gemini, Copilot) think — a different arrangement per project.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"vibeaudio": "bin/vibeaudio.js",
|
package/src/cli.js
CHANGED
|
@@ -99,6 +99,7 @@ Procedural focus music while your AI coding tools think.
|
|
|
99
99
|
--port <n> With --dashboard: the port (default ${require("./dashboard").DEFAULT_PORT}, else a free one)
|
|
100
100
|
--no-open With --dashboard: do not open the browser
|
|
101
101
|
--statusline Print that as one plain line for tmux or a prompt; prints nothing when idle
|
|
102
|
+
--why One plain line: why the music is playing or silent (the first line of --status)
|
|
102
103
|
--events Stream agent state changes as JSON lines, until stopped
|
|
103
104
|
--doctor Check the setup; each problem comes with its fix (exit 1 if any)
|
|
104
105
|
--stop Stop the background player, then exit
|
|
@@ -238,6 +239,7 @@ function parseArgs(argv) {
|
|
|
238
239
|
let statusFlag = false;
|
|
239
240
|
let stateFlag = false;
|
|
240
241
|
let statuslineFlag = false;
|
|
242
|
+
let whyFlag = false;
|
|
241
243
|
let eventsFlag = false;
|
|
242
244
|
let doctorFlag = false;
|
|
243
245
|
let notifyFlag = null;
|
|
@@ -422,6 +424,12 @@ function parseArgs(argv) {
|
|
|
422
424
|
continue;
|
|
423
425
|
}
|
|
424
426
|
|
|
427
|
+
if (arg === "--why") {
|
|
428
|
+
whyFlag = true;
|
|
429
|
+
i += 1;
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
|
|
425
433
|
if (arg === "--state" || arg === "--events") {
|
|
426
434
|
if (arg === "--state") stateFlag = true;
|
|
427
435
|
else eventsFlag = true;
|
|
@@ -649,6 +657,7 @@ function parseArgs(argv) {
|
|
|
649
657
|
status: statusFlag,
|
|
650
658
|
state: stateFlag,
|
|
651
659
|
statusline: statuslineFlag,
|
|
660
|
+
why: whyFlag,
|
|
652
661
|
music,
|
|
653
662
|
events: eventsFlag,
|
|
654
663
|
doctor: doctorFlag,
|
|
@@ -1837,6 +1846,7 @@ async function run() {
|
|
|
1837
1846
|
status: showStatus,
|
|
1838
1847
|
state: showState,
|
|
1839
1848
|
statusline: showStatusline,
|
|
1849
|
+
why: showWhy,
|
|
1840
1850
|
music,
|
|
1841
1851
|
events: followEvents,
|
|
1842
1852
|
doctor: showDoctor,
|
|
@@ -2011,6 +2021,13 @@ async function run() {
|
|
|
2011
2021
|
return;
|
|
2012
2022
|
}
|
|
2013
2023
|
|
|
2024
|
+
// --status's first line without the rest, plain: for the mod's pane and band (#60), a prompt segment, a script.
|
|
2025
|
+
if (showWhy) {
|
|
2026
|
+
const hooks = require("./hooks");
|
|
2027
|
+
console.log(hooks.explainMusic(musicFacts()).text);
|
|
2028
|
+
return;
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2014
2031
|
if (dashboard) {
|
|
2015
2032
|
const { startDashboard } = require("./dashboard");
|
|
2016
2033
|
let server;
|
package/src/hooks.js
CHANGED
|
@@ -266,7 +266,7 @@ const TARGETS = {
|
|
|
266
266
|
seed: () => ({}),
|
|
267
267
|
// Codex records a trusted_hash per hook in config.toml and asks before
|
|
268
268
|
// running one it has not seen, so the install is not live until approved.
|
|
269
|
-
note: "Codex asks you to trust each new hook the
|
|
269
|
+
note: "Codex asks you to trust each new hook once — in the desktop app via Review hooks in the composer (Allow all), in the CLI the first time each fires."
|
|
270
270
|
},
|
|
271
271
|
cursor: {
|
|
272
272
|
name: "Cursor",
|