# Oc — a Cargo-like CLI for OCaml beginners (AI-assisted, feedback very welcome)

**URL:** <https://discuss.ocaml.org/t/oc-a-cargo-like-cli-for-ocaml-beginners-ai-assisted-feedback-very-welcome/18020>\
**Category:** Ecosystem\
**Tags:** tools\
**Created:** [April 28, 2026, 10:22am UTC](https://discuss.ocaml.org/t/oc-a-cargo-like-cli-for-ocaml-beginners-ai-assisted-feedback-very-welcome/18020 "2026-04-28T10:22:01Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Emil\_Kloeden](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/emil_kloeden/32/6485_2.png) [@Emil\_Kloeden](https://discuss.ocaml.org/u/Emil_Kloeden)\
**Post date:** [April 28, 2026, 10:22am UTC](https://discuss.ocaml.org/t/oc-a-cargo-like-cli-for-ocaml-beginners-ai-assisted-feedback-very-welcome/18020/1 "2026-04-28T10:22:01Z")

</div>

Hi everyone,

I’m a newcomer to OCaml, and one of the things that has slowed me down is the tooling setup: understanding opam switches, remembering to `eval $(opam env)`, knowing when to regenerate `.opam`files. So (together with Claude Code) I built `oc` - a small CLI that wraps `opam` and `dune` and gives them a Cargo- or uv-like interface:

```auto
oc new my_app # scaffold project + initialise isolated switch
oc add yojson # add dependency, update oc.toml, install
oc build # ensure deps, dune build
oc run # ensure deps, dune exec

```

No `opam switch create`, no `eval $(opam env)`, no hand-editing `.opam` files.

## What it is:

A small, thin orchestration layer with no dependencies beyond opam and dune themselves. It calls opam to manage switches and resolve packages, and dune to build - wrapping the tools the community already uses and trusts rather than replacing them. It deliberately does less: if you want full control over your environment, opam gives you that directly.

## What it isn’t:

A replacement for opam or dune. The intention is to offer a simpler surface for those who prefer it, whether you’re just starting out or you’ve been writing OCaml for years and want less ceremony for everyday tasks.

## A note on AI assistance:

I should be upfront: this project was developed almost entirely with the help of Claude Code. I wrote the specs, made the design decisions, and reviewed everything - but the code is almost entirely AI-generated. I think that’s worth naming, both for transparency and because it’s an interesting case study in what AI-assisted development looks like for a small tool.

## Prior art:

I’m aware of a few similar efforts. `esy` is the closest in spirit - sandboxed builds, a lock file, a simpler manifest - but it makes some different choices: it requires Node.js (`npm install -g esy`) and brings its own dependency resolver rather than delegating to opam. `oc`  
is a narrower tool: no additional runtime dependencies, stays on top of standard opam and dune, and trades power for simplicity.` dune init project` handles scaffolding but leaves switch management to you. opam’s own local switches (`opam switch create . 5.2.0`) are essentially what `oc` automates, but you still have to drive them manually. If there’s something I’ve missed that already solves this cleanly, I’d genuinely like to know.

## Why not just shell aliases?

You probably could get close with a few shell functions. The reasons I went further: a cross-platform binary needs no shell setup, the lockfile gives reproducible builds across machines, and having a single `oc.toml` as the source of truth is cleaner than remembering which opam commands to run. Whether that’s worth it is a fair question.

## Why Go, not OCaml:

Partly the bootstrapping problem — it felt odd to write a tool that helps you set up OCaml before you can set up OCaml. More practically, Go made it easy to ship a single static binary with no runtime dependencies, and it let me build and iterate on the tool quickly. I’m not against a port to OCaml if someone wanted to take that on.

## Current state:

The tool works for my personal use, has a test suite, a lockfile, and basic CI. It’s rough around the edges and I’m sure there are things that would make an experienced OCaml developer wince. That’s part of why I’m posting - I’d genuinely value feedback on:

- Does this solve a real problem, or does the community have better answers I missed?
- Are there correctness issues with how `oc` manages switches or generates `.opam`files?
- What’s missing before this would be useful to you?

The homepage is at [emilkloeden.github.io/oc](https://emilkloeden.github.io/oc) and the source is at [github.com/emilkloeden/oc](https://github.com/emilkloeden/oc).

Thanks for reading and I look forward to your feedback.

---

<div class="post-metadata">

**Author:** ![lindig](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lindig/32/532_2.png) [@lindig](https://discuss.ocaml.org/u/lindig)\
**Post date:** [April 28, 2026, 10:57am UTC](https://discuss.ocaml.org/t/oc-a-cargo-like-cli-for-ocaml-beginners-ai-assisted-feedback-very-welcome/18020/2 "2026-04-28T10:57:43Z")

</div>

A lot of languages provide this type of scaffolding to create a new project. But I always wonder: is this not quite similar to starting from a template Git repository? A Git template repository does not depend on new tools and is easy to maintain. The moment where we have to edit the generated files is arriving sooner or later. So in my view a scaffolding tool is only useful at the start of a project.

---

<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:** [April 28, 2026, 5:59pm UTC](https://discuss.ocaml.org/t/oc-a-cargo-like-cli-for-ocaml-beginners-ai-assisted-feedback-very-welcome/18020/3 "2026-04-28T17:59:14Z")

</div>

Welcome to OCaml and thanks for sharing your project! 🙂

> Does this solve a real problem, or does the community have better answers I missed?

This is still an open problem in the ecosystem. You may be interested in comparing with these related efforts as well:

- [https://github.com/ocamlpro/drom](https://github.com/ocamlpro/drom)
- [https://github.com/tmattio/spin](https://github.com/tmattio/spin)
- [https://www.alicecaml.org/](https://www.alicecaml.org/)
- [OCaml Package Management With Dune - Dune documentation](https://dune.readthedocs.io/en/stable/tutorials/dune-package-management/index.html) (for which, coincidentally, we just published an update [Dune Package Management Updates](https://discuss.ocaml.org/t/dune-package-management-updates/18023/1))

There are also some unpublished/un-publicized efforts in this space which you may come across 🙂

---

<div class="post-metadata">

**Author:** ![Emil\_Kloeden](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/emil_kloeden/32/6485_2.png) [@Emil\_Kloeden](https://discuss.ocaml.org/u/Emil_Kloeden)\
**Post date:** [April 29, 2026, 7:59am UTC](https://discuss.ocaml.org/t/oc-a-cargo-like-cli-for-ocaml-beginners-ai-assisted-feedback-very-welcome/18020/4 "2026-04-29T07:59:24Z")

</div>

Hi!

Thanks for taking the time to give me feedback 😀.

Whilst I would summarise your feedback as “not something I would use”, I appreciate you making the effort to suggest an alternate workflow. I’ll admit you can go a long way with a good template. I think tools such as `uv` in the python system (for which I’m better acquainted) provide one advantage over the template which is the facility to iteratively add dependencies as you come across a need for them. Obviously you don’t _need_ a tool (or perhaps more accurately _another_ tool) for that.

Thanks again!

---

<div class="post-metadata">

**Author:** ![Emil\_Kloeden](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/emil_kloeden/32/6485_2.png) [@Emil\_Kloeden](https://discuss.ocaml.org/u/Emil_Kloeden)\
**Post date:** [April 29, 2026, 8:07am UTC](https://discuss.ocaml.org/t/oc-a-cargo-like-cli-for-ocaml-beginners-ai-assisted-feedback-very-welcome/18020/5 "2026-04-29T08:07:10Z")

</div>

Hi 👋

Thanks for the feedback and warm welcome. I appreciate you validating I’ve at least hit on a real problem. Thank you also for sharing additional prior-art. I’m not naive enough to think I’d be the first one to try to tackle a problem, but I didn’t expect there to be this many previous attempts 😅. Does kinda give me [XKCD standards](https://xkcd.com/927) vibes 😃 .It makes me think the underlying reason while it remains a problem must be an interesting one.

I have some reading to do, thanks again!

---

<div class="post-metadata">

**Author:** ![avsm](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/avsm/32/6_2.png) [@avsm](https://discuss.ocaml.org/u/avsm)\
**Post date:** [April 29, 2026, 11:23am UTC](https://discuss.ocaml.org/t/oc-a-cargo-like-cli-for-ocaml-beginners-ai-assisted-feedback-very-welcome/18020/6 "2026-04-29T11:23:07Z")

</div>

> [@Emil\_Kloeden](#):
>
> `# add dependency, update oc.toml, install`

The key thing in these tools (which are great to see!) is to avoid creating new metadata formats like `oc.toml`.

If your tool instead directly probed for dune-project and/or \*.opam files and updated the right thing (e.g. depending on whether dune opam file generation is active or not), you would interoperate with existing projects and not have another file format (which gets out of sync very fast).

---

<div class="post-metadata">

**Author:** ![Emil\_Kloeden](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/emil_kloeden/32/6485_2.png) [@Emil\_Kloeden](https://discuss.ocaml.org/u/Emil_Kloeden)\
**Post date:** [April 30, 2026, 2:15am UTC](https://discuss.ocaml.org/t/oc-a-cargo-like-cli-for-ocaml-beginners-ai-assisted-feedback-very-welcome/18020/7 "2026-04-30T02:15:47Z")

</div>

Thank you for the constructive criticism. What you say makes sense to me. A toml file might initially be more intuitive to someone with a background like mine, but less intuitive to others. It isn’t necessary for any user (the workflow being to use the add subcommand rather than manipulate a config file) so I have created an issue and tagged it for the next release.

Thanks for taking the time to provide input 😀!

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [May 1, 2026, 12:55am UTC](https://discuss.ocaml.org/t/oc-a-cargo-like-cli-for-ocaml-beginners-ai-assisted-feedback-very-welcome/18020/8 "2026-05-01T00:55:00Z")

</div>

> [@Emil\_Kloeden](#):
>
> it requires Node.js (`npm install -g esy`)

> <https://x.com/benjdod/status/2049958499791356017>

---

<div class="post-metadata">

**Author:** ![hyphenrf](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hyphenrf/32/2733_2.png) [@hyphenrf](https://discuss.ocaml.org/u/hyphenrf)\
**Post date:** [May 7, 2026, 7:32pm UTC](https://discuss.ocaml.org/t/oc-a-cargo-like-cli-for-ocaml-beginners-ai-assisted-feedback-very-welcome/18020/9 "2026-05-07T19:32:16Z")

</div>

fyi the command name `oc` is already taken by redhat’s [openshift](https://en.wikipedia.org/wiki/OpenShift)

> People started using npm as a system package manager, I guess because it’s easier than shipping to apt and yum […]

easier and [much less secure](https://cyberarmy.tech/blog/supply-chain-security-attacks-2025-2026) 🙂  
(Edit: well [I didn’t even get to catch my breath](https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem) on that one)

---

<div class="post-metadata">

**Author:** ![Emil\_Kloeden](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/emil_kloeden/32/6485_2.png) [@Emil\_Kloeden](https://discuss.ocaml.org/u/Emil_Kloeden)\
**Post date:** [May 10, 2026, 5:35am UTC](https://discuss.ocaml.org/t/oc-a-cargo-like-cli-for-ocaml-beginners-ai-assisted-feedback-very-welcome/18020/10 "2026-05-10T05:35:15Z")

</div>

> [@hyphenrf](#):
>
> already

Hi! Thanks for the feedback 😀. Given the uptake on this is likely to be extremely low, i can live with the clash 😅 (and two characters is nice).
