npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

claude-atone

v0.1.5

Published

When Claude Code admits a mistake, a little guy does penance squats in a popup terminal — a macOS Stop hook

Readme

claude-atone 🙇

ci npm license: MIT

When Claude Code admits a mistake, a little guy holds his ears and does up-down squats as punishment in a popup terminal.

Unofficial, community-maintained — not affiliated with Anthropic.

macOS only. Pure Node + ANSI — no dependencies, no GIF, no Homebrew. The animation is real pixel graphics painted as colored Unicode half-blocks (the chafa technique, built in). When Claude's reply matches a "mistake" phrase, a native dialog asks "Do you want me to atone? 🙏" — and only on Yes does the animation play.


Install

npx claude-atone
npx claude-atone --test      # pop the "atone?" dialog right now to verify it

That's it. The installer:

  1. Adds a Stop hook to ~/.claude/settings.json (appending — any existing hooks, e.g. claude-nudge, are preserved).
  2. Copies the runner (on-stop.mjs) + animation (updown.mjs) to ~/.claude/claude-atone/ (a stable path that survives npm cache cleanup).
  3. Snapshots your prior settings.json to ~/.claude/.claude-atone-backups/ (mode 0600, 5 most recent kept), then writes atomically (temp file + rename) so an interrupted write can never corrupt your config.

It takes effect on your next interaction with Claude Code.

Update

npx caches packages, so a bare npx claude-atone may run a stale version. Pin @latest to force a fresh fetch and re-copy the runner:

npx claude-atone@latest

Then npx claude-atone --doctor confirms it — it reports the installed runner's version and warns if it's stale relative to the package.

Uninstall

npx claude-atone --uninstall

Removes the Stop hook and the runner directory. Settings backups are kept.

Commands

| Command | Purpose | |---|---| | npx claude-atone | Install the Stop hook + runner | | npx claude-atone --test | Pop the "atone?" dialog now (bypasses the cooldown) | | npx claude-atone --doctor | Diagnose install health (platform, settings.json, runner, version, osascript) | | npx claude-atone --dry-run | Show proposed changes without writing anything | | npx claude-atone --uninstall | Remove the hook and the runner directory | | npx claude-atone --help | Show help | | npx claude-atone --version | Print version |

How it works

Claude finishes a reply
   └─► Stop hook runs  on-stop.mjs
          └─► reads Claude's last_assistant_message from the payload
                └─► if it matches a "mistake" phrase
                     (you're right / my mistake / I apologize / sorry /
                      I was wrong / good catch / my bad / oops …)
                       └─► native dialog: "Do you want me to atone? 🙏"  [No] [Yes]
                              ├─ Yes → open a small Terminal window, play
                              │        updown.mjs --once (~5s), then auto-close
                              └─ No / ignore (30s timeout) → nothing

Why a popup window? Claude Code owns its own terminal screen (it's a TUI), so an animation can't be painted into it without clashing. A separate window is its own TTY, so it plays cleanly.

A 20-second cooldown keeps a burst of apologetic replies from stacking dialogs.

Opens as a tab instead of a window? That's the macOS "Prefer tabs when opening documents" setting (System Settings → Desktop & Dock) — Terminal gives AppleScript no way to override it. Set it to "Manually" for a clean popup window. (Either way it still plays and closes itself afterward.)

macOS permission

Opening that popup uses Apple Events to control Terminal, which macOS gates behind the Automation permission. The first time the hook fires, macOS asks "…wants to control Terminal" — click OK.

Run it up front so the first real one isn't missed:

npx claude-atone --test

If you dismissed the prompt and the animation never appears, re-enable it in System Settings → Privacy & Security → Automation. (If permission is denied the hook just does nothing — it never blocks or errors Claude Code.)

What it writes to settings.json

  {
    "theme": "...",
    "permissions": { ... },
+   "hooks": {
+     "Stop": [
+       {
+         "hooks": [
+           {
+             "type": "command",
+             "command": "node /Users/<you>/.claude/claude-atone/on-stop.mjs"
+           }
+         ]
+       }
+     ]
+   }
  }

If you already have other Stop hooks, they are preserved — claude-atone appends its own entry alongside them and removes only its own on uninstall.

Try the animation directly

node ~/.claude/claude-atone/updown.mjs           # loops until Ctrl+C
node ~/.claude/claude-atone/updown.mjs --once     # ~5s, then exits

Tuning

| What | Where | | ---- | ----- | | Trigger phrases | TRIGGERS array in bin/on-stop.mjs | | Cooldown window | COOLDOWN_MS in bin/on-stop.mjs (default 20s) | | Figure size | W / H at the top of bin/updown.mjs | | Squat depth | the hipY formula in drawFigure | | Speed | setInterval(frame, 90) (frame period, ms) + the t * 0.5 ease factor | | Run length (--once) | ONCE_TICKS in bin/updown.mjs (frames at 90ms; 55 ≈ 5s) |

Debug toggles (env vars): CLAUDE_ATONE_DRYRUN=1 prints what would play instead of opening a window; CLAUDE_ATONE_DEBUG=1 logs to ~/.claude/claude-atone/run.log.

Security & privacy

  • All processing is local. Zero network calls. Zero telemetry. Zero runtime dependencies. Zero npm lifecycle scripts.
  • The hook reads Claude's last message (and, as a fallback, the tail of your transcript) only for case-insensitive substring matching — it is never transmitted anywhere, and never reaches an executed command.
  • osascript is invoked with argv (no shell), so there's no AppleScript/shell injection from LLM text.
  • The animation runs only after you click "Yes".
  • settings.json is snapshotted and written atomically.

Full threat model and load-bearing invariants: SECURITY.md.

Verifying the publish

npm audit signatures claude-atone

This package is published with npm provenance — attestations linking the tarball back to the GitHub build that produced it.

Requirements

  • macOS (Darwin) — uses osascript to open the popup window
  • Node.js ≥ 18
  • A 256-color terminal — every modern terminal qualifies, including the built-in Apple Terminal the popup opens in; 24-bit truecolor is used automatically where it's actually supported (iTerm2, VS Code)
  • Claude Code CLI installed

Roadmap

  • [ ] --enable / --disable toggle without full uninstall
  • [ ] Configurable trigger phrases via the env block
  • [ ] Linux/Windows window-spawning

Contributing

See CONTRIBUTING.md. Issues and PRs welcome at aashutosh-prakash/claude-atone.

Security

See SECURITY.md for disclosure policy and security properties. Report vulnerabilities privately to [email protected].

License

MIT — see LICENSE.


Unofficial, community-maintained. Not affiliated with Anthropic.