Configuration

All configuration lives in your app’s pyproject.toml under [tool.pyappdist]. pyproject.toml is the single source of truth.

It has three parts:

Before configuring anything, make sure the project itself is packageable — see What your project must satisfy.

All keys at a glance

Where

Keys

[tool.pyappdist]

python · name · version · manager · identifier

[[tool.pyappdist.launchers]]

name · entry · gui · icon · args

[[tool.pyappdist.targets]] (all formats)

name · platform · format · extras

targets, format = "msi"Windows — MSI installer

manufacturer · scope · upgrade-code · license · code-sign · code-sign-command · allow-same-version-upgrades

targets, format = "msix"Windows — MSIX (Microsoft Store / sideloading)

manufacturer · identity-name · publisher · display-name · logo

targets, format = "linux"Linux — .run installer

categories · compression

targets, format = "macos"macOS — .run installer (command-line tools)

compression

targets, format = "macapp" / "dmg"macOS — .app / .dmg (GUI apps)

min-macos · category · signing-identity · team-id · notary-profile · entitlements

targets, format = "image"Image archive (all platforms)

no-launcher

[tool.pyappdist]

python (required)

Python version for the bundled runtime, as X.Y or X.Y.Z (e.g. "3.12").

name

Display name of the app. Defaults to [project].name.

version

Product version. Defaults to [project].version (then "0.0.0"). When any target uses format = "msi" or "msix", the version must be dotted numeric (e.g. "1.2.3") — MSI’s ProductVersion cannot express pre-releases, so e.g. "1.0.0rc1" is rejected at load time.

manager

Package manager used to pin dependencies: "uv", "poetry", "pipenv", "pdm", or "requirements.txt". Auto-detected from the lockfile when omitted. See Dependency resolution.

identifier

CFBundleIdentifier in reverse-DNS form (e.g. "com.example.myapp"). Required when any target uses format = "macapp" or "dmg"; unused by the other formats. With multiple launchers each bundle derives <identifier>.<launcher>.

[tool.pyappdist]
name = "My App"
python = "3.12"
# identifier = "com.example.myapp"   # required for macapp/dmg targets

[[tool.pyappdist.launchers]]

An array of tables — one entry per executable to produce. At least one is required to build launchers. The same launcher set is used for every target; how a launcher is realized depends on the format (a compiled .exe on Windows, a relocatable shell wrapper on Linux/macOS).

name (required)

Output executable name without extension ("myapp"myapp.exe on Windows). Because the name becomes a filename and an installer record, it must not contain whitespace, control characters, or any of <>:"/\|?*.

entry (required)

Entry point, in one of two forms:

  • "module:callable" — import callable from module and invoke it with no arguments; its return value becomes the process exit code.

  • "module.path" (no colon) — run the module as python -m module.path (executed with __name__ == "__main__"). Use this for apps whose startup lives under an if __name__ == "__main__": guard (e.g. NiceGUI).

gui

true builds a windowed launcher using pythonw.exe (no console) on Windows. Defaults to false (console, python.exe). On Linux it only affects launchers that also set an icon: the generated .desktop entry gets Terminal=false when true (Terminal=true otherwise). Ignored by the macOS .run.

icon

A per-OS table of icon paths (relative to the project directory); each key is optional:

  • windows — an .ico, embedded in the .exe.

  • macos — a .png (ideally ≥1024×1024), converted to the .app’s .icns.

  • linux — an image (.png recommended) used for the .desktop entry.

A plain string is not accepted — give the format each platform needs. An omitted key means that platform gets no icon (macOS falls back to a generated placeholder).

args

Fixed arguments as a single string, prepended to the program’s argv.

[[tool.pyappdist.launchers]]
name = "myapp"
entry = "myapp:main"
gui = false
# args = "--profile default"

[[tool.pyappdist.launchers]]
name = "myapp-gui"
entry = "myapp.gui:main"
gui = true
icon = { windows = "assets/app.ico", macos = "assets/app.png", linux = "assets/app.png" }

[[tool.pyappdist.targets]]

An array of tables — one entry per output package. At least one target is required. The individual pipeline stages apply to all targets by default; pyappdist build builds the sole target, or the ones you name: pyappdist build <name> <name> (see Command-line interface).

These keys are common to every format; the format-specific keys live on the format pages.

platform (required)

Distribution platform (see Platform values).

format (required)

Output package. Must match the platform’s OS: "msi" or "msix" on Windows, "linux" on Linux, and on macOS either "macos" (a .run installer, like Linux) or "macapp" / "dmg" (a .app bundle, optionally inside a .dmg, for GUI distribution). A mismatch (e.g. "msi" with linux-x86_64) is rejected at load. "image" — an archive of the image tree with no installer — is the exception: it is valid on every platform. See Output formats.

name (required)

Label used to select this target on the command line and as its output subdirectory — artifacts in appdist/<name>/, intermediates in .appdist-build/<name>/. Must be unique across targets. Because it becomes a path component, it must not contain whitespace, control characters, or any of <>:"/\|?*, must not be . or .., and must not end with ..

extras (optional)

A list of [project.optional-dependencies] extras to bundle for this target, passed through to the lockfile export (e.g. uv’s --extra). Defaults to an empty list, i.e. production dependencies only (dev excluded). See Dependency resolution.

Platform values

Every platform additionally accepts format image.

windows-x86_64

Triple x86_64-pc-windows-msvc · OS windows · format msi / msix.

linux-x86_64

Triple x86_64-unknown-linux-gnu · OS linux · format linux.

macos-aarch64

Triple aarch64-apple-darwin · OS macos · format macos / macapp / dmg.

macos-x86_64

Triple x86_64-apple-darwin · OS macos · format macos / macapp / dmg.

Output formats

Each format has its own configuration keys, build requirements, and install behavior:

msi

.msi installer.

msix

.msix package (Store / sideloading).

linux

self-extracting .run.

macos

self-extracting .run, for command-line tools.

macapp / dmg

A macOS .app bundle (macapp), optionally wrapped in a .dmg (dmg), for GUI apps; Developer-ID-signed and notarized when configured.

image

No installer — an archive of the image tree (.zip on Windows, .tar.gz on Linux/macOS). Valid on every platform.

A single project can declare several targets and produce all of these at once:

[[tool.pyappdist.targets]]              # an MSI
name = "windows"
platform = "windows-x86_64"
format = "msi"
manufacturer = "Example Inc."
# upgrade-code = "..."    # auto-generated and written back if omitted

[[tool.pyappdist.targets]]              # a Linux .run installer
name = "linux"
platform = "linux-x86_64"
format = "linux"

[[tool.pyappdist.targets]]              # a macOS .run installer
name = "macos-arm"
platform = "macos-aarch64"             # or "macos-x86_64" for Intel
format = "macos"