I changed one sentence in a blog post, opened a pull request, and watched CI spend about 85 seconds installing a headless Chromium to confirm my prose still turned into HTML. The obvious fix, telling the workflow to ignore content paths, would have quietly broken every merge instead. Symptom: a browser for a one-line edit # Every pull request on this blog runs two jobs: a lint job, and a build-and-test job. The second one builds the site with Hugo, link-checks the output with htmltest, then installs a headless Chromium and runs a Playwright suite against a live hugo server. End to end, roughly 85 seconds, and almost all of it is Playwright.
I wrote a daemon to listen to Claude Code hooks. My first version read `$CLAUDE_HOOK_PAYLOAD` and logged empty bodies for two days straight. The payload was sitting on stdin the whole time. Building ClaudeDeck · Part 1 of 10 1 2 3 4 5 6 7 8 9 10 🧪 Tested with Claude Code 2.1.x · macOS This post is the five gotchas I hit while wiring up ClaudeDeck, a Stream Deck plugin (a small program that runs inside Elgato’s Stream Deck app on the USB grid of programmable LCD keys) that talks to Claude Code over its hooks system. Claude Code is Anthropic’s terminal CLI for Claude (claude in your shell), and its hooks are user-defined scripts it spawns at certain points in a session (before a tool call, on session start, on prompt submit). My daemon is a long-running background process the plugin and the hooks both talk to over a local socket. None of the gotchas are exotic. All of them cost me hours. Each one is a place where the docs were either silent, ambiguous, or contradicted by tribal knowledge I picked up from other people’s projects.
Boris Cherny created Claude Code. When he shared how he actually uses it day-to-day, the setup was surprisingly simple. I went through every tip, tried most of them, and have opinions about all of them. The original thread is on Boris’s X account. A good companion site is howborisusesclaudecode.com which compiles everything in one place.