CodeMirror State

Immutable document, selection, and transaction data structures for the CodeMirror code editor

Library
npm
v6.7.6
83 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
32 /100 Needs Attention
Development Activity 8
Maintenance 0
Community 40
Maturity 60
Momentum 20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
75 /100 Good
Architecture 85
Code Quality 78
Innovation 80
Learning Curve 55

@codemirror/state is the core data-modeling package behind the CodeMirror 6 code editor. It defines the EditorState, an immutable persistent object that combines a Text document, an EditorSelection, and any extension-defined fields into a single snapshot, updated only by producing a new Transaction rather than mutating in place.

Beyond the document/selection pair, the package exposes the Facet and StateField mechanisms that let extensions plug typed, computed values into the state, a RangeSet data structure for efficiently mapping tagged ranges (like decorations or diagnostics) through edits, and a rope-like Text implementation for fast indexing and structure-sharing updates on large documents. It has no rendering logic of its own — @codemirror/view and language packages build on top of it — which makes it usable in headless contexts (e.g. server-side linting or diffing) as well as inside the browser editor.

What You Get

  • EditorState: the immutable snapshot combining doc, selection, and extension state, updated only via state.update(...) transactions
  • Text: a rope-style immutable document representation with efficient line/offset indexing and structure-sharing edits
  • EditorSelection / SelectionRange: multi-range cursor and selection modeling with built-in mapping through changes
  • Facet and StateField: the extension points other CodeMirror packages (and third-party plugins) use to add typed, computed configuration and state
  • ChangeSet / ChangeDesc: a compact, invertible representation of document edits used to map positions and ranges across a change
  • RangeSet / RangeSetBuilder: an efficient tagged-range data structure for decorations, gutter markers, and diagnostics that stays correct across edits
  • Compartment: a mechanism for reconfiguring a slice of extensions at runtime without rebuilding the whole state

Common Use Cases

  • Building a CodeMirror 6-based code or text editor and needing the underlying document/selection/transaction model
  • Writing a CodeMirror extension (language mode, linter, autocompletion source) that needs to add its own StateField or Facet
  • Implementing collaborative editing or undo/redo on top of CodeMirror’s transaction and ChangeSet primitives
  • Running headless document diffing, transformation, or position-mapping logic (e.g. applying LSP edits) without loading the DOM-based view layer
  • Tracking decorations, diagnostics, or annotations that must stay correctly positioned as a document is edited, via RangeSet

Under The Hood

Architecture — @codemirror/state has no DOM or rendering code; it is a pure data-modeling layer consumed by @codemirror/view and language packages. The central class, EditorState (src/state.ts), is an immutable object holding a Configuration (the resolved set of extensions), a Text document, an EditorSelection, and a values array indexed by dynamically-assigned slot addresses for extension-defined StateFields. State transitions happen exclusively through Transaction objects (src/transaction.ts): state.update(spec) resolves a TransactionSpec into changes, a new selection, and any StateEffects, then produces both the new EditorState and the Transaction that describes how it was reached, enabling undo history and collaborative-editing extensions to replay or invert steps. Cross-cutting configuration flows through Facet and Compartment (src/facet.ts), a dependency-injection-like system where extensions register facet inputs and other code reads a single combined facet value, with Compartment allowing a subset of extensions to be swapped at runtime via a dedicated reconfigure effect.

Tech Stack — Written entirely in TypeScript (100% of repo bytes per GitHub’s language breakdown) targeting ES modules, with type: module in package.json and dual import/require entry points (dist/index.js / dist/index.cjs) built via the shared @codemirror/buildhelper tool. Its only runtime dependency is @marijn/find-cluster-break, a small grapheme-cluster-boundary helper used by the Text and char modules for UTF-16/codepoint-aware indexing — the package otherwise avoids external dependencies entirely, keeping it embeddable in any JS environment.

Code Quality — The test/ directory holds 7 suites (test-state, test-text, test-facet, test-selection, test-rangeset, test-charcategory, test-change; ~1,468 lines) exercised via the cm-runtests script, covering the core EditorState, Text, Facet, ChangeSet, and RangeSet behaviors against ~3,880 lines of source. Source files favor small, single-responsibility modules (change.ts, facet.ts, rangeset.ts, text.ts, transaction.ts, selection.ts) with consistent TSDoc /// comments preceding nearly every exported type and method, which are extracted directly into the published API reference. Internal-only members are explicitly marked @internal, and the EditorState class enforces immutability by convention (constructor is private; state is only produced via create/update), with the code and its comments explicitly warning against direct mutation.

API Design — The public surface is small and orthogonal: one way to build a state (EditorState.create), one way to change it (state.update), and a handful of composable primitives (Facet, StateField, Compartment, RangeSet) that every higher-level CodeMirror package builds on. Method names read close to plain English (state.field(f), tr.state, text.lineAt(pos)), and TypeScript generics make StateField<T>/Facet<Input, Output> usage type-safe end-to-end. The tradeoff is a real conceptual learning curve — understanding facets, compartments, and transaction specs requires reading the reference docs before writing a non-trivial extension, though the official docs and CodeMirror’s own language/view packages serve as thorough worked examples.

Used by 73 apps in this directory

TypeScript
88%
AGPL 3.0

OpenPanel

Analytics

7,057

Open-source Mixpanel alternative with session replay, MCP integration, and privacy-first product analytics you fully control.

View details
74
Repo Health
74
Technical
65
Dependency
Built with
TypeScript 88%
MDX 10%
Updated 2 weeks ago
Python
75%
AGPL 3.0

OpenViking

AI Development · AI Memory · Databases

38,819

An open-source context database that gives AI agents a unified filesystem for memory, resources, and skills with hierarchical tiered retrieval.

View details
85
Repo Health
75
Technical
64
Dependency
Built with
Python 75%
Rust 12%
Updated 1 weeks ago
TypeScript
90%
MIT

openwork

AI Assistants · Automation

23,765

OpenWork is a free, open-source desktop app for running AI agent workflows on your own files with 50+ LLMs, extensible skills, and MCP server support — the open-source alternative to Claude Cowork and Codex.

View details
87
Repo Health
89
Technical
67
Dependency
Built with
TypeScript 90%
Updated 1 weeks ago
JavaScript
64%
AGPL 3.0

overleaf

Collaboration · Productivity

18,188

Open-source, real-time collaborative LaTeX editor with sandboxed compilation and full TeXLive support for self-hosted academic and research teams.

View details
87
Repo Health
80
Technical
62
Dependency
Built with
JavaScript 64%
TypeScript 30%
Updated 3 weeks ago
TypeScript
94%
MIT

paperclip

AI Agents · Automation

90,417

The open-source control plane that turns a pile of AI agents into an actual company — with org charts, budgets, heartbeats, and governance.

View details
86
Repo Health
78
Technical
71
Dependency
Built with
TypeScript 94%
Updated 1 weeks ago
JavaScript
60%
Apache 2.0

peerd

AI Agents

415

The first AI agent harness native to the browser — a Chrome/Firefox extension that drives your tabs, spins up sandboxed compute (JS notebooks, WASM Linux VMs), and shares what it builds peer-to-peer, with no backend, no telemetry, and BYOK.

View details
78
Repo Health
70
Technical
0
Dependency
Built with
JavaScript 60%
TypeScript 38%
Updated 1 weeks ago
Python
49%
Other

Arize Phoenix

Analytics · Devops · Monitoring

11,641

Open-source AI observability platform for tracing, evaluating, and debugging LLM applications with built-in intelligence and MCP support.

View details
90
Repo Health
88
Technical
67
Dependency
Built with
Python 49%
TypeScript 42%
Updated 1 weeks ago
TypeScript
51%
ZLIB

Portainer

Devops

38,590

A lightweight, open-source web UI that puts Docker, Kubernetes, and Podman management within reach of any team—no CLI expertise required.

View details
92
Repo Health
79
Technical
65
Dependency
Built with
TypeScript 51%
Go 38%
Updated 2 weeks ago
Rust
63%
MIT

PostgresML

AI Development · Databases

6,825

Run ML training and LLM inference natively inside PostgreSQL with GPU acceleration — no data movement required.

View details
51
Repo Health
76
Technical
64
Dependency
Built with
Rust 63%
JavaScript 11%
Updated 1 years ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers