configstore

Easily load and persist config without having to think about where and how it's stored on disk.

Library
npm
v8.0.0
892stars
BSD-2-Clause

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
51/100Fair
Development Activity36
Maintenance24
Community56
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
70/100Good
Architecture78
Code Quality85
Innovation72
Learning Curve45

Configstore is a minimal Node.js library from Sindre Sorhus for reading and writing a JSON config file without dealing with paths, directories, or platform conventions yourself. It resolves an XDG Base Directory-compliant location automatically (falling back to a temp directory when none is available), lazily creates the file and its parent directories only on first write, and exposes dot-notation get/set/has/delete methods on top of the underlying object.

Writes go through atomically’s atomic writeFileSync, so a crash mid-write can’t leave a half-written file, and corrupted JSON is either cleared back to an empty object automatically or surfaced as a SyntaxError depending on the clearInvalidConfig option. It’s a common building block behind CLI tooling for storing small amounts of local, non-sensitive state such as preferences, onboarding flags, or cached timestamps.

What You Get

  • A single Configstore class with get/set/has/delete/clear methods plus .all, .size, and .path accessors.
  • Automatic resolution of an XDG Base Directory-compliant config file path, created lazily only on first write.
  • Built-in handling for missing config files, corrupted JSON, and filesystem permission errors.
  • Dot-notation support for reading and writing nested properties without manual object traversal.

Common Use Cases

  • Persisting CLI tool preferences and settings across sessions
  • Storing first-run/onboarding flags for command-line applications
  • Caching timestamps or small state (e.g. last-update-check) for periodic background tasks
  • Backing lightweight local settings for Node tools that don’t want to hand-roll file I/O

Under The Hood

Architecture The whole module is a single class with private fields (#path, #clearInvalidConfig) built around a getter/setter pair on all that lazily reads or writes the JSON file only when accessed — every other method (get, set, has, delete, size) funnels through that same accessor rather than maintaining separate in-memory state. Each concern is delegated to a small, focused dependency: graceful-fs for resilient file operations, xdg-basedir for platform-correct path resolution, atomically for crash-safe atomic writes, dot-prop for nested-key access, and is-safe-filename for validating the id argument before it ever touches a path. This flat, single-file design means the storage format or path strategy can change by touching only the all getter/setter.

Tech Stack The package is ESM-only ("type": "module"), targets Node.js >=20, and ships hand-authored TypeScript declarations (index.d.ts) alongside plain JS rather than compiling from a TypeScript source — there’s no bundler or build step since it’s distributed as-is via npm. Its runtime dependencies (atomically, dot-prop, graceful-fs, is-safe-filename, xdg-basedir) are all small, single-purpose libraries from the same maintainer ecosystem; testing uses ava and linting uses xo, both run via a single test script, with CI configured under .github/workflows.

Code Quality test.js covers CRUD operations, dot-notation nesting, undefined/null value handling, both corrupted-JSON recovery modes (clearInvalidConfig true and false), custom and global config paths, recursive subdirectory creation, and constructor-level filename validation — using ava’s beforeEach hook to clean up state between tests for isolation. Error handling is explicit: ENOENT returns an empty object, SyntaxError triggers either automatic clearing or a re-thrown error depending on configuration, and EACCES gets a custom user-facing permission message appended before rethrowing. Naming is consistent with the maintainer’s other packages (private class fields prefixed with #, camelCase throughout), types are hand-maintained in index.d.ts with full TSDoc comments, and xo’s opinionated lint rules are enforced as part of the test script.

API Design The public surface is deliberately tiny — get/set/has/delete/clear plus .all, .size, and .path — and dot-notation support means nested config values need no manual traversal. Getting started requires a single constructor call with sensible defaults (an auto-resolved path, no required options), and the defaults parameter merges with any existing on-disk values automatically. The tradeoff for that minimalism is scope: the README itself points users toward conf (“a more modern version of configstore”) for additional features, so the design favors a small, stable API over the more complete conf/electron-store-style feature which has followed it as its own maintainer’s suggested upgrade path.

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