I previously wrote about how i’d implemented a combination of 1Password’s CLI and direnv to avoid storing passwords on disk. This works great, most of the time. The problem comes when i want to add a secret and i’m in the middle of a complex multi-agent task – because the environment is loaded once before Claude or Codex or whatever starts, adding or rotating credentials during a build (e.g. if the agent needs an API key to a new service, or accidentally exposes a secret to its context) is tricky. So i’ve evolved the system slightly. What’s changed The main… Continue reading →
Recently at work, someone asked me why my team wasn’t creating detailed logical data models as part of their solution design. It seems quite simple to me – they don’t do it because nobody reads it. Most solution architecture documentation is out of date before it even gets logged in the architecture repository. Why do we even write documentation? I think we create documentation for one of two reasons: So really, design documentation is about ensuring that everyone’s on the same page, both now and in the future. Some designs are ephemeral – just to help us get our heads… Continue reading →
I’ve published an updated, simpler version of this process. I recommend using that – it starts the same as this setup but is easier to manage credential lifecycle. This is more notes to myself so i don’t forget. Goals: Benefits of 1Password: Initial set up 1. Install 1Password, 1password-cli, direnv. 1Password must be the direct download or Homebrew cask version, not the Mac App Store version as App Store enforces sandboxing. 2. Configure 1Password desktop app 3. Configure shell Add to ~/.zshrc. This causes direnv to evaluate a .env.tpl file each time you navigate in to a folder, and clear… Continue reading →
If you’re running Claude Code against your own API key or through a proxy instead of Anthropic’s native backend, you’ve probably noticed that the built-in WebSearch tool just doesn’t return results because it relies on a server-side API that only exists at Anthropic. Without web search, the agent cant research, so we built a self-hosted replacement using MCP. What we built The brilliant DDGS is an open source metasearch server that aggregates results from DuckDuckGo, Bing, Google, Brave, and Yahoo. It has a built in MCP server which exposes five tools: search_text, search_news, search_images, search_videos, and search_books. We deployed it… Continue reading →
Claude Code can do a lot of things. But can it keep a plant alive? The Plant: Act I — Fifty-Eight Days October 22 – December 19, 2025 On October 22, 2025, the moisture sensor read 1829, the first of 5,568 check-ins over fifty-eight days. The scale runs from wet at roughly 1100 to dry at 3400, putting that reading in the middle. The sensor is in the pot of a Tradescantia zebrina. There’s also a 5l jug of water with a pump, a grow light and a camera. Claude’s job is to keep the plant alive – basically, keep… Continue reading →
I have a personal GitHub account and a corporate one, and I found it annoying to have to select the correct SSH key for work repos, so I configured git and SSH to pick the correct key for me. After initial setup, there are three config files to modify: After the initial setup, there are three config files involved: How does it work? well I clone a work repo now and everything is already correct. Generating the keys SSH key first: Give it a passphrase, then add the public key (~/.ssh/work_id_ed25519.pub) to your work GitHub account under Settings > SSH… Continue reading →
By default, Kafka attempts to send records as soon as possible, sending up to max.in.flight.requests.per.connection messages per connection. If you attempt to send more than this, the producer will start batching messages, but ultimately if you saturate the connection so there are unacknowledged message batches pending, the producer enters blocking mode. We can optimise the way the producer batches messages to achieve higher throughput through two settings, batch.size and linger.ms. linger.ms is the number of milliseconds that the producer waits for more messages before sending a batch. By default, this value is 0, meaning that the producer attempts to send… Continue reading →
Claude Code is pretty amazing. It’s let me build prototypes and improve apps faster than I ever thought possible. But I was wondering – what else can it do? I’ve been using Emby for years, but recently I started to wonder what happened to Jellyfin, the project that forked Emby years ago. So i decided to ask Claude Code to help me by setting up a debate and mediating the answer. Setting up the debate Here’s the prompt i used: pretty basic stuff. It got to work, setting up a task list: The folder structure was quite basic: debate.md has… Continue reading →
Although builds were succeeding locally, during CI builds were failing on Linux with the error Error: Cannot find module @rollup/rollup-linux-x64-gnu. npm has a bug related to optional dependencies. The log suggested removing package-lock.json – but this obviously breaks deterministic builds. The root cause is a missing dependency – specifically, when Rollup needs native binaries for performance optimisation. Mac-generated lockfiles won’t include Linux-specific optional dependencies. First noted in npm bug 4828, it was fixed in npm 11.3.0+, but adding an explicit optional dependency prevents edge cases. The fix is: This allows builds to work reliably across platforms. Continue reading →
I’m rob. I spend my time exploring the world, playing board games with my family, solving complex technical problems, and learning new things. At work, I lead a team of solution architects designing and building complex realtime trading systems. Sometimes i write about things here, or code them on GitHub. I believe a few things that guide what I do and how I do it: