Multi-Project Skill Isolation

How to run Project A (Bootstrap + Owl) and Project B (Tailwind + React) without context conflicts.


The Problem

You have two web projects:

A single AI bot cannot serve both effectively. Odoo instructions pollute React context. React patterns leak into Odoo code. t-call advice makes no sense in JSX. useEffect has no place in QWeb.


The Solution: 3 Levels of Isolation

Level 1: CLAUDE.md (Project Constitution)

Each child bot starts claude -p in its own working directory. Claude Code automatically loads CLAUDE.md from the project root. This is the "constitution" of the bot.

Project A (/opt/repos/odoo-site/CLAUDE.md):

# Odoo Website Project

## Tech Stack
- Odoo 17 Community
- Python 3.11
- Bootstrap 5.3
- Owl (Odoo Web Library) framework
- QWeb templating engine
- PostgreSQL 16

## Conventions
- All templates use t-call for i18n
- No inline JavaScript in QWeb templates
- CSS follows BEM naming
- Python follows Odoo coding guidelines

Project B (/opt/repos/saas-app/CLAUDE.md):

# SaaS Application

## Tech Stack
- Next.js 15 (App Router)
- React 19
- TypeScript 5.4 (strict mode)
- Tailwind CSS 4.0
- Prisma ORM
- PostgreSQL 16

## Conventions
- Server Components by default, 'use client' only when needed
- Tailwind utility classes via cn() helper (no @apply in components)
- All API routes in app/api/ with Zod validation

These files never mix. Different directories, different processes, different bots.


Level 2: skills/ (Technology-Specific Expertise)

Each project gets only the skills relevant to its tech stack.

Project A skill set:

/opt/repos/odoo-site/skills/
├── _registry.json           ← Only Odoo-relevant entries
├── library/
│   ├── odoo-expert.md       ← Odoo module development
│   ├── odoo-owl-expert.md   ← Owl component patterns
│   └── postgres-pro.md      ← PostgreSQL optimization
├── code-review/
│   ├── skill.md
│   └── code-review.evals.json  ← Odoo-specific rules
└── git-manager/
    └── skill.md

Project B skill set:

/opt/repos/saas-app/skills/
├── _registry.json           ← Only React-relevant entries
├── library/
│   ├── react-patterns.md    ← RSC, hooks, state management
│   ├── tailwind-expert.md   ← Utility-first CSS patterns
│   └── nextjs-expert.md     ← App Router, middleware, ISR
├── code-review/
│   ├── skill.md
│   └── code-review.evals.json  ← React-specific rules
└── git-manager/
    └── skill.md

Notice: same structural skills (code-review, git-manager) but with different eval rules per project.


Level 3: _registry.json + Context Router (Smart Selection)

Even within a single project, the Context Router ensures only relevant skills are emphasized per message.

Project A registry (odoo-site/skills/_registry.json):

{
  "skills": [
    {
      "name": "odoo-expert",
      "triggers": ["odoo", "module", "QWeb", "t-call", "res.partner"],
      "keywords": ["template", "view", "action", "ORM", "XML", "controller"]
    },
    {
      "name": "odoo-owl-expert",
      "triggers": ["owl", "component", "t-on", "t-set"],
      "keywords": ["lifecycle", "hook", "state", "props", "template"]
    }
  ]
}

Project B registry (saas-app/skills/_registry.json):

{
  "skills": [
    {
      "name": "react-patterns",
      "triggers": ["component", "hook", "useState", "useEffect", "RSC"],
      "keywords": ["render", "props", "state", "context", "suspense"]
    },
    {
      "name": "tailwind-expert",
      "triggers": ["tailwind", "className", "dark mode", "responsive"],
      "keywords": ["utility", "variant", "breakpoint", "theme", "cn()"]
    }
  ]
}

When CEO sends "Fix the t-call in the product template" to Project A:

Context Router:
  odoo-expert: trigger "t-call" (2) + keyword "template" (1) = 3 pts
  odoo-owl-expert: keyword "template" (1) = 1 pt
  git-manager: 0 pts

→ SKILLS_HINT: odoo-expert, odoo-owl-expert

When CEO sends "Add dark mode toggle with Tailwind" to Project B:

Context Router:
  tailwind-expert: trigger "tailwind" (2) + trigger "dark mode" (2) = 4 pts
  react-patterns: keyword "component" (1) = 1 pt

→ SKILLS_HINT: tailwind-expert, react-patterns

Evals: Stack-Specific Quality Rules

Each project can have different eval rules even for the same skill.

Project A (odoo-site/skills/code-review/code-review.evals.json):

{
  "rules": [
    { "id": "cr-odoo-001", "name": "Must use t-call for i18n", "type": "regex_match", "pattern": "t-call|t-esc|_t\\(", "severity": "warning" },
    { "id": "cr-odoo-002", "name": "No inline JS in QWeb", "type": "string_not_contains", "value": "<script>", "severity": "warning" },
    { "id": "cr-odoo-003", "name": "No direct SQL queries", "type": "string_not_contains", "value": "cr.execute", "severity": "warning" }
  ]
}

Project B (saas-app/skills/code-review/code-review.evals.json):

{
  "rules": [
    { "id": "cr-react-001", "name": "No direct DOM manipulation", "type": "string_not_contains", "value": "document.getElementById", "severity": "warning" },
    { "id": "cr-react-002", "name": "No any types", "type": "string_not_contains", "value": ": any", "severity": "warning" },
    { "id": "cr-react-003", "name": "Prefer server components", "type": "string_not_contains", "value": "'use client'", "severity": "info" }
  ]
}

Same skill. Different rules. Same quality enforcement mechanism.


Learnings: Independent Memory Per Project

Corrections accumulate separately.

Project A (odoo-site/learnings.md):

- [2026-03-20] [fixit] Always use t-call for translations in QWeb
- [2026-03-22] [negative] Don't override base Odoo CSS — use custom class
- [2026-04-01] [fixit] Use sudo() only when security context requires it

Project B (saas-app/learnings.md):

- [2026-03-21] [fixit] Use server components by default in Next.js 15
- [2026-03-25] [negative] Don't use useEffect for data fetching — use RSC
- [2026-04-02] [fixit] Always validate API input with Zod schema

Project A's Odoo learnings never contaminate Project B's React context. Each bot's "immune memory" is 100% relevant to its own tech stack.


Metrics: Per-Project, Per-Skill

/quality on Project A:
  odoo-expert: 47x, 93% ok, thumbs-up 15/thumbs-down 1, avg 9.2s
  code-review: 12x, 83% ok, thumbs-up 4/thumbs-down 2, avg 5.1s

/quality on Project B:
  react-patterns: 31x, 87% ok, thumbs-up 8/thumbs-down 3, avg 6.7s
  tailwind-expert: 18x, 94% ok, thumbs-up 7/thumbs-down 0, avg 3.4s

The Karpathy Loop analyzes each project independently. If code-review is weak in the Odoo project but strong in the React project, only the Odoo project gets an improvement proposal.


Setup Steps

1. Create the projects

In Master Bot Telegram:
/new_project odoo-site
/new_project saas-app

2. Add CLAUDE.md per project

Write the project constitution describing tech stack, conventions, constraints.

3. Copy relevant library skills

# Project A
cp citadel-v2/skills/library/odoo-expert.md /opt/repos/odoo-site/skills/library/
cp citadel-v2/skills/library/odoo-owl-expert.md /opt/repos/odoo-site/skills/library/

# Project B — create new ones for your stack
write /opt/repos/saas-app/skills/library/react-patterns.md
write /opt/repos/saas-app/skills/library/tailwind-expert.md

4. Customize _registry.json per project

Add triggers and keywords relevant to each project's technology.

5. Write stack-specific evals

Create .evals.json files with rules that make sense for each stack.

6. Use and correct

Start working. Press Fix It when wrong. Press thumbs-down on bad responses. The system learns and adapts per project.


Why Not One Bot With "Modes"?

Approach Problem
One bot, switch context manually Leakage between projects, no persistent isolation
One bot, prefix every message Tedious, error-prone, no skill isolation
One bot, multiple CLAUDE.md Claude Code loads one CLAUDE.md per cwd
Arc OS: separate child bots Complete isolation at process level

The federated approach is more infrastructure (one tmux session per project), but eliminates all context mixing by design.