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:
- Project A: Odoo website — Bootstrap 5, Owl framework, QWeb templates, Python backend
- Project B: SaaS application — Tailwind CSS, React 19, Next.js 15, TypeScript
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.