monopack splits a Python monorepo into smaller, entrypoint-focused packages.
Packs are defined by files in packs/ (packs/<name>.py). For each pack, monopack traces imports, copies reachable first-party files, installs only the needed third-party distributions, and writes an isolated build output.
If packs/ is missing, or no pack files are found, the CLI exits with a clear error.
This was inspired by multi-function Lambda packaging, where smaller per-entrypoint artifacts often help cold start performance and reduce package bloat. The same approach works for any Python monorepo where you want tighter per-entrypoint packaging.
- Smaller per-pack artifacts from one shared codebase.
- Tighter dependency surface for each pack.
- Easier to inspect what each entrypoint actually ships.
Build one pack:
python -m monopack users_getBuild all discovered packs in packs/*.py:
python -m monopackRun test-mode build for one pack:
python -m monopack users_get --mode testDeploy-mode build with test gate:
python -m monopack users_get --mode deploy --with-tests--verify(default on): runs a generated verifier script inside the built pack to check importability of selected modules and validate pack entrypoint expectations (includinglambda_handleron the pack module).--mode test: builds the runtime payload, copies only relevant tests for that pack, runs them inside the build target, and does not write a deploy zip.--with-tests: same test execution behavior as above, but indeploymode so zip output is still produced if checks pass.
tests/ is required only when test execution is enabled (--mode test or --with-tests).
Command form:
python -m monopack [pack_name] [options]| Option | Default | Why it is useful |
|---|---|---|
pack_name (positional, optional) |
builds all discovered packs | Target a single pack while iterating locally or in CI. |
--version |
n/a | Print installed CLI version and exit. |
--packs-dir |
packs |
Use a non-default entrypoint directory. |
--build-dir |
build |
Change output location (for CI temp dirs or custom build roots). |
--mode deploy|test |
deploy |
deploy produces runtime payload + zip, test runs pack-scoped tests in build output (no zip). |
--with-tests |
False |
Run pack-scoped tests as a gate in deploy mode. |
--verify / --no-verify |
verify on | Keep safety checks on by default; disable for faster local loops. |
--auto-fix |
False |
Retry missing-module verification failures by updating managed inline config blocks (up to 3 attempts). |
--debug |
False |
Print detailed import and dependency resolution diagnostics to stderr. |
--jobs |
auto |
Parallelize multi-pack builds; set a number for fixed worker count. |
--sha-output |
hex |
Choose deploy digest output format(s): hex, b64, or hex,b64. |
--package-manager |
auto |
Select dependency source flow: auto, pip, uv, poetry, pipenv. |
--existing-install-python |
unset | Point to an existing Python install to reuse pip cache artifacts during dependency cache sync. |
Environment variables are also supported. CLI flags override env vars.
- Resolve target packs from
packs/or explicitpack_name. - Build an import graph from each pack entrypoint.
- Copy reachable first-party files into
build/<pack_name>/. - Resolve third-party import roots to distributions from pinned dependency sync.
- Install only that per-pack dependency subset into the build target.
- Run verifier and optional pack-scoped tests.
- In deploy mode, write zip artifact and optional digest files.
- CLI reference:
docs/cli.md - Fixture-driven testing notes:
docs/testing-fixtures.md - Publishing:
docs/publishing.md