# How to include version information from dune-project

**URL:** https://discuss.ocaml.org/t/how-to-include-version-information-from-dune-project/17699
**Category:** Learning
**Tags:** dune
**Created:** [January 15, 2026, 5:10pm UTC](https://discuss.ocaml.org/t/how-to-include-version-information-from-dune-project/17699 "2026-01-15T17:10:35Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![eureka-cpu](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/eureka-cpu/32/6351_2.png) [@eureka-cpu](https://discuss.ocaml.org/u/eureka-cpu)
#### Post date: [January 15, 2026, 5:10pm UTC](https://discuss.ocaml.org/t/how-to-include-version-information-from-dune-project/17699/1 "2026-01-15T17:10:35Z")

</div>

Howdy, I’m wanting to include the version of my package in a command line app I wrote and a quick search on github shows there’s a Dune\_project.version. I asked GPT about this and it told me to add (version X.X.X) to my dune-project file, then be sure to have (public\_name \<NAME\>) in my lib/bin dune files. I’ve done this but I still get an unbound module error. What is the canonical way of getting package version information into bin/lib so it can be accessed?

---

<div class="post-metadata">

### Author: ![shonfeder](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/shonfeder/32/424_2.png) [@shonfeder](https://discuss.ocaml.org/u/shonfeder)
#### Post date: [January 15, 2026, 6:53pm UTC](https://discuss.ocaml.org/t/how-to-include-version-information-from-dune-project/17699/2 "2026-01-15T18:53:31Z")

</div>

AFAIK, the blessed way to include version information in dune is via [`dune subst`](https://dune.readthedocs.io/en/latest/usage.html#dune-subst)

---

<div class="post-metadata">

### Author: ![eureka-cpu](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/eureka-cpu/32/6351_2.png) [@eureka-cpu](https://discuss.ocaml.org/u/eureka-cpu)
#### Post date: [January 15, 2026, 11:55pm UTC](https://discuss.ocaml.org/t/how-to-include-version-information-from-dune-project/17699/3 "2026-01-15T23:55:01Z")

</div>

Somehow this feels wrong 😅 I was hoping there was a way similar to how cargo handles the version in the package info.

---

<div class="post-metadata">

### Author: ![jrfondren](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jrfondren/32/3871_2.png) [@jrfondren](https://discuss.ocaml.org/u/jrfondren)
#### Post date: [January 16, 2026, 1:28am UTC](https://discuss.ocaml.org/t/how-to-include-version-information-from-dune-project/17699/4 "2026-01-16T01:28:01Z")

</div>

if it makes you feel better it reminds me most of an old Subversion feature: [https://svnbook.red-bean.com/en/1.6/svn.advanced.props.special.keywords.html](https://svnbook.red-bean.com/en/1.6/svn.advanced.props.special.keywords.html) e.g. `$Revision$` in files.

---

<div class="post-metadata">

### Author: ![eureka-cpu](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/eureka-cpu/32/6351_2.png) [@eureka-cpu](https://discuss.ocaml.org/u/eureka-cpu)
#### Post date: [January 16, 2026, 2:12am UTC](https://discuss.ocaml.org/t/how-to-include-version-information-from-dune-project/17699/5 "2026-01-16T02:12:10Z")

</div>

Hm, perhaps this is an opportunity to just write something. I assume there is a an existing lib for parsing a dune file?

---

<div class="post-metadata">

### Author: ![shonfeder](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/shonfeder/32/424_2.png) [@shonfeder](https://discuss.ocaml.org/u/shonfeder)
#### Post date: [January 16, 2026, 2:12am UTC](https://discuss.ocaml.org/t/how-to-include-version-information-from-dune-project/17699/6 "2026-01-16T02:12:54Z")

</div>

> [@eureka-cpu](#):
>
> Somehow this feels wrong 😅 I was hoping there was a way similar to how cargo handles the version in the package info.

In case it feels better, you could do something like this:

```auto
$ cat dune-project | rg package -A 5
(package
 (name foo)
 (version 1.1)
 (synopsis "Short description")
 (description "Longer description")
 (depends

$ tree version/
version/
└── dune

1 directory, 1 file

$ cat version/dune 
(library
 (name version))

(rule
 (action
  (with-stdout-to
   version.ml
   (run echo "let v = \"%{version:foo}\""))))

$ tree bin/
bin/
├── dune
└── foo.ml

1 directory, 2 files

$ cat bin/dune
(executable
 (public_name foo)
 (libraries version))
↳[0]

$ cat bin/foo.ml 
let () = print_endline Version.v

$ dune exec foo
1.1                                 

```

using the `version:<package>` variable documented at [Variables - Dune documentation](https://dune.readthedocs.io/en/stable/concepts/variables.html#variables)

The `dune subst` approach feels right to me, so it’s not clear to me how to motivate a need for this, but you could of course write something if you feel motivated! You could also [start a discussion on the dune repo](https://github.com/ocaml/dune/blob/main/CONTRIBUTING.md) if you think there’s a good case to be made for this kind of addition.

---

<div class="post-metadata">

### Author: ![eureka-cpu](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/eureka-cpu/32/6351_2.png) [@eureka-cpu](https://discuss.ocaml.org/u/eureka-cpu)
#### Post date: [January 16, 2026, 2:37am UTC](https://discuss.ocaml.org/t/how-to-include-version-information-from-dune-project/17699/7 "2026-01-16T02:37:58Z")

</div>

Ah yeah I saw this too but it also feels a bit wrong. I was really hoping for something akin to the cargo package parsing that happens in the clap crate. It just parses the toml and gets the version from there at compile time without needing to substitute a string, or run commands to generate code. If it makes life easier for someone (even if that someone is just me), I think it’s worth writing a small utility that does the same.

---

<div class="post-metadata">

### Author: ![shonfeder](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/shonfeder/32/424_2.png) [@shonfeder](https://discuss.ocaml.org/u/shonfeder)
#### Post date: [January 16, 2026, 3:00am UTC](https://discuss.ocaml.org/t/how-to-include-version-information-from-dune-project/17699/8 "2026-01-16T03:00:52Z")

</div>

Follow your heart 🙂

---

<div class="post-metadata">

### Author: ![eureka-cpu](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/eureka-cpu/32/6351_2.png) [@eureka-cpu](https://discuss.ocaml.org/u/eureka-cpu)
#### Post date: [January 16, 2026, 4:31am UTC](https://discuss.ocaml.org/t/how-to-include-version-information-from-dune-project/17699/9 "2026-01-16T04:31:44Z")

</div>

So this might actually be doable. Since dune knows the version, and there is a library `ppxlib` with a function [`ppx_get_env`](https://ocaml-ppx.github.io/ppxlib/ppxlib/examples.html#ppx_get_env) which can read an environment variable and expand the macro into a string at compile time. If there’s a way to set the environment variable from dune’s end (maybe a rule, I’m not super familiar with dune yet) and then use `ppxlib` to get that environment variable, it avoids needing the extra file and I can get the version from the dune-project as a singular source of truth for the version. There’s also an example repo with a deriver, which would be cool to then use on `cmdliner`’s `Cmd.Info` to auto-derive the version. This is probably as close to the rust/cargo/clap way of doing it as I imagine I will get. In rust you can just do:

```rust
use clap::{Command, Parser};

#[derive(Debug, Clone, Parser)]
#[command(version)]
struct MyCommand;

```

And this will just get the version from the `Cargo.toml`

```toml
[package]
version = "0.1.0"
...

```

I think there’s a few things it can automatically get from the `Cargo.toml`, so maybe once I get the version portion working I will also include other derivers.

---

<div class="post-metadata">

### Author: ![eureka-cpu](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/eureka-cpu/32/6351_2.png) [@eureka-cpu](https://discuss.ocaml.org/u/eureka-cpu)
#### Post date: [January 16, 2026, 7:27am UTC](https://discuss.ocaml.org/t/how-to-include-version-information-from-dune-project/17699/10 "2026-01-16T07:27:41Z")

</div>

OK, well. Unfortunately, `%{version:<pkg>}` is only available through actions. You can set environment variables that way, but I don’t think it will make it to the compiler in time. 🙁

Perhaps the only way would either to see if dune is willing to make the project metadata available at compile time, then something similar to this would be possible: [macros.rs - source](https://docs.rs/clap_builder/4.5.54/src/clap_builder/macros.rs.html#131)

Or maybe there is another way, but I’m not sure.

---

<div class="post-metadata">

### Author: ![n-osborne](https://avatars.discourse-cdn.com/v4/letter/n/4da419/32.png) [@n-osborne](https://discuss.ocaml.org/u/n-osborne)
#### Post date: [January 16, 2026, 8:29am UTC](https://discuss.ocaml.org/t/how-to-include-version-information-from-dune-project/17699/11 "2026-01-16T08:29:42Z")

</div>

There is the `dune-build-info` library: [Dune Libraries - Dune documentation](https://dune.readthedocs.io/en/stable/dune-libs.html#build-info)

---

<div class="post-metadata">

### Author: ![eureka-cpu](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/eureka-cpu/32/6351_2.png) [@eureka-cpu](https://discuss.ocaml.org/u/eureka-cpu)
#### Post date: [January 16, 2026, 8:40am UTC](https://discuss.ocaml.org/t/how-to-include-version-information-from-dune-project/17699/12 "2026-01-16T08:40:55Z")

</div>

Ah cool, thank you. I just opened a discussion on the dune repo [Consider `dune-project` environment variables · ocaml/dune · Discussion #13329 · GitHub](https://github.com/ocaml/dune/discussions/13329) but I will try this for the time being.

---

<div class="post-metadata">

### Author: ![eureka-cpu](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/eureka-cpu/32/6351_2.png) [@eureka-cpu](https://discuss.ocaml.org/u/eureka-cpu)
#### Post date: [January 17, 2026, 7:56am UTC](https://discuss.ocaml.org/t/how-to-include-version-information-from-dune-project/17699/13 "2026-01-17T07:56:53Z")

</div>

For the time being I ended up using `dune-build-info` to get the version information (though other information would also be nice to have) and on the nix side I wrote this parser which makes it much easier to set it and forget it on the nix side of things.

> **[GitHub - eureka-cpu/dunix: Parse dune-project files into nix expressions.](https://github.com/eureka-cpu/dunix)**
>
> Parse dune-project files into nix expressions.
