Blog
thoughts on tech and content.
2026
Hosted PartyKit shut down on October 23, 2026. Sunil Pai and Cloudflare replaced the cloud middleman with PartyServer—open-source Durable Objects on your own account.
Skill: follow-up
A small meta-skill that runs when I ask an agent to 'follow up' after a session. It reviews what changed, runs the right sync, or recommends durable updates only when the value clearly outweighs the cost.
How to Stop AI Coding Agents from Reading .env Files and Secrets
Keep .env files, API keys, access tokens, and credentials out of AI context with file permissions, isolated environments, and agent hooks.
How to Stop OpenCode from Reading .env Files
Use an OpenCode plugin to block common .env reads, credential-file access, and environment dumps before tool execution.
How to Stop Devin CLI from Reading .env Files
Stop Devin CLI from reading .env files with a registered tool hook. Block credential access and environment dumps using the correct denial exit code.
How to Stop Cursor from Reading .env Files
Protect .env files and API keys in Cursor with .cursorignore and file and shell hooks. Keep secrets out of indexing and AI context.
How to Stop Claude Code from Reading .env Files
Stop Claude Code from reading .env files with a registered PreToolUse hook. Block common secret-file reads and keep API keys out of AI context.
How to Stop Google Antigravity from Reading .env Files
Protect .env files, API tokens, and private keys in Google Antigravity with a PreToolUse hook and safe environment templates.
A File for Forgetting
What is a scratch.md file? How to keep a pinned, uncommitted scratchpad in your code editor for notes and throwaway scripts.
Switching to Fish, Part 3: Completions and the Tradeoff
Fish completions autoload from a folder with no plugin manager. Plus the one honest cost of switching: fish is not POSIX.
Switching to Fish, Part 2: Functions Instead of Alias Soup
Aliases break the moment you need a conditional or an argument. Fish functions are first-class, readable, and take five minutes to learn.
Switching to Fish, Part 1: Type Less Immediately
Fish gives you autosuggestions, syntax highlighting, and sane defaults out of the box. Install it, set it as your shell, and feel the difference in ten minutes.
2022
How to get WooCommerce default URLs with PHP functions
Get the WooCommerce cart, checkout, account, and shop URLs with built-in PHP functions instead of hardcoding them.
How to break line in React i18n JSON translations
Two ways to add a line break to text from a react-i18next JSON file — \n with white-space pre-line, or <br/> with the Trans component.
My daily grep commands
The grep commands I actually use every day — recursive search, excluding folders and file types, and listing matching file names only.
How to use ComponentWillUnmount in a Functional Component
Replace componentWillUnmount with a useEffect cleanup function in React functional components.
2021
Create a React Progress Bar Component
A reusable React reading progress bar (scroll progress indicator) with SCSS modules that only starts filling once the article reaches the top of the screen.
Translate any string in WordPress with the gettext filter
Use WordPress's gettext filter to translate or rename any string, even when your translation plugin refuses to cooperate.
How to change a WordPress username
WordPress greys out the username field. Change it with a plugin, or directly in the database through phpMyAdmin.
How to list all global npm packages
List every globally installed npm package with a single command.
Get new posts by email
New writing in your inbox. Unsubscribe anytime.