cd /news/ai-tools/show-hn-riot-a-modern-multicore-acto… · home topics ai-tools article
[ARTICLE · art-14146] src=riot.ml pub= topic=ai-tools verified=true sentiment=↑ positive

Show HN: Riot, a modern multicore actor-based ecosystem for OCaml

A new open-source ecosystem called Riot launched for the OCaml programming language, providing a complete stack with a multi-core actor-model runtime, package registry, and standard library. The project ships with an agent-facing skill system that instructs AI agents how to build, test, fuzz, and maintain projects, including structured JSON output for machine readability. Riot aims to simplify OCaml development by offering a single command-line tool for building, formatting, linting, testing, and fuzzing, with opinionated defaults and no configuration options for formatting.

read7 min publishedMay 26, 2026

Riot is a tech-demo of a stack and tooling for building applications in OCaml. It is heavily opinionated, and designed from the ground up to get out of your way and help you ship great software with agents.

It comes with a single tool for all your needs, a modern package registry, a multi-core ready actor-model runtime, a whole new standard library, and first-class support for agentic work.

Riot is also a tool: riot — and it's the only tool you need in this stack.

Riot ships with agent-facing instructions, not just human docs. The riot-ml skill tells agents how to use the stack, which commands to prefer, where workflows live, and how to keep package discovery grounded in pkgs.ml.

Every new Riot project created with riot init includes an .agents folder with the Riot skill already there. Start the project, then use your agent.

The local skill explains how to build, test, benchmark, run, format, fix, fuzz, and maintain Riot projects.

Riot commands prefer structured output with --json, so agents can inspect build results, diagnostics, test runs, package metadata, and registry flows without scraping prose.

The skill links deeper workflow references for testing, fuzzing, benchmarking, snapshots, and package lookup, so agents can run the right loop instead of guessing.

/llms.txt is the public discovery map for agents that find Riot from the web; inside a Riot workspace, the local skill is the starting point.

riot build

Easy, fast builds

Riot builds packages. A package is the unit of the build, and each package is defined by a plain riot.toml file.

Riot implements a new package-aware build system, so package boundaries, dependencies, targets, and generated artifacts all belong to the same model.

riot.toml is ordinary TOML: no S-expressions, no separate configuration language, and no hidden build folklore.

Build one package, the whole workspace, debug builds, release builds, and cross targets from the same command.

Target selection supports exact triples and broad patterns like linux.

riot fmt

One house style

riot fmt is a fast zero-config formatter optimized

for readability and minimizing diffs. There is one house style, and no options. Done.

Formatting is part of the stack, not a project-by-project bikeshed.

Output should be readable first and stable enough that reviews show the actual change.

riot fix

Linting and codemods

riot fix is an extensible linter with automated fixes, codemods, and package-provided rules.

Riot fix should not just tell you something is wrong. When Riot knows the fix, it shows the edit and can apply it.

Packages can register lint rules and fixes, then workspaces or packages can enable those rules in riot.toml.

This is what makes upgrades smoother: the package that changed can ship the rule that helps your code move with it.

riot test

Testing

Unit tests, property tests, snapshot tests, and fuzz cases live under one test runner.

Use unit tests for exact behavior, property tests for broad invariants, and snapshots for generated output that needs review. Fuzz cases declared with the test API replay under riot test, so weird inputs found later become part of the ordinary regression loop.

Package and suite filters keep the local loop tight when you only need one slice of the workspace. riot fuzz

Coverage-guided fuzzing

riot fuzz runs coverage-guided fuzzing campaigns against narrow boundaries such as parsers, codecs, protocol handlers, and CLI parsers.

A fuzz case is an ordinary Std.Test case declared with Test.fuzz, with seeds, corpus files, and mutator hints.

Generated coverage-increasing inputs are stored under .riot/fuzzing/<package>/<suite>/<case>/corpus/ as local state.

Crashes are saved under crashes/, with captured stdout, stderr, and status in crash-artifacts/ for triage.

A real finding should become a small durable regression: an inline seed, a curated fixture, or a minimized tracked crash input.

riot snapshots

Snapshot review

Snapshot testing checks generated output by comparing it against a saved expected file. When the output changes, the test writes a new candidate so you can inspect the diff and decide whether the change is correct.

riot snapshots is the review loop for those candidates: approve the new expected output, reject it, or leave it pending until you understand what changed.

Use snapshots for output where the full shape matters: formatter output, diagnostics, generated docs, parser fixtures, and text reports. Snapshot candidates are written as pending files, so generated changes do not silently replace the expected behavior.

Interactive review lets you approve, reject, ignore, or quit without manually hunting through fixture paths.

The goal is not to bless every diff. The goal is to make expected-output changes visible, reviewable, and boring to manage.

riot bench

Benchmarking

riot bench runs small and large benchmarks, then records and compares runs from the same toolchain.

Benchmark suites run through Riot, so they use the same package, profile, and toolchain model as the rest of the workspace.

--record persists a run under .riot/bench when you want history, and --compare brings previous comparable runs into the current report.

Use release profile benchmarks when the performance question is about optimized code. pkgs.ml is the Riot package registry: package index, publish flow, search surface, generated docs, and

public usage stats. The registry is powered by GitHub and Cloudflare, but the workflow stays in Riot: add, remove, update, publish, yank, search, login, and logout.

Publishing a package can generate documentation and make it available under docs.pkgs.ml.

The registry tracks useful public statistics, like downloads and version usage, so maintainers can see what still needs support.

Package operations stay scriptable for local workflows and agents with --json where automation needs it. riot initriot new

Golden-path scaffolding

riot init and riot new create workspaces and packages from the blessed path instead of assembling boilerplate by hand.

riot init starts a workspace with the files Riot expects, including package manifests and the OCaml toolchain config.

riot new adds a package inside an existing workspace without making you remember the directory shape.

The first generated project should already feel like Riot: a package, a manifest, a test loop, and a clear next command.

riot toolchain

OCaml toolchains

Riot ships vendored, precompiled OCaml toolchains and compilers for supported architectures.

A workspace declares the OCaml version and target set in ocaml-toolchain.toml.

Riot provisions and validates the toolchain under ~/.riot/toolchains, including cross-toolchain components when targets need them.

Builds, docs, tests, benches, fuzzing, and package commands use the same toolchain decision.

riot doc

Documentation

riot doc generates package documentation locally

for your packages and dependencies. Documentation is written in Markdown in source comments and package docs, then generated into static pages.

Generated docs follow Riot's Jolly Roger, so package docs, API reference pages, and registry docs share one readable style.

Publishing to pkgs.ml can publish docs under docs.pkgs.ml as part of the package flow.

riot run

Run executables

riot run runs Riot executables from your workspace, GitHub repos, and URLs.

Run local workspace binaries without manually finding the build output path.

Disambiguate by package when a workspace has more than one runnable target.

Run remote sources for project generators, scaffolding helpers, and one-off tools.

Forward runtime arguments after -- so the command remains scriptable.

riot <pkg>:<cmd>

Package provider commands

Packages can register first-class Riot commands, so dependencies can extend your workflow without becoming separate global tools.

A package can declare commands in riot.toml; Riot discovers them from the workspace and runs them as riot package:command.

Riot builds the package before executing the command, so provider commands stay in sync with the package version you depend on.

That makes package-specific workflows feel native: migrations, code generation, asset compilation, schema checks, and project upgrades can all live behind Riot.

What’s possible in Riot?

Riot is for building OCaml software as one piece: tools, services, databases, packages, experiments, and systems that need to stay understandable while they grow.

Multi-core applications

Build actor-oriented systems on top of the runtime in std/runtime and the actor interface exposed through std/actor. Spawn work, supervise it, and let Riot use the cores you have.

Command line interfaces

Build fast CLIs with structured output, clear errors, and the kind of terminal behavior agents and humans can both drive.

Cloud and networked services

Use actors, supervision, message passing, and a practical standard library to build services that do real IO. The std/IO surface includes ioSlice for zero-copy operations when bytes need to move without extra copying.

Developer tooling

Write formatters, linters, code generators, release tools, migration scripts, and project automation with the same toolchain they plug into.

TUI applications

Build terminal interfaces with Riot packages like minttea and gooey: structured state, keyboard-driven UI, and native terminal ergonomics.

Web applications

Build web surfaces with suri, including LiveView support in suri/liveview, typed domain logic, and agent-friendly APIs without giving up the ergonomics of OCaml.

Database-backed systems

Build typed database flows with sqlx, connect to PostgreSQL through postgres, and use sqlite when the right database is a local file.

Agentic workflows

Create workflows that can be run, inspected, repaired, and repeated by agents: JSON output, stable diagnostics, clear command boundaries, and recoverable failure modes.

── more in #ai-tools 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/show-hn-riot-a-moder…] indexed:0 read:7min 2026-05-26 ·