Comparisons

Single File vs Hierarchical AI Rules

One .cursorrules at the root or CLAUDE.md files in every subdirectory? Comparison of simplicity vs precision, context relevance, monorepo patterns, token efficiency, and when hierarchy adds value vs unnecessary complexity.

7 min readยทMay 21, 2025

Express middleware rules loaded while editing a React component โ€” the flat file caused the confusion

Context relevance, monorepo patterns, token efficiency, when flat is sufficient, and structuring hierarchy

One File for Everything vs Rules Where They Apply

The single-file approach: one rule file at the project root (.cursorrules, copilot-instructions.md, or a single CLAUDE.md). All rules for all parts of the project in one place. Simple: one file to maintain, one file to read, one file that every AI interaction loads. The AI sees: every rule on every interaction, regardless of which part of the codebase the developer is working in. The frontend React rules load when editing the Express API. The TypeScript strict rules load when editing a shell script.

The hierarchical approach: a root CLAUDE.md with project-wide rules, plus additional CLAUDE.md files in subdirectories with context-specific rules. packages/web/CLAUDE.md adds React rules. packages/api/CLAUDE.md adds Express rules. packages/shared/CLAUDE.md adds utility library rules. When Claude Code works in packages/web/: it sees the root rules AND the web-specific rules. When it works in packages/api/: it sees the root rules AND the api-specific rules. Each context gets: relevant rules only.

The question is: does the precision of hierarchical rules justify the maintenance overhead? For single-package projects: hierarchy adds no value (there is only one context). For monorepos with diverse packages: hierarchy adds significant value (each package gets rules matched to its technology). This article maps: when flat is sufficient, when hierarchy helps, and how to structure hierarchical rules effectively.

Context Relevance: All Rules vs Relevant Rules

The flat-file problem in diverse projects: a monorepo with a React frontend, Express API, and Python ML service. One .cursorrules file contains: React conventions ("use Server Components by default"), Express patterns ("use middleware for auth"), and Python conventions ("use type hints on all functions"). When the AI edits a React component: it also has Express middleware rules and Python type hint rules in context. These irrelevant rules: consume context window tokens (wasted space), may confuse the model (conflicting patterns from different paradigms), and dilute the signal (relevant rules are mixed with irrelevant ones).

The hierarchical solution: root CLAUDE.md has: universal rules (TypeScript strict, git conventions, testing requirements). packages/web/CLAUDE.md has: React Server Components, Tailwind, Next.js App Router patterns. packages/api/CLAUDE.md has: Express middleware, Zod validation, REST conventions. packages/ml/CLAUDE.md has: Python type hints, FastAPI, pytest conventions. When Claude Code works in packages/web/: it sees universal + React rules. No Express. No Python. The context is: 100% relevant to the current work.

The relevance impact: AI models follow instructions better when the instructions are relevant and focused. A 500-token focused rule set (only React rules when editing React) produces better results than a 2000-token mixed rule set (React + Express + Python when editing React). The irrelevant rules are not just wasted tokens โ€” they can cause the model to apply the wrong convention (Express middleware patterns in a React component, for example). Hierarchy is: context filtering for AI instructions.

  • Flat file: all rules loaded on every interaction, regardless of current context
  • Hierarchical: root universal + subdirectory-specific rules matched to current work
  • Irrelevant rules: waste tokens, may confuse the model, dilute the signal
  • 500 focused tokens > 2000 mixed tokens for AI instruction adherence
  • Hierarchy is context filtering: the AI sees only rules relevant to the current directory
๐Ÿ’ก 500 Focused Tokens > 2000 Mixed Tokens

A 500-token rule file with only React rules produces better AI output than a 2000-token file with React + Express + Python mixed together. Irrelevant rules waste tokens and can confuse the model (Express middleware patterns suggested in a React component). Hierarchy is context filtering for AI.

Monorepo Patterns: Where Hierarchy Shines

The typical monorepo that benefits from hierarchy: root/ (project-wide rules: TypeScript, git, CI), apps/web/ (Next.js App Router, React, Tailwind), apps/mobile/ (React Native, Expo), packages/api/ (Express or Fastify, REST, database), packages/shared/ (utility library, pure TypeScript), and scripts/ (build scripts, automation). Each directory has: a different technology stack, different conventions, and different AI behavior requirements. A flat file must: contain all conventions for all stacks. A hierarchical file: gives each directory its own focused rules.

The hierarchy structure: root CLAUDE.md: '# Project. Monorepo with pnpm workspaces. TypeScript strict. Vitest for testing. pnpm for package management. Git: conventional commits.' apps/web/CLAUDE.md: '# Web App. Next.js 16 App Router. React Server Components default. Tailwind CSS 4. shadcn/ui components. Use client only for interactivity.' packages/api/CLAUDE.md: '# API. Express with TypeScript. Drizzle ORM. Zod validation on every endpoint. REST with versioning.' Each file is: short (100-200 words), focused (one context), and complementary (inherits from root).

The maintenance trade-off in monorepos: flat file maintenance is: one file, all rules, edit once. Hierarchy maintenance is: one root file + N subdirectory files. For a 5-package monorepo: 6 files instead of 1. But: each file is shorter (focused rules, not everything), changes are localized (updating React rules only touches apps/web/CLAUDE.md), and the AI output is better (relevant rules produce more accurate code). The maintenance increase is: linear in number of packages. The quality increase is: proportional to project diversity.

  • Monorepo: root (universal) + apps/web/ (React) + packages/api/ (Express) + packages/shared/ (utils)
  • Each CLAUDE.md: 100-200 words, focused on one context, inherits root rules
  • Flat alternative: 800+ word file with all stacks mixed โ€” AI gets confused which rules apply
  • Maintenance: 6 short focused files vs 1 long mixed file โ€” localized changes, less drift
  • Quality: relevant rules produce more accurate code than mixed rules
โ„น๏ธ Each File: 100-200 Words, One Context

Root CLAUDE.md: 'TypeScript strict, pnpm, Vitest, conventional commits.' apps/web/CLAUDE.md: 'Next.js App Router, RSC default, Tailwind, use client only for interactivity.' Each file is short and focused. The AI gets exactly the rules it needs for the current directory. No noise.

Token Efficiency: Less Is More for AI Instruction

Every rule file consumed by the AI uses context window tokens. Flat file for a diverse project: 1500-3000 tokens (all rules for all contexts loaded every time). Hierarchical root + one subdirectory: 300-500 tokens (universal rules) + 200-400 tokens (context-specific rules) = 500-900 tokens total. The hierarchical approach uses: 50-70% fewer tokens per AI interaction. For models with limited context (GPT-4 at 128K): fewer tokens for rules means more tokens for code context.

Token efficiency matters because: rule files compete with code context for the model's attention window. A 3000-token rule file in a 128K context is: 2.3% of the window. A 700-token rule file is: 0.5%. The difference: 2300 tokens freed for additional code context. In practice: the AI can see 2-3 more files when the rule file is smaller. Those extra files: may be the ones that contain the pattern the AI needs to follow. Smaller rule files: better code context, better AI output.

The token argument for hierarchy is: strongest with smaller context models (GPT-4 128K), moderate with medium context (Claude Sonnet 200K), and weakest with large context (Claude Opus 1M in Claude Code). At 1M context: 3000 vs 700 tokens is negligible (0.3% vs 0.07%). But: even at large context, focused rules produce better instruction adherence than mixed rules. The relevance benefit persists regardless of context size; the token savings matter mainly for smaller contexts.

When a Single File Is Sufficient

A flat file is sufficient when: your project has one technology stack (React + TypeScript + Tailwind โ€” no conflicting conventions), all code follows the same conventions (every file uses the same patterns, no context-specific rules needed), the rule file is under 1000 tokens (short enough that irrelevance overhead is minimal), and you use .cursorrules or copilot-instructions.md (neither supports hierarchy โ€” flat is the only option). Most single-package projects: work perfectly with a flat file.

Stay flat until: you add a second package with a different technology stack (the rules start conflicting), the flat file exceeds 1500 tokens (the irrelevance overhead becomes meaningful), or the AI applies wrong-context rules (Express middleware pattern in a React component โ€” the flat file caused the confusion). These are the triggers: the moment a flat file causes AI confusion, hierarchy becomes beneficial.

The pragmatic progression: start flat (one CLAUDE.md or .cursorrules at the root). When you add diverse packages: add subdirectory CLAUDE.md files (Claude Code supports this). For tools that do not support hierarchy (.cursorrules, copilot-instructions.md): keep the flat file and accept the mixed-context trade-off. RuleSync: generates hierarchical CLAUDE.md (for Claude Code) and flat .cursorrules (for Cursor) from the same source. Each tool gets: the best format it supports.

  • Flat sufficient: one stack, same conventions everywhere, under 1000 tokens, .cursorrules format
  • Stay flat until: second stack added, file exceeds 1500 tokens, or AI applies wrong-context rules
  • Start flat, add hierarchy when needed: root CLAUDE.md first, subdirectory CLAUDE.md as packages grow
  • .cursorrules: flat only (no hierarchy support). CLAUDE.md: flat or hierarchical
  • RuleSync: generates hierarchical CLAUDE.md + flat .cursorrules from one source
โš ๏ธ Start Flat, Add Hierarchy When Confused

Triggers to add hierarchy: AI applies Express middleware in a React component (wrong-context rule applied), rule file exceeds 1500 tokens (too much for every interaction), or a second technology stack is added to the monorepo. These signals mean: the flat file is causing confusion, hierarchy will fix it.

How to Structure Hierarchical Rules Effectively

Root CLAUDE.md content: project description (what this project is, what it does), universal conventions (language: TypeScript strict. Package manager: pnpm. Testing: Vitest. Git: conventional commits), and security rules (input validation, authentication patterns, no secrets in code). The root is: the foundation that every subdirectory inherits. Keep it: focused on universal rules that apply everywhere. Length: 200-400 tokens.

Subdirectory CLAUDE.md content: technology stack (Next.js App Router, React Server Components, Tailwind), framework-specific patterns (use client only for interactivity, server actions for mutations), file structure conventions (pages in app/, components in _components/, hooks in _hooks/), and testing patterns specific to this package (React Testing Library for component tests, MSW for API mocking). The subdirectory is: the context-specific layer. Keep it: focused on what differs from the root. Length: 150-300 tokens.

The inheritance model: subdirectory rules ADD to root rules (not replace). If the root says "TypeScript strict" and the subdirectory says "use React Server Components": both apply. If the subdirectory needs to OVERRIDE a root rule: state it explicitly ("In this package, use CommonJS instead of ESM" overrides the root ESM default). Conflicts are: resolved by the most specific file (subdirectory overrides root for files in that directory). Keep overrides: rare and explicitly documented (a comment explaining why this directory differs).

Comparison Summary

Summary of single file vs hierarchical AI rules.

  • Flat file: simple, one place, all rules loaded every time โ€” works for single-stack projects
  • Hierarchical: root + subdirectories, context-relevant rules only โ€” works for diverse monorepos
  • Context relevance: flat loads React + Express + Python rules for React edits. Hierarchy: React only
  • Token efficiency: hierarchy uses 50-70% fewer tokens per interaction โ€” more room for code context
  • Monorepo: hierarchy shines โ€” each package gets focused rules matching its technology stack
  • Flat sufficient: one stack, under 1000 tokens, .cursorrules format (no hierarchy support)
  • Start flat, add hierarchy when: second stack, file too long, or AI applies wrong-context rules
  • Root: universal rules (200-400 tokens). Subdirectory: context-specific (150-300 tokens). Inherit, rarely override