Your AI builder operating system.
Turn Claude Code from a per-session tool into a workspace that remembers, maintains itself, and never goes stale.
You start a Claude Code session. Claude doesn't know:
So you repeat yourself. Every. Single. Session.
Maybe you've tried fixing this with a massive CLAUDE.md file, @-mentions pointing at markdown docs, or manual context dumps at session start. It works... until it doesn't. Files go stale. Your CLAUDE.md becomes a junk drawer. You forget to update things. Claude starts making decisions based on outdated information. And the bigger your workspace gets, the worse it breaks.
This is the duct tape phase. Everyone goes through it. BASE is what comes after.
BASE turns your Claude Code workspace into a managed operating system. Instead of scattered markdown files and manual context loading, you get:
Structured data that Claude reads automatically. Your active projects, backlog items, client lists — anything you want Claude to passively know about — lives in structured JSON files. Lightweight hooks inject compact summaries into every session automatically. You never type "here's what I'm working on" again.
Health monitoring that catches drift before it hurts. A drift score tracks how far your workspace state has drifted from reality. When things go stale, BASE tells you. When grooming is overdue, BASE tells you. You fix it with a guided maintenance cycle, not a weekend of cleanup.
A manifest that drives everything. One config file (workspace.json) declares what your workspace contains, how each area should be maintained, and what projects are in play. Every command reads from it. Your workspace is self-describing.
You open Claude Code. Before you type anything, Claude already knows:
<active-awareness items="5">
[URGENT]
- [ACT-001] Client Portal Launch (Blocked: API auth)
DUE: 2026-03-20
[HIGH]
- [ACT-002] Course Module 3 (In Progress)
- [ACT-003] MCP Server Refactor (In Review)
BEHAVIOR: PASSIVE AWARENESS ONLY.
Do NOT proactively mention unless user asks or deadline < 24h.
</active-awareness>
Claude doesn't nag. It doesn't start the session with "here are your tasks." But the moment you ask "what should I work on?" — the answer is instant and accurate. No file reading. No context window wasted. No stale data.
A "data surface" is just a structured JSON file paired with a hook that injects it into Claude's context. That's it.
JSON file (your data) → Hook (reads + summarizes) → Claude knows it
BASE ships with two built-in surfaces:
| Surface | What It Tracks |
|---|---|
| Active | Current projects, tasks, blockers, deadlines, status |
| Backlog | Future work, ideas, deferred items with review deadlines |
But you can create surfaces for anything — clients, contacts, content pipelines, API keys, whatever persistent data you want Claude to passively know about. The /base:surface create command walks you through it: define a schema, pick an injection format, and BASE generates the JSON file, the hook, and the wiring automatically.
workspace.json is the brain. It registers:
Every BASE command reads from this manifest. You configure it once during setup, and the system maintains itself from there.
BASE uses Claude Code's hook system to inject context automatically. There are two types:
Every prompt (UserPromptSubmit) — Fire on every message you send, keeping Claude's awareness current throughout the session:
| Hook | What It Does |
|---|---|
| Pulse check | Calculates workspace drift score, warns if grooming is overdue |
| PSMM injector | Re-injects important session moments (decisions, corrections, insights) into Claude's context so they don't get buried in a long session. Details below. |
| Surface hooks | One per data surface (active, backlog, or custom). Reads the JSON, outputs a compact summary so Claude passively knows the current state |
Session start (SessionStart) — Runs once when a Claude Code session begins:
| Hook | What It Does |
|---|---|
| PAUL project detection | Scans your workspace for PAUL project files (.paul/paul.json) and auto-registers new ones into workspace.json. Only needs to run once — your project list doesn't change mid-session. (More on PAUL below.) |
All hooks are lightweight Python — they read JSON files and output compact XML summaries. No network calls, no heavy dependencies, no noticeable latency. A hook that has nothing to report outputs nothing and exits silently.
npx @chrisai/base --global --workspace
One command. Two layers:
--global installs commands and the framework to ~/.claude (shared across all your workspaces)--workspace installs the data layer to .base/ in your current directoryThen open Claude Code and run /base:scaffold to configure your workspace with a guided setup.
# Full install — most users start here
npx @chrisai/base --global --workspace
# Already installed globally? Wire up a new workspace
npx @chrisai/base --workspace
# Global only — set up workspaces later with /base:scaffold
npx @chrisai/base --global
| Flag | What It Does |
|---|---|
--global |
Commands + framework to ~/.claude (shared) |
--workspace |
Data layer to .base/ in current directory |
--local |
Commands to ./.claude instead of global |
--config-dir <path> |
Custom Claude config directory |
--workspace-dir <path> |
Target a specific workspace path |
~/.claude/ Shared across all workspaces
├── commands/base/ 11 slash commands
├── skills/base/ Skill entry point + package sources
└── base-framework/
├── tasks/ How each command works (pulse, groom, audit...)
├── templates/ Schemas for workspace.json, STATE.md, surfaces
├── context/ Core principles
├── frameworks/ Audit strategies, project registration
└── hooks/ Session hook sources
.base/ Per-workspace
├── workspace.json The manifest — everything is registered here
├── data/
│ ├── active.json Active work surface
│ └── backlog.json Backlog surface
├── hooks/
│ ├── _template.py Hook template for creating new surfaces
│ ├── active-hook.py Injects active work into Claude's context
│ └── backlog-hook.py Injects backlog into Claude's context
├── base-mcp/ MCP server for surface operations (CRUD)
└── carl-mcp/ MCP server for rules engine operations
.claude/hooks/ Registered in settings.json
├── base-pulse-check.py [UserPromptSubmit] Drift + groom reminders
├── psmm-injector.py [UserPromptSubmit] Session meta memory
└── satellite-detection.py [SessionStart] PAUL project discovery
Most workspace management tools are set-and-forget. BASE is designed around the reality that workspaces are living things that drift.
/base:pulse runs automatically via hook. It reads your manifest, checks filesystem timestamps, and calculates a drift score:
| Drift Score | What It Means | What to Do |
|---|---|---|
| 0 | Everything is current | Work normally |
| 1-7 | Minor drift | Fix at next groom |
| 8-14 | Moderate — Claude may be acting on stale info | Groom soon |
| 15+ | Critical — workspace context is unreliable | Groom now |
No stop hooks. No unreliable session-end tracking. Pulse always starts from filesystem ground truth.
/base:groom is a guided, voice-friendly walkthrough of your entire workspace. It reviews one area at a time, oldest-first:
Result: drift score resets to 0, summary gets logged, next groom date is set.
/base:audit goes deeper than grooming. Each tracked area maps to a configurable audit strategy:
| Strategy | Applies To | What It Does |
|---|---|---|
staleness |
Working memory files | Checks file age against thresholds |
classify |
Directories (projects/, clients/) | Lists items for triage: active, archive, or delete |
cross-reference |
Tools with config files | Finds orphaned tools and broken config references |
dead-code |
System directories | Finds unused hooks, commands, skills |
pipeline-status |
Content or task workflows | Flags stuck items and bottlenecks |
The number of audit phases is dynamic — generated from your manifest, not hardcoded. A small workspace gets 3 phases. A large one gets 12. Same command, adapted to your reality.
BASE ships two MCP servers so Claude can read and write your workspace data through structured tool calls instead of raw file edits.
A generic CRUD interface for all registered surfaces. Claude can add items, update status, archive old work, and search across everything:
| Tool | What It Does |
|---|---|
base_list_surfaces |
List all surfaces with item counts |
base_get_surface |
Read all items from a surface |
base_get_item |
Get one item by ID |
base_add_item |
Add item (auto-generates ID, validates against schema) |
base_update_item |
Update specific fields (preserves everything else) |
base_archive_item |
Move item to archive with timestamp |
base_search |
Search across one or all surfaces by keyword |
When you create a new surface, the MCP server auto-discovers it from workspace.json. No code changes needed.
CARL (Context Augmentation & Reinforcement Layer) is a dynamic rules engine for Claude Code. On its own, CARL stores behavioral rules in domain files — groups of rules that load automatically based on what you're doing. Say "check Skool" and CARL loads your Skool community rules. Start coding and it loads your development standards. The rules are just config files in .carl/.
CARL is fully independent — it works without BASE, and BASE works without CARL. But BASE bundles CARL's MCP server as an optional capability. If you use CARL, BASE gives it MCP superpowers (programmatic rule management, decision logging, session memory). If you don't use CARL, this MCP server sits idle and everything else in BASE works normally.
When both are active, Claude gets programmatic access to three powerful systems:
Claude can read, search, and manage your rule domains through tool calls instead of file edits:
| Tool | What It Does |
|---|---|
carl_list_domains |
List all rule domains and their status |
carl_get_domain_rules |
Read rules for a specific domain |
carl_stage_proposal |
Stage a new rule proposal for review (more on this below) |
Decisions get lost. You make a call in one session — "we're using OAuth, not API keys" — and three sessions later Claude asks you the same question. Or worse, it makes the opposite choice because it has no memory of what you decided.
CARL's decision logger fixes this. Decisions are stored per domain (e.g., decisions/development.json, decisions/global.json) and load automatically alongside domain rules. When CARL loads the "development" domain because you're coding, every decision you've ever logged in that domain loads with it as lightweight metadata. Claude reads your decisions before acti
$ claude mcp add base-v1 \
-- python -m otcore.mcp_server <graph>