← back

The passenger problem. The fluency debt. Two tools built to fix both.

Butler and Relay started as two lines in a CLAUDE.md file. One captures decisions as they're made so you can write the case study months later. The other hands control back, one small task at a time, so you actually learn the codebase you're building.

Praise Ofumaduadike
Nigeria·May 2026·~7 min read
ButlerRelayClaude CodeDev Tools
01The problem

I'm a product designer who started building my portfolio in code about six months ago. No prior coding background. Just a design eye, a set of opinions about interfaces, and a serious ambition to become a design engineer.

The build went fast. Embarrassingly fast. Claude would implement an entire component, state, animation, dark mode, the works, while I watched the terminal. I'd review it, say “looks good,” commit it, and move on. The portfolio grew. The git log filled up. My actual coding knowledge stayed exactly where it started.

But there was a second problem I didn't notice until much later. A few months in, I sat down to write a case study for a piece I'd built. And I couldn't remember why anything worked the way it did.

With Figma you can duplicate a frame and keep every version of a decision. With code, every new component overwrites the old one. The reasoning disappears and only the output survives.

In Figma, design history is ambient. You can go back and look at the version where you tried the modal layout before switching to a full page. In code, none of that exists by default. Every iteration is a rewrite. The git diff shows what changed, not why. And if you weren't the one typing the code in the first place, you have even less to go on.

Figma
Duplicate a frame to preserve old versions
Compare iterations side by side
History is ambient, decisions leave traces
Case study evidence is already there
Code
Every new component overwrites the old one
Git diff shows what changed, not why
Reasoning disappears, only output survives
Case study requires memory or documentation

These two problems needed two different tools. Butler solves the memory problem: capturing decisions as they're made so you can reconstruct the thinking months later. Relay solves the passenger problem: making sure you're actually running part of the build, not just approving Claude's output from the sidelines.

02Butler, the silent logger

The hardest part of writing a case study isn't the writing. It's the archaeology. You're trying to reconstruct decisions that felt obvious at the time but left no trace: why you chose the tab pattern over an accordion, what constraint made you reach for a workaround, which alternatives you considered and dismissed. Butler is the trail of breadcrumbs you forgot to leave.

It runs silently in the background during a Claude Code session, logging every meaningful design decision to a .butler-log.md file in the project root, incrementally, as decisions happen, so nothing is lost if the session ends abruptly.

What Butler logs, and what it doesn't

The scope question was the hardest design decision for Butler itself. Log everything and the file becomes noise. Log too little and it misses what matters. The rule is simple: log decisions, not implementation.

Always logged

Choices and rejections

When one pattern beats another, and crucially, what was ruled out and why. The rejected approach is often the most useful case study material.

Always logged

Constraints that shaped the code

Framework limits, existing token systems, performance considerations: the invisible forces that explain why something works the way it does.

Conditionally logged

Edge cases handled

Empty states, error states, loading: when Claude handles these without being asked, Butler notes it and why.

Never logged

Routine implementation

Boilerplate, syntax, anything self-evident from reading the diff. Butler isn't a git log with extra steps.

A real log entry

.butler-log.md · Session — 2026-05-10 09:41

Animation replay pattern

WhatKey-based remount instead of imperative replay for entrance animations
WhyFramer Motion doesn't expose a replay API. Remounting with a new key is the idiomatic pattern and keeps the component stateless
RejecteduseAnimation hook: adds imperative state for something that should stay declarative
Filecomponents/hero/hero-section.tsx

Dark mode approach

WhatCSS variables for theming, not a React context provider
WhyAvoids re-renders on theme toggle, works across the whole site without wrapping components, consistent with the token architecture already in place
Filestyles/tokens.css

The “Rejected” line is worth paying attention to. It's the most underrated part of any case study: the thing you tried that didn't work, and why. Butler captures it automatically because it's present in almost every meaningful decision Claude makes.

Always-on, never lost

The original version was a paragraph pasted into every session. Two failure modes: forgetting to paste it, and sessions ending before the log was saved. The fix was making the write operation continuous. Butler appends to the log as each decision happens, not at the end. Session dies mid-build, the last five decisions are already on disk.

butler logSurface a clean summary of this session in chat
butler off / onPause or resume logging
butler clearWipe the log and start fresh (asks for confirmation)
$npx skills add kene-praise/butler
03Relay, the handoff system

I've always wanted to know how to code. When Claude Code arrived, I thought it would teach me. Instead it did everything and I watched. The metaphor that made Relay make sense to me: a senior engineer and an intern.

A good senior doesn't write all the code while the intern observes. They write some of it, explain what they're doing, then hand over a task that's within reach, something that will stretch the intern slightly but not break them. The intern does the work, the senior reviews. Over time the tasks get bigger. Relay is that dynamic, designed in.

Senior

Handles complex implementation, logic, architecture decisions. Reviews what the intern produces. Explains the reasoning behind choices. Knows when to take something back.

Intern

Gets assigned tasks that are within reach but require learning. Makes the change, reports back, gets feedback. Earns bigger tasks as confidence builds. Asks for help without shame.

Relay

Decides who does what. Formats the handoff so it's clear. Adjusts the balance as patterns emerge. Knows when to step back in.

Three intensity levels

Apprentice

Claude does almost everything. Occasional tweak cards for isolated values.

Your share of the work

Builder

default

Tweak cards for all simple changes. Claude handles logic and structure.

Your share of the work

Engineer

Implementation briefs. You write the code. Claude reviews.

Your share of the work

The tweak card, Builder level

At Apprentice and Builder, Relay uses tweak cards for simple isolated changes. Not instructions for Claude to execute, instructions for you. File, line, what to find, what to change it to, and why. The why is where the learning is: over time you stop needing the card for values you've already seen and understood.

Your turn
Filecomponents/hero/hero-section.tsx
Line42
Findduration: 0.3
Change toduration: 0.6 (try 0.4-0.8 to feel the range)
WhyControls how long the fade-in takes. Higher = slower and more editorial. This is the value that makes entrances feel considered rather than snappy.

The implementation brief, Engineer level

At Engineer level the format changes. Relay isn't handing you a number to swap, it's handing you a task to implement. What needs to happen, which file, where to look, and a hint you can turn off if you want to work it out yourself. Claude only steps back in if you call /relay do it.

Your turn · Engineer
WhatAdd an active state to the nav link: current page gets a different color and a subtle underline
Filecomponents/nav/nav-link.tsx
Look atclassName logic around line 18, you're adding a conditional based on whether href matches the current pathname
HintNext.js has a usePathname hook from 'next/navigation' that gives you the current route
When doneTell me and I'll review

Auto-detection

Relay watches how you handle handoffs and adjusts your level when a pattern is clear. Consistently completing handoffs without passing things back → bump up. Frequently calling /relay do it → step down. It always tells you before it adjusts, and you can override anytime. The point is keeping tasks in the right range: hard enough to stretch you, not hard enough to stall you.

/relay level: apprentice|builder|engineerSet intensity at any time
/relay hints: on|offToggle hints on handoff cards
/relay do itClaude takes over the current handoff
/relay logWhat Claude did vs what you did this session
/relay off | onPause or resume Relay
$npx skills add kene-praise/relay
04Using them together

Butler and Relay are independent but designed to work in the same session. Relay decides who does what. Butler logs the decisions behind everything Claude does, including every handoff it gave you and every /relay do it call you made.

At the end of a session, butler log gives you Claude's decision record. /relay loggives you yours: a ledger of what you built versus what you handed back. Together they create something more useful than either alone: an honest account of where your confidence is growing and where you're still leaning on the senior engineer.

This portfolio is the case study. A real account of a designer learning to build, not a curated highlight reel.

The pattern underneath both:Both tools are scaffolding. They don't build anything themselves. They make the building process legible. That's a design instinct applied to a development workflow, and it's probably the most honest answer I have to the question of what kind of engineer I'm becoming.

$npx skills add kene-praise/butler
$npx skills add kene-praise/relay
Claude SkillsDesign EngineeringDeveloper ToolsLearning in PublicClaude Code

A portfolio should not be a scaffold for work. The work starts from the portfolio.

Overheard somewherea thought while you wait