Skip to content

Add hooks: vibestretch - #5780

Closed
Eliasjunit wants to merge 1 commit into
JSONbored:mainfrom
Eliasjunit:add-vibestretch
Closed

Add hooks: vibestretch#5780
Eliasjunit wants to merge 1 commit into
JSONbored:mainfrom
Eliasjunit:add-vibestretch

Conversation

@Eliasjunit

Copy link
Copy Markdown

Single-entry submission: content/hooks/vibestretch.mdx.

What it is

A hooks-based Claude Code plugin that prints one stretch, micro-workout, or eye exercise into the session when an agent turn has kept the user waiting. Three hooks do the accounting — UserPromptSubmit opens a turn, PostToolUse adds the wait and fires the nudge when it is due, Stop closes the turn.

The part worth reviewing is what it counts: agent-wait time, not desk time. A nudge needs a long current turn, enough accumulated waiting since the last break, and an expired cooldown, so short turns and fast models stay silent with no configuration. A 45-minute absence clears the debt, and on macOS the system idle clock keeps an overnight run at an empty chair from counting at all.

Sources

Install

/plugin marketplace add Eliasjunit/vibestretch
/plugin install vibestretch@vibestretch

Safety and privacy

No dependencies, no daemon, no telemetry, no network calls, no accounts. Prompt and tool content is never read — only timestamps and elapsed seconds. State is a handful of plain files under ~/.cache/vibestretch. The nudge is a systemMessage shown to the user and never added to the model context. On macOS the scripts shell out to ioreg for the idle clock and afplay for a bundled chime; on Linux paplay. Nothing is written outside the plugin's own state directory.

Both note fields are filled in the entry. This is my own work, submitted per CONTRIBUTING path 2 (direct PR), MIT licensed.

@JSONbored

Copy link
Copy Markdown
Owner

First, credit where it is due: this has the best provenance of anything in the current queue. Your 285-line scriptBody is byte-identical to scripts/vibestretch.sh at main — I diffed it, clean, 285 lines each — and copySnippet is byte-identical to hooks/hooks.json. Nothing paraphrased, nothing drifted. That is how a hook entry should be built.

I am closing on two claims in the safety and privacy blocks that the shipped plugin contradicts.

1. safetyNotes: "Writes nothing outside its own state directory and never modifies your project or your settings."

True of the hook script — every write targets $STATE_DIR. Not true of the plugin. You also ship skills/statusline/SKILL.md, which your own entry body advertises ("/vibestretch:statusline adds a status line segment"), and that skill's text says the setup "edits the user's own configuration", wrapping or installing a statusLine command under ~/.claude. It is opt-in and defensive — disable-model-invocation: true, "Run on explicit user request only", backs up first — but "never modifies your ... settings" does not survive contact with what you ship.

2. privacyNotes: "Prompt and tool content is never read. Only timestamps and elapsed seconds are recorded."

The script reads the first 4 KB of the hook payload, which on PostToolUse contains tool input and output:

SID=$(head -c 4096 | sed -n 's/.*"session_id"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')

Nothing is retained and nothing is transmitted — I grepped the script for curl|wget|nc|http:// and got zero hits, so your "no network calls of any kind" claim is solid. But "never read" is not the same as "never recorded", and on a privacy note the difference is the whole point.

Both are small rewrites:

safetyNotes:  "The hook writes only to its own state directory. The optional
               /vibestretch:statusline skill, when you run it explicitly,
               edits your ~/.claude configuration and backs it up first."

privacyNotes: "Reads the first 4 KB of the hook payload to extract session_id.
               Nothing from prompts or tool output is retained or transmitted;
               only timestamps and elapsed seconds are stored."

Fix those two and resubmit — everything else, including the byte-identical script body, I am happy with. Minor while you are in there: scriptLanguage says bash but the shebang is #!/bin/sh (your prerequisites correctly say "A POSIX shell", so it is the metadata that is wrong).

@JSONbored JSONbored closed this Aug 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants