plugins/ocaml-dev/skills/project-setup/SKILL.md
Standards for OCaml project metadata files. Use when initializing a new OCaml library/module, preparing for opam release, setting up CI, discussing project structure, or ensuring proper .mli/.ocamlformat files exist.
npx skillsauth add avsm/ocaml-claude-marketplace project-setupInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Every OCaml project needs:
| File | Purpose |
|------|---------|
| dune-project | Build configuration, opam generation |
| dune (root) | Top-level build rules |
| .ocamlformat | Code formatting (required) |
| .gitignore | VCS ignores |
| LICENSE.md | License file |
| README.md | Project documentation |
| CI config | GitHub Actions / GitLab CI / Tangled |
Every library module must have an .mli file for:
(* lib/user.mli *)
(** User management.
This module provides types and functions for user operations. *)
type t
(** A user. *)
val create : name:string -> email:string -> t
(** [create ~name ~email] creates a new user. *)
val name : t -> string
(** [name u] is the user's name. *)
val pp : t Fmt.t
(** [pp] is a pretty-printer for users. *)
Documentation style:
[name args] is/does ...[name] is ...For modules with a central type t:
type t
val v : ... -> t (* pure constructor *)
val create : ... -> (t, Error.t) result (* constructor with I/O *)
val pp : t Fmt.t (* pretty-printer - required *)
val equal : t -> t -> bool (* equality *)
val compare : t -> t -> int (* comparison *)
val of_json : Yojson.Safe.t -> (t, string) result
val to_json : t -> Yojson.Safe.t
Required: .ocamlformat in project root.
version = 0.28.1
Run dune fmt before every commit.
Each module using logging should declare a source:
let log_src = Logs.Src.create "project.module"
module Log = (val Logs.src_log log_src : Logs.LOG)
Log levels:
Log.app - Always shown (startup)Log.err - Critical errorsLog.warn - Potential issuesLog.info - InformationalLog.debug - Verbose debuggingRead from ~/.claude/ocaml-config.json:
{
"author": { "name": "Name", "email": "[email protected]" },
"license": "ISC",
"ci_platform": "github",
"git_hosting": { "type": "github", "org": "username" },
"ocaml_version": "5.2.0"
}
Every source file starts with license header:
(*---------------------------------------------------------------------------
Copyright (c) {{YEAR}} {{AUTHOR}}. All rights reserved.
SPDX-License-Identifier: ISC
---------------------------------------------------------------------------*)
project/
├── dune-project
├── dune
├── .ocamlformat
├── .gitignore
├── LICENSE.md
├── README.md
├── lib/
│ ├── dune
│ ├── foo.ml
│ └── foo.mli # Required for every .ml
├── bin/
│ ├── dune
│ └── main.ml
├── test/
│ ├── dune
│ ├── test.ml
│ └── test_foo.ml
├── .github/workflows/ # GitHub Actions
├── .gitlab-ci.yml # GitLab CI
└── .tangled/workflows/ # Tangled CI
(lang dune 3.21)
(name project_name)
(source (tangled handle/project_name)) ; or (github user/repo)
(license ISC)
(authors "Name <email>")
(generate_opam_files true)
(license ISC)
(authors "Name <[email protected]>")
(maintainers "Name <[email protected]>")
(source (tangled user.domain/project_name))
(package
(name project_name)
(synopsis "Short description")
(description "Longer description")
(depends
(ocaml (>= 5.2))
(alcotest (and :with-test (>= 1.7.0)))))
Source options:
(source (tangled handle/repo)) - Tangled hosting (default for monopam)(source (github user/repo)) - GitHub hosting(source (gitlab user/repo)) - GitLab hostingNote: Don't add (version ...) - added at release time.
For projects hosted on tangled.org, use the succinct source stanza:
(source (tangled user.domain/project-name))
Examples:
(source (tangled anil.recoil.org/ocaml-brotli))(source (tangled user.example.org/my-library))For projects hosted on tangled.org, create .tangled/workflows/build.yml:
when:
- event: ["push", "pull_request"]
branch: ["main"]
engine: nixery
dependencies:
nixpkgs:
- shell
- stdenv
- findutils
- binutils
- libunwind
- ncurses
- opam
- git
- gawk
- gnupatch
- gnum4
- gnumake
- gnutar
- gnused
- gnugrep
- diffutils
- gzip
- bzip2
- gcc
- ocaml
- pkg-config
steps:
- name: opam
command: |
opam init --disable-sandboxing -a -y
- name: repo
command: |
opam repo add aoah https://tangled.org/anil.recoil.org/aoah-opam-repo.git
- name: deps
command: |
opam install . --confirm-level=unsafe-yes --deps-only
- name: build
command: |
opam exec -- dune build
- name: test
command: |
opam install . --confirm-level=unsafe-yes --deps-only --with-test
opam exec -- dune runtest --verbose
| Field | Description |
|-------|-------------|
| when | Trigger conditions: event (push/pull_request) and branch |
| engine | Build engine, use nixery for Nix-based builds |
| dependencies.nixpkgs | List of Nix packages to include |
| environment | Global or per-step environment variables |
| steps | Build steps with name and command |
Per-step environment variables:
steps:
- name: test
environment:
MY_VAR: value
command: |
echo $MY_VAR
See templates/ directory for:
dune-project.templatedune-root.templateci-github.ymlci-gitlab.ymlci-tangled.ymlgitignoreocamlformatLICENSE-ISC.mdLICENSE-MIT.mdREADME.template.mdtools
Working with the OxCaml extensions to OCaml. Use when the oxcaml compiler is available and you need high-performance, unboxing, stack allocation, data-race-free parallelism
development
Creating OCaml library tutorials using .mld documentation format with MDX executable examples. Use when discussing tutorials, documentation, .mld files, MDX, or interactive documentation.
development
Testing strategies for OCaml libraries. Use when discussing tests, alcotest, eio mocks, test structure, or test-driven development in OCaml projects.
development
Security hardening for OCaml libraries through systematic vulnerability research. Use when Claude needs to: (1) Research CVEs in similar implementations (C, Rust, Go, Python) and add regression tests, (2) Add fuzz tests for parsers and encoders, (3) Audit integer handling and buffer operations, (4) Test boundary conditions and malformed input, (5) Review cryptographic usage, (6) Add defensive checks against common vulnerability classes