[Caml-list] Attn: Development Editor, Latest OCaml Weekly News

Alan Schmitt
2026-03-03T13:55:00Z

[-- Attachment #1: Type: text/plain, Size: 48919 bytes --]

Hello

Here is the latest OCaml Weekly News, for the week of February 24 to
March 03, 2026.

Table of Contents
─────────────────

Lwt.6.1.0, Lwt_ppx.6.1.0
OCaml Platform Newsletter: November 2025 to January 2026
Announcing the first release of Alice, a radical OCaml build system
mnet, a new TCP/IP stack for unikernels in OCaml
Experiment: format-line
Caml in the Capital - Registrations Open!
Experimental tools for migrating from Lwt to Eio
First alpha release of OCaml 5.5.0
NotInriaCaml_Std.Wenv@0.1.0 - create Windows envs on macOS [dk0]
Running Real Docker Containers in OCaml Tests
I wrote a DSL for AI personalities in OCaml
Outreachy May 2026
Old CWN

Lwt.6.1.0, Lwt_ppx.6.1.0
════════════════════════

Archive:
<https://discuss.ocaml.org/t/ann-lwt-6-1-0-lwt-ppx-6-1-0/17770/2>

Continuing this thread, Raphaël Proust announced
────────────────────────────────────────────────

Lwt.6.1.1 has been released. It contains a fix to support build with
OCaml.5.5. Thanks to @kit-ty-kate for the contribution.

OCaml Platform Newsletter: November 2025 to January 2026
════════════════════════════════════════════════════════

Archive:
<https://discuss.ocaml.org/t/ocaml-platform-newsletter-november-2025-to-january-2026/17845/1>

Sabine Schmaltz announced
─────────────────────────

Welcome to the seventeenth edition of the OCaml Platform newsletter!

In this November 2025 to January 2026 edition, we are excited to bring
you the latest on the OCaml Platform, continuing our tradition of
highlighting recent developments as seen in [previous editions]. To
understand the direction we're headed, especially regarding
development workflows and user experience improvements, check out our
[roadmap].

You can [subscribe to this newsletter on LinkedIn]!

*Highlights:*

• *opam 2.5.0 Released*: Major release featuring incremental opam file
loading for up to 70% faster `opam update', improved shell
integration, and better macOS sandbox support
• *Relocatable OCaml Merged*: The final piece of the relocatable OCaml
puzzle was merged in December, enabling opam to clone switches
instead of recompiling them. This will be available in the first
alpha release of OCaml 5.5
• *Dune 3.21.0*: Large release with dozens of fixes, improvements, and
new features including OxCaml compiler support and copy-on-write
file operations
• *Enhanced Editor Support*: OCaml-LSP 1.25.0 adds `.mlx' file support
with formatting, diagnostics, and code actions, plus new custom
requests
• *Merlin 5.6.1-504*: Performance optimizations, smarter signature
help, and fixed completion for inlined record labels
• *opam-publish 2.7.1*: Fixes for GitHub API token permissions
• *dune-release 2.2.0*: Full compatibility with cmdliner 2.0.0
• *opam-repository Archival*: January 1, 2026 archival run removed
3,264 package versions to maintain repository sustainability

*Backstage OCaml:*

• [OCaml Infrastructure: How the opam-repository Works] (Nov 5, 2025)

*Stable Releases:*

• [opam-publish 2.7.1] (Nov 18, 2025)
• [opam 2.5.0] (Nov 27, 2025)
• [Merlin 5.6.1-504] (Dec 20, 2025)
• [OCaml-LSP 1.25.0] (Dec 20, 2025)
• [Dune 3.21.0] (Jan 16, 2026)
• [dune-release 2.2.0] (Jan 29, 2026)

*Unstable Releases:*

• [opam 2.5.0~rc1] (Nov 20, 2025)
• [opam 2.5.0~beta1] (Nov 10, 2025)

[previous editions] <https://discuss.ocaml.org/tag/platform-newsletter>

[roadmap] <https://ocaml.org/docs/platform-roadmap>

[subscribe to this newsletter on LinkedIn]
<https://www.linkedin.com/newsletters/ocaml-platform-newsletter-7305270694567661568/>

[OCaml Infrastructure: How the opam-repository Works]
<https://ocaml.org/backstage/2025-11-05-how-the-opam-repository-works>

[opam-publish 2.7.1]
<https://ocaml.org/changelog/2025-11-18-opam-publish-2.7.1>

[opam 2.5.0] <https://ocaml.org/changelog/2025-11-27-opam-2.5.0>

[Merlin 5.6.1-504]
<https://ocaml.org/changelog/2025-12-20-merlin-v5-6-1-504>

[OCaml-LSP 1.25.0]
<https://ocaml.org/changelog/2025-12-20-ocaml-lsp-1-25-0>

[Dune 3.21.0] <https://ocaml.org/changelog/2026-01-16-dune-3-21-0>

[dune-release 2.2.0]
<https://ocaml.org/changelog/dune-release/2026-01-29-dune-release-2.2.0>

[opam 2.5.0~rc1] <https://ocaml.org/changelog/2025-11-20-opam-2-5-0-rc1>

[opam 2.5.0~beta1]
<https://ocaml.org/changelog/2025-11-10-opam-2-5-0-beta1>

OCaml Compiler
╌╌╌╌╌╌╌╌╌╌╌╌╌╌

◊ Relocatable OCaml Merged

In December 2025, the final piece of the [Relocatable OCaml] puzzle
was merged, enabling opam to clone switches instead of recompiling
them. This feature will be available in the first alpha release of
OCaml 5.5.

*What Relocatable OCaml Enables:*

This feature allows the OCaml compiler and its associated tools to be
moved to different filesystem locations after installation without
breaking functionality. Key benefits include:

• Binary distributions that work regardless of installation path
• Improved flexibility for package managers organizing OCaml
installations
• Bundling of specific OCaml versions by developer tools without path
conflicts
• Simplified cross-platform distribution

The implementation is the culmination of work by David Allsopp, with
review from Samuel Hym, Jonah Beckford, and others. See the
[announcement on Discuss] and the [merged PRs] ([#14244], [#14245],
[#14246], [#14247]) for technical details.

[Relocatable OCaml]
<https://www.dra27.uk/blog/platform/2025/12/17/its-merged.html>

[announcement on Discuss]
<https://discuss.ocaml.org/t/relocatable-ocaml/17253>

[merged PRs] <https://github.com/ocaml/ocaml/pull/14243>

[#14244] <https://github.com/ocaml/ocaml/pull/14244>

[#14245] <https://github.com/ocaml/ocaml/pull/14245>

[#14246] <https://github.com/ocaml/ocaml/pull/14246>

[#14247] <https://github.com/ocaml/ocaml/pull/14247>

Build System
╌╌╌╌╌╌╌╌╌╌╌╌

◊ Dune

[Dune 3.21.0] (January 16, 2026) is a large release including dozens
of fixes, improvements, and additions from many contributors.

*Notable Additions:*

• (Experimental): `library_parameter' stanza for the OxCaml compiler
• Copy-on-write (COW) when copying files on supporting filesystems
(Btrfs, ZFS, XFS) under Linux
• Support for Tangled ATproto-based code repositories
• New `(dir ..)' field on packages to filter stanzas with
`--only-packages'
• `dune promotion show' command to preview corrected files
• New `(lang rocq)' build mode for Rocq 9.0 and later
• Support for instantiating OxCaml parameterised libraries
• `dune describe tests' to list tests in the workspace
• Horizontal scrolling in TUI
• Support for expanding variables in `(promote (into ..))'

*Notable Fixes:*

• Fixed `include_subdirs qualified' picking the furthest module
instead of the closest
• Improved error messages for invalid version formats with non-ASCII
characters
• Fixed crash when running `dune build @check' on libraries with
virtual modules
• Allow `$ dune init' to work on absolute paths
• Stop hiding the `root_module' from the include path

For the complete list of changes, see the [full release on GitHub].

*Dune Maintained by*: Rudi Grinberg (@rgrinberg, Jane Street), Nicolás
Ojeda Bär (@nojb, LexiFi), Marek Kubica (@Leonidas-from-XIV,
Tarides), Ali Caglayan (@Alizter, Tarides), Stephen Sherratt
(@gridbugs, Tarides), Antonio Nuno Monteiro (@anmonteiro), Sudha
Parimala (@Sudha247, Tarides), Ambre Suhamy (@ElectreAAS, Tarides),
Puneeth Chaganti (@punchagan, Tarides)

[Dune 3.21.0] <https://ocaml.org/changelog/2026-01-16-dune-3-21-0>

[full release on GitHub]
<https://github.com/ocaml/dune/releases/tag/3.21.0>

Package Management
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌

◊ opam

[opam 2.5.0] (November 27, 2025) is a major release with significant
performance and usability improvements.

*Key Features:*

• *Massive speedup for `opam update'*: Thanks to @arozovyk, opam
update now loads opam files incrementally, only parsing files that
have changed since the last update. For typical small diffs, this
means operations that took seconds now complete in milliseconds
• *Improved shell integration*: Fixed issues where parts of a previous
environment were kept in the current environment, causing various
problems
• *Changed default shell integration file*: Now writes to `.bashrc'
instead of `.profile' when bash is detected, preventing infinite
loop issues
• *AppArmor profile*: The install script now installs an appropriate
apparmor profile on systems configured with apparmor (enabled by
default on Ubuntu)
• *macOS sandbox improvements*: Allow writing to `/var/folders/' and
`/var/db/mds/' directories as required by some macOS core tools

*Build Changes:*

• *Ecosystem cmdliner 2.0.0 compatibility*: opam no longer depends on
`cmdliner', removing a key blocker that prevented cmdliner 1.x and
2.0.0 from being co-installable. This change enables ecosystem-wide
migration to cmdliner 2.0.0
• OCaml 5.5 (trunk) support when using dune's dev profile
• The release archive (`opam-full-*.tar.gz') is now reproducible
• OpenBSD binary is now a full static binary

For more details, see the [official opam 2.5.0 announcement blog] and
[full release notes on GitHub].

*opam Maintained by*: Raja Boujbel (@rjbou, OCamlPro), Kate Deplaix
(@kit-ty-kate, Ahrefs), David Allsopp (@dra27, Tarides)

[opam 2.5.0] <https://ocaml.org/changelog/2025-11-27-opam-2.5.0>

[official opam 2.5.0 announcement blog]
<https://opam.ocaml.org/blog/opam-2-5-0/>

[full release notes on GitHub]
<https://github.com/ocaml/opam/releases/tag/2.5.0>

◊ opam-publish

[opam-publish 2.7.1] (November 18, 2025) fixes bugs related to the
GitHub API token permissions introduced in version 2.7.0.

*Changes:*

• Advertise the need, and check, for the `workflow' scope for GitHub
personal access tokens
• Enforce the git remote used to push branches to users' fork to be
used instead of the SSH method
• Avoid potential previously used tokens with wrong permissions to be
used instead of the new one
• Add support for the opam 2.5 API

*Maintained by*: Raja Boujbel (@rjbou, OCamlPro), Kate Deplaix
(@kit-ty-kate, Ahrefs)

[opam-publish 2.7.1]
<https://ocaml.org/changelog/2025-11-18-opam-publish-2.7.1>

◊ opam-repository Archival: January 1, 2026

On January 1, 2026, the opam-repository completed its scheduled
archival run, removing *3,264 package versions* (881 unique packages)
marked with `x-maintenance-intent: archival'. This ongoing maintenance
process helps keep the repository manageable by removing unmaintained
or obsolete package versions.

*What This Means:*

• Archived packages are no longer available in the default opam
repository
• CI systems and lock files may need updates if they depend on
archived versions
• The archival is based on metadata explicitly set by package
maintainers

*Background:*

The archival process was announced by Hannes Mehnert in December 2025
(see the [Discuss announcement]), giving package maintainers and users
time to prepare. Packages can be restored from archival by maintainers
upon request.

This maintenance practice ensures the opam repository remains
sustainable and focused on actively maintained packages.

[Discuss announcement]
<https://discuss.ocaml.org/t/opam-repository-archival-next-run-scheduled-2026-01-01/17587>

◊ dune-release

[dune-release 2.2.0] (January 29, 2026) brings full compatibility with
cmdliner 2.0.0, continuing the ecosystem-wide migration that began
with opam 2.5.0's removal of the cmdliner dependency.

*Why This Matters:*

cmdliner 2.0.0 introduced stricter requirements that improve CLI
reliability but prevent co-installability with cmdliner 1.x. Following
opam 2.5.0's lead in removing this conflict, dune-release 2.2.0
updates to use cmdliner 2.0.0 exclusively. This coordinated effort
across the platform tools enables users to upgrade without
encountering dependency conflicts.

*Important Changes:*

• *Breaking*: Following cmdliner 2.0's stricter requirements,
prefix-matching for command options is no longer supported
• Users must now provide the full wording for all flags (for example,
`--skip-tests' instead of `--skip-test')
• This change ensures compatibility with cmdliner 2.0.0 and aligns
with modern CLI best practices
• If you have automation scripts using shortened flags, update them
before upgrading

For technical details, see the [cmdliner 2.0.0 documentation] and the
[dune-release PR #512].

*Maintained by*: Tarides

[dune-release 2.2.0]
<https://ocaml.org/changelog/dune-release/2026-01-29-dune-release-2.2.0>

[cmdliner 2.0.0 documentation]
<https://erratique.ch/software/cmdliner/doc/Cmdliner>

[dune-release PR #512]
<https://github.com/tarides/dune-release/pull/512>

Editor Tools
╌╌╌╌╌╌╌╌╌╌╌╌

*Roadmap: [Edit / (W19) Navigate Code]*

[Edit / (W19) Navigate Code]
<https://ocaml.org/tools/platform-roadmap#w19-navigate-code>

◊ OCaml-LSP Server

[OCaml-LSP 1.25.0] (December 20, 2025) introduces support for `.mlx'
files and new custom requests.

*Features:*

• *`.mlx' Support*: Added support for `.mlx' files, including
diagnostics, code actions, hover, and formatting via
`ocamlformat-mlx'
• *New Custom Requests*: Added `typeExpression', `locate', and
`phrase' requests to the server
• *Code-Lens Configuration*: Code-lens for nested `let' bindings is
now configurable

*Fixes:*

• The server now falls back to `.merlin' configuration if a
`dune-project' file is missing, provided [dot-merlin-reader] is
installed
• Improved precision of timestamps for collected metrics

[OCaml-LSP 1.25.0]
<https://ocaml.org/changelog/2025-12-20-ocaml-lsp-1-25-0>

[dot-merlin-reader] <https://github.com/ocaml/merlin>

◊ Merlin

[Merlin 5.6.1-504] (December 20, 2025) brings performance
optimizations and improved stability.

*Key Improvements:*

• *Smarter Signature Help*: Now triggers correctly on unfinished `let
... in' bindings and no longer appears redundantly on function
names
• *More Reliable Completion*: Fixed issues with completion for inlined
record labels
• *Improved Performance*: Optimized buffer indexing and path
calculations
• *Bug Fixes*: Resolved a bug where the `document' command
concatenated labels and variants incorrectly

*OCaml LSP Server maintained by*: Ulysse Gérard (@voodoos, Tarides),
Xavier Van de Woestyne (@xvw, Tarides), Rudi Grinberg (@rgrinberg,
Jane Street)

*Merlin maintained by*: Ulysse Gérard (@voodoos, Tarides), Xavier Van
de Woestyne (@xvw, Tarides), Muluh Godson (@PizieDust, Tarides)

[Merlin 5.6.1-504]
<https://ocaml.org/changelog/2025-12-20-merlin-v5-6-1-504>

◊ OCaml-eglot

We have drastically modified the `xref' backend (allowing navigation
from definition to definition) to make it more suitable for OCaml.

In addition, we added the ability to annotate the type of an enclosing
active_ (used with the `ocaml-eglot-type-enclosing' command) or simply
to type the selection.

These updates have been merged into `main', making them available via
a MELPA update.

*ocaml-eglot maintained by*: Xavier Van de Woestyne (@xvw, Tarides)

Platform Infrastructure
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌

◊ OCaml Infrastructure: How the opam-repository Works

The [November 5, 2025 article on the opam-repository] provides an
in-depth look at this critical piece of OCaml infrastructure. The opam
repository serves as the central package registry for the OCaml
ecosystem, hosting over 4,500 packages. It relies on dedicated
volunteer maintainers who review every submission.

—

As always, we encourage feedback and contributions from the community
as we continue to improve the OCaml Platform ecosystem.

[November 5, 2025 article on the opam-repository]
<https://ocaml.org/changelog/2025-11-05-how-the-opam-repository-works>

Announcing the first release of Alice, a radical OCaml build system
═══════════════════════════════════════════════════════════════════

Archive:
<https://discuss.ocaml.org/t/announcing-the-first-release-of-alice-a-radical-ocaml-build-system/17472/45>

Continuing this thread, Steve Sherratt announced
────────────────────────────────────────────────

Announcing the release of [Alice v0.5.0] which introduces parallel
builds.

[Alice v0.5.0] <https://www.alicecaml.org/blog/alice-v0-5-0/>

mnet, a new TCP/IP stack for unikernels in OCaml
════════════════════════════════════════════════

Archive:
<https://discuss.ocaml.org/t/ann-mnet-a-new-tcp-ip-stack-for-unikernels-in-ocaml/17851/1>

Calascibetta Romain announced
─────────────────────────────

I am pleased to announce a series of releases for developing
unikernels with OCaml 5 and [Miou]. After extensive testing, we are
now able to offer a new TCP/IPv4 and IPv6 stack in OCaml that aims to
replace [mirage-tcpip] and pave the way for direct-style unikernel
development. Below is an overview of the libraries we have built to
make this possible.

[Miou] <https://github.com/robur-coop/miou>

[mirage-tcpip] <https://github.com/mirage/mirage-tcpip>

mkernel
╌╌╌╌╌╌╌

`mkernel' is a small library that provides the essentials for
developing a unikernel targeting [Solo5] or [Unikraft]. Its purpose is
to expose hypercalls (the unikernel equivalent of syscalls) so that
your application can interact with network and block devices.

We recommend reading the `mkernel' [documentation] to understand the
key concepts behind unikernels (hypercalls, devices, tenders,
etc.). The [slides] we presented at the last [MirageOS retreat] are
also helpful for understanding our new workflow. Compiling a unikernel
now only requires `dune' and vendored libraries. We have therefore
chosen not to resolve dependencies automatically (as [opam-monorepo]
did) or to impose them (as the `mirage' tool does), giving developers
full freedom to build their unikernels as they see fit. In particular,
this makes it straightforward to use ppx rewriters, which was
difficult or impossible with the `mirage' tool.

[Solo5] <https://github.com/solo5/solo5>

[Unikraft] <https://unikraft.org/>

[documentation]
<https://robur-coop.github.io/mkernel/local/mkernel/Mkernel/index.html>

[slides]
<https://github.com/robur-coop/mkernel/blob/main/slides/retreat.md>

[MirageOS retreat] <https://retreat.mirageos.org/>

[opam-monorepo] <https://github.com/tarides/opam-monorepo>

◊ A new workflow and targets

This release is experimental: Xen is not yet supported, and Unikraft
support is partial. However, both platforms are on our roadmap, so if
you are interested in them, please let us know! We are also developing
tooling to streamline the workflow, with the guiding principle that
these tools should never dictate which dependencies your unikernel
uses or which build system you choose.

mnet
╌╌╌╌

`mnet' is the centerpiece of this release. It is designed to replace
(and improve upon) [mirage-tcpip] by offering a direct-style API built
on effects. The API deliberately mirrors the `Unix' socket interface:
`connect', `listen', `accept', `read', `write', and `close' all behave
the way you would expect.

Here is a small example of an echo server:
┌────
│ let run (ipv4, gateway, ipv6) =
│ Mkernel.(run [ rng; Mnet.stack ~name:"service" ?gateway ~ipv6 ipv4 ])
│ @@ fun rng (daemon, tcp, udp) ->
│ let@ () = fun () -> Mnet.kill daemon in
│ let@ () = fun () -> Mirage_crypto_rng_mkernel.kill rng in
│ let listen = Mnet.TCP.listen tcp 9000 in
│ let flow = Mnet.TCP.accept tcp listen in
│ let buf = Bytes.create 4096 in
│ let rec echo () =
│ let len = Mnet.TCP.read flow buf in
│ if len > 0 then begin
│ Mnet.TCP.write flow (Bytes.sub_string buf 0 len);
│ echo ()
│ end
│ in
│ let@ () = fun () -> Mnet.TCP.close flow in
│ echo ()
└────

TLS support (via [ocaml-tls]) is already available, allowing you to
establish secure connections with your unikernel. DNS resolution (via
[ocaml-dns]) and the [Happy Eyeballs] algorithm are also included, so
that a unikernel can resolve hostnames and connect to remote services
over both IPv4 and IPv6.

A [short tutorial] walks you through creating an echo server as a
unikernel, similar to what we [already offer] for Miou. For the
curious, an article about IPv4 and Miou is available [here].

Beyond the move to effects for all scheduling, I would like to give
special thanks to:
• Edwin Török for proposing fixes to prevent denial-of-service
attacks, which have been integrated into `mnet' (in particular for
[ARP]).
• Nicolas Ojeda Bär for contributing an IPv6 implementation that we
adopted and improved (caches, packet fragmentation and reassembly,
etc.)
• Reynir for patiently debugging PCAP traces
• Hannes for sharing his deep knowledge of the TCP protocol and its
interactions with IPv4 and IPv6

As well as others who participated in the development of `mnet' in one
way or another.

[mirage-tcpip] <https://github.com/mirage/mirage-tcpip>

[ocaml-tls] <https://github.com/mirleft/ocaml-tls>

[ocaml-dns] <https://github.com/mirage/ocaml-dns>

[Happy Eyeballs] <https://github.com/robur-coop/happy-eyeballs>

[short tutorial] <https://robur-coop.github.io/mnet/>

[already offer] <https://robur-coop.github.io/miou/echo.html>

[here] <https://blog.robur.coop/articles/utcp_and_effects.html>

[ARP] <https://osv.dev/vulnerability/OSEC-2026-02>

◊ Developing and deploying unikernels

This library also marks a turning point in our approach to
unikernels. We no longer treat a regular OCaml application as
something that can be transparently turned into a
unikernel. Developing a unikernel now means developing a unikernel
from the start. In our experience, trying to retrofit an existing
application into a unikernel was neither practical nor worthwhile.

Our tutorial therefore covers both the development and deployment of
unikernels. On the deployment side, we also recommend exploring
[Albatross].

[Albatross] <https://github.com/robur-coop/albatross>

utcp
╌╌╌╌

[`utcp'] is a pure OCaml implementation of the TCP protocol, used
internally by `mnet' to handle TCP connections. The implementation is
based on a state machine and performs no I/O itself, making it easy to
test and reason about.

`utcp' covers the full TCP lifecycle: the three-way handshake,
reliable in-order data delivery with retransmissions, flow control,
congestion control, and connection teardown. It has been tested
extensively through our end-to-end unikernel tests (a simple [echo]
server and client, and a [DNS resolver]).

[`utcp'] <https://github.com/robur-coop/utcp>

[echo] <https://github.com/robur-coop/mnet/tree/main/unikernels/echo>

[DNS resolver]
<https://github.com/robur-coop/mnet/tree/main/unikernels/resolver>

◊ Unikernels and proofs

`utcp' also reflects our ambition to incorporate, as time permits,
proof-based implementations. Other examples include:
• miou with its priority queue (see the [VOCAL] project)
• mirage-crypto with certain cryptographic primitives (see the [fiat]
project)
• and now utcp (see [netsem])

This effort is still in its early stages, but we welcome improvements
and collaborations in this area.

[VOCAL] <https://inria.hal.science/hal-01561094>

[fiat] <https://github.com/mit-plv/fiat-crypto>

[netsem] <https://www.cl.cam.ac.uk/~pes20/Netsem/>

mhttp
╌╌╌╌╌

To reach a wider audience, we also provide an HTTP protocol
implementation for unikernels, building on the work we started (and
currently use in production) with [httpcats].

`mhttp' is essentially a unikernel-oriented counterpart to `httpcats',
using [ocaml-h1] and [ocaml-h2] as its HTTP/1.1 and H2 backends.

[httpcats] <https://github.com/robur-coop/httpcats>

[ocaml-h1] <https://github.com/robur-coop/ocaml-h1>

[ocaml-h2] <https://github.com/anmonteiro/ocaml-h2>

◊ Ecosystem and composability

Although `mhttp' is a small project, it illustrates a broader
principle behind our cooperative's approach to library development. As
we have [stated before], everything we build is designed to be
reusable with schedulers other than Miou and in contexts other than
unikernels. Regardless of which scheduler one prefers, we believe in a
pragmatic, cooperative approach to contributing to the community.

Our primary focus remains unikernel development, but years of
experience building protocol and format libraries have taught us that
keeping them scheduler-agnostic is in everyone's best interest, for
maintainability, testability, and reliability alike. Wherever
possible, you will find a general-purpose library alongside its
unikernel counterpart: `httpcats' and `mhttp' are one such pair.

[stated before]
<https://discuss.ocaml.org/t/on-concurrency-models/15899/13?u=dinosaure>

Vifu
╌╌╌╌

As [previously announced], we have developed a web framework for OCaml
5 called [vif], which we use in production for our [builds.robur.coop]
website (we recommend the [tutorial] presented at [FUN OCaml] 2025).

`vif' now has a unikernel variant: `vifu'. It offers nearly the same
interface as `vif' (except for static file management), making it
possible to build websites entirely in OCaml. Here is a small
unikernel that displays "Hello World!":

┌────
│ let hello_world req _server () =
│ let open Vifu.Response.Syntax in
│ let* () = Vifu.Response.with_text req "Hello World!\n" in
│ Vifu.Response.respond `OK
│
│ let run (ipv4, gateway, ipv6) =
│ Mkernel.(run [ rng; Mnet.stack ~name:"service" ?gateway ~ipv6 ipv4 ])
│ @@ fun rng (daemon, tcp, udp) ->
│ let@ () = fun () -> Mnet.kill daemon in
│ let@ () = fun () -> Mirage_crypto_rng_mkernel.kill rng in
│ let cfg = Vifu.Config.v 80 in
│ let routes = Vifu.[ get (rel /?? any) --> hello_world ] in
│ Vifu.run ~cfg tcp routes ()
└────

*disclaimer*: If you would like to use `vifu', please note that
although a recent release has been made, one final fix is still
needed to compile a unikernel with this library (to avoid pulling in
the `unix' module). We recommend pinning `vifu' for now.

[previously announced]
<https://discuss.ocaml.org/t/ann-httpcats-ocaml-h1-vif-hurl-a-webstack-for-ocaml-5/17104>

[vif] <https://github.com/robur-coop/vif>

[builds.robur.coop] <https://builds.robur.coop>

[tutorial] <https://robur-coop.github.io/vif/>

[FUN OCaml] <https://fun-ocaml.com>

Unikernels
╌╌╌╌╌╌╌╌╌╌

Behind all these libraries, there are concrete projects that we would
like to share with you:
• Our [`immutable'] unikernel, a web server for static files (which
can be generated, for example, with [YOCaml]).
• A DNS resolver unikernel: [`pagejaune']
• A small search engine for emails from an archive such as the
caml-list: [`blame']. More details are available [here].

[`immutable'] <https://github.com/dinosaure/immuable>

[YOCaml] <https://github.com/xhtmlboi/yocaml>

[`pagejaune'] <https://github.com/dinosaure/pagejaune>

[`blame'] <https://github.com/robur-coop/blame>

[here]
<https://blog.robur.coop/articles/2025-04-12-ptt-search-webapp.html>

Conclusion
╌╌╌╌╌╌╌╌╌╌

After several years of work, we are now able to develop unikernels
with OCaml 5 in earnest. We hope that our new workflow will be of
interest to the community and that these libraries will be a useful
contribution to the OCaml ecosystem.

If you would like to try it out, we recommend starting with the [mnet
tutorial] and the [mkernel documentation]. Feel free to open issues or
reach out to us if you have any questions!

[mnet tutorial] <https://robur-coop.github.io/mnet/>

[mkernel documentation]
<https://robur-coop.github.io/mkernel/local/mkernel/Mkernel/index.html>

Experiment: format-line
═══════════════════════

Archive:
<https://discuss.ocaml.org/t/ann-experiment-format-line/17854/1>

Emile Trotignon announced
─────────────────────────

I made this little experiment a while back:
<https://github.com/ahrefs/format-line>

The idea is to provide a complement to ocp-indent to decide which
token should be separated by whitespace and which should not. For now
it is based only on lexing information, which make the code simple but
also does not always provide enough information to have a nice
formatting.

An idea of the output can be read here:
<https://github.com/ahrefs/format-line/blob/master/test/run.t>

The project itself is formatted with ocamlformat, and in the there is
a diff of what this changes compared to ocamlformat, on the main
source file.

I think this approach could be improved by having a hybrid ast-token
stream datastructure. Something where you work on a stream of token
but you can query the AST context of a given token.

What do you think ?

Caml in the Capital - Registrations Open!
═════════════════════════════════════════

Archive:
<https://discuss.ocaml.org/t/ann-caml-in-the-capital-registrations-open/17776/6>

Continuing this thread, Sacha Ayoun announced
─────────────────────────────────────────────

And here is the [link to the recording]!

We'd like to thank our speakers Jeremy and Nick again, as well as the
~30 attendees to the meetup! It was great having you, and we hope to
see you again next time :)

[link to the recording] <https://www.youtube.com/watch?v=6CM9J2C58dg>

Experimental tools for migrating from Lwt to Eio
════════════════════════════════════════════════

Archive:
<https://discuss.ocaml.org/t/ann-experimental-tools-for-migrating-from-lwt-to-eio/17855/1>

Jules announced
───────────────

We developed tools to help us migrate Ocsigen libraries and
applications to direct-style concurrency and we are happy to share
them.

There are 4 independent tools for different purposes:

• Replacing every uses of `lwt_ppx' with `Lwt' function calls
(e.g. replacing `let%lwt ... in' with `let* ... in'). This is
purely syntactic and allows you to easily remove a PPX. It handles
inserting `open Lwt.Syntax' at the top of the file.

• Warning about occurrences of `let _ = ...' and `ignore ...', which
make the next tools less reliable. These are called “implicit fork”
because code run concurrently if the ignored value is an Lwt
thread. This requires an explicit call to `Fiber.fork' with Eio.

• Migrating uses of `Lwt_log' to `Logs'. It was used on
[ocsigenserver] for example. At this point we generate code working
as before and did not introduce a dependency on Eio.

• Migrating uses of `Lwt' to `Eio'. It rewrites code written in
monadic style into direct-style, for example this code:

┌────
│ let _ =
│ let* x = f 1 in
│ let+ y = f 2 in
│ Lwt.bind (f 3) (fun z ->
│ Lwt.return (x + y + z))
└────

is rewritten to:

┌────
│ let _ =
│ let x = f 1 in
│ let y = f 2 in
│ let z = f 3 in
│ x + y + z
└────

It also rewrite `Lwt' function calls to their equivalent in `Eio'
and handles many IO operations.

Unfortunately, this tool doesn’t generate fully equivalent code and
requires manual modifications. Comments are inserted in many places
where intervention is needed.

An example of generated incorrect code is:

┌────
│ let _ =
│ let a = operation_1 () in
│ let* b = operation_2 () in
│ let* a = a in
│ Lwt.return (a + b)
└────

which is rewritten into:

┌────
│ let _ =
│ let a = operation_1 () in
│ let b = operation_2 () in
│ let a = a in
│ a + b
└────

This is incorrect because `operation_1' and `operation_2' are now
sequential but were concurrent before. This is a case of an implicit
fork that cannot easily be detected. The correct transformation
would be:

┌────
│ let _ =
│ let a, b = Eio.Fiber.pair operation_1 operation_2 in
│ a + b
└────

We could achieve the migration on [eliom] and [ocsigenserver]

All the tools use OCamlformat under the hood to generate the
code. This has the inconvenient of enforcing the use of OCamlformat
before using them as they will reformat the entire codebase.

The last two tools use Merlin under the hood to locate uses of `Lwt'
functions in the source files. This works by reading Merlin’s
ocaml-index files built by Dune to extract the location in the source
files that we need.

Currently, it only supports Eio as a backend but can easily be
[adapted] to other direct-style concurrency libraries.

This work was made possible thanks to the support of the [NGI Zero
Core fund] through the [Nlnet foundation], and is perfomed by
[Tarides].

[ocsigenserver] <https://github.com/ocsigen/ocsigenserver/pull/256>

[eliom] <https://github.com/ocsigen/eliom/pull/846>

[ocsigenserver] <https://github.com/ocsigen/ocsigenserver/pull/269>

[adapted]
<https://github.com/tarides/ciao-lwt/blob/main/bin/ciao_lwt/to_direct_style/concurrency_backend.ml>

[NGI Zero Core fund] <https://nlnet.nl/thema/NGIZeroCore.html>

[Nlnet foundation] <https://nlnet.nl/>

[Tarides] <https://tarides.com/>

First alpha release of OCaml 5.5.0
══════════════════════════════════

Archive:
<https://discuss.ocaml.org/t/first-alpha-release-of-ocaml-5-5-0/17856/1>

octachron announced
───────────────────

Four months after the release of OCaml 5.4.0, the set of new features
for the future version 5.5.0 of OCaml has been frozen. We are thus
happy to announce the first alpha release for OCaml 5.5.0.

This alpha version is here to help fellow hackers join us early in our
bug hunting and opam ecosystem fixing fun (see below for the
installation instructions). More information about the release process
is available at
<https://github.com/ocaml/ocaml/blob/trunk/release-info/introduction.md>.

The progress on stabilising the ecosystem is tracked on the [opam
readiness for 5.5.0 meta-issue] .

There is also a companion alpha opam repository available for this
alpha release
┌────
│ $ opam repo add alpha git+https://github.com/kit-ty-kate/opam-alpha-repository.git
└────
which contains in-progress alpha releases of opam packages that are
being updated for OCaml 5.5.0 .

The full release is expected between May and June. There are more
information available in the [prospective release calendar].

If you find any bugs, please report them on the [OCaml's issue
tracker].

If you are interested in the ongoing list of new features and bug
fixes, the updated [change log for OCaml 5.5.0 is available on
GitHub].

Happy hacking, Florian Angeletti for the OCaml team

[opam readiness for 5.5.0 meta-issue]
<https://github.com/ocaml/opam-repository/issues/29463>

[prospective release calendar]
<https://github.com/ocaml/ocaml/blob/trunk/release-info/calendar.md>

[OCaml's issue tracker] <https://github.com/ocaml/ocaml/issues>

[change log for OCaml 5.5.0 is available on GitHub]
<https://github.com/ocaml/ocaml/blob/5.5/Changes>

Installation Instructions
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌

The base compiler can be installed as an opam switch with the
following commands on opam 2.1 and later:

opam update opam switch create 5.5.0~alpha1

The source code for the alpha is also available at these addresses:

• GitHub: <https://github.com/ocaml/ocaml/archive/5.5.0-alpha1.tar.gz>
• OCaml archives at Inria:
<https://caml.inria.fr/pub/distrib/ocaml-5.5/ocaml-5.5.0~alpha1.tar.gz>

Fine-Tuned Compiler Configuration
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌

If you want to tweak the configuration of the compiler, you can switch
to the option variant with:

┌────
│ opam update
│ opam switch create <switch_name> ocaml-variants.5.5.0~alpha1+options <option_list>
└────

where `option_list' is a space separated list of `ocaml-option-*'
packages. For instance, for a flambda and no-flat-float-array switch:
┌────
│ opam switch create 5.5.0~alpha1+flambda+nffa ocaml-variants.5.5.0~alpha1+options ocaml-option-flambda ocaml-option-no-flat-float-array
└────

All available options can be listed with `opam search ocaml-option'.

NotInriaCaml_Std.Wenv@0.1.0 - create Windows envs on macOS [dk0]
════════════════════════════════════════════════════════════════

Archive:
<https://discuss.ocaml.org/t/ann-notinriacaml-std-wenv-0-1-0-create-windows-envs-on-macos-dk0/17858/1>

jbeckford announced
───────────────────

It is my pleasure to announce the following package for [the dk0 build
system] that creates a Windows environment ("wenv") using a custom
Wine build for macOS:

• [NotInriaCaml_Std.Wenv@0.1.0]

Here is a sample session:

┌────
│ # Simplest way to install dk0 today. Use ~git pull~ if exists already.
│ $ git clone --branch V2_5 https://github.com/diskuv/dk.git dksrc
│
│ # Clear out data, cache and intermediate files from any prior
│ # experiments (from the "--trial" option seen in [ANN] posts)
│ $ rm -rf t/
│
│ # With the default Lua rules ("-I dksrc/etc/dk/v"), run the
│ # OCaml Windows environment creation rule ("run
│ # NotInriaCaml_Std.Wenv.Create@0.1.0"). Tell the rule to create the
│ # wenv at target/my-wenv/ ("dir=...") and make a mount
│ # ("mount[]=...") inside the wenv where the Unix directory $PWD is
│ # mapped to Windows M:\project. Depending on Internet, expect 3-4
│ # minutes for a single-threaded download of artifacts (581MB).
│ $ dksrc/dk0 --trial -I dksrc/etc/dk/v \
│ run NotInriaCaml_Std.Wenv.Create@0.1.0 \
│ dir=$PWD/target/my-wenv \
│ "mount[]=type=bind,src=$PWD,dst=M:/project"
└────

┌────
│ # Then enter the wenv by running Command Prompt ("cmd.exe"). Turn
│ # off Wine debug messages ("WINEDEBUG=-all"). Remember that
│ # Ctrl-Z is the Windows equivalent of Ctrl-D (EOF) in Unix.
│ $ WINEDEBUG=-all target/my-wenv/bin/enter cmd.exe
│
│ Microsoft Windows 10.0.19045
│ Z:\> ocamlopt -config
│ Z:\> gcc --version
│ Z:\> dir M:
│ 02/27/2026 10:24 AM project
│ Z:\> ocaml
│ OCaml version 5.4.1
│
│ Enter #help;; for help.
│
│ # 1+1 ;;
│ - : int = 2
│
│ # ^Z
│
│ Z:\> echo let () = print_endline "abcxyz" > letters.ml
│ Z:\> ocamlopt -o letters.exe letters.ml
│ Z:\> .\letters.exe
│ abcxyz
│ Z:\> exit
└────

Details:

• MinGW with UCRT Windows API and LLVM toolchain (llvm-mingw) for Wine
on the host (macOS). X11 has been disabled.
• MinGW with MSVCRT Windows API and GNU compiler and BusyBox binaries
(w64devkit) inside Windows guest.
• Wine has good support for programs that use Windows conventions
(MSVC, Windows API rather than `syscall', etc). But there are
important programs that won't work correctly today: MSYS2/Cygwin,
Rust uutils.

Enjoy! –jonah

[the dk0 build system]
<https://discuss.ocaml.org/t/ann-the-dk0-build-system/17709>

[NotInriaCaml_Std.Wenv@0.1.0]
<https://github.com/diskuv/dk/blob/a29e9da3f30df41fa3cfc855b323fdcda6a106c2/etc/dk/v/NotInriaCaml_Std/Wenv.values.lua>

Running Real Docker Containers in OCaml Tests
═════════════════════════════════════════════

Archive:
<https://discuss.ocaml.org/t/ann-running-real-docker-containers-in-ocaml-tests/17859/1>

Sachin announced
────────────────

Hi everyone,

I’ve been working on a project called *[testcontainers-ocaml]*, which
brings Testcontainers style integration testing to OCaml.

The idea is simple:

Instead of mocking infrastructure (Postgres, Redis, Kafka,
etc.), start real Docker containers inside your test suite
and tear them down automatically.

—

[testcontainers-ocaml]
<https://github.com/benodiwal/testcontainers-ocaml>

Why?
╌╌╌╌

In many OCaml projects, integration tests either:

• Rely on mocks

• Depend on globally running services

• Or are skipped entirely in CI

Mocks are useful, but they don’t catch issues like:

• Schema mismatches

• Connection pool behavior

• Real networking failures

• Startup timing problems

• Migration issues

Spinning up disposable containers per test gives us:

• Isolated test environments

• No shared global state

• CI reproducibility

• Real infrastructure behavior

Current Status
╌╌╌╌╌╌╌╌╌╌╌╌╌╌

The project is currently incubating under the Docker organization.

I’m still actively shaping the API and would really appreciate
feedback from the OCaml community on:

• API ergonomics

• Prebuilt modules (Postgres, Redis, etc.)

• Testing best practices in OCaml

If anyone here has experience with integration testing patterns in
OCaml, I’d love to hear thoughts.

Thanks!

I wrote a DSL for AI personalities in OCaml
═══════════════════════════════════════════

Archive:
<https://discuss.ocaml.org/t/i-wrote-a-dsl-for-ai-personalities-in-ocaml/17860/1>

Griffin announced
─────────────────

Hi guys,

<https://github.com/GriffinCanCode/Callosum>

<https://pypi.org/project/callosum-dsl/>

I wanted a more deterministic way to create personalities for my AI
agents that was consistent in production. The interesting catch being
that the compiler had to output a prompt, and it needed to be
accessible for agents in Python. The solution was this DSL, a format
for writing deterministic categories (similar to YAML) that compile to
a prompt injectable into Langchain agents. OCaml was the natural
choice due to its performance and proven capabilities to host
compilers (Rust obv). Looking for beta testers and any feedback is
welcome!

Outreachy May 2026
══════════════════

Archive: <https://discuss.ocaml.org/t/outreachy-may-2026/17863/1>

Patrick Ferris announced
────────────────────────

Hello everyone,

The OCaml community has signed up to Outreachy May 2026 (see [past]
[posts])!

*What is Outreachy?*

Outreachy is a paid, remote internship program. Outreachy
promotes diversity in open source and open science. Our
internships are for people who face under-representation,
and discrimination or systemic bias in the technology
industry of their country.

The current round is still ongoing with interns making great progress
with @tmattio on [Raven], with @xvw on [YOCaml] and with myself on
[ocaml-tiff].

[past] <https://discuss.ocaml.org/t/outreachy-december-2024-round>

[posts] <https://discuss.ocaml.org/t/outreachy-june-2025>

[Raven] <https://raven-ml.dev/>

[YOCaml] <https://yocaml.github.io/doc/yocaml/index.html>

[ocaml-tiff] <https://github.com/geocaml/ocaml-tiff/>

Important Dates
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌

For this next round, the important dates are as follows (these are
always subject to some change):

• Mar 1 - Community sign up deadline :white_check_mark:
• Mar 14 - [Mentor Signup]
• Mar 17 to Apr 15 - Contribution period
• May 18 to Aug 17 - Internship period

*Our next deadline is for mentors to sign up to the OCaml community*
with a project idea. Please do consider being an Outreachy mentor. If
you have any questions or ideas you can always reach out to me
directly. If you need a refresher of past projects, there’s a
dedicated page on the OCaml website: [OCaml Outreachy
Internships]. Feel free to discuss ideas on this thread too!

The OCaml community is currently able to financially support Outreachy
internships thanks to the generous support of [Tarides] and
[Janestreet]. This includes being able to fund mentors as well.

Thanks! :camel:

[Mentor Signup] <https://www.outreachy.org/communities/cfp/ocaml/>

[OCaml Outreachy Internships] <https://ocaml.org/outreachy>

[Tarides] <https://tarides.com>

[Janestreet] <https://www.janestreet.com>

Old CWN
═══════

If you happen to miss a CWN, you can [send me a message] and I'll mail
it to you, or go take a look at [the archive] or the [RSS feed of the
archives].

If you also wish to receive it every week by mail, you may subscribe
to the [caml-list].

[Alan Schmitt]

[send me a message] <mailto:alan.schmitt@polytechnique.org>

[the archive] <https://alan.petitepomme.net/cwn/>

[RSS feed of the archives] <https://alan.petitepomme.net/cwn/cwn.rss>

[caml-list] <https://sympa.inria.fr/sympa/info/caml-list>

[Alan Schmitt] <https://alan.petitepomme.net/>

[-- Attachment #2: Type: text/html, Size: 72364 bytes --]