The opam manual

This manual gathers reference information on opam and its file formats. It is primarily of use for packagers, package maintainers and repository maintainers.

  • For simple usage of opam, see the Usage page, and the comprehensive built-in documentation opam [command] --help.
  • For a gentler introduction to packaging, see the Packaging guide
  • If you want to hack on opam or build related tools, the API documentation can be browsed here

File hierarchies

opam root

opam holds its configuration, metadata, logs, temporary directories and caches within a directory that we will call opam root. By default, this is ~/.opam, and we may refer to it by this name in this manual for the sake of simplicity, but this can be changed using the OPAMROOT environment variable or the --root command-line argument.

An existing opam root is required for opam to operate normally, and one is created upon running opam init. The initial configuration can be defined through a configuration file at ~/.opamrc, /etc/opamrc or at a location specified through the --config command-line option. If none is present, opam defaults to its built-in configuration that binds to the OCaml repository at

Except in explicit cases, opam only alters files within its opam root. It is organised as follows:

  • ~/.opam/config: the global opam configuration file
  • ~/.opam/repo/: contains the mirrors of the configured package repositories
  • ~/.opam/repo/repos-config: lists the configured package repositories and their URLs
  • ~/.opam/repo/<repo>: mirror of the given repository
  • ~/.opam/opam-init/: contains opam configuration scripts for the outside world, e.g. shell environment initialisation
  • ~/.opam/download-cache/: caches of downloaded files
  • ~/.opam/plugins/<plugin>: reserved for plugins
  • ~/.opam/<switch>: prefixes of named switches


Repositories are collection of opam package definitions. They respect the following hierarchy:

  • /repo: repository configuration file
  • /packages/<pkgname>/<pkgname>.<version>/opam: holds the metadata for the given package. url and descr may also be present, in which case they override what may already be present in the opam file
  • /packages/<pkgname>/<pkgname>.<version>/files/: contains files that are copied over the root of the source tree of the given package before it gets used.
  • /cache/: cached package files, by checksum. Note that the cache location is configured in the repo file, this name is only where opam admin cache puts it by default.
  • /archives/: this is no longer used by opam automatically, but is the canonical place where you should place your package archives if you want to serve them from the repository server directly. The URLs of the packages will have to be set accordingly.
  • /index.tar.gz: archive containing the whole repository contents (except the cache), needed when serving over HTTP. It can be generated using opam admin index.

opam repositories can be accessed using local or remote (ssh) paths, HTTP URLs, or one of the supported version control systems (git, Mercurial, Darcs). A repository is set up using

opam repository add <name> <URL> [--this-switch|--all-switches|--set-default]

The last flag sets what switches are affected by the new repository:

  • --this-switch (default) selects only the current switch
  • --all-switches affects all the currently existing switches
  • --set-default affects all switches created in the future

Creating a new switch using e.g. a custom repository overlay on the default repository can be done in a single call using:

opam switch create --repos=<name>=<URL>,default

which will define the new repository <name> at <URL> if needed.

Use opam repository list --all for an overview of configured repositories. Repository selection is always ordered, with the definition of a given version of a package being taken from the repository with the lowest index where it is found.

Data from the configured repositories is updated from the upstreams manually using the opam update command. This only updates repositories in use by the currently selected switches, unless --all is specified.


opam is designed to hold any number of concurrent installation prefixes, called switches. Switches are isolated from each other and have their own set of installed packages, selection of repositories, and configuration options. All package-related commands operate on a single switch, and require one to be selected.

The current switch can be selected in the following ways:

  • globally, using opam switch <switch>. opam will use that switch for all further commands, except when overridden in one of the following ways.
  • for local switches, which are external to the opam root, when in the directory where the switch resides or a descendant.
  • by setting the OPAMSWITCH=<switch> environment variable, to set it within a single shell session. This can be done by running eval $(opam env --switch <switch>) to set the shell environment at once, see below.
  • through the --switch <switch> command-line flag, for a single command.

Switches have their own prefix, normally ~/.opam/<switch>, where packages get installed ; to use what is installed in a switch, some environment variables need to be set, e.g. to make executables installed into ~/.opam/<switch>/bin visible, that directory needs to be added to PATH, but individual packages can define their own settings as well.

Command opam env returns the environment updates corresponding to the current switch, in a format readable by your shell, and when needed opam will prompt you to run:

eval $(opam env)

A switch is created using opam switch create <switch> (<compiler>|--empty).

  • <switch> can be either a plain name, or a directory name (if containing / or starting with .). In the latter case the switch is local and instead of being held at ~/.opam/<switch>, it will be created in the given directory, as a _opam subdirectory. Local switches are automatically selected depending on the current directory, see above.
  • If a <compiler> is selected, opam will install the corresponding packages and their dependencies in the new switch. These packages will be marked as base, protected against removal and unaffected by upgrade commands. <compiler> can be selected among packages which have the compiler flag set, or their versions. Use opam switch list-available to list them.


If we define <switch-prefix> as:

  • ~/.opam/<switch> for plain switches
  • <switch>/_opam for local switches, when <switch> is a path

Switches are laid out thusly:

  • <switch-prefix>/: prefix of the switch, holding the installation hierarchy in the UNIX /usr standard (with subdirectories bin, lib, share, man, doc, etc...)
  • <switch-prefix>/.opam-switch/: holds all opam data regarding this switch
  • <switch-prefix>/.opam-switch/switch-config: switch-specific configuration
  • <switch-prefix>/.opam-switch/switch-state: stores the sets of installed, base, pinned packages
  • <switch-prefix>/.opam-switch/environment: contains the environment variable settings for this switch
  • <switch-prefix>/.opam-switch/reinstall: list of packages marked for reinstallation (development packages where changes have been detected)
  • <switch-prefix>/.opam-switch/config/<pkgname>.config: installed package's, opam specific configuration
  • <switch-prefix>/.opam-switch/install/<pkgname>.install: .install files used to install the given package
  • <switch-prefix>/.opam-switch/install/<pkgname>.changes: file system changes done by the installation of the given package, as tracked by opam
  • <switch-prefix>/.opam-switch/packages/<pkgname>.<version>/: metadata of the given package as it has been used for its installation
  • <switch-prefix>/.opam-switch/sources/<pkgname>.<version>/ or <pkgname>/: unpacked sources of packages. The version is omitted from the directory name for pinned packages, which are typically synchronised to a version-control system rather than unpacked from an archive.
  • <switch-prefix>/.opam-switch/overlay/<pkgname>/: custom definition for the given pinned packages
  • <switch-prefix>/.opam-switch/build/<pkgname>.<version>/: temporary directories where the packages are compiled
  • <switch-prefix>/.opam-switch/remove/<pkgname>.<version>/: temporary directories used for calling the packages' remove commands, when those need the source.
  • <switch-prefix>/.opam-switch/backup: snapshots of previous states of the switch, and other backup files.


Pinning is an operation by which a package definition can be created or altered locally in a switch.

In its most simple form, opam pin <package> <version>, <package> is bound to the specified version and won't be changed on opam upgrade (assuming it is an existing package). opam pin edit <package> provides a way to directly pin and edit the metadata of the given package, locally to the current switch, for example to tweak a dependency.

opam pin [package] <URL> can further be used to divert the source of a package, or even create a new package ; this is very useful to point to a local path containing a development or patched version of the package source. When pinning a package, the source is searched for metadata in an opam or <pkgname>.opam file, either at the root of the source tree or in an opam directory. You can also replace that file by a directory containing an opam file and optionally other metadata, like a files/ subdirectory.

As the package argument is optional, opam guesses package name from the <URL> or the opam file found. Note that for local VCS pinning, when given without package name, opam retrieves the locally found opam file, even if not versioned. If this file is versioned, opam relies on the versioned version.

Whenever an install, reinstall or upgrade command-line refers to a pinned package, opam first fetches its latest source. opam update [--development] is otherwise the standard way to update the sources of all the packages pinned in the current switch.

opam install <DIR> is an automatic way to handle pinning packages whose definitions are found in <DIR>, synchronise and install them. The upgrade, reinstall and remove commands can likewise be used with a directory argument to refer to pinned packages.

Common file format


Syntax is given in a BNF-like notation. Non-terminals are written <like this>, terminals are either plain text or written in double-quotes ("terminal"), curly brackets denote zero or more repetitions when suffixed with *, or one or more when suffixed with +, and square brackets denote zero or one occurrence. Parentheses are for grouping. (") and (""") respectively mean one and three quotation mark characters.

As a special case, and for readability, we add simplified notations for lists and options:

  • [ <list-contents> ... ] means "[" { <list-contents> }* "]" | <list-contents>. It corresponds to a case of the <list> non-terminal and is a list of <list-contents> repeated any number of times. The square brackets can be omitted when <list-contents> occurs just once.
  • <element> { <opt> ... } means <element> "{" { <opt> }* "}", and is a shortcut for the <option> non-terminal.
  • <element> { <opt> } means <element> [ "{" <opt> "}" ]. It corresponds to a specific case of the <option> non-terminal where there is exactly one element within the braces..

General syntax

<file-contents> ::= { <file-item> }*
<file-item>     ::= <field-binding> | <section>
<field-binding> ::= <ident> : <value>
<section>       ::= <ident> [ <string> ] "{" <file-contents> "}"
<ident>         ::= { <identchar> }* <letter> { <identchar> }*
<varident>      ::= [ ( <ident> | "_" ) { "+" ( <ident> | "_" ) }* : ] <ident>
<identchar>     ::= <letter> | <digit>  | "_" | "-" | "+"
<letter>        ::= "a".."z" | "A".."Z"
<digit>         ::= "0".."9"
<value>         ::= <bool> | <int> | <string> | <ident> | <varident> | <operator> | <list> | <option> | "(" <value> ")"
<bool>          ::= true | false
<int>           ::= [ "-" ] { <digit> }+
<string>        ::= ( (") { <char> }* (") ) | ( (""") { <char> }* (""") )
<term>          ::= <string> | <varident>
<operator>      ::= { "!" | "=" | "<" | ">" | "|" | "&" }+ | [ ":" ] <operator> [ ":" ]
<list>          ::= "[" { <value> }* "]"
<option>        ::= <value> "{" { <value> }* "}"
<comment>       ::= ( "(*" { <char> }* "*)" ) | ( "#" { <char\newline> }* <newline> )

The opam file formats share a common base syntax. The files are UTF-8 encoded and define a list of fields and sections.

opam uses a range of different files, each allowing their own set of fields and sections, in a specific format.

Base values can be literal booleans, integers or strings, identifiers, and operators. Strings allow the escapes \", \\, \n, \r, \b, \t, as well as three-digit decimal and two-digit hexadecimal character codes (\NNN and \xNN), and escaped newlines. As a special case, they can be enclosed in triple double-quotes ("""), so that single quotes don't need to be escaped. Lists must be enclosed in square brackets unless they contain a single element. Values can be followed by an argument in braces. Parentheses may be used to group sub-expressions.

Comments may be either enclosed in (* and *), or # and newline. They are ignored by opam.

Package Formulas

Package formulas are used to express requirements on the set of installed packages.

<package-formula> ::= <package-formula> <logop> <package-formula>
                    | ( <package-formula> )
                    | <pkgname> { { <version-formula> }* }
<logop>           ::= "&" | "|"
<pkgname>         ::= (") <ident> (")
<package>         ::= (") <ident> "." <version> (")
<version-formula> ::= <version-formula> <logop> <version-formula>
                    | "!" <version-formula>
                    | "(" <version-formula> ")"
                    | <relop> <version>
<relop>           ::= "=" | "!=" | "<" | "<=" | ">" | ">="
<version>         ::= (") { <identchar> | "+" | "." | "~" }+ (")

Package names have the same restrictions as idents — only letter, digits, dash and underscore, and contain at least one letter — but must be enclosed in quotes. Versions are non-empty strings, with some restrictions on the characters allowed.

We are using logic formulas with the operators & and | for AND and OR, over package names. & is higher priority than |, so the parentheses in this example are required:

("neat_package" | "also_neat_package") & "required_package"

Package names can be suffixed with version constraints, which restricts the requirement further. Version constraints have the form <relop> <version> and can be combined with binary AND & and OR |, and prefix NOT !. The allowed relational operators are =, !=, <, <=, > and >=, and their meaning is defined by Version Ordering. They always have higher priority than logical operators.

Version Ordering follows the basics of the Debian definition.

It is basically "lexicographical order, with numbers handled properly". In more detail (see the Debian page for full details):

  • Version strings are sliced into alternate, possibly empty non-digit / digit sequences, always starting with a non-digit sequence. 1.0~beta2 is thus ["";1;".";0;"~beta";2].

  • Those sequences are sorted lexicographically. Because of the split as non-digit; digit; non-digit; ..., non-digit sequences are always compared to non-digit sequences (and conversely). For example, the versions a and 1 are sliced into ["a"] and [""; 1], so we have 1 < a because the non-digit component of 1, which is the empty string "", is smaller than "a".

  • For non-digit components, the ordering used is that letters are always smaller than non-letters (for example z < "#"), while non-letters are compared by ASCII order.

  • The ~ character is special as it sorts even before the end of sequence (i.e. before anything shorter: "~" sorts before "", "a~b" before "a"). It's most convenient for pre-releases, allowing 1.0~beta to be before 1.0.

Here is an example of an ordered sequence: ~~, ~, ~beta2, ~beta10, 0.1, 1.0~beta, 1.0, 1.0-test, 1.0.1, 1.0.10, dev, trunk.

Here is a full example:

"foo" { >= "3.12" } & ("bar" | "baz" { !(> "2" & < "3.5") & != "5.1" })



Variables may appear at a few different places in opam files and configuration. They can be used in two forms:

  • raw idents: foo < bar
  • within strings, using interpolation, when enclosed in %{ and }%: "%{foo}%/bar"

For both forms, and within values that allow them, the variables are replaced by their contents, if any, just before the value is used. Variable contents can be either strings, booleans, lists of strings or undefined, and automatic conversion may take place using the strings "true" and "false" (leading to an undefined bool when converting from any other string). Undefined values are propagated through boolean expressions, and lead otherwise to context-dependent default values (the empty string or false, depending on the expected type, unless specified otherwise).

The syntax"%{var?string-if-true:string-if-false-or-undefined}%" can be used to insert different strings depending on the boolean value of a variable.

Additionally, boolean package variables may be combined using the following form: name1+name2+name3:var is the conjunction of var for each of name1, name2 and name3, i.e it is equivalent to name1:var & name2:var & name3:var.

Warning: if the package name contains a + character (e.g. conf-g++), their variables may only be accessed using opam 2.2 via string interpolation, with the following syntax:



The defined variables depend on the specific fields being defined. There are three scopes:

  1. Global variables correspond to the general current configuration, or to the current switch settings (system setup, opam configuration, current switch name, etc.). For example opam-version, arch, or make.

  2. Package variables have the form package-name:var-name and contain values specific to a given package, for example foo:installed is a boolean variable that can be used to check if package foo is installed, and foo:lib is its library installation directory.

    foo:bar refers to bar in the installed version of foo, and may be undefined if foo is not installed: for example, a package depending on foo can use foo:version to toggle different compatibility modes depending on the installed version of foo.

    One exception is references emanating from the package being defined itself: within foo's definition, foo:bar, which can in this case be abridged in _:bar, always refers to the version being defined.

  3. Some fields define their own local variables, like success and with-dev-setup (since opam 2.2) in the field post-messages. Other examples of this include the with-test, with-doc and with-dev-setup (since opam 2.2) variables, available in the depends:, depopts:, build:, install: and remove: fields.

    Within package definition files, the variables name and version, as shortcuts to _:name and _:version, corresponding to the package being defined, are always available.

Pre-defined variables

The following variables are dynamically defined by opam, but can still be overridden from configuration. You can get the list of currently defined variables by running:

opam config list # opam 2.0
opam var         # opam 2.1.0

Global variables

  • opam-version: the version of the running opam
  • root: the current opam root (e.g. ~/.opam)
  • jobs: opam's jobs (-j) parameter, i.e. the number of parallel builds opam is allowed to run
  • make: the system's make command to use
  • arch: the host architecture, typically one of "x86_32", "x86_64", "ppc32", "ppc64", "arm32" or "arm64", or the lowercased output of uname -m, or "unknown"
  • os: the running OS, typically one of "linux", "macos", "win32", "cygwin", "freebsd", "openbsd", "netbsd" or "dragonfly", or the lowercased output of uname -s, or "unknown"
  • os-distribution: the distribution of the OS, one of "homebrew", "macports" on "macos", or "android" or the Linux distribution name on Linux. Equal to the value of os in other cases or if it can't be detected
  • os-family: the more general distribution family, e.g. "debian" on Ubuntu, "windows" on Win32 or Cygwin, "bsd" on all bsds. Useful e.g. to detect the main package manager
  • os-version: the release id of the distribution when applicable, or system otherwise

Extra variables can be defined in the file ~/.opam/config, using the global-variables: (static) or eval-variables (dynamic) fields.

Switch variables

The following standard paths are defined as variables in the global scope and depend on the current switch:

Additionally, two variables user and group are statically set at switch creation time.

Extra variables can be defined in the file <switch-prefix>/.opam-switch/switch-config, using the variables {} section.

Package variables

These variables need to be prefixed with <pkgname>:, or _:, except for name and version, or if they can unambiguously be resolved as variables of the package being defined.

  • name: name of the package
  • version: version of the package
  • depends: resolved direct dependencies of the package
  • installed: whether the package is installed
  • enable: takes the value "enable" or "disable" depending on whether the package is installed
  • pinned: whether the package is pinned
  • bin, sbin, lib, man, doc, share, etc: the corresponding directories for this package (similar to <pkgname>.install)
  • build: directory where the package was built
  • hash: hash of the package archive
  • dev: true if this is a development package, i.e. it was not built from a release archive
  • build-id: a hash identifying the precise package version and metadata, and that of all its dependencies
  • opamfile: if the package is installed, path of its opam file, from opam internals, otherwise not defined

Extra variables can be defined by any package at installation time, using a <pkgname>.config file with a variables {} field.

Additionally, the following are limited to some package fields (depends:, depopts:, build:, install:, remove:):

  • with-test: only true if tests have been enabled for this specific package
  • with-doc: similarly for documentation
  • with-dev-setup (since opam 2.2): similarly for developer tools

The following are only available in the depends: and depopts: fields, and are used as dependency flags (they don't have a defined true or false value outside of a given operation):

  • build: limits the dependency to a build-time one, avoiding recompilation if it changes
  • post: marks the dependency as unordered, i.e. to be ignored when computing the order of compilations. In other words, this ensures the package will get installed along with the current one, but not that it will be compiled and installed before. This flag can be used to break dependency cycles.


Filters are formulas based on variables. Their main use is as optional conditions to commands or command arguments, using the postfix-braces syntax:

[ "./configure" "--use-foo" {foo:installed} ]

In build instructions, this adds condition foo:installed to the "--use-foo" argument, which will cause it to be omitted unless the variable foo:installed is true. This is evaluated just when the command is going to be run.

<filter> ::= <filter> <logop> <filter>
           | "!" <filter>
           | "?" <filter>
           | ( <filter> )
           | <filter> <relop> <filter>
           | <varident>
           | <string>
           | <int>
           | <bool>

Filters are evaluated at a certain point in time, and should not be mistaken with package formulas, which express requirements.

The following are allowed in filters:

  • String, integer and boolean literals
  • Idents
  • Parentheses
  • Logical operators (binary AND &, binary OR |, prefix, unary NOT !)
  • The unary operator ? for detecting whether a value is defined. ?expr evaluates to true if expr evaluates to a defined value, and false if it evaluates to an undefined value.
  • Binary relational operators (=, !=, <, <=, >, >=)

The comparisons are done using Version Order, including for integers, which are treated as strings. Relational operators have a higher precedence than logical operators.

Undefined values are propagated through relational operators, and logical operators unless absorbed (undef & false is false, undef | true is true). Undefined values may be detected using the ? operator, for example, !(?foo & foo != bar) requires either foo to be undefined or equal in value to bar.

Filtered package formulas

This extension to package formulas allows variables to be referenced within version constraints, and parts of the formula to be made optional. This is evaluated as a first pass, before any action is taken, to deduce a concrete package formula.

The definition is similar to that of <package-formula>, except that two cases <filter> and <relop> <filter> are added to <version-formula>

<filtered-package-formula> ::= <filtered-package-formula> <logop> <filtered-package-formula>
                             | ( <filtered-package-formula> )
                             | <pkgname> { { <filtered-version-formula> }* }

<filtered-version-formula> ::= <filtered-version-formula> <logop> <filtered-version-formula>
                             | "!" <filtered-version-formula>
                             | "?" <filtered-version-formula>
                             | "(" <filtered-version-formula> ")"
                             | <relop> <version>
                             | <filter>
                             | <relop> <filter>

For example, a dependency on "foo" { = version } will require package foo at the version defined by variable version (which is the version of the package being defined). Conditions can be added using the same logical operators present in pure package formulas, so one can also write "foo" { >= "3.12" & build }, which makes the dependency dependent on the boolean value of the variable build.

When the version formula reduces to false, as would be the case here when build=false, the dependency is removed from the formula.


Some files can be rewritten using variable interpolation expansion: in cases where this is available, when looking for file and is found, any %{var}% interpolations found in it are replaced by the contents of var and the results are written back to file.

This can also be done explicitly using the command opam config subst "file".

Environment updates

Some fields define updates to environment variables in the form:

<ident> <update-op> <string>

The allowed update operators update-op denote how the string is applied to the environment variable. Prepend and append operators assume list of elements separated by an OS-specific character.

  • = override (or set if undefined)
  • += or := prepend. They differ when the variable is unset of empty, where := adds a trailing separator.
  • =+ or =: append. They differ when the variable is unset of empty, where =: adds a leading separator.
  • =+= is similar to +=, except that when the variable was previously altered by opam, the new value will replace the old one at the same position instead of being put in front.

FOO = "" causes FOO to be set but empty on Unix but unset on Windows.

FOO += "", FOO := "", etc. are all ignored - i.e. opam never adds empty segments to an existing variable.

Environment update portability

Some fields define an environment update portability specification. In the opam file it is the x-env-path-rewrite: field, of the form:

<environment-rewrites> ::= { <environment-rewrite> }*
<environment-rewrite>  ::= <ident> <bool>
                         | <ident> <separator-formula> <path-format-formula>

<separator-formula>    ::= <separator-formula> "|" <separator-formula>
                         | ( <separator-formula> )
                         | <separator> { { <distrib-formula> }* }
<path-format-formula>  ::= <path-format-formula> "|" <path-format-formula>
                         | ( <path-format-formula> )
                         | <path-format> { { <distrib-formula> }* }

<separator>            ::= (") ":" (") | (") ";" (")
<path-format>          ::= (") "host" (") | (") "host-quoted" (") | (") "target" (") | (") "target-quoted" (")

<distrib-formula>      ::= <distrib-formula> <logop> <distrib-formula>
                         | "!" <distrib-formula>
                         | "(" <distrib-formula> ")"
<logop>                ::= "&" | "|"

The <separator> defines the path separator to use for the variable. The <path-format> defines the way to handle variables path formatting:

  • host: use the host interpretation of PATHs (i.e. convert via cygpath on Windows).
  • host-quoted: use the host interpretation of entries and double-quote any entries which include the separator character.
  • target: use the target interpretation of entries (i.e. rewrite slashes to backslashes on Windows).
  • target-quoted: use the target interpretation of entries and double-quote any entries which include the separator character.

If a variable is not mentioned in x-env-path-rewrite, the separator is assumed to be ; on Windows and : on all other systems; no slash or quoting transformations are performed. There are two special default cases:

  • MANPATH uses : separator and is host
  • PATH on Windows uses ; separator and is target-quoted

For example, on Windows:

  • [FOO false]: FOO won't be translated nor rewritten, and default separator is used if needed
  • [FOO true]: FOO is rewritten using defaults ; and target with slash rewriting
    • FOO = "a:/path/to" -> FOO=a:\path\to
  • [FOO ":" "target-quoted"]: FOOwill be appended using:separator, if the added path contains '/' they are transformed into`, and if the added path contains a :, the added path will be quoted
    • FOO += "a/path/to" -> FOO=a\path\to:R:\previous\path
    • FOO += "a:path/to" -> FOO="a:path\to":R:\previous\path
  • [FOO ":" "host"]: FOOwill be appended using:, and its path will be translated according to the host translator, i.e. cygpath <path>`:
    • FOO += "A:\path\to" -> FOO=/cygdrive/a/path/to:/previous/path


URLs are provided as strings. They can refer to:

  • raw local filesystem paths
  • ssh addresses user@host:path
  • URLs of the form http://, https://, ftp://, ssh://, file://, rsync://
  • Version control URLs for git, mercurial and darcs: git://, hg://, darcs://. This assumes http transport for hg and darcs, i.e. hg:// is short for hg+http://.
    • Note that Github disabled git:// protocol support.
  • Version control bound to a specific URL: <vc>+<scheme>://, e.g. git://, hg+https://, git+file://, etc. (NOTE: this has been added in opam 1.2.1)

In addition, version control URLs may be suffixed with the # character and a reference name (branch, commit, HEAD...): git://, hg+file://

The URLs given for user information (e.g. package homepages and bugtrackers) are not concerned and should just load nice in common browsers.


<checksum> ::= (") [ "md5=" | "sha256=" | "sha512=" ] { <hexchar> }+ (")
<hexchar>  ::= "a".."f" | "A".."F" | "0".."9"

Checksums are specified as strings, in hexadecimal form, and should be prefixed by the name of the hashing algorithm (when unspecified, MD5 is assumed, for backwards compatibility only).

Additionally, the number of hexadecimal chars must match exactly what is expected by the corresponding algorithm (resp. 32, 64 and 128 for MD5, SHA256 and SHA512).

Until opam 2.2.0, if openssl was installed on the system, it would be used for faster computation of SHA hashes.

Specific file formats

This section describes the precise file formats of the different kinds of files used by opam.

Public configuration files

These files are intended to be publicly distributed as part of public repositories or initial distributions or packages.


The repo file is placed at the root of a repository, and allows one to specify some specifics of the repository. It has the following optional fields:

  • opam-version: <string>: File format and repository format version, should be 2.0 as of writing.
  • browse: <string>: An URL where the users may browse available packages online
  • upstream: <string>: The source that this repo is generated and maintained from. Typically, a version-control system address.
  • redirect: [ <string> { <filter> } ... ]: List of URLs to (permanently) redirect to if their filters evaluate to true. Can be used to serve different repositories for different OSes or different versions of opam. Relative URLs are supported from opam 2.0, but discouraged for compatibility reasons.
  • archive-mirrors: [ <string> ... ]: Archive proxy URLs specific to this repository, with the same semantics as the similar config field, except a path without a protocol:// prefix is accepted and will be considered relative to the repository root (e.g. cache/).
  • announce: [ <string> { <filter> } ... ]: Messages that will be printed to the user on initialisation or update of this repository, with optional conditions.


This file has a format close to that of config, and can be used to define an initial setup for opam. When running opam init, if ~/.opamrc or /etc/opamrc is present, or if --config was specified, the configuration options from that file will be used, overriding the defaults.

The default, built-in initial config of opam can be seen with opam init --show-default-opamrc.

Package definitions

Package definitions can be a single opam file. A files/ subdirectory can also be used to add files over the package source. Older versions of opam used descr and url files besides the opam file, and this is still supported, but the preferred way is now to include their information into the opam file instead.

<pkgname>.install and <pkgname>.config, on the other hand, are metadata files used by opam but that are found in the package source directory, after it has been built.


Package definition files, specifying a package's metadata. Usage of the opam lint command is recommended to check the validity and quality of your opam files.

opam files allow the following fields and sections:

  • opam-version: <string> (mandatory): the file format version, should be 2.0 as of writing.

  • name: <pkgname>, version: <version>: the name and version of the package. Both fields are optional when they can be inferred from the directory name (e.g. when the file sits in the repository), but should always be set for package definitions within source trees.

  • maintainer: [ <string> ... ] (mandatory): A contact address for the package maintainer (the format "name <email>" is allowed).

  • authors: [ <string> ... ]: a list of strings listing the original authors of the software.

  • license: [ <string> ... ]: The SPDX expression of the license(s) under which the source software is available (see The SPDX standard allows to define custom licenses if necessary using the LicenseRef-your-custom-name syntax (e.g. license: "LicenseRef-My-Custom-Non-Commercial-License"). When several licenses are defined, the combination of them is equivalent to a single license expression separated by AND. For instance: license: ["MIT" "ISC"] is equivalent to license: "MIT AND ISC".

  • homepage: [ <string> ... ], doc: [ <string> ... ], bug-reports: [ <string> ... ]: URLs pointing to the related pages for the package, for user information

  • dev-repo: <string>: the URL of the package's source repository, which may be useful for developers: not to be mistaken with the URL file, which points to the specific packaged version.

  • tags: [ <string> ... ]: an optional list of semantic tags used to classify the packages. The "org:foo" tag is reserved for packages officially distributed by organization ``foo''.

  • patches: [ <string> { <filter> } ... ]: a list of files relative to the project source root (often added through the files/ metadata subdirectory). The listed patch files will be applied sequentially to the source as with the patch command, stripping one level of leading directories (-p1) -- which is what version control systems generally use . Variable interpolation is available, so you can specify patches: [ "file" ] to have the patch processed from

    Patches may be applied conditionally by adding filters.

  • substs: [ <string> ... ]: a list of files relative to the project source root. These files will be generated from their .in counterparts, with variable interpolations expanded.

  • build: [ [ <term> { <filter> } ... ] { <filter> } ... ]: the list of commands that will be run in order to compile the package.

    Each command is provided as a list of terms (a command and zero or more arguments) ; individual terms as well as full commands can be made conditional by adding filters: they will be ignored if the filter evaluates to false or is undefined. Variable interpolations are also evaluated. These commands will be executed in sequence, from the root of a fresh package source tree.

    The commands executed during the build: stage may write exclusively to this source tree, should be non-interactive and should perform no network i/o. All libraries, syntax extensions, binaries, platform-specific configuration and package-name.config or package-name.install files are expected to be produced within the source directory subtree, i.e. below the command's $PWD, during this step.

    The with-test, with-doc, and with-dev-setup (since opam 2.2) variables are available in the scope of this field: filter testing commands with e.g. [make "test"] {with-test}. The dev variable can also be useful here to detect that the package is not installed from a release tarball, and may need additional preprocessing (e.g. automake).

    If a term is undefined (e.g. an undefined variable), the empty string is used as positional argument.

  • install: [ [ <term> { <filter> } ... ] { <filter> } ... ]: the list of commands that will be run in order to install the package.

    This field follows the exact same format as build:. It is used to move products of build: from the build directory to their final destination under the current prefix, and do any required additional setup. Commands in install: are executed sequentially, from the root of the source tree from where the build: commands have been run. These commands should only write to subdirectories of prefix, without altering the source directory itself.

    This field contains typically just [make "install"]. If a package-name.install is found at the source of the build directory, opam will install files from there to the prefix according to its instructions after calling the commands specified in the install: field have been run, if any.

    Variables with-test, with-doc, and with-dev-setup (since opam 2.2) are also available to the filters used in this field, to run specific installation commands when tests or documentation have been requested.

  • build-doc: [ [ <term> { <filter> } ... ] { <filter> } ... ], build-test: [ [ <term> { <filter> } ... ] { <filter> } ... ] (deprecated): you should use the build: and install: fields with filters based on the with-test and with-doc variables, to specify test and documentation specific instructions. The instructions in the deprecated build-test: are currently understood as part of the run-test: field.

  • run-test: [ [ <term> { <filter> } ... ] { <filter> } ... ]: specific instructions for running the package tests, in a format similar to the build: field. Run only when the package is explicitly installed with --with-test.

  • remove: [ [ <term> { <filter> } ... ] { <filter> } ... ]: commands to run before removing the package, in the same format as build: and install:. As of 2.0, opam tracks the files added to the prefix during package installation, and automatically removes them on package removal, so this should not be needed anymore in most cases (and may even be harmful if files from different packages overlap, which remove scripts generally don't handle). Use it for special actions, like reverting updates to files, or stopping daemons: removing what was just added is already taken care of.

    The commands are run from the root of a fresh copy of the package source, unless the light-uninstall package flag is present, in which case they are run from the prefix.

  • depends: [ <filtered-package-formula> ... ]: the package dependencies. This describes the requirements on other packages for this package to be built and installed. It contains a list of filtered package formulas, understood as a conjunction.

    The filtered package formula can access the global and switch variables, but not variables from other packages. Additionally, special boolean variables build, post, with-test, with-doc, and with-dev-setup (since opam 2.2) are defined to allow limiting the scope of the dependency.

    • build dependencies are no longer needed at run-time: they won't trigger recompilations of your package.
    • post dependencies will be installed along with the package, but are not required to build it. This can be used to cut build cycles of interdependent packages, while making sure they get installed together. Note that, in case of failed or interrupted builds, opam can not guarantee the invariant that !build dependencies are always installed.
    • with-test dependencies are only needed when building tests (when the package is explicitly installed with --with-test)
    • likewise, with-doc dependencies are only required when building the package documentation
    • likewise, with-dev-setup (since opam 2.2) dependencies are only required for a developer tool
  • depopts: [ <pkgname> { <filtered-package-formula> } ... ]: the package optional dependencies. This field is similar to depends: in format. It contains packages that will be used, if present, by the package being defined, either during build or runtime, but that are not required for its installation. The implementation uses this information to define build order and trigger recompilations, but won't automatically install depopts when installing the package.

    Variables in the filtered package formula are evaluated as for depends:, with the same specific variables available (except for post, which wouldn't make sense).

    Note that depopts: [ "foo" { = "3" } ] means that the optional dependency only applies for foo version 3, not that your package can't be installed with other versions of foo: for that, use the conflicts: field.

  • conflicts: [ <filtered-package-formula> ... ]: a list of package names with optional version constraints indicating that the current package can't coexist with those. Conflicts are only allowed on a disjunction of packages: the & connector is disallowed between packages or package versions. For example, you can conflict with "foo" {>= "3"} | "bar", but not with "foo" {>= "3"} & "bar" or even "foo" {>= "3" & < "4"}.

  • conflict-class: [ <pkgname> ... ]: an alternate, symmetric way of defining package conflicts. Conflict classes defined by this field have the same syntactic constraints as package names, but occupy a different namespace. Any two packages having a common conflict class will be considered incompatible. This is useful to define sets of mutually conflicting packages.

  • depexts: [ [ <string> ... ] { <filter> } ... ]: the package external dependencies. This field is used to describe the dependencies of the package toward packages external to the opam ecosystem; opam will then use its knowledge of the system package manager to determine the availability of the package, and install these external dependencies on the system as prerequisites of the package, asking the user for administrator rights if required.

    Each [ <string> ... ] { <filter> } element declares the strings to the left as identifiers to required system-managed packages, while the filter to the right allows one to select the systems they will be active on.

    The filters typically use variables arch, os, os-distribution, os-version, os-family. The depexts information can be retrieved through the opam list --depexts command (which can be targeted to a specific system other than the host by using the appropriate --vars bindings). These variables are guaranteed to be defined, and are set to the string "unknown" if the detection failed.

    The depexts: field should preferably be used on conf packages, which makes the dependencies clearer and avoids duplicating the efforts of documenting the appropriate system packages on the various OSes available.

  • messages: [ <string> { <filter> } ... ]: used to display an additional (one-line) message when prompting a solution implying the given package. A typical use-case is to tell the user that some functionality will not be available as some optional dependencies are not installed.

  • post-messages: [ <string> { <filter> } ... ]: allows one to print specific messages to the user after the end of installation. The special boolean variable failure is defined in the scope of the filter, and can be used to print messages in case there was an error (typically, a hint on how it can be resolved, or a link to an open issue). success is also defined as syntactic sugar for !failure. The with-dev-setup (since opam 2.2) variable is also available in the scope of this field.

  • available: [ <filter> ]: can be used to add constraints on the OS and other global variables. In case the filter doesn't evaluate to true, the package is disabled.

    This field is evaluated before request solving or any actions take place ; it can only refer to global variables, since it shouldn't depend on the current switch state. An unavailable package won't generally be seen on the system, except with opam list -A.

  • flags: [ <ident> ... ]: specify package flags that may alter package behaviour. Currently available flags are:

    • light-uninstall: the package's uninstall instructions don't require the package source.
    • verbose: when this is present, the stdout of the package's build and install instructions will be printed to the user.
    • plugin: the package installs a program named opam-<name> and may be auto-installed and run with opam <name>. The convention is to name the plugin package opam-<name>.
    • compiler: the package is to be treated as a compiler, and will be advertised for installing as a compiler package when creating a fresh prefix through the opam switch command.
    • conf: this is a "conf" package, that is intended to document capabilities of the system, or the presence of software installed outside of opam. As such, the package may not include a source URL or install anything, but just do some checks, and fail to install if they don't pass. conf packages should have a name starting with conf-, and include the appropriate depexts: field.
    • avoid-version: this gives the package version lowest priority when computing the solution to user requests. The priority is not only related to other versions of the same package: if all of a package's versions are marked with avoid-version, the package will only get installed if there are no alternatives, or if asked for explicitely. This can be affected by the solver criteria. This can be useful for beta releases, or to discourage installation of releases with known bugs. Note that this behaviour is disabled when a flagged version of the package is already installed.
    • deprecated: this flag is equivalent to avoid-version except for the addition of a deprecation message after the package is installed as well as marked as deprecated in the solution shown to the user upon installation.
  • features: [ <ident> { <pkgname> { <filtered-package-formula> } ... } { <string> } ... ] (EXPERIMENTAL): This field binds given idents to dependency formulas, and a documentation text. The intent is to allow, in the future, packages to depend on additional characteristics of their dependencies. This can be understood as a way to further document the consequences of the presence of absence of optional dependencies.

  • synopsis: <string>: defines a short description (one line) for the package. This can also be defined as the first line of an external descr file.

  • description: <string>: defines a long description (one or more paragraphs) for the package. This can also be defined as the body of an external descr file.

  • url "{" <url-file> "}": defines the URL where the package source can be obtained. This section has contents in the same format as the url file, and has the same effect as using a separate url file.

  • setenv: [ <environment-update> ... ]: defines environment variables updates that will be applied upon installing the package. The updates will be visible to any dependent package, as well as exported to the shell environment through opam env and ~/.opam/opam-init/ scripts. Note that while it is guaranteed that dependents will see the environment updates, and dependencies won't, other cases are unspecified. The order in which setenv: updates done by different packages are applied is deterministic, but also unspecified. In particular, it is not currently guaranteed to follow dependency order.

  • build-env: [ <environment-update> ... ]: defines environment updates that will be applied when running the package's build, install and remove scripts.

    The following environment variables are set by opam (but can be overridden by build-env):

    • CDPATH=
    • OPAM_PACKAGE_NAME=<pkg> (<pkg> is the name of the package being built/installed/removed)
    • OPAM_PACKAGE_VERSION=<ver> (<ver> is the version of the package being built/installed/removed)
    • OPAMCLI=2.0 (since opam 2.1)
    • TMP and TMPDIR are set by the sandbox script (bubblewrap), but should not be relied on since the sandbox is not used on all platforms and can be disabled by the user.
    • CYGWIN=winsymlinks:native on Windows, or CYGWIN=$CYGWIN winsymlinks:native if CYGWIN is defined and not empty and CYGWIN does not contain either winsymlinks:native or winsymlinks:nativestrict already (since opam 2.2). In some cases noglob can also be added to this variable, such that the default value becomes CYGWIN=winsymlinks:native noglob (since opam 2.1)

    See x-env-path-rewrite: for path portability of environment variables on Windows.

  • extra-source <string> "{" <url-file> "}": allows the definition of extra files that need downloading into the source tree before the package can be patched (if necessary) and built. The format is similar to that of the url section, but here it is expected to point to a single file (version-controlled remotes are not allowed). The leading <string> indicates the name the file should be saved to, and is relative to the root of the source tree.

See x-env-path-rewrite: for path portability of environment variables on Windows.

  • extra-files: [ [ <string> <checksum> ] ... ]: optionally lists the files below files/ with their checksums. Used internally for integrity verifications.

  • pin-depends: [ [ <package> <URL> ] ... ]: this field has no effect on the package repository, but is useful for in-source specification of development packages. When source-pinning the package, either through opam pin or opam install <DIR>, opam will prompt to pin every specified <package> to the associated <URL>. There are two important limitations:

    1. If you want the pinned package be a dependency you need to add its <pkgname> to depends: field.
    2. pin-depends: are NOT transitive, that is, pin-depends: of packages getting pinned through pin-depends: are ignored
    3. They won't get updated on opam update, the users will need to use opam pin or opam install|upgrade DIR again to get the new pins if the field has changed. Even then, this won't unpin any packages that would have been removed from pin-depends:.
  • x-env-path-rewrite: [ <environment-update-rewrite> ... ]: a specific extra field, used to specify rewrite rules for environment variables defined in setenv: and build-env. See environment update portability for syntax.

  • x-*: <value>: extra fields prefixed with x- can be defined for use by external tools. opam will ignore them except for some search operations.


Descr is a plain UTF-8 text file without specific syntactic constraints. The first line of the file defines the package's synopsis, while the rest defines its long description.

This information can be embedded in opam package definition files using the synopsis: and description: fields since opam version 2.0. However, if a descr file is present alongside the opam file, it takes precedence.


The url file describes the source of the package and how it may be obtained. It has the following fields:

  • One of src: <string> or archive: <string>, specifying the URL where the package can be downloaded from. When using HTTP or FTP, this should be an archive. The older alternative field names http:, local:, git:, hg: and darcs: are deprecated, prefer explicit URLs.

    On the official repository, this should always point to a stable archive over HTTP or FTP.

  • checksum: [ <checksum> ... ]: the checksums of the referred-to archive, to warrant integrity. At least one is mandatory on the official repository.

  • mirrors: [ <string> ... ]: an optional list of mirrors. They must use the same protocol as the main URL.

These contents can be embedded within the url {} section of an opam file, which is the preferred way. You shouldn't have both an url file and an opam file with an url {} section: in that case, the url file will be ignored with a warning.


A special subdirectory that can appear in package definition directories, alongside the opam file.

This subdirectory may contain any files or directories (of reasonable size) that will be copied over the root of the package source. If already present, files are overwritten, and directories are recursively merged. opam file fields like patches: refer to files at that same root, so patches specific to opam are typically included in this subdirectory.

Also see the extra-sources: opam section, which has a similar behaviour and is processed before the files/ are copied.


This file format describes the installation from a source directory to an installation prefix. It will be used by opam if present at the root of the package's source directory after the build: instructions have been run: it can thus be generated by the build system, be static in the package source, or be added by opam through the files/ mechanism.

To avoid duplicating efforts for managing installations, a stand-alone opam-installer tool is provided with opam that can perform installations and uninstallations from these files, or even generate corresponding shell scripts, without requiring opam.

All the fields have the form

field: [ <string> { <string> } ]

The following take a list of filenames (relative to the root of the package source) to be installed to the field's respective directory. An optional relative path and destination filename can be given using the postfix braces syntax. A leading ? in the origin filename is stripped and informs opam to continue silently when the file is not found.

Absolute paths, or paths referencing the parent directory (..), are not allowed.

  • lib: installs to <prefix>/lib/<pkgname>/
  • lib_root: installs to <prefix>/lib/ (since opam 2.0.0)
  • libexec: installs to <prefix>/lib/<pkgname>/, but the exec bit is set (since opam 1.2.1)
  • libexec_root: installs to <prefix>/lib/, with the exec bit set (since opam 2.0.0)
  • bin: installs to <prefix>/bin/, with the exec bit set
  • sbin: installs to <prefix>/sbin/, with the exec bit set
  • toplevel: installs to <prefix>/lib/toplevel/
  • share: installs to <prefix>/share/<pkgname>/
  • share_root: installs relative to <prefix>/share/ (since opam 1.2.0)
  • etc: installs to <prefix>/etc/<pkgname>/
  • doc: installs to <prefix>/doc/<pkgname>/
  • stublibs: installs to <prefix>/lib/stublibs/, with the exec bit set

The following are treated slightly differently:

  • man: installs relative to <prefix>/man, with the exception that when the destination is unspecified, the proper destination directory is extracted from the extension of the source file (so that man: [ "foo.1" ] is equivalent to man: [ "foo.1" {"man1/foo.1"} ]
  • misc: requires files to specify an absolute destination, and the user will be prompted before the installation is done.


This file is used by packages to give opam specific options upon installation. A file with this name will be installed by opam into <switch-prefix>/.opam-switch/config/ if found at the root of the package source tree after its installation instructions have been run.

  • opam-version: <string>: the file format version.
  • file-depends: [ "[" <string> <checksum> "]" ... ]: when a package defines absolute-filename - hash bindings using this field, on state-changing operations, opam will check that the file at the given path still exists and has the given hash. This can be used to guarantee the consistency of packages that rely on system-wide files or system packages when those are changed, e.g. by apt-get upgrade. The user will be warned if the file was removed, and the package marked for reinstallation if it was changed. If the checksum is zero, then the file is assumed not to exist and opam will detect its appearance as requiring the package to be marked for reinstallation.
  • variables "{" { <ident>: ( <string> | [ <string> ... ] | <bool> ) ... } "}": allows the definition of package variables, that will be available as <pkgname>:<varname> to dependent packages.

Local configuration files

These files are local to the opam root, and managed by opam. config and switch-config can be manually edited to set configuration options when opam isn't running. switch-state and repos-config store internal state and are documented here, but shouldn't be edited except by opam.


This file is stored as ~/.opam/config and defines global configuration options for opam. Field values can be displayed and some of them modified with opam option --global.

  • opam-version: <string>: the version of the format of this opam root, used in particular to trigger format migrations.

  • repositories: [ <string> ... ]: the set of configured repositories to use for newly created switches. The repositories themselves are set up using the repos-config file.

  • installed-switches: [ <string> ... ]: lists the switches configured in this opam root, either internal or local. Deleted local switches are collected by opam automatically, and it is possible to use local switches that are not recorded in this field. It remains useful for cross-switch listings, repository configuration updates, or opam format migrations.

  • switch: <string>: the currently globally selected switch.

  • jobs: <int>: the number of concurrent jobs to run for build processes. If not defined, the value is calculated from the number of cores.

  • download-jobs: <int>: the maximum number of concurrent downloads. The default value is 3.

  • download-command: [ ( <string> | <ident> ) { <filter> } ... ]: the command to use for downloading packages. If set to a single element, will use the curl and wget presets if set to those idents, and use the named executable with a curl-compatible command-line otherwise. Should otherwise be a full command, and in this scope, the following variables (only) are defined:

    • opam-version is the current opam version
    • url is the remote URL to fetch from
    • out is the expected output file
    • retry is the number of retries allowed
    • compress is whether HTTP compression should be enabled
    • checksum is the expected checksum of the file, including the md5=/sha256=/sha512= prefix
    • hashalgo is the hashing algorithm used (md5, sha256 or sha512)
    • hashvalue is the raw value of the hash, in hexa, without prefix
    • hashpath is a relative path that can be used for per-hash caching, containing hashing algorithm, two-digit prefix and full hash value, e.g. md5/d4/d41d8cd98f00b204e9800998ecf8427e.
  • archive-mirrors: [ "<URL>" ... ]: defines proxy URLs that package archives can be retrieved from. The URL may use any supported non-version control protocol, and the files will be looked up by (their first) hash with the relative path <hash-algo>/<first-2-hash-characters>/<hash>, where the hash is in hexadecimal. Proxies are tried in order, and the file is looked up from upstream if not found. They can also be configured per-repository. The command opam admin cache generates a suitable cache in ./cache, see the Repositories section.

  • solver-criteria: <string>: can be used to tweak the solver criteria used for the resolution of operations. These depend on the solver used, see the Solver Criteria page for details.

  • solver-upgrade-criteria: , solver-fixup-criteria: : similar to solver-criteria, but specific to some actions.

  • best-effort-prefix-criteria: , this is the string that must be prepended to the criteria when the --best-effort option is set, and is expected to maximise the opam-query property in the solution. For recent aspcud, this can be e.g. +sum(solution,opam-query), ; a valid setting for mccs is +count[opam-query:,false],.

  • solver: [ ( <string> | <ident> ) { <filter> } ... ]: the solver to use. See the External Solvers section of the install guide for context. If set to a single <ident> element, that may point to a built-in solver, or one of the aspcud, packup or mccs predefined command-lines. Otherwise, the following variables are defined in the command scope:

    • input is the name of the input file, in Cudf format
    • output is the expected name of the output file, containing the solution
    • criteria is the defined solver criteria.
  • global-variables: [ "[" <ident> ( <string> | [ <string> ... ] | <bool> ) <string> "]" ... ]: allows the definition of global variables. The last <string> is for documentation and is shown in the output of opam config list.

  • eval-variables: [ "[" <ident> [ <string> ... ] <string> "]" ... ]: allows the definition of global variables that will be lazily initialised to the output of the given command. The last <string> documents the variable.

  • pre-build-commands: [ [ <term> { <filter> } ... ] { <filter> } ... ], pre-install-commands: [ [ <term> { <filter> } ... ] { <filter> } ... ], pre-remove-commands: [ [ <term> { <filter> } ... ] { <filter> } ... ]: specify commands that will be run just before processing the package's commands for the corresponding action, on any package. The filters are evaluated in the same scope as the package commands.

  • wrap-build-commands: [ [ <term> { <filter> } ... ] { <filter> } ... ], wrap-install-commands: [ [ <term> { <filter> } ... ] { <filter> } ... ], wrap-remove-commands: [ [ <term> { <filter> } ... ] { <filter> } ... ]: specify wrappers around every command executed during the corresponding action of any package. The command-line elements will be prefixed to the package command, so for example command [ make "install" ] with wrapper [ "time" "-o" "/tmp/timings" "-a" ] will result in the command [ "time" "-o" "/tmp/timings" "-a" make "install" ]. The filters are evaluated in the same scope as the package commands.

    As init-scripts: are stored in the hook directory, when using a wrapper script defined by init-scripts:, use the variable %{hook}% as prefix for you script filename.

  • post-build-commands: [ [ <term> { <filter> } ... ] { <filter> } ... ], post-install-commands: [ [ <term> { <filter> } ... ] { <filter> } ... ], post-remove-commands: [ [ <term> { <filter> } ... ] { <filter> } ... ]: specify commands that will be run just after processing the package's commands for the corresponding action, and the <pkgname>.install file in the case of install and remove, on any package. The post commands are run wether or not the package script succeeded. The filters are evaluated in the same scope as the package commands, with the addition of the variable error-code, which is the return value of the package script, and hooks which is the directory where scripts created using opamrc's init-scripts: field are created.

    The post-install-commands hook also has access to an extra variable installed-files which expands to the list of files and directories added or modified during the installation of the package. Note that this hook is run after the scan for installed files is done, so any additional installed files won't be recorded and must be taken care of by a pre-remove-commands hook. However, modified or deleted installed files during the post-install-commands will be handled correctly by opam.

  • pre-session-commands: [ [ <term> { <filter> } ... ] { <filter> } ... ], post-session-commands: [ [ <term> { <filter> } ... ] { <filter> } ... ]: These commands will be run once respectively before and after the sequence of actions done by a given instance of opam. Only the switch variables are available, since this doesn't concern one single package, plus the following, related to the sequence of actions. They correspond respectively to the expected final state for pre-session, and to the actually reached state for post-session.

    • installed: all installed packages with versions.

    • new: all packages or versions that are getting installed but weren't present before the session.

    • removed: all packages or versions that were installed before, but no longer after the session. Note that an upgrade of foo.0.1 to foo.0.2 is considered as removal of foo.0.1 and addition of foo.0.2. Reinstallations aren't visible with these variables.

    • success (and failure, which is !success): only for post-session, success is true only if all the expected operations were successful (a subset of the package actions may have been successful even if false).

    • depexts: for pre-session, the list of depexts: inferred for the host system on installed.

    • hooks: the directory where scripts created using opamrc's init-scripts: field are created.

In addition, the output of these hooks is printed to the user, so
`post-session-commands` may be used to output extra information upon session
  • repository-validation-command: [ <term> { <filter> } ... ]: defines a command to run on the upstream repositories to validate their authenticity. When this is specified, and for repositories that define trust anchors, opam will refuse any update that doesn't pass this validation. The command should return 0 on successful validation, and the following opam variables are made available:
    • anchors: comma-separated list of fingerprints
    • quorum: integer, the currently defined quorum
    • repo: directory containing the already-validated state of the repository (empty for an initial validation)
    • patch: for incremental validation, filename of a patch applying to repo (with patch -p1) and that needs verification
    • dir: for initial validation, the directory to verify
    • incremental: false if doing an initial validation based on dir, true for an incremental validation based on repo and patch.
Since there are two modes (initial and incremental), all variables may not be
defined in all cases.
  • default-compiler: [ <package-formula> ... ]: a list of compiler package choices. On opam init, the first available compiler in the list will be chosen for creating the initial switch if --bare wasn't specified. Note that default-invariant: will still be used, so the alternatives listed here should be compatible with it.

  • default-invariant: [ <package-formula> ... ]: the default switch invariant that will be set on newly created switches, in cases where nothing else was specified.

  • depext: <bool>: enable or disable system dependency handling. When packages declare dependencies on system packages using the depexts field (typically, bindings to C libraries like SDL, require the library to be installed, which is outside the scope of opam), if this is set to true (the default), opam will check the availability of such dependencies using the host system package manager, and prompt the user to install them when needed.

  • depext-run-installs: <bool>: if true (the default), opam is allowed to run installations through the host system package manager (e.g. apt, yum or brew) when required for the installation of opam packages through their depexts. This is generally done through sudo, and always after prompting the user (unless --yes was specified). if disabled, the installation command is printed to stdout, and opam pauses to let the user proceed.

  • depext-cannot-install: <bool>: instructs opam that no system package can be installed on the system. Any opam package declaring system dependencies towards a system package that is not yet installed will be marked as unavailable.

  • depext-bypass: [ <string> ... ] : assume the listed system packages to be already installed, bypassing the checks normally done when depext is enabled.

  • swh-fallback: <bool>: If true, opam try to retrieve a unreachable package source from Software Heritage archive if the swhid is present in the opam file.


This file is located in <switch-prefix>/.opam-switch/switch-config and contains configuration options specific to that switch:

As config, field values can be displayed and some of them modified with opam option.


This file, located at <switch-prefix>/.opam-switch/switch-state, is used by opam to store the current state of a switch. All fields are lists of <package> (i.e. [ "<pkgname>.<version>" ... ]).

  • opam-version: <string>: the file format version.
  • compiler: [ <string> ... ]: the package that form the base of the current switch. They won't be affected by opam upgrade, and are protected against deletion.
  • roots: [ <string> ... ]: lists the package "roots", i.e. packages that have been installed manually by the user (as opposed to the ones which got installed to fulfil dependencies). Note that packages in this list may not be installed, if they were removed due to build failures.
  • installed: [ <string> ... ]: lists all currently installed packages.
  • pinned: [ <string> ... ]: lists all packages which have been pinned, and to what version. If an overlay package definition is present in <switch-prefix>/.opam-switch/overlay/<pkgname>/, that can be used to alter the package definition and modify its source URL. Otherwise, the package is simply pinned to the given version.


This file is at ~/.opam/repo/repos-config and lists all package repositories configured on the system, and their source URLs.

Note that repositories without URLs can be used. In this case, the corresponding subdirectory in ~/.opam/repo/ is supposed to be put in place and updated by the user, so opam will never write to it and won't cache its contents.