---
title: "How my Claude Code workflow kit works"
description: "One repository of rules, agents, guards and a GitHub board server that all my projects plug into, so Claude Code agents work the same way in each of them."
date: 2026-10-16T12:00:00+02:00
lastmod: 2026-11-03T00:52:19+01:00
url: https://klimek.link/posts/claude-workflow-kit/
author: "Marcin Klimek"
source: https://klimek.link/posts/claude-workflow-kit/
---

# How my Claude Code workflow kit works

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.

*Diagram: 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.

*Diagram: 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](/projects/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.

Source: https://klimek.link/posts/claude-workflow-kit/
