GitHub - metaist/cosmofy: Cosmopolitan Python Bundler

10 min read Original article ↗

cosmofy: Cosmopolitan Python Bundler

Build PyPI Supported Python Versions

cosmofy bundles your python app using uv into a single executable which runs on Linux, macOS, and Windows using Cosmopolitan libc.

Install

First, make sure you have uv installed.

To use the latest version of cosmofy without installing, use uvx:

To install cosmofy locally:

uv tool install cosmofy # recommended
# or
pip install cosmofy # classic

You can also install the cosmofy binary directly.

macOS / Linux:

dest=~/.local/bin/cosmofy
curl -sSz $dest -o $dest -L https://github.com/metaist/cosmofy/releases/latest/download/cosmofy
chmod +x $dest

Windows:

$dest = "$env:LOCALAPPDATA\cosmofy\cosmofy.exe"
New-Item -ItemType Directory -Force -Path (Split-Path $dest)
Invoke-WebRequest -Uri "https://github.com/metaist/cosmofy/releases/latest/download/cosmofy" -OutFile $dest

Examples

To bundle a project, first make sure you define [project.scripts] in your pyproject.toml:

[project.scripts]
my_command = "my_command.__main__:main"

The bundle the whole project:

uvx cosmofy bundle # produces `dist/my_command`

You can also bundle individual python files:

uv init --script myscript.py # or uv add --script myscript.py <some dependency>
uvx cosmofy bundle --script myscript.py # produces `dist/myscript`

Limitations

  • Currently, we can only bundle pure-Python code (no C extensions) (see #94)
  • Currently, we're tied to the latest Cosmopolitan Python version (see #44).
  • Automatically compiling Python bytecode is currently disabled (see #41).

Self Updater

Warning

This is an experimental feature. See Security Considerations.

There is experimental support for adding a self-updater to a cosmofy bundle:

uvx cosmofy updater add dist/my_cmd # produces dist/mc_cmd.json

This produces a .json receipt that you should publish together with your bundle.

  • If the bundle is run with --self-update anywhere in the arguments, the cosmofy updater will run. It will compare it's internal build date with the date at --receipt-url and will download any updates, if they exist.

  • Otherwise, the bundle will run as normal by calling .args. See below for minor limitations.

Security Considerations

The self-updater verifies downloaded binaries against the hash in the receipt, but does not cryptographically verify the receipt itself. If you control the receipt hosting, this provides integrity verification. For higher-assurance scenarios, receipt signing is planned for a future release (see #53).

Supported Python CLI

Cosmopolitan Python apps have a special .args file which is read when it starts up. The contents of this file are typically set during cosmofy bundle and can be adjusted with cosmofy fs args. However, when using the self-updater, we need to check for the --self-update option first.

If --self-update is NOT present, we want to process the rest of the .args as usual. However, since Python has already started, we only support the following Python Command Line Interface options:

  • -c <command>: run a command
  • -m <module-name>: run a module (this is the most common)
  • -: read a command from stdin (rare, but we support it)
  • <script>: run a script on the filesystem
  • -V, --version: display the Python version (we also support -VV)
  • -h, -?, --help: show relevant portions of the help message
  • -i: enter python REPL after executing a script (-c, -m, -, or <script>)
  • -q: don't display copyright and version messages in interactive mode

If no option is provided, the Python REPL will run.

Commands

cosmofy

A Cosmopolitan Python bundler.

Usage: cosmofy [OPTIONS] <COMMAND>

Commands:
  bundle                    build and bundle a project
  updater                   install/uninstall bundle self-updater
  fs                        inspect and modify an existing bundle
  self                      manage the `cosmofy` executable

Options:
      --version             display the program version and exit

Global options:
  -h, --help                show this help message
  -q, --quiet...            show quiet output
  -v, --verbose...          show verbose output
      --dry-run             do not make any filesystem changes
      --color <COLOR>       control output color
                            [default: auto][choices: auto, always, never]
                            (auto checks `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR`,
                            `CLICOLOR_FORCE` and tty support)

cosmofy bundle

Build a Python project into a Cosmopolitan bundle.

Usage: cosmofy bundle [OPTIONS]

Input options:
      --entry <NAME>        `console_script` entry points to bundle
      --script <PATH>       paths to bundle

      If neither --entry nor --script is specified, all entry points
      will be bundled. If both are specified, entries will be bundled first.

      --python-url <URL>    URL from which to download Cosmopolitan Python
                            [default: https://cosmo.zip/pub/cosmos/bin/python]
                            [env: COSMOFY_PYTHON_URL=]

Output options:
  -o, --output-dir <PATH>   output directory
                            [default: project-root/dist]

Cache options:
  -n, --no-cache            do not read or save to the cache
                            [env: COSMOFY_NO_CACHE=]
      --cache-dir <PATH>    store Cosmopolitan Python downloads
                            [default: ~/.cache/cosmofy]
                            [env: COSMOFY_CACHE_DIR=]

Global options:
  -h, --help                show this help message
  -q, --quiet...            show quiet output
  -v, --verbose...          show verbose output
      --dry-run             do not make any filesystem changes
      --color <COLOR>       control output color
                            [default: auto][choices: auto, always, never]
                            (auto checks `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR`,
                            `CLICOLOR_FORCE` and tty support)

cosmofy updater

EXPERIMENTAL: Manage a bundle's self-updater.

Usage: cosmofy updater [OPTIONS] <COMMAND>

Commands:
  add                       add self-updater to a bundle
  remove                    remove self-updater from a bundle
  check                     check if the bundle has updates

Global options:
  -h, --help                show this help message
  -q, --quiet...            show quiet output
  -v, --verbose...          show verbose output
      --dry-run             do not make any filesystem changes
      --color <COLOR>       control output color
                            [default: auto][choices: auto, always, never]
                            (auto checks `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR`,
                            `CLICOLOR_FORCE` and tty support)

cosmofy updater add

EXPERIMENTAL: Add self-updater to a cosmofy bundle.

Usage: cosmofy updater add <BUNDLE> [OPTIONS]

Arguments:
  <BUNDLE>                  Cosmopolitan file bundle

Receipt options:
      --receipt <PATH>      output path to the JSON receipt
                            default is <BUNDLE> + `.json`
      --receipt-url <URL>   URL to the published receipt
                            default is --release-url + `.json`
                            [env: RECEIPT_URL=]
      --release-url <URL>   URL to the file to download
                            default is --receipt-url without `.json`
                            [env: RELEASE_URL=]
      --release-version <STRING>
                            release version
                            default is $(<BUNDLE> --version)

Process options:
      --no-copy             skip copying `cosmofy` code
                            (e.g., its already a dependency)
                            [env: COSMOFY_NO_COPY=]
      --no-args             skip setting `.args`
                            [env: COSMOFY_NO_ARGS=]

read more: https://github.com/metaist/cosmofy#self-updater

Global options:
  -h, --help                show this help message
  -q, --quiet...            show quiet output
  -v, --verbose...          show verbose output
      --dry-run             do not make any filesystem changes
      --color <COLOR>       control output color
                            [default: auto][choices: auto, always, never]
                            (auto checks `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR`,
                            `CLICOLOR_FORCE` and tty support)

cosmofy updater remove

EXPERIMENTAL: Remove cosmofy self-updater from a cosmofy bundle.

Usage: cosmofy updater remove <BUNDLE> [OPTIONS]

Arguments:
  <BUNDLE>                  Cosmopolitan file bundle

Process options:
      --no-args             skip setting `.args`
                            [env: COSMOFY_NO_ARGS=]

Global options:
  -h, --help                show this help message
  -q, --quiet...            show quiet output
  -v, --verbose...          show verbose output
      --dry-run             do not make any filesystem changes
      --color <COLOR>       control output color
                            [default: auto][choices: auto, always, never]
                            (auto checks `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR`,
                            `CLICOLOR_FORCE` and tty support)

cosmofy updater check

EXPERIMENTAL: Check if a cosmofy bundle has an update.

Usage: cosmofy updater check <BUNDLE> [OPTIONS]

Arguments:
  <BUNDLE>                  Cosmopolitan file bundle

Options:
      --receipt-url <URL>   override the published receipt URL
                            [env: RECEIPT_URL=]

Global options:
  -h, --help                show this help message
  -q, --quiet...            show quiet output
  -v, --verbose...          show verbose output
      --dry-run             do not make any filesystem changes
      --color <COLOR>       control output color
                            [default: auto][choices: auto, always, never]
                            (auto checks `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR`,
                            `CLICOLOR_FORCE` and tty support)

cosmofy fs

Cosmopolitan file system tool.

Usage: cosmofy fs [OPTIONS] <COMMAND>

Commands:
  ls                        list files in bundle
  cat                       print file contents
  add                       add files to bundle
  rm                        remove files from bundle
  args                      get/set special `.args` file in bundle

Global options:
  -h, --help                show this help message
  -q, --quiet...            show quiet output
  -v, --verbose...          show verbose output
      --dry-run             do not make any filesystem changes
      --color <COLOR>       control output color
                            [default: auto][choices: auto, always, never]
                            (auto checks `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR`,
                            `CLICOLOR_FORCE` and tty support)

cosmofy fs ls

List contents of a Cosmopolitan bundle.

Usage: cosmofy fs ls <BUNDLE> [OPTIONS] [FILE]...

Arguments:
  <BUNDLE>                  Cosmopolitan file bundle
  [FILE]...                 one or more file patterns to show

Filter options:
  -a, --all                 show entries whose name starts with `.`
  -B, --ignore-backups      hide entries whose name ends with `~`
      --hide <PATTERN>      hide matching entries, unless --all
  -I, --ignore <PATTERN>    hide matching entries, even with --all

Sort options:
  -r, --reverse             reverse the sort order
      --sort <MODE>         [choices: none, name, size, time, extension]
                            [default: name]

Output options:
  -l, --long                show permissions, size, and modified date
  -h, --human-readable      show sizes using powers of 1024 like 1K 2M 3G etc.
      --si                  show sizes using powers of 1000 (implies -h)

Global options:
      --help                show this help message
  -q, --quiet...            show quiet output
  -v, --verbose...          show verbose output
      --dry-run             do not make any filesystem changes
      --color <COLOR>       control output color
                            [default: auto][choices: auto, always, never]
                            (auto checks `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR`,
                            `CLICOLOR_FORCE` and tty support)

cosmofy fs cat

Print contents of a file within a Cosmopolitan bundle.

Usage: cosmofy fs cat <BUNDLE> <FILE>... [OPTIONS]

Arguments:
  <BUNDLE>                  Cosmopolitan file bundle
  <FILE>...                 one or more file patterns to show

  tip: Use `--` to separate options from filenames that start with `-`
  Example: cosmofy fs cat bundle.zip -- -weird-filename.txt

Options:
  -p, --prompt              prompt for a decryption password

Global options:
  -h, --help                show this help message
  -q, --quiet...            show quiet output
  -v, --verbose...          show verbose output
      --dry-run             do not make any filesystem changes
      --color <COLOR>       control output color
                            [default: auto][choices: auto, always, never]
                            (auto checks `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR`,
                            `CLICOLOR_FORCE` and tty support)

cosmofy fs add

Add files to a Cosmopolitan bundle.

Usage: cosmofy fs add <BUNDLE> [OPTIONS] <FILE>...

Arguments:
  <BUNDLE>                  Cosmopolitan file bundle
  <FILE>...                 files relative to current directory to add

  tip: Use `--` to separate options from filenames that start with `-`
  Example: cosmofy fs add bundle.zip -- -weird-filename.txt

Options:
  -f, --force               overwrite existing files
      --chdir <PATH>        change to this directory before adding
      --dest                prefix to add in the bundle
                            Most python packages go into `Lib/site-packages`

Global options:
  -h, --help                show this help message
  -q, --quiet...            show quiet output
  -v, --verbose...          show verbose output
      --dry-run             do not make any filesystem changes
      --color <COLOR>       control output color
                            [default: auto][choices: auto, always, never]
                            (auto checks `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR`,
                            `CLICOLOR_FORCE` and tty support)

cosmofy fs rm

Remove files from a Cosmopolitan bundle.

Usage: cosmofy fs rm <BUNDLE> [OPTIONS] <FILE>...

Arguments:
  <BUNDLE>                  Cosmopolitan file bundle
  <FILE>...                 files to remove

  tip: Use `--` to separate options from filenames that start with `-`
  Example: cosmofy fs rm bundle.zip -- -weird-filename.txt

Options:
  -f, --force               ignore nonexistent files
  -r, --recursive           recursively remove directories

Global options:
  -h, --help                show this help message
  -q, --quiet...            show quiet output
  -v, --verbose...          show verbose output
      --dry-run             do not make any filesystem changes
      --color <COLOR>       control output color
                            [default: auto][choices: auto, always, never]
                            (auto checks `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR`,
                            `CLICOLOR_FORCE` and tty support)

cosmofy fs args

Get or set the special `.args` files in a Cosmopolitan bundle.

These are the arguments to the Cosmopolitan Python.

Usage: cosmofy fs args <BUNDLE> [OPTIONS] [VAL]

Arguments:
  <BUNDLE>                  Cosmopolitan file bundle
  [VAL]                     value to set (if omitted, current value is printed)

Global options:
  -h, --help                show this help message
  -q, --quiet...            show quiet output
  -v, --verbose...          show verbose output
      --dry-run             do not make any filesystem changes
      --color <COLOR>       control output color
                            [default: auto][choices: auto, always, never]
                            (auto checks `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR`,
                            `CLICOLOR_FORCE` and tty support)

cosmofy self

Manage the `cosmofy` executable.

Usage: cosmofy self [OPTIONS] <COMMAND>

Commands:
  update                    update `cosmofy`
  version                   display `cosmofy`'s version

Global options:
  -h, --help                show this help message
  -q, --quiet...            show quiet output
  -v, --verbose...          show verbose output
      --dry-run             do not make any filesystem changes
      --color <COLOR>       control output color
                            [default: auto][choices: auto, always, never]
                            (auto checks `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR`,
                            `CLICOLOR_FORCE` and tty support)

cosmofy self update

Update `cosmofy`.

Usage: cosmofy self update [OPTIONS]

Global options:
  -h, --help                show this help message
  -q, --quiet...            show quiet output
  -v, --verbose...          show verbose output
      --dry-run             do not make any filesystem changes
      --color <COLOR>       control output color
                            [default: auto][choices: auto, always, never]
                            (auto checks `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR`,
                            `CLICOLOR_FORCE` and tty support)

cosmofy self version

Display `cosmofy`'s version.

Usage: cosmofy self version [OPTIONS]

Options:
      --short               only print the version
      --output-format NAME  [default: text][choices: text, json]

Global options:
  -h, --help                show this help message
  -q, --quiet...            show quiet output
  -v, --verbose...          show verbose output
      --dry-run             do not make any filesystem changes
      --color <COLOR>       control output color
                            [default: auto][choices: auto, always, never]
                            (auto checks `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR`,
                            `CLICOLOR_FORCE` and tty support)

License

MIT License