Skip to content


Inputs define a set of files that will be used to assemble the final package.


# Add a file or directory for every platform. They will be placed into 
# the working directory at the same location. Globs are supported.
app.inputs += path/to/a/file
app.inputs += path/to/a/directory
app.inputs += /opt/foo/bar/*.sh

# GRADLE USERS: See the Getting Started doc for what to do!

# You can change where the file is placed.
app.inputs += a/file -> other-dir/file

# That's shorthand for this longer form:
app.inputs += { 
  from = a/file
  to = other-dir/file

# URLs are downloaded. The https:// prefix is implied if missing.
app.inputs +=
app.inputs += "data:IyEvYmluL2Jhc2gKZWNobyBTYW1wbGUgc2NyaXB0Lg== ->"

# Raw content can be embedded in the config. It will be de-indented for you.
app.inputs += {
  content = """
    echo Hello world!
  to = bin/

# Archives are extracted (but not JARs).
# Any input spec may use brace expansion with nesting. {} are special in HOCON so you
# must quote the string.
# If the files in an archive are under a single root directory, the contents 
# of that dir are extracted instead of the root.
app.inputs += "files/vendor-{core,utils,extras{,-2}} -> vendor-stuff"
app.inputs += foobar.tar.{gz,bz2,xz,Z,ztd}

# Archives can have content be remapped or dropped during extraction.
app.inputs += {
  from =
  remap = [
    "**"                       # Include everything.
    "samples/*.conf -> conf"   # But move files ending in .conf to the conf 
                               # directory (and subdirs as appropriate).
    "-**/*.unwanted"           # Don't extract files ending in .unwanted, anywhere in the tree
    "-.git/**"                 # or anything under .git

# OS / CPU / libc specific inputs, see below for full list of paths you can use.
app.linux.aarch64.glibc.inputs += linux-arm-natives.tar.gz -> lib

# Add a JDK and it will be jlinked and used as the application runtime.
# You must use the OS/CPU/libc specific inputs for this as a JVM is inherently platform specific.
app.jdk.linux.amd64.inputs +=

app.inputs An array of input definitions (see below). Each input is extracted into the working directory one after the other, with later inputs overwriting files from previous inputs. You can add a new input to the end of the array by using the += HOCON operator. You can append an object, but when you append a string specification it is parsed and treated as shorthand for an object with from and to fields, in which the from field is the URL/path of the input. Brace expansion is applied to the string form to create multiple inputs.

Certain keys are derived from the name of the first input if not specified, which works well if you use the convention that the first input contains the core software of the app (i.e. not a dependency).

Paths should always use the UNIX path separator (/) and are interpreted relative to the location of the config file containing the input definition (i.e. if you include a file that specifies inputs, relative paths are relative to the included file, not the including file).

Object syntax

The string syntax is shorthand for the object syntax, they can always be treated identically. Objects may consist of these keys:

from A string interpreted as either a file/directory if it exists relative to the config file, or a URL if the file isn't found missing. An https prefix is optional. The string is brace expanded and may contain glob characters when it refers to a path on the file system, thus a single specified input may be expanded to multiple actual inputs that share the same to field.

content A string that will be placed in the given destination file. It's de-indented for you, so you can place the content at the right offset to look good in the config. On UNIX if it starts with a shebang line it will be marked executable automatically. The HOCON """ multi-line string literal syntax is useful here but remember that if you want to include HOCON substitutions, you have to do that outside the string, so you'll need to write something like """${my-var}""".

to The location in the staging area where the input should be placed or extracted to. By default this is the root.

remap A list or multi-line string of remap rules. See below for details. If not specified the default is [ ** ] which means "copy everything to the same location" in the staging area.

Remap rules

When an input has a list of remap rules every file being copied or extracted is tested against each item in the list. A rule defines a set of files that match and optionally, a location in the destination to place them. At least one rule must match for the file to be included, which means if you specify your own remap list then it will by default match nothing. Each rule is written as:

[-]path/to/files/** [-> some/location]

If no location is given, it's the same as the location of the matched file. Files can be excluded by prefixing a more specific rule with -.

Precedence. The ordering of rules doesn't matter. The winning rule is the most specific, defined as the rule for which the pattern part matches the least. Therefore ** is the least specific rule (because it matches everything) and can be overridden by any other.

To match a file must match a glob (the standard *, ? characters) or the ** glob, which matches any sequence of characters across directory boundaries.


Remap rules are tested against files not directories. Therefore, specifying a directory as a source won't work, you must use globs to do that, i.e. lib won't copy anything out of the lib directory, but lib/** will.

Root directories. When extracting a zip that has exactly one root directory entry the remap rules are applied to the files within that directory, but when extracting a tarball the fact that there's a single root is only known at the end of the extraction process, so the rules then are applied to the root of the tarball, thus a single root directory must be taken into account in the remap rules.

Primary input

If you don't specify all needed fields the file name of the first input will be parsed and some missing values derived from it. Each one of these can be overridden if you don't like the derived values. The rules are:

  1. The file extension is dropped.
  2. The file name is split on - and _ characters. The first component that starts with a number starts the version, which is placed in app.version. The name before the version is assigned to app.fsname and is used as the base for anywhere a name is needed on the filesystem. It is conventionally all lower case and uses - to split words.

Machine specific inputs

Conveyor calls the combination of an operating system, CPU architecture and (for Linux) libc a machine. A machine is identified by a dot separated triple os.cpu[.libc]. You can specify which machines to build packages for using the app.machines key. A machine name is made of:

  • OS: Can be linux, windows or mac. Some common alternative names are also supported (e.g. win, osx, macos and darwin)
  • CPU: Can be amd64 or aarch64. Again some common alternatives are supported.
  • LibC: (Linux only) Can be glibc or muslc and again, alternatives are recognized.

When an app is built the actual list of inputs to use comes from the app[.jdk].$machine.inputs paths, so for example when making a standard package for Linux the inputs will be taken from app.linux.amd64.glibc.inputs. The default configuration aliases each set of inputs along the hierarchy, meaning any files you add further up will be propagated. This lets you put data files used by any type of machine in app.inputs, data files used only on macOS in app.macos.inputs and binaries compiled specifically for Apple's M1 chip in app.macos.aarch64.inputs.

All platforms Conveyor supports implement symlinks, but on Windows they are called junction points and cannot point to directories. Packages need to be "hermetic", meaning that there are no symlinks inside them that point outside them. On Linux nothing enforces this and in some cases it can be reasonable to include such symlinks, but Apple treats such symlinks as a security violation. For this reason when files, directories or archives are being copied into an input staging area, symlinks are followed unless they point inside the directory tree or archive. The rules are:

  • If an input is a symlink it's followed.
  • If an input is a directory it's copied recursively, or if it's an archive it's extracted, and all symlinks within:
    • That point to a path outside that directory are followed, with the symlink being replaced by the file or directory tree it points to.
    • That point to a path inside that directory are left as is and will be packaged as symlinks.