↓ Skip to main content
  1. posts/

How my Claude Code workflow kit works

··Index: 9·View as Markdown·

I use Claude Code agents in several repositories: this site, the home automation setup, client projects and a few small tools. Each of them used to have its own CLAUDE.md, rules and habits. Whatever I taught the agents in one project never reached the others. To change that I moved all of it into one repository, claude-workflow-kit, and all my projects plug into it now.

It’s private for now, but most of the ideas are easy to copy.

Modules and one profile per project
#

The kit is split into modules. A module brings rules (Markdown files the agents read), skills, agent definitions, hooks and sometimes an MCP server. core is always on, and a project adds the others it needs: board to track tasks on GitHub Projects, dotnet to work on C# with a Roslyn-based code navigator, desktop-tests for tests that open windows on my machine, file-safety for code that touches data outside the repository, and a few more.

The kit repository holds modules; a project selects some of them, and kit.py links them into the project's .claude folder, while the project's CLAUDE.md profile narrows the rulesclaude-workflow-kitcorerules, agents, guards, skillsboarddotnetdocsfile-safetydesktop-testsupstreamagencybin/kit.pyinit, sync, check, update, boardsubmoduleand linksor pluginsa project.claude/kit.jsonmodules, push targets, guard config.claude/rules, skills, agentslinks into the kit, not copies,recreated by syncCLAUDE.mdProfile: checks, default branch,risky paths, push targetsInvariants, Overrides.claude/board/board.jsonGitHub project, fields, areasserved by the board MCP server
The kit holds the modules, the project holds its profile

Nothing gets copied. The kit sits inside projects as a git submodule, kit.py sync links the chosen rules, skills and agents into .claude/, and a change in the kit reaches all projects after kit.py update. A newer plugin mode makes modules Claude Code plugins. A hook at session start checks GitHub for a newer version of the kit and tells the agent to update before doing anything else.

Whatever differs between projects goes into a ## Profile table in the project’s CLAUDE.md. It says how to run the checks and what counts as a pass, names the default branch and the risky paths, and lists where pushes may go and which kinds of change need my approval. Next to it sits ## Invariants, a short list of things that must always hold, each with the check that proves it. Projects may narrow kit rules, but to deviate from one I have to write it down under ## Overrides with a reason, and kit.py check verifies that.

The board is the task list
#

With the board module, tasks are GitHub issues on a Projects board. The body of an issue is the contract: scope, what’s out of scope, test mode, acceptance checks, the exact commands to verify it and the dependencies. An issue moves to Todo when that checklist passes. Other moves between statuses have guards you can observe, which beats a feeling that the work looks done.

One task in the workflow kit: an issue goes from Todo through claim, a worker in its own worktree, checks, a handoff and an independent review to a merge by the coordinatorownercoordinatorworkerreviewerwrites or answersan issue on the boardapproves the pusha push deploysReady checkscope, tests, acceptanceclaim_taskbranch task/N = the lockreview statusmerged, verified, remainingmerge --no-ffchecks again on mainwork in a worktreecommits on task/Nnever pushesrun the checkseach result namesthe tested commithandoff blockrejected without SHAor evidencefresh agent, read-onlysees only the contract, the diff, the checks and the handofffindings or ok
One task, from the board to a merge

Claiming a task creates the branch task/<n>, and that branch is the lock. Labels and assignees can’t do this job because all my agents post as the same GitHub account. Workers do their job in separate git worktrees and stop after they commit there. Merging and pushing is left to the coordinator session, and it waits for me to say so.

A finished worker posts a handoff block. The board server rejects it if the passing checks don’t name the commit they tested, or if “done” items come without evidence. A check that didn’t run gets written down as not run with a reason, never as a pass.

GitHub sends no webhooks for projects owned by user accounts, so a small watcher polls the board without any model and prints one line per event. A cheap model reads the issue and sums up what I asked for, then the coordinator decides what to do about it.

Cheap models first, then a second pair of eyes
#

When I start a subagent I pick the cheapest model that can do the job, and I set it explicitly on every call. Haiku gets mechanical work like counts, renames and collecting command output. Sonnet gets ordinary implementation with clear checks. Opus gets changes where mistakes cost money, data or access, and judgement (specs, design options, audits) goes to Fable.

Checks measure but they don’t judge, so code changes also go through an independent review. Reviewers are fresh agents that see the contract, the diff, the check results and the handoff, never the implementer’s reasoning, and they can’t edit anything. Docs get no review, code gets a Sonnet reviewer by default, and risky paths or anything that needs my approval get Opus.

Guards
#

Rules are text, and agents ignore text now and then, so the most important rules are hooks as well. A push guard lets git push and GitHub writes through only for repositories on the project’s list. It blocks all writes to repositories marked as mine only and refuses edits to the guard files themselves. Agents are told not to probe the guards, and to stop and report when one blocks something legitimate.

The rest of core covers how agents talk and plan. They chat with me in Polish, but issues, rules and handoffs are in plain English with one fact or instruction per sentence. Labels such as FACT, ASSUMPTION or DECISION mark places where later readers could be misled (a loose borrowing from Simplified Technical English and SDL state machines). One skill looks up earlier solutions before the first edit and folds lessons back into how-to notes afterwards. One rule says tests must never steal window focus from me, and a sampler proves it during full test runs.

What it looks like in practice
#

This site runs on a copy of the kit (wiring it in as a submodule is still on the board), and so does my TV dashboard, where most screens went from spec to merged branch through this loop. Right now I’m building a dispatcher, a cheap process that runs all the time, polls the board and the issue trackers, and starts a model only when something happens, with limits on time and money for each run.

Related