# Batteries Included is the OCaml community's answer to a standard library nobody shipped

> Batteries Included is a community-maintained foundation library for OCaml that bundles a standard set of modules behind one consistent API. It ships under a permissive ISC-style licence, is built with dune, and still carries an ExtLib compatibility layer.

**ocaml-batteries-team/batteries-included** — Batteries Included project

- Repository: https://github.com/ocaml-batteries-team/batteries-included
- Website: http://ocaml-batteries-team.github.com/batteries-included/hdoc2/
- Stars: 524 · Forks: 108
- Language: OCaml
- License: NOASSERTION
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/ocaml-batteries-team-batteries-included

## A standard set of libraries that OCaml itself never shipped

OCaml Batteries Included, or just Batteries, is a community-maintained foundation library for OCaml projects. The README states three properties, and they explain the project better than the name does.

It defines a standard set of libraries which may be expected on every compliant installation of OCaml. It organizes these libraries into a hierarchy of modules, with a single source of documentation. And it provides a consistent API for otherwise independent libraries.

That third point is the one that is hardest to achieve on your own. The OCaml ecosystem has long had many small, well-written libraries that do one thing, each with its own naming, its own exception conventions, its own option and result types, and its own idea of how to represent a map. The pain this creates is not that any individual library is bad, it is that using three of them together means three different ways to spell the same concept. Batteries takes the position that the ecosystem should converge on one set of module names and one API shape, and it re-exports the alternatives behind that shape.

The scope is explicitly a foundation rather than an application framework. It is the layer you build on, not the layer you write your program in. The people it is for are OCaml developers who are assembling a project out of libraries and want the plumbing to be uniform.

The name is a play on the phrase for a device that ships with everything you need to operate it, and it is a slight jab at the standard library, which in the OCaml world has always been deliberately minimal. Batteries is the community's alternative answer to that minimalism, built by a group rather than by the language designers.

## The build is dune, and the Makefile is a thin wrapper

The repository builds with dune, and the Makefile exists mostly so that the familiar make targets keep working. The mapping is short enough to see the whole build system at once:

```make
all:
	dune build @all

install:
	dune build @install
	dune install

test:
	dune runtest
```

So make all builds everything, make install installs it, make test runs the test suite through dune, and make clean runs dune clean. The doc target builds both the library and its documentation, and there is a test_install target that runs a script from scripts/ to check the installation actually works, which is a sensible thing to have for a library whose whole purpose is being found and used by other tools.

There are also targets that reveal the project's history. A bench target runs the benchmark suite and tees output into bench.log, echoing that benchmarking results are written to bench.log. A release target stashes local modifications, then calls release-cleaned, which assumes an irreproachably pristine working directory, runs doc and test-native, and produces a tarball named after the VERSION file through git archive piped into gzip. The upload-docs target builds the documentation, copies it into an hdoc2/ directory on the gh-pages branch and pushes it, which is how the hosted documentation gets updated.

The release process being a git archive of a tagged commit rather than a build of a working directory is a good sign, since it means the published tarball is exactly what is in the repository. The VERSION file, the batteries.opam file and a dune-project file are all present at the top level, alongside a ChangeLog, a FAQ and a README.folders describing the folder layout.

## The requirements list tells you what era of OCaml this targets

The build requirements are stated in the README and they are specific enough to date the project.

You need OCaml 3.12.1 or newer, Findlib 1.5.3 or newer, and GNU make. Then there are three optional pieces, all for tests. OUnit to build and run the tests, qtest 2.0.1 or newer to build and run the tests, and ocaml-benchmark to build and run the performance tests.

That the test tooling is optional is itself informative. It means the library compiles and installs without any of them, so a downstream user who only wants the library does not need a test framework, and a developer adding a module to the tree can build and install without pulling the test stack.

The two test tools have different jobs. qtest is a quick test framework, and the project carries a qtest/ directory at the top level, plus a batteries_dev.el Emacs file that has extra highlighting to support writing quicktests, so quicktesting is a first-class part of the development workflow rather than an afterthought.

There is a benchsuite/ directory and a examples/ directory that contains a benchmark folder alongside euler, pleac, snippets and tools subfolders. The presence of a pleac directory is a nod to the classic Perl/Python feature comparison, and examples/ is where the per-module example code lives.

The two exported environment variables are worth knowing about. DOCROOT sets where the documentation is installed, and the README warns that you must set it before starting the build because this location is stored in the Batteries_config module generated during compilation. BATTERIES_NATIVE=false disables native compilation, and BATTERIES_NATIVE_SHLIB=false disables building of native shared libraries. The second one matters if you are targeting a platform where native shared libraries are a problem.

## The ExtLib compatibility note is the sharpest edge in the README

If your project currently uses ExtLib, the README says most likely you can just change -package extlib to -package batteries and add open ExtLib to the top of any extlib-using modules.

The reason that works is the module naming scheme. Batteries' modules are all named BatFoo to differentiate them from ExtLib's modules, so one can use Batteries and ExtLib in the same project. The open ExtLib line then gives you the original names, and the Bat-prefixed names coexist without collision.

The compatibility note is a warning rather than a guarantee. If you're using ExtLib's Unzip module, it does not have a corresponding module in batteries at the moment. One gap, but it is exactly the kind of gap that bites when you assume the swap is mechanical.

So the migration story is: mostly a package name change plus an open, with the module names changing to the Bat-prefixed forms and one documented hole. That is a much better migration than most reimplementations of a standard library offer, because the two libraries can sit side by side in one project while you move module by module.

The FAQ file at the top of the repository and the ChangeLog are the two places to look before you commit, since the FAQ presumably covers the recurring migration questions and the ChangeLog is where removals and additions get recorded. The hosted documentation is generated with hdoc2, and the project's own hdoc2/ directory on the gh-pages branch is what the upload-docs target updates.

## Getting started at the toplevel, and how the project is organised

To get started using Batteries at the toplevel, the README says to copy the ocamlinit file to your ~/.ocamlinit:

```bash
    $ cp ocamlinit ~/.ocamlinit
```

If you already have findlib in your ~/.ocamlinit, you only need the last line in the project's ocamlinit to load batteries. That detail is a real convenience, since it means you can add Batteries to an existing setup without rewriting the file.

The toplevel/ directory at the top of the repository is where that ocamlinit comes from, and the rest of the tree shows how a foundation library is organised in practice. There is src/ for the library source, testsuite/ for the main test suite, test-build/ for build-level tests, qtest/ for the quick test framework, benchsuite/ for performance tests, examples/ for the example code, howto/ for how-to documentation, build/ for build support, scripts/ for helper scripts, and plot/ as a top-level entry.

The presence of a plot entry is curious and worth a note, since it is not a directory in the listing but a plain entry alongside the others. Whatever it holds, it is small enough to sit at the root.

The README also points at the batteries-included wiki for more usage help, and there is a separate guidelines wiki page for developers who want to extend the library. Extending a shared foundation library is a different activity from using one, and the project has a separate document for it, which is a sensible sign of how seriously it treats the API surface.

The .github/ directory, .travis.yml and .travis.sh indicate continuous integration on Travis, and the .mailmap file is the kind of housekeeping that matters in a project with many contributors over a long history.

## Where Batteries Included is the wrong tool

The first wrong-tool case is a project that deliberately wants few dependencies. Batteries is a bundle by definition. If your team has a policy of depending only on what you use, then pulling in a foundation layer to get, say, a map and a string module is the wrong move, because you take the maintenance and version surface of the whole bundle for a fraction of its contents. The trade is only worth it when you are actually using a substantial part of it.

The second case is a project that needs a module Batteries does not have, or has removed. The Unzip gap is the documented example, and the general problem is that a foundation library is a fixed surface. Anything outside it means writing your own or reaching for another dependency, which reintroduces the inconsistency the library was meant to remove.

The third case is a team that needs a guaranteed support commitment. Batteries is a community project, and the version history shows long gaps between releases: 3.11.0 on 2026-06-25, 3.10.0 on 2025-10-07, and then 3.3.0 back on 2021-03-02. The last push to the repository was on 2026-06-25, so the tree is being maintained, but a multi-year gap in the middle of that list shows that a release is not something you can schedule against.

The alternative approach is to pick one library per need and manage the inconsistency yourself, which is what a lot of OCaml code does and what ExtLib was an attempt to fix. The difference in approach is that ExtLib-style aggregation is a thin naming layer over a curated set of third-party libraries with their own maintenance, whereas Batteries is a single repository with one coordinated API, one documentation source and one build, so the versions move together and the module boundaries are consistent. If your project is small and uses two libraries, the second approach costs you nothing. If you are assembling a service out of eight libraries, the first is what stops the module names from multiplying.

There is also the option of the standard library plus the ecosystem's own modern choices, but that path means making the consistency decision yourself, and it is the decision Batteries has already made for you.

## A permissive licence, and a version number that moves in steps

The licence recorded for the repository is a custom one that GitHub cannot classify, so the LICENSE file is the text that governs use. The project describes itself as community-maintained and the ecosystem it serves is the OCaml one, where permissive licences are the norm and the source is permissively licensed in practice.

This is a documentation point rather than legal advice, and the practical reason to read the LICENSE file yourself is simple: for a library that a large number of downstream projects depend on, the exact terms matter, and the classification field on the repository page is not going to tell you anything.

On versions, the pattern is worth understanding. The recent releases are 3.11.0 on 2026-06-25, 3.10.0 on 2025-10-07 and 3.3.0, described as a minor release, on 2021-03-02. So the project uses a three-component version, and 3.11.0 to 3.3.0 is not a downgrade, it is a jump through the minor series. The gap between 3.3.0 and 3.10.0 covers a long period with the version climbing by minor increments, which is consistent with a library that adds modules over time without breaking changes.

The default branch is master, and the release tarball is produced from a git archive of a tagged commit named batteries-$(VERSION), so the version in the tarball and the version in the VERSION file are the same thing.

Taken together, the picture is of a project with a long history, a permissively licensed, coordinated API, an actively maintained tree, and a release cadence that moves in irregular steps. Pin an exact version in your opam file rather than a floating constraint, and read the ChangeLog between the version you are on and the one you are moving to.

## Conclusion

Batteries Included suits an OCaml developer who wants a batteries-included base of data structures, file and process helpers, and a uniform API across independent libraries, and who is comfortable with a community-run foundation layer. It does not suit someone who wants a small dependency footprint, since the whole point is bundling, nor someone who needs the modules ExtLib provided and Batteries dropped, such as Unzip. Before adopting, read the FAQ and ChangeLog for the current module set, confirm the OCaml and Findlib versions you have meet the stated requirements, and check the licence file, since GitHub cannot classify it.

## FAQ

### What is OCaml Batteries Included?

It is a community-maintained foundation library for OCaml projects. It defines a standard set of libraries that may be expected on every compliant OCaml installation, organizes them into a hierarchy of modules with a single source of documentation, and provides a consistent API across otherwise independent libraries.

### How do I build and install Batteries Included?

Run `make all` to build it, `make test` to run the test suite, and `sudo make install` to install. The Makefile targets wrap dune commands, so `dune build @all` and `dune install` do the same work directly.

### Can I use Batteries Included alongside ExtLib?

Yes. Change -package extlib to -package batteries and add open ExtLib to your modules. Batteries' modules are all named BatFoo so the two libraries can coexist in one project, though ExtLib's Unzip module has no Batteries counterpart.

### What do I need to build Batteries Included from source?

OCaml 3.12.1 or newer, Findlib 1.5.3 or newer, and GNU make. OUnit, qtest 2.0.1 or newer and ocaml-benchmark are optional and only needed to build and run the tests and performance tests.

## Sources

- [Issues](https://github.com/ocaml-batteries-team/batteries-included/issues)
- [ocaml-batteries-team/batteries-included on GitHub](https://github.com/ocaml-batteries-team/batteries-included)
- [Project website](http://ocaml-batteries-team.github.com/batteries-included/hdoc2/)
- [README](https://github.com/ocaml-batteries-team/batteries-included/blob/master/README.md)
- [Releases](https://github.com/ocaml-batteries-team/batteries-included/releases)

---

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