Reason's build paths: dune for the build, esy for the tests, opam for the pin
Simple, fast & type safe code that leverages the JavaScript & OCaml ecosystems
At a glance
- What is it?
- The reasonml/reason repository is contributor infrastructure rather than an install guide: the README hands new users to reasonml.github.io and leaves the toolchain split across a Makefile. Several targets there promise more than they actually run, so a contributor reading them in order will mispredict what each one does.
- Who is it for?
- Reach for this repository if you already work in OCaml and want to work close to the JavaScript ecosystem; it is a compiler workspace with contributor docs, not a one command install. Before you rely on anything here, check reasonml.github.io for the documentation that matches the release you checked out, and read the Makefile targets instead of trusting their names, because testFormat runs no formatter and the coverage report silently skips files it cannot find.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly OCaml, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- reasonml/reason10,339 ★ · +15
| Repository | 2026-09-22 | 2026-11-14 |
|---|---|---|
| reasonml/reason | 10.3k | 10.3k |
15 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
dune builds, esy tests, and the README flow runs neither
Three toolchains meet in one Makefile. `default` depends on `build`, which runs `dune build`, so a bare `make` never reaches npm. Tests go the other way: `test` runs `esy dune runtest`, and `test-watch` adds `--watch`. Installation is a third path again, and the file comments that CI uses opam while the regular workflow need not. The command sequence the README gives contributors is yet another route, installing esy from npm before invoking it directly.
build:
dune build
test:
esy dune runtestnpm install -g esy@next
git clone https://github.com/reasonml/reason.git
cd reason
esy
esy test # Run the testsA contributor who clones and types `make test` without esy on the PATH gets a missing command, not a test failure.
testFormat runs a build and the test suite, and no formatter
The Makefile defines `testFormat: build test-once-installed`. The name promises a formatting check; the recipe delivers a compile and a test run, and nothing else. The repository root does carry `.ocamlformat` and `.ocamlformat-ignore`, so formatting configuration exists somewhere in the project, yet no rule in the Makefile invokes a formatter or diffs its output against the tree. If you rely on `make testFormat` to catch style drift before opening a pull request, nothing is caught. The README names no formatter command either.
make install pins the working tree into your opam switch
`install` runs `opam pin add reason. -y`. The `-y` answers the confirmation prompt for you, and the pin points the reason package at the current directory rather than at a published version, so your switch now resolves Reason from whatever sits on disk. `test-ci` chains `install` and `test-once-installed`, which means every continuous integration run repins before it tests. The next target is where the file admits a gap: the comment on `all-supported-ocaml-versions` says the `--dev` flag has been omitted and should be reintroduced eventually, so the command that claims to cover supported OCaml versions currently runs without that flag.
install:
opam pin add reason . -y
all-supported-ocaml-versions:
# the --dev flag has been omitted here but should be re-introduced eventually
dune build @install @runtest --root .package.json still says 3.6.2 while releases reach 3.18.0
The root `package.json` declares name `reason` and version `3.6.2`, sets `main` to `refmt.js`, and lists reason, ocaml, react, and javascript as keywords. The releases in this repository run ahead of that field: 3.18.0 on 2026-06-23, 3.17.3 on 2026-01-21, and 3.17.2 on 2025-11-30. The badge in the README points somewhere else entirely, tracking the latest version of the esy package published on npm under the name `@esy-ocaml/reason`. Three places can hand you a version number and they will not agree. Read the release tags or the npm badge instead of `package.json`, and if a script or CI job pins the `3.6.2` string, expect it to describe a build far older than the source you have checked out.
User documentation lives on a site and a repository that are not this one
The README sends every new user away from the source tree. It says the user docs live online at https://reasonml.github.io, gives the repository for those docs as github.com/reasonml/reasonml.github.io, and links a getting started page at https://reasonml.github.io/docs/en/installation plus a community page at https://reasonml.github.io/docs/en/community.html. What stays in this repository is the `docs/` directory, and the README scopes that directory to contributors to Reason itself rather than to people using it. After cloning you therefore have only the contributor build steps in the README, not a user installation guide, and the guide you consult is versioned independently of the tag you checked out.
Parser diagnostics come from a Menhir target that warns about CPU and memory
Changing the grammar requires a regeneration step that the Makefile exposes as `all_errors`, and the target prints a warning that this will take a while and use a lot of CPU and memory before it does anything.
menhir --explain --strict --unused-tokens src/reason-parser/reason_parser.mly --list-errors > src/reason-parser/reason_parser.messages.checked-inThe output path is a checked-in file, which means the human readable parser errors are versioned next to the grammar that produces them. That coupling cuts both ways. If you edit the grammar and skip the regeneration, the messages shown to users keep describing the older parser.
The coverage target deletes every bisect_ppx output before it measures
The `coverage` rule opens by removing artifacts and closes the same way.
coverage:
find -iname "bisect*.out" -exec rm {} \;
make test-once-installed
bisect-ppx-report -ignore-missing-files -I _build/ -html coverage-after/ bisect*.out ./*/*/*/bisect*.out
find -iname "bisect*.out" -exec rm {} \;Two limits follow from that shape. The report reads whatever the test run emitted, so a run that produces no `bisect*.out` files hands the reporter an empty set, and the `-ignore-missing-files` flag turns anything it cannot locate into a quiet skip rather than an error, which means a broken instrumentation run looks like a clean one. The second glob also reaches only three directory levels, so coverage output written deeper in the tree never reaches the report even when it exists.
Four build descriptors and a Nix flake share one repository root
The root holds `dune-project`, `esy.json`, `esy.lock.json`, `package.json`, and `reason.opam`, plus a second set for the REPL: `rtop.json`, `rtop.opam`, and `rtop.esy.lock/`. Alongside them sit `flake.nix` with `flake.lock`, a `nix/` directory, a `js/` directory, `scripts/`, and files named `PLAN`, `ORIGINS.md`, and `CHANGES.md`. The README covers only the esy steps, so the README does not say which descriptor is authoritative when they disagree, or what the `js/` and `nix/` directories are for. The Makefile hints at one more path: `esy-prepublish` runs `node ./scripts/esy-prepublish.js` to publish esy releases to npm, and `doc` runs `esy dune build @doc`.
Editorial conclusion
Reach for this repository if you already work in OCaml and want to work close to the JavaScript ecosystem; it is a compiler workspace with contributor docs, not a one command install. Before you rely on anything here, check reasonml.github.io for the documentation that matches the release you checked out, and read the Makefile targets instead of trusting their names, because testFormat runs no formatter and the coverage report silently skips files it cannot find.
Frequently asked questions
How do I run the Reason test suite from this repository?
The Makefile `test` target runs `esy dune runtest`, and `test-watch` adds `--watch` for a rerun loop. The README's contributing steps install esy first with `npm install -g esy@next` and then run `esy test`, so esy has to be on your PATH either way.
Which npm package carries Reason?
The README points at the native esy package on npm, published as `@esy-ocaml/reason`, and the version badge in the README reads the latest version from that package. The root `package.json` in the repository is named `reason` and does not carry the same version.
Does this repository's Makefile format the source?
No. `testFormat: build test-once-installed` depends on a build and the test suite, and no rule in the Makefile invokes a formatter, even though `.ocamlformat` and `.ocamlformat-ignore` are present in the repository root.
Where do I find the Reason user documentation?
The README says the user docs live online at https://reasonml.github.io, gives their repository as github.com/reasonml/reasonml.github.io, and links a getting started page at https://reasonml.github.io/docs/en/installation. The `docs/` directory in this repository is scoped to contributors to Reason itself.
What does `make install` do to an opam switch?
It runs `opam pin add reason . -y`, pointing the reason package at your current directory and answering the confirmation automatically. Since `test-ci` chains `install` with `test-once-installed`, every CI run repins the package before testing.
Is the Reason repository still maintained?
The repository is not archived and its last push was 2026-10-04, with release 3.18.0 published on 2026-06-23 after 3.17.3 on 2026-01-21 and 3.17.2 on 2025-11-30.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/reasonml-reason)Star history chart for your README
[](https://hysenlabs.com/projects/reasonml-reason)Was this useful?