# Peggy turns a grammar into a parser, and its own grammar is written in Peggy

> Peggy is a MIT licensed parser generator for JavaScript and the successor to PEG.js, taking a grammar and producing a fast parser with good error reporting, usable from a browser, from a command line or through a JavaScript API, with source map support. The migration from PEG.js is a rename, and the project parses its own options grammar with itself.

**peggyjs/peggy** — Peggy: Parser generator for JavaScript

- Repository: https://github.com/peggyjs/peggy
- Website: https://peggyjs.org/
- Stars: 1,185 · Forks: 79
- Language: JavaScript
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/peggyjs-peggy

## A generator that targets three environments at once

Peggy is described as a simple parser generator for JavaScript that produces fast parsers with excellent error reporting, and the stated use is to process complex data or computer languages and build transformers, interpreters, compilers and other tools easily.

The three environments in the feature list are the interesting part, because they determine what the generated code has to look like. It is usable from your browser, from the command line, or via the JavaScript API. A grammar that is compiled in a browser has to be self contained, which is why the package ships a browser bundle at browser/peggy.min.js, exposed through the unpkg and jsdelivr fields in the package metadata, and why the package's main entry is lib/peg.js with types at lib/peg.d.ts.

The two other claims in the feature list are about the grammar model and the diagnostics. The grammar syntax is described as simple and expressive, and the generator integrates both lexical and syntactical analysis, which means you do not need a separate tokenizer grammar and parser grammar in the way some tools require. Parsers have excellent error reporting out of the box, and the formalism is parsing expression grammar, which the README describes as more powerful than traditional LL(k) and LR(k) parsers.

That last comparison needs the usual caveat. PEG gets its expressiveness partly from ordered choice, which means a rule can commit to an alternative and then fail, where an LR parser would backtrack at the token level. The practical result is that a PEG grammar is far easier to write by hand, and that some grammars that are easy in LR are awkward in PEG. The trade is real and it is the right trade for a DSL or a config format, where the grammar is written once by hand and read many times.

## The online version is the fastest way to try a grammar

The Getting Started section is short, and it points at the browser version as the easiest way to generate a parser. You enter your grammar, try parsing a few inputs, and download the generated parser code.

That is the workflow the project is designed around, and it is a good one. A grammar is the kind of artefact where the feedback loop matters more than the theory, and a page where you can type a grammar, type an input, see the parse tree or the error, and adjust is exactly the tool for that loop.

The generated code is what you take away, and it is a normal JavaScript module. The package metadata shows how it ships, with main at lib/peg.js, types at lib/peg.d.ts, the browser bundle at browser/peggy.min.js, and a bin entry mapping the peggy command to bin/peggy.js. The published files are AUTHORS, the bin directory with its type definitions, lib and browser.

For a project that will generate parsers at build time rather than by hand, the same generator is available from the command line, and the documentation site at peggyjs.org carries the full reference, with the project wiki and the GitHub Discussions board as the places for questions.

## Migrating from PEG.js is a rename and a reinstall

Peggy is the successor of PEG.js, and the migration section is refreshingly short, which tells you how much the project invested in keeping the ecosystem intact.

Peggy version 1.x.x is API compatible with the most recent PEG.js release. The steps are: uninstall pegjs, and if you use the DefinitelyTyped definitions, uninstall @types/pegjs as well, because peggy now includes type definitions as part of the package itself. Then replace all require("pegjs") or import statements from "pegjs" with the peggy equivalent, and change any scripts that use the pegjs command line tool to use peggy instead.

That is the whole procedure, and it is a good model for a project taking over from a popular predecessor. The API compatibility means the code that calls the parser does not change, the type definitions move from a separate package into the project, and the command line tool keeps its shape.

The caveat is in the sentence that says version 1.x.x is compatible with the most recent PEG.js release. That is a statement about the 1.x line, and the project is now at 5.1.0. The compatibility guarantee is a historical fact about a particular version pair rather than a promise about the current release, so a team upgrading from a recent PEG.js to Peggy 5 should read the changelog rather than assume the rename is still sufficient.

## The project parses its own options with its own generator

The development section of the README contains a detail that says more about the project than any feature list: the parser script is Peggy generating a parser.

In the package scripts, the parser target runs node bin/peggy.js -c src/opts.mjs, which is Peggy compiling the options module that defines how the command line tool is configured. Peggy is self hosting, which is a nice property for a parser generator, because the grammar of the tool's own configuration is parsed by the tool.

The examples directory shows the range of what the tool is pointed at in practice, and the filenames are a catalogue of the usual suspects. There is arithmetics.pegjs and fizzbuzz.peggy for the arithmetic and tutorial cases, css.pegjs for a stylesheet grammar, javascript.pegjs for a JavaScript grammar, json.pegjs for JSON, semver.peggy for semantic version strings, source-mappings.peggy for source map data, and xml.peggy for XML. The .pegjs extension on some of them is a small historical marker, since the older files kept the name their predecessor used.

The build itself is a modern JavaScript toolchain. The project uses pnpm with a workspace, Jest for the unit tests run with node --experimental-vm-modules, ESLint for linting, tsup for the TypeScript build, and a webpack step in the build script. There is a separate web-test directory with its own npm project for the browser test suite, and a benchmark directory with a run_bench.js script, which is wired to a browser benchmark suite published on the project site.

The development setup, if you want to work on Peggy itself, is a clone, an npm install, an install in the docs and web-test directories, and then a build and the web tests:

```bash
git clone https://github.com/peggyjs/peggy.git
cd peggy
npm install
(cd docs && npm install)
(cd web-test && npm install)
npm run build
npm run test:web
```

## Source maps decide how debuggable the generated parser is

One feature in the list deserves more attention than it usually gets: source map support.

A parser generator produces code that nobody wrote and everybody has to debug, because the stack trace in a user's browser points at a line in a generated file. Source maps are the difference between a stack trace that points at rule 12 of your grammar and one that points at a character offset in a minified bundle. There is an example grammar in the repository for source mappings, source-mappings.peggy, which suggests the maintainers treat it as a first class case rather than an afterthought.

The same concern shows up in the browser build. The browser bundle at browser/peggy.min.js is minified, and the package metadata wires it into unpkg and jsdelivr so it can be loaded straight from a script tag. The build scripts show a headers target that stamps a licence header onto the generated browser and documentation bundles, and a deploy target that copies the browser bundle into the docs vendor directory, so the online version at peggyjs.org and the published package ship the same artefact.

The test infrastructure is where this gets verified. The npm scripts separate the unit tests from the web tests, with test running Jest and test:web running the browser suite in the web-test directory, and test:all running both. The browser test suite and the browser benchmark suite are both published on the project site, which means the generated parsers are exercised in a real browser and measured there, rather than only in Node.

## One maintainer, a clear contribution policy, and an MIT licence

Peggy was originally developed by David Majda and is currently maintained by Joe Hildebrand, and the README is direct about how contributions should happen. Pull requests are welcome, but unless your contribution is really trivial you should get in touch first on the Discord server, and the stated reason is that this can prevent wasted effort on both sides.

That is a reasonable policy for a project with this much grammar design in it, since a change to the generator's behaviour has a much larger blast radius than a change to an application. It also means that a substantial feature proposal is more likely to end in a discussion than a pull request, which is the trade a small maintainer team makes to stay in control of the design.

The project is MIT licensed, with the licence file at the root of the repository, and the version line has been steady. The recent releases are 5.1.0 in March 2026, 5.0.6 in August 2025 and 5.0.5 in July 2025, and the repository is not archived with the last push on 2026-10-13.

For a team choosing a parser generator, the practical checklist is short. Decide whether the PEG model fits your grammar, which for most configuration formats and small languages it does, and check the things that would hurt if they were missing, in particular error message quality, source map support, and whether the generated parser runs in the environments you need, since the browser bundle and the Node entry point are both first class here.

## Conclusion

Peggy suits a JavaScript team that needs a parser for a configuration format, a DSL or a small language and would rather write a grammar than hand code a tokenizer and a recursive descent parser, especially where the error messages matter to the people using the format. It does not suit a project that needs an LR parser's determinism guarantees, and it is the wrong tool when the grammar has to be extended by people who will not learn a DSL. Verify first that the constructs your grammar needs are covered by the PEG model, in particular the lack of left recursion, and check the source map support and the browser bundle if you plan to ship the parser to a front end, because the generated code is a build artefact and its debuggability depends on that.

## FAQ

### What is Peggy and what is it used for?

Peggy is a parser generator for JavaScript that produces fast parsers with excellent error reporting, and it is meant for processing complex data or computer languages, for building transformers, interpreters, compilers and other tools. It is the successor of PEG.js.

### How do I migrate from PEG.js to Peggy?

Uninstall pegjs and, if you use them, the @types/pegjs definitions, because Peggy now ships its own types, then replace the require or import of pegjs with peggy and change any pegjs command line usage to peggy. Peggy 1.x.x was API compatible with the most recent PEG.js release.

### Can I use Peggy in the browser?

Yes. The generator is usable from your browser, from the command line or via the JavaScript API, the package ships a browser bundle at browser/peggy.min.js exposed through unpkg and jsdelivr, and there is an online version at peggyjs.org/online where you can enter a grammar, try inputs and download the generated parser.

### What does the Peggy documentation cover?

Full documentation is available at peggyjs.org, and the project also has a wiki, an issue tracker, a Discussions board, a browser test suite and a browser benchmark suite.

### How do I build Peggy from source?

Clone the repository, run npm install, install the dependencies in the docs and web-test directories, then run npm run build and npm run test:web. The build uses pnpm workspaces, Jest for the unit tests, tsup for the TypeScript build and rollup for the bundles.

## Sources

- [License: MIT](https://github.com/peggyjs/peggy/blob/main/LICENSE)
- [peggyjs/peggy on GitHub](https://github.com/peggyjs/peggy)
- [Project website](https://peggyjs.org/)
- [README](https://github.com/peggyjs/peggy/blob/main/README.md)
- [Releases](https://github.com/peggyjs/peggy/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/peggyjs-peggy
