Verwendung
- Installationsbefehl kopieren und das Quellpaket vor der Installation in der eigenen Agentenumgebung prüfen.
- Benötigte Werkzeuge, Zugangsdaten und Hosts im Original prüfen.
- Eingabe und gewünschtes Ergebnis beschreiben und die Ausgabe mit den Quellen abgleichen.
npx skills add https://github.com/bryantleft/bruhs-skills --skill bruhsVor dem Start
- Die Installation umfasst weder Modellabo noch API-Kontingent oder Dateizugriffsrechte.
- Sterne und Installationen zeigen Aktivität, keine unabhängige Qualitäts- oder Sicherheitsprüfung.
Aus dem Quell-Repository gerendert; Überschriften, Beispiele, Code, Tabellen, Links und Bilder bleiben erhalten.
bruhs
Index
|commands|spawn,claim,cook,verify,yeet,walk,land,peep,dip,slop,doodle,deepen,drill,recap |practices|engineering-principles,type-driven-design,architecture-deepening,testing-infrastructure,source-ground-truth,_common,writing,design-docs,pr-review,typescript-react,typescript-hono,python,python-fastapi,effect-ts,effect-,rust,rust-,ui-design,design-engineering |config|CLAUDE.md + AGENTS.md (bruhs:state and bruhs:rules blocks)
Commands Quick Reference
|spawn|Create project or add to monorepo|commands/spawn.md |claim|Initialize config for existing project|commands/claim.md |cook|Plan + Build feature end-to-end|commands/cook.md |verify|Prove a claim with falsifiable evidence (VERIFIED/NOT VERIFIED/INCONCLUSIVE)|commands/verify.md |yeet|Ship: Linear ticket → Branch → Commit → PR|commands/yeet.md |walk|Generate reviewer walkthrough (markdown or interactive HTML canvas)|commands/walk.md |land|Watch PR checks and iterate on CI failures until green|commands/land.md |peep|Address PR review comments, or self-review with linked context, evidence gates and a ship verdict, then merge|commands/peep.md |dip|Clean up after merge, switch to base branch|commands/dip.md |slop|Deep codebase analysis, AI slop cleanup (--quick for branch-diff only)|commands/slop.md |doodle|Visualize architecture as tldraw diagrams (PRs, modules, deps, compare, map, freeform)|commands/doodle.md |deepen|Find shallow modules, propose architectural deepenings (explore → candidates → grill)|commands/deepen.md |drill|Find missing/weak test-infra layers, propose adoptions (explore → candidates → grill)|commands/drill.md |recap|Status update from git log over a time window (bugfix/tech-debt/net-new)|commands/recap.md
Lifecycle Map
Commands compose into an end-to-end loop. Typical flow:
spawn / claim → project setup
↓
cook <feature> → plan + build
↓
verify <claim> → prove the behavior changed (recommended for fixes)
↓
slop --quick → clean up branch-diff slop before shipping
↓
yeet → Linear ticket + branch + commit + PR
↓
walk --post → reviewer walkthrough comment (large PRs)
↓
land → watch CI to green
↓
peep → address review comments (compose with land via --land)
↓
dip → post-merge cleanupOut-of-band, any time:
slop— deep codebase auditdoodle/deepen/drill— structural / test-infra investigationrecap— status update for standup or retro
Invocation
/bruhs→ Interactive menu (AskUserQuestion)/bruhs:<command>→ Direct to command/bruhs:cook <feature>or/bruhs:cook TICKET-123→ With argument/bruhs:verify [claim | PR#] [--keep-artifacts]→ Falsifiable verification/bruhs:walk [PR#] [--canvas|--post|--commit-body]→ Reviewer walkthrough/bruhs:land [PR#] [--no-fix|--max-iterations N]→ Watch CI to green/bruhs:peep [PR# | TICKET] [--land|--resolve-conflicts]→ Address review comments/bruhs:slop [path] [--quick|--fix|--report] [--severity ...]→ Codebase analysis/bruhs:doodle <mode> [args] [--out|--gist|--commit|--pr-comment|--format|--depth]→ Render diagram (modes: pr, module, deps, dependents, compare, map, freeform)/bruhs:deepen [path | module-name] [--no-explore]→ Find shallow modules, propose deepenings/bruhs:drill [path | layer-name] [--no-explore]→ Find missing/weak test-infra layers, propose adoptions/bruhs:recap [window] [--all-authors|--linear|--branch <name>]→ Status update from git log
Engineering Doctrine
Every command uses this shared vocabulary:
| Term | Meaning |
|---|---|
| Landmine | A harmless-looking decision that creates a delayed failure |
| Receipt | Inspectable evidence or reasoning behind a decision |
| Tripwire | An executable guardrail that fails actionably when an assumption breaks |
| Simple | Logic that decomposes naturally and removes complexity |
| Obvious | Code whose purpose, state, errors, and next change are visible in one pass |
The governing rules:
- Think from first principles. Preserve invariants and user outcomes, not accidental complexity.
- No receipt, no operational number. Timeouts, retries, memory budgets, concurrency limits, queue bounds, cache sizes, and similar values must be derived from measurements, quotas, capacity math, research, incidents, contracts, or an explicit user requirement.
- Fail loudly and actionably. State what failed, why, which assumption or limit was violated, and what fixes it. Degraded behavior must be explicit and observable.
- Turn assumptions into tripwires. Comments describe; validation, constraints, exhaustive handling, assertions, and CI enforce.
- Understand before optimizing. Remove unnecessary work and pathological shapes first; measure when an optimization introduces a real trade-off.
- Prefer obvious over clever. Use direct control flow, narrow interfaces, explicit state, and domain language.
- Minimize hidden state. Make mutation, caching, retries, fallbacks, I/O, and lifecycle ownership visible.
- Design for maintenance. Delete obsolete code. Add abstractions only when they centralize an invariant, remove duplication, or hide real complexity.
Read practices/engineering-principles.md before planning, implementing, reviewing, or verifying. It wins when another practice conflicts with it.
Type-Driven Design
A function's type signature should tell you everything about what it does.
Priority Hierarchy (fix in this order)
- Missing/wrong type signatures - Types ARE documentation
- Hidden side effects - Signature lies about behavior
- any types - Type system disabled
- ! or as on external data - Compiler trust violated
- Fast-path violations -
awaitin loops, N+1 queries, sync-in-async, per-request client construction (see Performance below) - Other implementation issues - Secondary to type correctness
Checklist
Signatures:
- [ ] Explicit return types on public functions
- [ ] No any - use unknown + validation
- [ ] No ! - handle null explicitly
- [ ] No as for external data - validate instead
- [ ] Errors in return type, not thrown silently
- [ ] readonly parameters signal no mutation
- [ ] Discriminated unions for state (not multiple booleans)
Errors:
- [ ] Errors visible in return type (Result<T,E> or union)
- [ ] Typed errors, not strings
- [ ] Handle at call site, not deferred
- [ ] No empty catch blocks
Immutability:
- [ ] Prefer const over let
- [ ] Don't mutate parameters
- [ ] Return new objects instead of mutating
Patterns
// ❌ Signature hides truth
function getUser(id: string): User // might throw, might be null
// ✅ Signature tells full story
function getUser(id: string): Promise<Result<User, NotFoundError | NetworkError>>
// ❌ Multiple booleans = impossible states
type State = { isLoading: boolean; isError: boolean; data: User | null }
// ✅ Discriminated union = only valid states
type State =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: User }
| { status: 'error'; error: Error }For full patterns → practices/type-driven-design.md
Architectural Deepening
A deep module hides a lot of behaviour behind a small interface. A shallow module's interface is nearly as complex as its implementation.
Use the /bruhs:deepen command to find shallow modules and propose deepenings. Distinct from /bruhs:slop (line-level audit) — this is structural.
Vocabulary (use these terms exactly)
| Term | Meaning |
|---|---|
| Module | Anything with an interface and an implementation (function, class, package, slice) |
| Interface | Everything a caller must know — types, invariants, ordering, errors, configuration |
| Depth | Behaviour-per-unit-of-interface. Deep = lots of behaviour behind a small interface |
| Seam | A place where you can alter behaviour without editing in that place (Feathers) |
| Adapter | A concrete thing that satisfies an interface at a seam |
| Leverage | Caller-side benefit of depth — capability per unit of interface learned |
| Locality | Maintainer-side benefit — change/bugs/tests concentrate in one place |
Core principles
- Depth is a property of the interface, not the implementation. Internal seams are fine; don't expose them.
- The deletion test. Imagine deleting the module. If complexity vanishes → pass-through, merge it. If it scatters across N callers → the module earns its keep.
- The interface is the test surface. If you want to test past it, the module is the wrong shape.
- One adapter means a hypothetical seam. Two adapters means a real one. Don't add a port for a single implementation.
When to invoke /bruhs:deepen
- A codebase feels like it bounces between many small files for one operation
- Tests feel like they're testing the wrong thing (mocks everywhere, brittle to refactors)
- Callers must learn implementation details (transport, encoding, storage) to use a "domain" module
- Same invariant repeats across N call sites
- During
/bruhs:slopyou keep flagging "architecture" — promote to/bruhs:deepenfor structural treatment
For full glossary, dependency categories, seam discipline, design-it-twice mechanics → practices/architecture-deepening.md
Testing Infrastructure
A test suite is a layered safety net. Each layer catches a different bug class. A missing layer isn't covered by the others — it's just where bugs ship from.
Use the /bruhs:drill command to find missing or weak layers and propose adoption plans. Companion to /bruhs:deepen: deepen modules, drill tests.
The 8 layers
| # | Layer | Catches |
|---|---|---|
| 1 | Acceptance specs | Intent drift — no executable definition of "done" |
| 2 | Unit tests | Regressions in module behaviour at the interface |
| 3 | Coverage gate | Untested code landing (measured on changed lines per PR, not total) |
| 4 | Mutation runner | Tests that exist but assert nothing meaningful — the kill ratio is the only number that proves coverage is doing work |
| 5 | Complexity composite | High-complexity / low-coverage hotspots (the worst-of-both — Savoia's "CRAP") |
| 6 | Architecture checker | Layer / dependency rule violations — encodes ADRs so they're enforced, not just documented |
| 7 | Test-code linter | Rot in test files themselves; AI-generated test code becoming a second untyped codebase |
| 8 | CI orchestrator | Discipline collapse — runs every layer as hard gates. The 8th is load-bearing |
Core principles
- Hard gate, advisory, or ratchet — pick one, defend it. Indefinite advisory is decoration. Ratchet ("no worse than baseline") is honest about legacy debt and locks in improvement.
- The orchestrator is load-bearing. Layers 1–7 without a real CI gate are theatre.
continue-on-error: trueon a gated layer is advisory regardless of what the config claims. - Replace, don't layer. Old advisory checks become waste once a hard gate exists. Old shallow-module tests become waste once the deeper module's interface is tested. Delete; don't preserve out of guilt.
- The "what would slip through" test. Don't propose adopting a layer unless you can name a concrete bug class it catches in this codebase.
When to invoke /bruhs:drill
- Tests pass but bugs still ship — the suite isn't catching what it claims to catch
- Coverage is high but feels meaningless (no mutation kill ratio measured)
- ADRs exist but get violated; "clean architecture" decisions erode unenforced
- AI-generated test files are accumulating without review
- CI is green; the build still feels unreliable — likely an advisory orchestrator
- During
/bruhs:slopyou keep flagging "no test for X" — promote to/bruhs:drillfor safety-net treatment
For full layer specs, diagnostics, gating posture, rejected framings → practices/testing-infrastructure.md
Common Rules
Naming
| Type | Convention | Example |
|---|---|---|
| Components | PascalCase | UserCard.tsx |
| Hooks | camelCase + use | useAuth.ts |
| Utilities | camelCase | formatDate.ts |
| Constants | SCREAMING_SNAKE | MAX_RETRIES |
| Booleans | is/has/can/should | isLoading, hasPermission |
| Functions | verb + noun | getUser, createOrder |
| Handlers | handle/on prefix | handleSubmit, onUserClick |
Code Organization
- Functions do ONE thing
- If you need comments to separate sections → extract functions
- Treat length as a signal, not a rule. Split only when doing so makes responsibilities and state more obvious.
- Do not introduce line-count limits without a repository-specific receipt.
Error Handling
- Specific messages:
User "${id}" not foundnotSomething went wrong - Validate at boundaries, trust internal code
- Never swallow errors (empty catch blocks)
Git
<type>: <description>
Fixes TICKET-123
Assisted-by: Claude:claude-opus-5-5Types: feat|fix|refactor|chore|docs|test
Every agent-written commit (including land/peep/doodle fixups) carries Assisted-by: <Agent>:<model-id> with the running model, never Co-Authored-By. Details → practices/_common.md → AI Attribution.
Branch: <type>/<ticket-id>-<short-description>
Stacked PRs → commands/yeet.md → Stacked PRs.
Comments
- ✅ WHY (business logic, workarounds, non-obvious decisions)
- ❌ WHAT (code already says what it does)
- ❌ Commented-out code
- ❌ TODO without ticket reference
- ❌ Plan IDs, people, line numbers (provenance goes in the commit or PR body)
Writing
Anything a person reads (PR bodies, tickets, review replies, commits, recaps): fewest words that keep the meaning, point first, lowercase in chat and sentence case in documents, no AI text tells. Scan practices/writing.md before sending.
Design docs: 1–3 pages, the problem explained cold with evidence, one labelled diagram, only hard-to-reverse decisions. Shape and gates → practices/design-docs.md.
External Searches
Always include current year in WebSearch queries for fresh results.
For full guidelines → practices/_common.md
Performance (Fast-Path-By-Default)
Pick the fast path by default. You don't need a benchmark to avoid an anti-pattern.
Philosophy
- Correctness first, but equivalent-correctness patterns are not equivalent. When two patterns solve the same problem, pick the faster one — even without a measurement.
- Obvious perf wins don't require benchmarks. N+1 queries,
awaitin a loop, sync I/O on the event loop, per-request client construction — these are anti-patterns, not "premature optimization." - Measure when the tradeoff is real (readability cost, complexity cost, risk of regression). Don't measure to justify avoiding an anti-pattern.
- Measure at boundaries, not inside — p50/p95/p99 at ingress/egress; internal timers lie about contention.
- Operational bounds need receipts. Never copy a concurrency, timeout, retry, or cache value from these examples into production without deriving it from the real system.
Universal Defaults
- Batch at boundaries. One round-trip of N beats N round-trips (DB, HTTP, IPC, GPU, syscalls).
- Stream, don't buffer. Start bytes moving before you have them all — SSR, JSON, file I/O, LLM tokens.
- Don't block the hot loop. Event loop, render thread, request handler — push CPU off, I/O async, never sync-in-async.
- Colocate data with consumer. Query next to its route, fetch next to its RSC, cache next to its reader.
- Built-ins beat rewrites.
Array.prototype,itertools,std::collections, platformfetch. - Bound concurrency on user input.
p-limit,asyncio.Semaphore,buffer_unordered(n)— unboundedPromise.allover user data is a DoS. - Singleton clients. Never
new Client()per request — it defeats connection pooling.
LLM-Common Traps (flag these in review)
awaitin aforloop over independent items →Promise.all/gather/join!.map().filter().reduce()chains over large arrays → one pass or lazy iterator- N+1 ORM access in "clean" code → eager/join loading
useMemo/useCallbacksprinkled without a measured re-render problemJSON.parse(JSON.stringify(x))for deep clone →structuredCloneor targeted copy- Unbounded
Promise.all/ recursion over user input → clamp concurrency - Sync hashing/crypto in request path → worker / threadpool
- Per-request client construction (
new PrismaClient,httpx.AsyncClient(),reqwest::Client::new()) → singleton - Full-body logging in hot paths → structured log fields
- Parsing config / reading env per request → load once at boot
Per-stack performance patterns → practices/<stack>.md (Performance section in each)
Source as Ground Truth
Code is the best ground truth over docs.
Whenever the work touches a third-party package, repo, or dependency, resolve its real behavior from the installed source, not from training memory or docs that may have drifted. Docs orient; the source decides. When they disagree, the version in the lockfile wins.
Use `opensrc` to pull a package's source on demand:
npm install -g opensrc
rg "parse" $(opensrc path zod) # search the real implementation
cat $(opensrc path zod)/src/types.ts # read a specific file
find $(opensrc path pypi:requests) -name "*.py" # non-npm via pypi: prefixReach for it before citing an API you're unsure of, when docs are thin or contradict behavior, when an error points into a dependency, or when a review finding hinges on what a library actually does. Reading source is not running it — execute untrusted / AI-generated code in a sandbox, never your host (see Config → stack sandboxing).
For full guidance (version-matching, context7-vs-source, fallbacks) → practices/source-ground-truth.md
Command Details
Each command's full workflow lives in its own file. Read the specific file when executing that command:
| Command | File |
|---|---|
| cook | commands/cook.md |
| verify | commands/verify.md |
| yeet | commands/yeet.md |
| walk | commands/walk.md |
| land | commands/land.md |
| peep | commands/peep.md |
| dip | commands/dip.md |
| spawn | commands/spawn.md |
| claim | commands/claim.md |
| slop | commands/slop.md |
| doodle | commands/doodle.md |
| deepen | commands/deepen.md |
| drill | commands/drill.md |
| recap | commands/recap.md |
Interactive Menu
When /bruhs is invoked without arguments, present the command list via AskUserQuestion and route to the selected command's file. Options: spawn, claim, cook, yeet, peep, doodle, dip, deepen, drill. slop is intentionally excluded from the menu — invoke directly with /bruhs:slop.
Config Reference
Project state lives in two marker-bounded blocks inside CLAUDE.md and AGENTS.md (mirrored). The model reads them every session — no separate config file to keep in sync. Hand-written rules live outside the blocks and are never touched.
Block 1 — bruhs:state (auto-maintained JSON)
<!-- bruhs:state:begin v1 -->
<!-- AUTO-MAINTAINED BY /bruhs. Edits inside this block will be overwritten. -->
### Project State (managed by /bruhs)
{ "integrations": { "linear": { "mcpServer": "linear-<workspace>", "team": "<team-id>", "teamName": "Team Name", "project": "<project-id>", "projectName": "Project Name", "labels": { "feat": "Feature", "fix": "Bug", "chore": "Chore", "refactor": "Improvement" } } }, "tooling": { "mcps": ["linear", "notion", "context7"], "skills": ["superpowers", "shadcn", "vercel-react-best-practices"] }, "stack": { "structure": "single|monorepo", "framework": "nextjs|tanstack-start|astro|hono|...", "styling": ["tailwind", "shadcn"], "database": ["drizzle-postgres", "convex", "..."], "auth": "better-auth|clerk|...", "gpu": ["modal", "runpod", "lambda"] } }
<!-- bruhs:state:end -->Block 2 — bruhs:rules (stack-derived behavioral rules)
<!-- bruhs:rules:begin v1 -->
<!-- AUTO-MAINTAINED BY /bruhs. Stack-specific rules derived from detected stack. -->
### Stack-Specific Rules (managed by /bruhs)
#### Convex
- Convex actions that import the `ai` SDK MUST live in a file whose first line is `'use node'`.
- ...
<!-- bruhs:rules:end -->Rules are derived from the detected stack via scripts/derive_stack_rules.py — short, high-signal, and only stack-specific. Universal behavioral rules (the kind that map to your failure modes) should be hand-written by you, outside the bruhs blocks.
Scripts
| Script | Purpose |
|---|---|
scripts/sync_bruhs_block.py | Atomically write a bruhs:state or bruhs:rules block into CLAUDE.md + AGENTS.md. |
scripts/read_bruhs_block.py | Read the JSON state (or rules markdown) back out. Falls back to legacy .claude/bruhs.json for --kind state during the transition. |
scripts/derive_stack_rules.py | Given state JSON on stdin, emit the markdown rules body to pipe into sync_bruhs_block.py --kind rules. |
Migration from .claude/bruhs.json
Legacy .claude/bruhs.json is still read by read_bruhs_block.py as a fallback. /bruhs:claim detects the legacy file and offers to port it into the marker blocks, then prompts before deleting the old file.
Linear MCP
Tool format: mcp__<mcpServer>__linear_<method>
Common tools:
| Tool | Purpose |
|---|---|
linear_get_teams | List teams (includes labels) |
linear_get_user | Current user (for assigneeId) |
linear_create_issue | Create ticket |
linear_edit_issue | Update status |
linear_get_issue | Fetch ticket by ID |
Multi-workspace: Each project's bruhs:state block points to its Linear workspace via mcpServer.
Example:
// Load the tool
ToolSearch(`select:mcp__${config.integrations.linear.mcpServer}__linear_create_issue`)
// Create issue
const issue = call(`mcp__linear-sonner__linear_create_issue`, {
title: "Add leaderboard",
teamId: config.integrations.linear.team,
projectId: config.integrations.linear.project,
assigneeId: user.viewer.id,
labelIds: [labelId]
})
// Use Linear's generated branch name
const branchName = issue.gitBranchName // "sonner-140-add-leaderboard"


