Skip to main content

Codebase cartographer MCP server — part of the khimaira workspace. Generates and maintains structural documentation: feature CLAUDE.md files, barrel exports, dependency graphs, symbol manifests.

Project description

Scarlet

To find what is hidden, hold a séance. To bind the names you find, give them to Scarlet.

Scarlet now ships inside khimaira as a workspace member at packages/scarlet/. Its tools are re-registered on khimaira's MCP server under source-prefixed names (mcp__khimaira__scarlet_analyze_project, etc.). The standalone scarlet serve path below still works for backward compatibility.

Scarlet is a codebase cartographer — an MCP server that walks any project, extracts structural metadata via tree-sitter, and generates the documentation scaffolding AI assistants need to actually understand a feature-organized codebase: per-feature CLAUDE.md files, barrel exports (index.js/index.ts), Mermaid dependency graphs, and symbol manifests.

Built for Claude Code, but works with any MCP-compatible client.

The dark cousin of Séance: Séance retrieves knowledge from the dead code via vector search; Scarlet inscribes the names of every entity into a permanent record. Both now live inside the khimaira workspace.

Why "Scarlet"

Named for the Scarlet Woman of Revelation 17 — the figure who sits on a beast "full of names of blasphemy" with a name written on her forehead and a cup full of mysteries in her hand. She is defined by the inscribed names she bears. A catalog walking around in human form.

That maps directly onto what the tool does:

  • Catalogs named entities (components, hooks, slices, types, interfaces) from a codebase
  • Inscribes them into permanent records — per-feature CLAUDE.md files, barrel exports, symbol manifests
  • Surfaces what was hidden — gotchas, invariants, TODOs, deep imports that bypass barrels

Other scarlet threads in scripture reinforce the metaphor:

  • Isaiah 1:18"though your sins be as scarlet…". Scarlet was the dye that couldn't be washed out; the stain that remained visible. Documentation fixes structure in the same way — makes the shape of a feature indelible so refactors can't silently erase it.
  • Rahab's scarlet cord (Joshua 2:18) — a visible marker placed on the house that should be preserved when everything around it is destroyed. Every generated CLAUDE.md is a scarlet cord: a feature tied to an inscription so it survives refactors that would otherwise erase its shape.

There's also Hawthorne's Scarlet Letter — a public mark that fixes identity, making a person's defining characteristic impossible to ignore. Scarlet does the same to features: once their symbols are inscribed, their identity is legible to anyone (or anything) reading the record.

And it pairs with its sibling tool in the ritual:

To find what is hidden, hold a séance. To bind the names you find, give them to Scarlet.

Séance is the summoning. Scarlet is the scribe at the ritual — the one who takes down what comes through.

What it does

flowchart LR
    A[Any Project] -->|claude mcp add| B[Scarlet MCP]
    B --> C[Tools]
    C --> D[analyze_project]
    C --> E[scan_features]
    C --> F[extract_feature_metadata]
    C --> G[generate_barrel]
    C --> H[build_claude_md]
    C --> I[generate_dep_graph]
    C --> J[lint_claude_md]

    D & E & F & G & H & I & J --> L[Project gets:<br/>CLAUDE.md per feature<br/>Barrel exports<br/>Mermaid dep graph<br/>Lint reports]

The core principle

Deterministic parts run in Python. Judgment parts run in Claude.

Generated by Scarlet (Python + tree-sitter) Generated by Claude (synthesis)
Public API list Vocabulary (domain terms)
Key files index Conventions and invariants
Cross-feature consumers Common task recipes
Dependency graph Known issues and gotchas
Barrel exports One-paragraph feature description
Symbol manifests The why behind every "don't do X"

The tools generate structure. Claude generates meaning. On every CLAUDE.md update, the auto-derivable sections refresh and the human/Claude-written sections are preserved using <!-- BEGIN MANUAL --> ... <!-- END MANUAL --> markers.

Indexing pipeline

flowchart TD
    A[Project root] --> B[analyze_project]
    B --> C{Detect framework, state mgmt,<br/>features root, package manager}
    C --> D[scan_features]
    D --> E[For each feature]
    E --> F[Walk source files]
    F --> G[Tree-sitter parse]
    G --> H[Extract exports:<br/>components, hooks, slices,<br/>interfaces, types]
    H --> I[Find consumers via import graph]
    I --> J[Build skeleton from template]
    J --> K{Existing CLAUDE.md?}
    K -->|Yes| L[Preserve manual sections,<br/>refresh auto sections]
    K -->|No| M[Write new skeleton with<br/>placeholder manual sections]
    L --> N[Write CLAUDE.md]
    M --> N

The CLAUDE.md template

Every generated CLAUDE.md follows the same shape — auto sections refresh on every update, manual sections persist:

  • Description (manual) — one-paragraph summary
  • Vocabulary (manual) — domain terms specific to this feature
  • Public API (auto) — exported components, hooks, slices, types
  • Key files (auto) — every source file with the symbols it defines
  • Conventions and patterns (manual) — invariants, idioms, the why behind every rule
  • Consumers (auto) — features that import from this one
  • Common tasks (manual) — step-by-step recipes
  • Known issues and gotchas (manual) — landmines, deprecated patterns
  • See also (auto) — cross-references to study guides and rules

Installation

Prerequisites

  • Python 3.12+
  • uv package manager

Setup

git clone git@github.com:fsocietydisobey/scarlet.git
cd scarlet
uv sync

No API keys required — Scarlet is fully local and stateless.

CLI usage

# Scan a project — overview + feature table
uv run scarlet scan ~/work/jeevy_portal

# Generate or refresh one feature's CLAUDE.md
uv run scarlet describe ~/work/jeevy_portal drawings
uv run scarlet describe ~/work/jeevy_portal drawings --dry-run   # preview only

# Refresh all feature CLAUDE.md files
uv run scarlet sync ~/work/jeevy_portal

# Generate a barrel export for a feature
uv run scarlet barrel ~/work/jeevy_portal drawings --ext js

# Generate a Mermaid dependency graph
uv run scarlet graph ~/work/jeevy_portal -o shared-docs/feature-deps.mmd

# Lint all CLAUDE.md files for staleness and missing sections
uv run scarlet lint ~/work/jeevy_portal

# Start the MCP server
uv run scarlet serve

MCP integration

Claude Code

Register globally so it's available in every project:

claude mcp add -s user scarlet -- uv --directory /path/to/scarlet run scarlet serve

Once registered, Claude gets these tools:

Tool What it does
analyze_project Detect framework, state mgmt, package manager, feature count
scan_features List all features with state (CLAUDE.md, barrel, counts)
extract_feature_metadata Pull all exports from one feature
generate_barrel Create a barrel export file for one feature
build_claude_md Generate or refresh a feature's CLAUDE.md
generate_dep_graph Output Mermaid or JSON dependency graph
lint_claude_md Validate a feature's CLAUDE.md for staleness
list_consumers Find all features that import from a given feature

Other MCP clients

{
  "mcpServers": {
    "scarlet": {
      "command": "uv",
      "args": ["--directory", "/path/to/scarlet", "run", "scarlet", "serve"]
    }
  }
}

Configuration

Create a .scarlet.yml at the root of any project to declare conventions:

project_type: nextjs
state_management: redux-toolkit
test_framework: jest
features_root: frontend/src/features
study_guides_path: frontend/study-guides
barrel_export_strategy: re_export_default

This makes Scarlet reusable across projects with different shapes. Without .scarlet.yml, Scarlet uses sensible defaults and detects most things heuristically.

Architecture

graph TB
    subgraph "src/scarlet/"
        CLI[cli.py<br/>CLI entry point]
        SRV[server.py<br/>MCP server]
        CFG[config.py<br/>.scarlet.yml loader]

        subgraph "analyzer/"
            PR[project.py<br/>framework detection]
            FT[features.py<br/>feature scanning]
            MD[metadata.py<br/>tree-sitter export extraction]
            IM[imports.py<br/>import graph walker]
        end

        subgraph "generator/"
            BR[barrel.py<br/>index.js generator]
            CM[claude_md.py<br/>CLAUDE.md generator]
            DG[dep_graph.py<br/>Mermaid renderer]
            TPL[template.py<br/>skeleton template]
        end

        subgraph "validator/"
            LN[linter.py<br/>staleness checks]
        end
    end

    CLI --> PR & FT & MD & BR & CM & DG & LN
    SRV --> PR & FT & MD & BR & CM & DG & LN & IM
    CM --> MD & IM & TPL
    BR --> MD
    DG --> IM

Composition with Séance and Serena

Scarlet is the writer. It produces structure for the read tools to consume:

flowchart BT
    A[Source Code<br/>ground truth]
    A --> B[Serena<br/>LSP - exact symbolic queries]
    A --> C[Séance<br/>vector search - semantic queries]
    B & C --> D[Scarlet<br/>analysis + writing]
    D --> E[Generated Docs<br/>CLAUDE.md, barrels, dep graphs]
    E --> F[Architecture MCP<br/>serves curated docs]
Tool Question it answers Mode
Serena "Where is symbol X defined? Who calls it?" Read (LSP-precise)
Séance "Find code related to concept X" Read (semantic-fuzzy)
Scarlet "Generate or refresh the structural docs" Write
Architecture MCP "What does the curated map say about X?" Read (curated prose)

The four together form a complete loop: Scarlet writes, the others read.

Tech stack

  • tree-sitter — AST parsing for Python, TypeScript, JavaScript
  • MCP Python SDK — Model Context Protocol server
  • Click — CLI framework
  • PyYAML — Config file parsing
  • uv — Package management

No vector database, no API keys, no embeddings. Scarlet is fully local, deterministic, and stateless.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

khimaira_scarlet-0.2.0.tar.gz (32.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

khimaira_scarlet-0.2.0-py3-none-any.whl (38.7 kB view details)

Uploaded Python 3

File details

Details for the file khimaira_scarlet-0.2.0.tar.gz.

File metadata

  • Download URL: khimaira_scarlet-0.2.0.tar.gz
  • Upload date:
  • Size: 32.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.12 {"installer":{"name":"uv","version":"0.11.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for khimaira_scarlet-0.2.0.tar.gz
Algorithm Hash digest
SHA256 8e8ed65ffd162b993e1c681affe5b074d4fe7ab58b119c9aae0afc050ee0a6b9
MD5 d7f008c13795a05396e7846bcbff5ad6
BLAKE2b-256 f2f42239149f79fd0a3f60f4ea8b2d4882181a545a70845d2426bd546e849014

See more details on using hashes here.

File details

Details for the file khimaira_scarlet-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: khimaira_scarlet-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 38.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.12 {"installer":{"name":"uv","version":"0.11.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for khimaira_scarlet-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 42ba64536ca4887cf58aa59cdf2ac618cc3c42bd5a1780aec2842db4c952c862
MD5 98c7b9f9b114f1d202e620ac873bbcd3
BLAKE2b-256 b3ba5702acdf123ab1d38cd33c1a2ab3b7db1ec392256d91b01ceefb99ff3d95

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page