Documentation

Complete guide to setting up and using the CUITE framework.

Prerequisites

Before installing CUITE, make sure you have the following tools available on your system:

Installation

Run the one-liner from your project root:

curl -fsSL https://cuite.quest/install.sh | bash

Or do it manually:

cd /path/to/your-project
git clone https://github.com/fentas/cuite.git /tmp/cuite
/tmp/cuite/bin/cuite init
rm -rf /tmp/cuite

Both methods do the same thing: clone cuite to a temp directory, run cuite init (which uses git subtree add to embed the framework at .claude/cuite/), and clean up.

Here is what the init command does under the hood:

  1. Adds a git remote named cuite pointing to the CUITE repository.
  2. Creates the subtree at .claude/cuite/ using git subtree add.
  3. Sets up symlinks so Claude Code can find hooks, commands, and agent definitions in the locations it expects (directly under .claude/).
  4. Copies starter files such as CLAUDE.md, settings.json, and template domain files into your project root and .claude/ directory.
Note The installer never overwrites existing files. If you already have a CLAUDE.md or settings.json, CUITE will skip those files and let you merge manually.

direnv Setup (optional)

If you use direnv, you can add cuite to your PATH automatically:

.claude/cuite/bin/cuite envrc
direnv allow

This creates or updates your .envrc so you can run cuite directly instead of .claude/cuite/bin/cuite. The /cuite-init command will also offer to set this up for you.

First Run

After installation, open Claude Code in your project and run the initialization command:

/cuite-init

This command triggers a full project scan. Here is what happens:

  1. Language detection — scans file extensions, package manifests, and build files to identify the languages and frameworks used in your project.
  2. Sub-project discovery — looks for monorepo patterns, separate build roots, and isolated dependency trees.
  3. Domain proposal — based on the scan results, CUITE proposes a set of domains (e.g., backend, frontend, infra) and presents them for your approval.
  4. Configuration generation — on approval, generates domains.md, domain-map.conf, and starter expertise files for each domain under .claude/agents/experts/.
Tip You can re-run /cuite-init at any time. It will detect new sub-projects and propose additional domains without overwriting your existing configuration.

Hybrid Layout

CUITE uses a hybrid architecture combining a git subtree for the framework itself with symlinks that bridge into the locations Claude Code expects. Your project-specific files live outside the subtree and are never touched by framework updates.

project/
  CLAUDE.md                       # customized from template
  .claude/
    cuite/                        # git subtree (framework)
    hooks -> cuite/hooks          # symlink
    commands -> cuite/commands    # symlink
    agents/
      *.md -> cuite/agents/*.md   # symlinks
      templates -> cuite          # symlink
      experts/
        your-domain/              # YOUR files (never pushed)
    settings.json                 # YOUR file
    domains.md                    # YOUR file
    domain-map.conf               # YOUR file

The key insight is separation of concerns: the framework code travels via subtree, your domain expertise stays local, and symlinks make everything discoverable by Claude Code without any path hacks.

File Categories

Every file in the CUITE installation falls into one of three categories:

Category Location Updated By
Framework Inside .claude/cuite/ Updated by cuite pull
Project-specific .claude/ (real files) Updated by you
Symlinks .claude/.claude/cuite/ Refreshed by cuite link

This three-tier approach means you can pull framework updates without worrying about your settings, domains, or expertise files being overwritten. The subtree boundary acts as a clean firewall between framework code and project-specific configuration.

Why This Works

Each architectural concern maps to a specific solution:

Concern Solution
Push only framework code Subtree prefix isolates .claude/cuite/ from everything else
Claude Code finds hooks Symlinks bridge .claude/hooks.claude/cuite/hooks
Your settings stay yours Real files live outside the subtree at .claude/settings.json
Domain experts are yours Real directories under .claude/agents/experts/
Hooks resolve paths correctly All hook scripts use $PWD for path resolution

domains.md

The primary domain registry lives at .claude/domains.md. This file is the single source of truth for what domains exist in your project, what they contain, and how to work with them. Every ## heading in this file defines one domain.

Commands like /do, /do-teams, and /improve read this file first when deciding which domain to target. The file uses a structured markdown format:

## backend
- **Description**: Express API server
- **Keywords**: API, endpoint, route, middleware
- **Paths**: `src/api/`, `src/server/`
- **Language**: TypeScript
- **Build**: `npm run build`
- **Test**: `npm test`

Each field serves a specific purpose:

domain-map.conf

The domain map at .claude/domain-map.conf provides glob-to-domain mappings used by hooks for fast path-based domain resolution. This is the second lookup method after domains.md keywords.

Format: one mapping per line, pattern = domain.

src/api/* = backend
src/ui/* = frontend
.github/* = devops
infra/* = infrastructure
docs/* = documentation
*.proto = backend

Hooks use this file to determine which domain a file belongs to without parsing the full domains.md. This makes scope enforcement fast, even in large monorepos with hundreds of files.

Note Patterns use simple glob syntax. A single * matches within one directory level. To match deeply nested files, use patterns like src/api/**.

experts/ Directory

Each domain gets its own directory at .claude/agents/experts/{domain}/. This directory contains all the knowledge and agent definitions specific to that domain.

A fully populated domain directory contains:

These files are never pushed to the CUITE framework repository. They are your project-specific knowledge and stay entirely within your project.

Domain Discovery

When a command needs to determine which domain to target, CUITE uses a 4-step fallback chain:

  1. Read domains.md — match the task description against domain keywords and paths. This is the primary and most reliable method.
  2. Read domain-map.conf — match file path globs when the task references specific files. Fast and deterministic.
  3. Scan experts/ directory — check which domain directories exist and inspect their expertise.yaml for additional matching signals.
  4. Fallback — if no domain matches, use the generic build-agent for implementation tasks or ask the user to clarify.

This layered approach means CUITE can always find the right domain, even if your configuration is incomplete. The fallback chain degrades gracefully rather than failing.

Core Agents

CUITE ships with three core agents that handle cross-domain work. These are not tied to any specific domain and can operate on any part of the codebase.

Agent Access Purpose
build-agent Full (Read/Write/Edit/Bash) General-purpose implementation. Used as the fallback when no domain-specific agent matches.
scout-agent Read-only Codebase exploration and research. Reads files, searches patterns, maps dependencies. Cannot modify anything.
review-agent Read-only + Task Code review and quality gate. Analyzes implementations, checks for issues, and produces structured review reports.

Core agents are defined in .claude/agents/ as symlinks to their framework definitions in .claude/cuite/agents/. They receive the same expertise injection as domain agents when the hook can determine which domain is relevant.

Domain Agents

For each domain, CUITE creates four specialized agents. These agents are scoped to a single domain and receive that domain's expertise on every spawn.

Agent Role Description
{domain}-plan-agent Planner Read-only access. Analyzes the task, reads relevant code, and produces a detailed implementation spec. Does not write any code.
{domain}-build-agent Builder Full access. Takes the spec from the plan agent and implements it. Writes code, runs builds, executes tests.
{domain}-improve-agent Improver Read + Edit on expertise files only. Reviews what was built and learned, then updates tips.md and expertise.yaml.
{domain}-question-agent Answerer Read-only access. Answers questions about the domain using codebase context and expertise files. Fast and cheap.

Agent definitions live at .claude/agents/experts/{domain}/ and are generated from templates during /cuite-init. You can customize them freely — they are your project files.

Models & Access

Different agent types use different models based on their complexity requirements and cost profile:

Agent Type Model Access Level
plan-agent sonnet Read-only
build-agent sonnet Full (Read/Write/Edit/Bash)
improve-agent sonnet Read + Edit expertise files
question-agent haiku (fast, cheap) Read-only
Team leads opus (when needed) Can use opus for complex orchestration

The model selection is intentional: sonnet provides the best balance of capability and cost for most work, haiku keeps question-answering cheap and fast, and opus is reserved for complex multi-domain orchestration where the additional reasoning capability justifies the cost.

/do — Single Domain

The /do command is the primary workflow for single-domain tasks. It routes your task to the appropriate domain and orchestrates a plan-build-review-improve cycle.

/do operates in three patterns depending on the nature of the task:

Pattern A: Implementation

For tasks that require writing or modifying code. This is the full cycle.

plan-agent → spec ↓ User: "Proceed?" → [Yes] / [No] ↓ build-agent → implementation ↓ review-agent → quality report + suggestions ↓ User: "Apply suggestions?" → [Yes] / [Skip] ↓ improve-agent → updates expertise

The user has two decision points: approving the plan before implementation begins, and acknowledging the review suggestions before expertise updates. This keeps you in control while the agents do the heavy lifting.

Pattern B: Question

For tasks that are questions about the codebase rather than implementation requests. The question-agent answers directly using domain expertise and codebase context. No build or review cycle is needed.

Pattern C: Simple

For tasks like running linters, formatting code, or validating configurations. The build-agent executes the task directly without a plan or review phase. These are one-shot operations.

/do-teams — Parallel Teams

The /do-teams command spawns multiple domain specialists to work in parallel. This is the workflow for tasks that span multiple domains or require coordinated changes across the codebase.

Experimental Agent teams require the CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 environment variable. This is a Claude Code experimental feature.

/do-teams operates in two patterns:

Implementation

Spawns domain specialists who each own a set of files, work in parallel, and coordinate through a shared task list.

TeamCreate → initialize team workspace ↓ TaskCreate → break work into domain-scoped tasks ↓ Spawn specialists → one per domain ↓ [domain-a-build] [domain-b-build] [domain-c-build] ↓ ↓ ↓ ↓↓↓ work in parallel ↓↓↓ ↓ Shut down specialistsreview-agent → cross-domain quality check ↓ improve-agent → updates expertise per domain ↓ TeamDelete → clean up team workspace

File ownership is enforced during parallel work: each specialist can only modify files within their domain's paths. This prevents merge conflicts and ensures clean boundaries.

Council

Spawns domain analysts for independent review. Each analyst examines the task from their domain's perspective and provides an assessment. No code is written — the output is a multi-perspective analysis.

/improve — Maintenance

The /improve command is a standalone expertise update workflow. It reviews recent work and updates domain knowledge without building anything new.

When you run /improve:

  1. Reviews git log for recent changes.
  2. Maps changed files to domains using domain-map.conf.
  3. Spawns an improve-agent for each affected domain.
  4. Each improve-agent reviews the changes and updates tips.md and expertise.yaml with any new knowledge.

You can also target a specific domain: /improve backend will only update the backend domain's expertise.

Tip Run /improve after significant manual changes or after merging a large PR. It ensures your domain expertise stays current with the actual state of the code.

The Flywheel

CUITE is designed around a self-improvement loop. Every build cycle feeds back into the expertise system, making subsequent agent spawns smarter and more effective.

You work on code → hooks track touched domains → /do runs review-agent after builds → review suggests expertise improvements → user acknowledges → improve-agent updates expertise → next agent spawn gets better knowledge → agents make better decisions → repeat

The flywheel accelerates over time. Early sessions produce generic expertise. After a few cycles, your agents know your project's specific patterns, conventions, pitfalls, and non-obvious behaviors. The expertise compounds with each iteration.

tips.md vs expertise.yaml

CUITE maintains two levels of domain knowledge. Each serves a different purpose in the injection pipeline:

Aspect tips.md expertise.yaml
Format Markdown bullet points Structured YAML
Injection order Injected first (fast context) Injected second (full context)
Size Compact, typically under 50 lines Comprehensive, can be hundreds of lines
Content Operational facts, gotchas, exact commands Patterns, anti-patterns, architectural decisions, critical paths
Update frequency Updated frequently as new facts are discovered Updated after significant changes or reviews
Analogy Sticky notes on your monitor The team wiki page

The two-tier approach ensures agents get the most critical information first (tips.md loads fast and fits in early context), with deep knowledge available when needed (expertise.yaml provides full context for complex decisions).

Expertise Injection

The inject-expertise.sh hook runs on every SubagentStart event. When Claude Code spawns a sub-agent, this hook intercepts the spawn and enriches it with domain knowledge.

The injection process:

  1. Match agent to domain — the hook extracts the domain name from the agent name (e.g., backend-build-agentbackend).
  2. Load tips.md — injected first as fast context. These are the operational facts the agent needs immediately.
  3. Load expertise.yaml — injected second as comprehensive context. Contains patterns, anti-patterns, and deep domain knowledge.
  4. Inject into agent prompt — the knowledge is prepended to the agent's system instructions so it is available from the first token.

This happens transparently. You do not need to manually pass context to agents. The hook system handles it automatically, and agents arrive at their tasks already knowing your project's conventions and gotchas.

Hooks Overview

CUITE ships with six hooks that enforce security boundaries, track domain activity, and inject expertise. Hooks run automatically on specific Claude Code lifecycle events.

Hook When What It Does
scope-enforcement.sh PreToolUse Enforces project boundaries, gates network egress against domain whitelist, triggers supply chain verification for new packages.
validate-intent.sh PostToolUse Runs syntax checks on edited shell scripts. Catches broken shell before it gets committed.
detect-injection.sh PostToolUse Scans content fetched via WebFetch for prompt injection patterns. Flags suspicious content and blocks malicious domains.
track-learnings.sh PostToolUse Records which domains were touched during the session. Used by /improve to know which domains need expertise updates.
inject-expertise.sh SubagentStart Matches spawned agent to domain and injects tips.md and expertise.yaml into the agent's context.
session-context.sh SessionStart Reports active domains, recent activity, and blacklist status at the beginning of each session.

All hooks are shell scripts located at .claude/cuite/hooks/ and symlinked to .claude/hooks/. They are registered in .claude/settings.json.

Supply Chain Verification

When CUITE hooks detect that an agent is installing a new package (via npm, pip, cargo, go get, or similar), the scope-enforcement.sh hook prints a SUPPLY_CHAIN_CHECK marker.

This marker instructs Claude to:

  1. Pause the installation — do not proceed until verification is complete.
  2. Fetch registry metadata — use WebFetch to check the package registry (npm, PyPI, crates.io, etc.) and confirm the package exists, the version is valid, and the publisher is legitimate.
  3. Verify the package — check download counts, publication date, maintainer identity, and look for signs of typosquatting or malicious packages.
  4. Proceed or block — only install the package after verification passes. If anything looks suspicious, block the install and notify the user.
Important Never guess version numbers. Hallucinated versions can resolve to malicious packages published by attackers who squat on plausible version strings. Always verify against the registry.

Network Egress

All network calls made by agents (via WebFetch or Bash commands that access the network) are gated against a domain whitelist defined in .claude/settings.json.

The whitelist controls which external domains agents can access. Requests to domains not on the whitelist are blocked by the scope-enforcement.sh hook. This prevents agents from:

To add a domain to the whitelist, update the relevant section in .claude/settings.json. The whitelist is project-specific and never overwritten by framework updates.

Prompt Injection Detection

After every WebFetch operation, the detect-injection.sh hook instructs Claude to review the fetched content for prompt injection red flags. This includes:

When suspicious content is detected:

  1. The domain is added to .claude/.cache/blocked-domains.txt.
  2. The user is notified about the suspicious content.
  3. Future requests to that domain are blocked automatically.

This defense layer is especially important when agents fetch documentation, READMEs, or API responses from the internet, where an attacker could embed injection payloads.

Adding a New Domain

You can add a new domain to your CUITE installation either manually or by re-running /cuite-init.

Manual Setup

  1. Create the directory:
    mkdir -p .claude/agents/experts/my-domain/
  2. Create expertise.yaml with your domain knowledge. Start with the most important patterns and anti-patterns.
  3. Create tips.md with quick operational facts — exact commands, environment variables, gotchas.
  4. Copy the 4 agent templates from .claude/agents/templates/ and rename them with your domain prefix:
    cp .claude/agents/templates/*-plan-agent.md .claude/agents/experts/my-domain/my-domain-plan-agent.md
    cp .claude/agents/templates/*-build-agent.md .claude/agents/experts/my-domain/my-domain-build-agent.md
    cp .claude/agents/templates/*-improve-agent.md .claude/agents/experts/my-domain/my-domain-improve-agent.md
    cp .claude/agents/templates/*-question-agent.md .claude/agents/experts/my-domain/my-domain-question-agent.md
  5. Add to domains.md with a new ## my-domain section containing description, keywords, paths, language, build, and test commands.
  6. Add path mappings to domain-map.conf so hooks can resolve files to your new domain.

Automatic Setup

Run /cuite-init again. It will detect new sub-projects and propose additional domains. Existing domains are preserved.

Writing Good Expertise

The quality of your expertise files directly determines how effective your agents are. Prioritize information that is hard-won, non-obvious, or specific to your project.

What to include

Bad example

testing: "Make sure to test your code"

This tells the agent nothing it does not already know. It is noise in the context window.

Good example

critical_patterns:
  async_error_handling: |
    CRITICAL: Express error middleware requires 4 parameters.
    Missing any parameter makes Express skip the handler silently.
    Always use: (err, req, res, next) => { ... }

    The order matters. If you write (req, res, next, err),
    Express treats it as a regular middleware and errors
    will fall through to the default handler.

This is specific, actionable, and describes a silent failure mode that would waste debugging time. This is the kind of knowledge that makes agents dramatically more effective.

Settings Sync

The cuite settings command compares your project's hook configuration in .claude/settings.json against the framework's template. It ensures all hooks are wired correctly while preserving your custom permissions and whitelist settings.

Run this after pulling framework updates to ensure new hooks are registered:

cuite settings

The command will report which hooks are missing, which are outdated, and apply updates with your confirmation. Your permissions, whitelist, and other custom settings are never modified.

Pulling Updates

To pull the latest CUITE framework updates into your project:

cuite pull

This command:

  1. Runs git subtree pull to update .claude/cuite/ with the latest framework code.
  2. Refreshes symlinks to ensure they point to the updated files.
  3. Checks settings for any new hooks that need to be registered.

Your files are never touched. settings.json, domains.md, domain-map.conf, and everything under experts/ remain exactly as you left them.

Pushing Changes

If you have forked CUITE and want to contribute improvements back to the framework:

cuite push

This command uses git subtree push to extract only the .claude/cuite/ directory and push it to the remote. Your project-specific files (settings, domains, expertise) are excluded by the subtree prefix.

Note Fork the CUITE repository first if you want to push improvements. The push command sends changes to the cuite remote, which should point to your fork.

Conflicts

Merge conflicts during a cuite pull can only happen inside .claude/cuite/. Your project-specific files are outside the subtree and cannot conflict.

If you encounter conflicts, the simplest resolution is to accept the upstream version:

git checkout --theirs .claude/cuite/
git add .claude/cuite/
git commit -m "merge cuite updates"

This is safe because .claude/cuite/ contains only framework code. If you have made local modifications to framework files, review the conflicts manually and merge as appropriate.

Common Issues

"Agent teams not available"

Agent teams are an experimental Claude Code feature. Set the environment variable before launching Claude Code:

export CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1

"Hooks not firing"

Check that the hooks section in .claude/settings.json is properly configured. Each hook needs a matching entry with the correct event type (PreToolUse, PostToolUse, SubagentStart, or SessionStart). Run cuite settings to diagnose and fix hook wiring.

"Agent doesn't know my domain"

The agent name must contain the domain keyword for expertise injection to work. If your domain is backend, the agent must be named something like backend-build-agent. Check the agent filenames under .claude/agents/experts/{domain}/.

"Expertise not injected"

Verify that expertise.yaml exists in the domain's expert directory. The inject-expertise.sh hook looks for this file by path. Also check that the inject-expertise.sh hook is registered in settings.json under the SubagentStart event.

"/do picks wrong domain"

Add more keywords to the domain's entry in domains.md. The keyword matching is the first step in domain discovery. If your task description uses terms that are not in the keyword list, /do may route to the wrong domain or fall back to the generic agent.

"/improve doesn't find changes"

The /improve command reads git log to find recent changes. If your changes are uncommitted, /improve will not see them. Commit first, then run /improve.

FAQ

Will subtree pull overwrite my domains?

No. The subtree pull only updates files inside .claude/cuite/. Your domains.md, domain-map.conf, settings.json, and everything under experts/ are outside the subtree and are never modified by pull operations.

Will subtree push include my project files?

No. The subtree push extracts only .claude/cuite/ and sends it to the remote. Your project code, settings, and domain expertise are excluded by the subtree prefix.

Do symlinks survive git clone?

Yes. Git tracks symlinks as part of the repository. When someone clones your project, the symlinks are recreated. If any symlinks break (e.g., after a framework restructuring), run cuite link to refresh them.

How do hooks resolve paths?

All hook scripts use $PWD for path resolution. This means they work correctly regardless of where the framework subtree is located, as long as Claude Code is launched from the project root. No hardcoded paths are used anywhere in the hook system.

Cost Guide

CUITE costs depend on which workflow you use and how many agents are involved. Here are approximate costs per invocation based on typical usage:

Action Model Approx. Cost
/do question haiku ~$0.01
/do implementation sonnet x3 ~$0.10–0.30
/do-teams 2 teammates sonnet x3 ~$0.30–0.80
/do-teams 3 teammates sonnet x4–5 ~$0.50–1.50

Costs scale primarily with the number of agents spawned and the complexity of the task. Questions are cheap because they use haiku and require only one agent. Full implementation cycles cost more because they involve plan, build, review, and improve phases. Team workflows multiply the cost by the number of parallel specialists.

Tip Use /do with Pattern B (question) for quick lookups and Pattern C (simple) for lint/format tasks. Reserve full Pattern A (implementation) and /do-teams for substantial work where the multi-agent cycle pays for itself in quality.