CodeMirror State

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

Library
npm
v6.7.1
83stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
33/100Needs Attention
Development Activity12
Maintenance0
Community40
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
75/100Good
Architecture85
Code Quality78
Innovation80
Learning Curve55

@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 68 apps in this directory

TypeScript
99%
Other

Activepieces

Automation · AI Assistants

23,887

Open-source AI automation platform that converts 280+ workflow integrations into MCP servers for LLMs, with no-code builders and TypeScript extensibility.

View details
92
Repo Health
85
Technical
65
Dependency
Built with
TypeScript99%
Updated today
TypeScript
94%
MIT

Actual

Invoicing Finance

28,224

Local-first personal finance with envelope budgeting, end-to-end encryption, and multi-device sync — no subscription required.

View details
93
Repo Health
85
Technical
77
Dependency
Built with
TypeScript94%
Updated yesterday
Python
66%
Apache 2.0

Agent Control

AI Agents

295

An open-source runtime control plane for AI agents — define safety guardrails once, apply them across agents built on LangChain, CrewAI, Google ADK, or AWS Strands, and update controls without redeploying code.

View details
79
Repo Health
71
Technical
70
Dependency
Built with
Python66%
TypeScript33%
Updated yesterday
TypeScript
95%
Apache 2.0

AionUi

AI Agents · Productivity

32,102

Free, open-source Cowork desktop app that unifies Claude Code, Codex, Gemini CLI, and 20+ AI agents into a single platform with multi-agent teams, 24/7 cron automation, and zero-config built-in agent.

View details
88
Repo Health
76
Technical
66
Dependency
Built with
TypeScript95%
Updated today
Go
60%
Apache 2.0

Apache Answer

Community

15,652

Open-source Q&A platform for communities, help centers, and knowledge bases with AI assistant and plugin extensibility

View details
85
Repo Health
78
Technical
69
Dependency
Built with
Go60%
TypeScript36%
Updated 2 days ago
TypeScript
69%
Other

Budibase

Low Code Platforms · No Code Platforms

28,220

Build AI agents, automations, and internal apps on a single open-source platform with full self-hosting control.

View details
92
Repo Health
81
Technical
63
Dependency
Built with
TypeScript69%
Svelte26%
Updated today
Go
62%
Apache 2.0

Coroot

Analytics · Monitoring

7,877

eBPF-powered observability with AI root cause analysis — zero code changes required, full-stack visibility out of the box.

View details
88
Repo Health
80
Technical
65
Dependency
Built with
Go62%
Vue36%
Updated yesterday
Ruby
62%
GPL 2.0

Discourse

Community

47,672

Open-source community platform with dynamic trust levels, real-time chat, and a powerful plugin architecture for self-hosted forums.

View details
89
Repo Health
89
Technical
67
Dependency
Built with
Ruby62%
JavaScript31%
Updated today
Java
34%
Apache 2.0

Enso

Analytics · Data Engineering · Low Code Platforms

7,437

A visual and textual programming platform for data prep and analysis where the node graph and the underlying Enso code are always perfectly in sync, built by an Alteryx co-founder on a GraalVM engine.

View details
70
Repo Health
90
Technical
62
Dependency
Built with
Java34%
TypeScript27%
Scala26%
Updated 1 weeks 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

Search