English | 简体中文
Slap your MacBook, it yells back.
"this is the most amazing thing i've ever seen" - @kenwheeler
"I just ran sexy mode with my wife sitting next to me...We died laughing" - @duncanthedev
"peak engineering" - @tylertaewook
Uses the Apple Silicon accelerometer (Bosch BMI286 IMU via IOKit HID) to detect physical hits on your laptop and plays audio responses. Single binary, no dependencies.
By default, every slap also spawns an on-screen whip overlay that types Ctrl+C plus a scolding "ADD DEBUG LOGS" macro into your focused terminal - physically whip Claude Code into shape. Pass --no-whip to keep just the audio.
- macOS on Apple Silicon (any M-series chip M2 or greater, or the M1 Pro SKU specifically, no other M1/A-series chips!)
sudo(for IOKit HID accelerometer access)- Go 1.26+ (if building from source)
- For whip mode (on by default):
node+npmon your user PATH (spank installs the rest into~/.cache/spank/whip/on first run). If node isn't found, spank logs a warning and continues with audio only.
Download from the latest release.
Or build from source:
go install github.com/taigrr/spank@latestNote:
go installplaces the binary in$GOBIN(if set) or$(go env GOPATH)/bin(which defaults to~/go/bin). Copy it to a system path sosudo spankworks. For example, with the default Go settings:sudo cp "$(go env GOPATH)/bin/spank" /usr/local/bin/spank
# Default - says "ow!" AND whips Claude Code on each slap
sudo spank
# Sexy mode - escalating audio + whip
sudo spank --sexy
# Halo mode - Halo death sounds + whip
sudo spank --halo
# Fast mode - faster polling and shorter cooldown
sudo spank --fast
sudo spank --sexy --fast
# Custom mode - your own MP3 files
sudo spank --custom /path/to/mp3s
# Audio only - disable the whip overlay
sudo spank --no-whip
sudo spank --sexy --no-whip
# Adjust sensitivity with amplitude threshold (lower = more sensitive)
sudo spank --min-amplitude 0.1 # more sensitive
sudo spank --min-amplitude 0.25 # less sensitive
sudo spank --sexy --min-amplitude 0.2
# Set cooldown period in millisecond (default: 750)
sudo spank --cooldown 600
# Set playback speed multiplier (default: 1.0)
sudo spank --speed 0.7 # slower and deeper
sudo spank --speed 1.5 # faster
sudo spank --sexy --speed 0.6Pain mode (default): Randomly plays from 10 pain/protest audio clips when a slap is detected.
Sexy mode (--sexy): Tracks slaps within a rolling 5-minute window. The more you slap, the more intense the audio response. 60 levels of escalation.
Halo mode (--halo): Randomly plays from death sound effects from the Halo video game series when a slap is detected.
Custom mode (--custom): Randomly plays MP3 files from a custom directory you specify.
Whip overlay (default, disable with --no-whip): Each detected slap spawns an on-screen whip overlay (vendored from OpenWhip, bundled inside the spank binary) and auto-cracks it, sending Ctrl+C plus a scolding macro ("THATS WRONG ADD DEBUG LOGS", etc.) to your focused window. The number of cracks scales with slap amplitude (light tap = 1 crack, hard wallop = 4 cracks, fired ~150 ms apart). Composes with all audio modes.
Prerequisites:
nodeandnpmon$SUDO_USER's PATH (install from nodejs.org,brew install node, or via nvm/asdf)- macOS: grant Accessibility permission to
Electron(System Settings → Privacy & Security → Accessibility) so it can synthesize keystrokes - Linux:
sudo apt install xdotool
How it works: the whip overlay is embedded in the spank binary. On first launch, spank extracts it to ~/.cache/spank/whip/ and runs npm install once (downloads Electron, ~200 MB, takes a minute). Subsequent launches reuse the cached install. Spank itself runs as root for accelerometer access, then de-escalates via sudo -u "$SUDO_USER" -E node spawn.js --listen-stdin so Electron + tray + Accessibility work in your user session. If anything goes wrong (no node, no SUDO_USER, etc.), spank logs the reason and continues with audio only.
Use --fast for a more responsive profile with faster polling (4ms vs 10ms), shorter cooldown (350ms vs 750ms), higher sensitivity (0.18 vs 0.05 threshold), and larger sample batch (320 vs 200).
You can still override individual values with --min-amplitude and --cooldown when needed.
Control detection sensitivity with --min-amplitude (default: 0.05):
- Lower values (e.g., 0.05-0.10): Very sensitive, detects light taps
- Medium values (e.g., 0.15-0.30): Balanced sensitivity
- Higher values (e.g., 0.30-0.50): Only strong impacts trigger sounds
The value represents the minimum acceleration amplitude (in g-force) required to trigger a sound.
To have spank start automatically at boot, create a launchd plist. Pick your mode:
Pain mode (default)
sudo tee /Library/LaunchDaemons/com.taigrr.spank.plist > /dev/null << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.taigrr.spank</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/spank</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/spank.log</string>
<key>StandardErrorPath</key>
<string>/tmp/spank.err</string>
</dict>
</plist>
EOFSexy mode
sudo tee /Library/LaunchDaemons/com.taigrr.spank.plist > /dev/null << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.taigrr.spank</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/spank</string>
<string>--sexy</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/spank.log</string>
<key>StandardErrorPath</key>
<string>/tmp/spank.err</string>
</dict>
</plist>
EOFHalo mode
sudo tee /Library/LaunchDaemons/com.taigrr.spank.plist > /dev/null << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.taigrr.spank</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/spank</string>
<string>--halo</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/spank.log</string>
<key>StandardErrorPath</key>
<string>/tmp/spank.err</string>
</dict>
</plist>
EOFNote: Update the path to
spankif you installed it elsewhere (e.g.~/go/bin/spank).
Whip overlay + launchd: the whip overlay needs a user session for tray + Accessibility. The launchd plists above run spank as root with no user session, so add
--no-whiptoProgramArguments(or run spank from your normal login shell instead of launchd) unless you've configuredUserName+ passwordless sudo for accelerometer access.
Load and start the service:
sudo launchctl load /Library/LaunchDaemons/com.taigrr.spank.plistSince the plist lives in /Library/LaunchDaemons and no UserName key is set, launchd runs it as root - no sudo needed.
To stop or unload:
sudo launchctl unload /Library/LaunchDaemons/com.taigrr.spank.plist- Reads raw accelerometer data directly via IOKit HID (Apple SPU sensor)
- Runs vibration detection (STA/LTA, CUSUM, kurtosis, peak/MAD)
- When a significant impact is detected, plays an embedded MP3 response
- Optional volume scaling (
--volume-scaling) - light taps play quietly, hard slaps play at full volume - Optional speed control (
--speed) - adjusts playback speed and pitch (0.5 = half speed, 2.0 = double speed) - Whip overlay (default, opt out with
--no-whip) - pipes a one-line JSONcrackevent ({"cmd":"crack","amplitude":0.42,"cracks":2}) to a bundled Electron child running as$SUDO_USER; crack count is bucketed from amplitude (1-4 cracks, ~150 ms apart) - 750ms cooldown between responses to prevent rapid-fire, adjustable with
--cooldown
Sensor reading and vibration detection ported from olvvier/apple-silicon-accelerometer.
Whip overlay (everything under whip/) is vendored from GitFrog1111/OpenWhip, MIT licensed.
MIT
