Setting up a new OCaml environment in 2026 is not yet a fluid experience

This is one that I remember running into and also can’t replicate easily.

What I might be remembering is that dune complains about the orphan .opam file if you change the name of the project:

$ dune init proj d1 && cd d1
d1$ sed -i 's/d1/d2/' dune-project
d1$ dune build
File "d1.opam", line 1, characters 0-0:
Error: This opam file doesn't have a corresponding (package ...) stanza in
the dune-project file. Since you have at least one other (package ...) stanza
in your dune-project file, you must a (package ...) stanza for each opam
package in your project.

deleting d1.opam and rebuilding indeed leaves you with a good d2.opam.

Guides try to provide the desired fluid experience by ushering you past the details of dune to get you right into a reasonable default project that can be worked with. But then, since an understanding of dune was skipped, anything it does that’s different is automatically frustrating. I’m using to verbose build systems and dune’s terse (“did my tests pass? did it even do anything?”). I’m used to build systems strictly working from the project root but dune works in relation to a dynamically found root. I’m used to a strict filesystem layout or exhaustive configuration in one file but dune’s much more flexible and has configuration distributed through ‘dune’ files.

With more of an understanding of dune, I like it a lot more. The impression I get from it is the same as I get from a lot of OCaml, that it’s aimed at reducing friction for more experienced users and is providing features that I don’t want yet. There’s a universe of alternatives that “just work” at the start but then get more frustrating as you want to do more with them. A build system that’s just a short bash script or a short Makefile is famously like this. A cargo hello-world .toml is no work at all (some guides even have you install a 128-dependency CLI program to edit dependencies into it for you) but a more advanced project has multiple such files that path to each other, and additional configuration like .cargo/config.toml, and a build.rs.

Giant YAML files have me really tired of configuration languages so I like Zig just making the build system part of the standard library, but that

  1. draws the same complaint that there’s more early-on friction
  2. in my experience, requires a lot more time and configuration work, and more frequent work. Dune stanzas are very little to type and very little to read and there’s a lot of development that I can do without having to touch them at all.

On OCaml generally optimizing for the more experienced user, I don’t mean that some more friction early on is always necessary, just that it’s given less attention. Take ocamlgraph’s docs. I used this library for the first time last month and I really like the library and the docs after I found some other help on even getting to “hello world” with it. Or fmt’s documentation which I got nothing out of until I found some Q&A here. For contrast, man rsync and man getaddrinfo and imitators like perldoc File::Find::Rule. There’s a synopsis which is expected to be all you need to immediately get some use, there’s a long description, there can be examples that you don’t have to go hunting for because they’re on the first page that you see.