# \[ANN\] ocamlgrep 0.1.1

**URL:** <https://discuss.ocaml.org/t/ann-ocamlgrep-0-1-1/18350>\
**Category:** Community\
**Tags:** announce\
**Created:** [July 13, 2026, 7:14am UTC](https://discuss.ocaml.org/t/ann-ocamlgrep-0-1-1/18350 "2026-07-13T07:14:13Z")\
**Posts on this page:** 1\
**Showing post:** 1

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [July 13, 2026, 7:14am UTC](https://discuss.ocaml.org/t/ann-ocamlgrep-0-1-1/18350/1 "2026-07-13T07:14:13Z")

</div>

We are happy to announce the first public release of `ocamlgrep`, a tool for structural grepping of OCaml code.

This tool has existed within the walls of LexiFi for a long time and we were keen on open-sourcing it, but it was not in a form that could be used by the wider public. Now, thanks to the work of @mjambon, we are able to to finally do so.

> **[Release 0.1.1 · LexiFi/ocamlgrep](https://github.com/LexiFi/ocamlgrep/releases/tag/0.1.1)**
>
> CHANGES:
> 
> Fix the build so as to not require test-only dependencies for the
> main build (#20).
> Add a --dune-root option that allows running ocamlgrep on a Dune
> project built with --root such as a te...

To install:

```auto
$ opam install ocamlgrep

```

The idea behind the tool is simple: you call it from within your Dune project\[1\] with a query (after having built all `.cmt`/`.cmti` artifacts, eg by doing `dune build @check`), and the tool returns the list of matches it can find in the source tree. A _query_ is syntactically an OCaml expression, possibly with _holes_ `__` in it. Some examples follow to give an idea of how the tool is used in practice.

The following query searches for the anti-pattern `List.rev e1 @ e2` (where `e1` and `e2` are arbitrary expressions.

```auto
$ ocamlgrep 'List.rev __@__ `

```

Note that as the tool works at the level of the OCaml AST, it will also match expressions of the form `(@) (e1 |> List.rev) e2`, since they produce the same AST.

The syntax of type constraints `(e : ty)` is overloaded to impose a type condition on the search term. For example, the following search query looks for function calls where the first argument is an `int` and the second one a `string`.

```auto
$ ocamlgrep '__(__ : int) (__ : string)'

```

The _holes_ can be numbered, ` __1`, `__ 2`, etc, to express repetitions of the same term. For example, the following query searches for a pattern matching on an option that sends `Some x` to `Some x` (ie reconstructing the same value):

```auto
$ ocamlgrep 'match __with Some__ 1 -> Some __1 | None ->__'

```

We can also look for applications of the polymorphic operator `=` applied to `float` arguments:

```auto
$ ocamlgrep '(__: float) =__'

```

Historically, this tool has been useful for large-scale refactorings and linting of our codebase. Nowadays, such refactorings can often be done using AI agents. However, the tool is still able to do things that seem a bit beyond of what AI agents can do today, eg to look for applications of polymorphic functions where one of the arguments is of a specific type. This was for example useful when [migrating](https://www.lexifi.com/blog/ocaml/floatarray-migration/) our codebase to `no-flat-float-array` mode, where we wanted to make sure that polymorphic array operations were not being applied to `float array` values.

Happy grepping!

Cheers,  
Nicolas

* * *

1. Only Dune projects are supported for now. Adding support for other build systems should not be very hard, issues and/or PRs are welcome.

---

_[View the full topic](https://discuss.ocaml.org/t/ann-ocamlgrep-0-1-1/18350)._
