PyPI packages
Install pure-Python dependencies with compatibility evidence and reproducible locks
Kipferl can resolve and install pure-Python wheels from PyPI without pip or a system Python installation in Kipferl 0.7.2. Install the stable release to use these commands; v0.6.0 predates the package manager.
Find a package that fits
kipferl deps catalog
# Full machine-readable evidence and artifact hashes:
kipferl deps catalog --jsonThe built-in catalog records tested package versions and known incompatibilities. It is available offline. Results describe an exact wheel, runtime, and target; they are not permanent approvals or rejections of an entire library.
| Status | What it establishes |
|---|---|
| Tested | The recorded checks passed for that artifact and runtime. Read the evidence for the functions exercised. |
| Incompatible | A specific blocker was reproduced, such as unsupported syntax or a required native extension. |
| Unverified | No matching test evidence is available. This includes new versions and different runtime builds. |
A successful import does not establish that every function works. Add application tests for the package APIs you actually use, including error paths. Host test evidence does not establish behavior on the other build targets. To contribute repeatable checks, see extending the catalog.
The compatibility guide starts with verified workflows, explicit limits, and a ranked list of future support priorities. The broader audit supplies source and metadata findings. Verified syntax failures add exact blockers to the catalog; its compilation-only successes never promote a package to tested.
A current source build also provides kipferl deps verified (or --json) to
show only tested workflow scopes matching its exact runtime and platform.
This command and the fix for provably inactive optional transitive dependencies
are unreleased; they are not part of the 0.7.2 download. The package cards
include exact commands for the released CLI.
Add a dependency
Run kipferl add '<requirement>' inside a project containing kipferl.json.
Quote requirements containing shell metacharacters. The command resolves the
dependency tree, downloads wheels into .kipferl/cache under their SHA-256
hashes, verifies their contents,
and compiles Python sources with the embedded runtime. This compilation does
not import or execute the package.
By default, packages need matching catalog evidence. Use
kipferl add <requirement> --allow-unverified when you intend to evaluate an
unverified package with your own application tests. This flag does not bypass
known incompatibilities, invalid wheels, hash mismatches, or syntax failures.
The choice applies to the resolved dependency tree and is recorded in the lock,
so sync --locked does not need the flag. Each subsequent add evaluates the
whole tree again; include the flag again if it still contains unverified packages.
Version ranges resolve to the latest stable candidates that satisfy the
dependency constraints; pin a tested version when the newest version has no
matching evidence.
Successful installation updates the dependencies array in kipferl.json,
writes kipferl.lock, and installs files under .kipferl/packages. A failed
compatibility check leaves the prior configuration and installation intact;
downloaded wheels may remain cached for another attempt.
Try a recorded positive
The release pipeline generates tzdata==2025.2 evidence for each exact runtime
on macOS Apple Silicon, macOS Intel, Linux x86_64, and Linux ARM64. All four
v0.7.0 release binaries passed with their own matching records. Inspect
kipferl deps catalog for your binary. The reviewed
checks cover version constants and the TZif headers of four timezone data
files. This is evidence for loading package resources;
it does not establish timezone conversion support or provide zoneinfo.
With the v0.7.2 CLI and a project, install the exact version:
kipferl deps catalog
kipferl add 'tzdata==2025.2'For example, put this in app.py:
import os
import tzdata
resource = os.path.join(os.path.dirname(tzdata.__file__), "zoneinfo/UTC")
with open(resource, "rb") as source:
assert source.read(4) == b"TZif"
print("Timezone data:", tzdata.__version__)Run kipferl run, then build and test the executable. A different runtime hash
or target correctly reports this version as unverified until matching evidence
is recorded. Many pure-Python libraries still need syntax or CPython APIs that
PocketPy does not implement; the catalog also records those concrete blockers.
Restore and inspect
Commit kipferl.json and kipferl.lock. Keep .kipferl out of version control;
new project templates already ignore it.
kipferl sync --locked
kipferl deps list
kipferl deps check
kipferl test
kipferl buildThe lock records exact artifacts, installed file hashes, the embedded runtime hash, and its operating-system/CPU target. A locked sync restores those artifacts without selecting newer versions. Once the wheels have been cached in that project, restoration can work without network access:
kipferl sync --locked --offlinedeps list shows the locked package versions and their current catalog statuses
after validating the configuration,
runtime identity, and dependency constraints. deps check also hashes every
installed file and detects missing, changed, or extra files. It also rechecks
current catalog evidence, so a newly recorded blocker is not bypassed by an
older lock. Neither command
runs package tests. Run, dev, test, and build validate the installation before
preparing the application.
| Failure | Recovery |
|---|---|
| Installed files changed or disappeared | Run kipferl sync --locked to restore the installation. |
| A cached wheel has the wrong hash | Remove the specific cache file named in the error, then run kipferl sync --locked online. |
| A wheel is missing in offline mode | Run kipferl sync --locked online once to populate this project's cache. |
| Requirements, runtime hash, or target changed | Run kipferl add '<requirement>' again to resolve the current requirements and repeat compatibility checks. |
Review and commit a changed lock after resolving. Do not edit wheel hashes or runtime identity in the lock to work around a mismatch.
Upgrade to 0.7.2
Version 0.7.2 refreshes the 1,000-package source audit. Each release CLI embeds
its platform's report for the exact runtime it ships and exposes it offline
with kipferl deps audit. Verified compiler failures join the installation
catalog only for their recorded artifact, runtime, and target. Packages whose
sources compile remain unverified: the audit does not test their imports,
dependency closure, or application behavior.
Install the current stable release,
then check kipferl --version and kipferl deps audit. Refresh your dependency
lock using the commands below if the runtime hash has changed; never edit the
hash by hand. Run your application's tests after resolving.
The homepage video was recorded with 0.7.1 and still demonstrates the same project, package, and bundling workflow.
Upgrade to 0.7.1
Version 0.7.1 completes the product rename. The temporary aliases from 0.6 are removed from new CLIs, runtimes, release assets, and the Homebrew formula:
| Old spelling | Use in 0.7.1 |
|---|---|
ucharm command or Homebrew formula | kipferl |
from ucharm import ... | from kipferl import ... |
UCHARM_* environment variables | The matching KIPFERL_* variables |
MCHARM_TEST_KEYS | KIPFERL_TEST_KEYS |
ucharm-* release download filenames | kipferl-* filenames from the installation guide |
Update shell scripts, CI configuration, Python imports, and environment settings
before upgrading. Native imports such as import tui remain available. Remove
an old command symlink or a stale binary directory from PATH if it still
selects the previous executable, and verify kipferl --version reports
v0.7.2. Homebrew users can run brew update and brew upgrade kipferl;
users of the old formula should follow the
replacement instructions.
The Kipferl v1 universal format preserves its existing wire bytes. Previously built standalone executables remain usable; this patch does not require rebuilding them solely for the rename. New runtime binaries have new hashes, so project dependency locks still need the refresh described below.
Upgrade to 0.7.0
The import changes below arrived in 0.7.0. Refresh dependency locks when upgrading from 0.6 or any earlier 0.7 build, including 0.7.1 to 0.7.2.
An existing kipferl.lock identifies the exact runtime binary and platform.
Switching from a release candidate, development build, or another target can
invalidate it even when the visible version matches. Run kipferl add again for your declared
requirements, review the resolved versions and new lock, then run your tests:
kipferl add 'tzdata==2025.2'
kipferl deps check
kipferl test
kipferl buildUse your own declared requirement in place of the example. Repeat
--allow-unverified only when you intentionally accept and test the whole
unverified dependency tree; it does not override concrete incompatibilities.
Commit the resulting configuration and lock together. Do not change hashes
manually to bypass a mismatch. Keep your prior project revision and stable
executable available for rollback.
Dynamic imports also change: __import__("http.client") now returns the root
http, following Python's behavior. If your code previously used that result
as the child module, replace it with import http.client as http, then call
http.HTTPConnection(...). A nonempty positional fromlist also returns the
requested child. Relative from-import statements work; nonzero dynamic import
levels, namespace packages, and custom import finders remain unsupported.
Use and ship the package
Import installed modules normally. The PyPI distribution name can differ from the Python import name; consult the package's documentation.
Kipferl 0.7 supports ordinary dotted imports:
import http.client
import urllib.parse as urls
connection = http.client.HTTPSConnection("example.com")
print(urls.quote("hello world"))An unaliased dotted import binds the root package; an alias binds the requested
child. Packages initialize before their children. Relative from-imports,
reexports, circular imports, and failed-import retries have regression coverage
against CPython. Dynamic __import__ returns the root by default; a nonempty
positional fromlist returns the leaf. Nonzero dynamic import levels, custom
finders, and custom __path__ searches remain unsupported. sys.modules
reflects loading and loaded modules, but editing it does not control the native
import cache. Use regular __init__.py packages and static imports when bundling.
New editor configurations include .kipferl/packages in extraPaths. For an
existing project, add that entry to pyrightconfig.json to enable package
completions. Package annotations do not expand Kipferl's runtime API support.
The packager follows static imports through installed packages and carries
their resources and license metadata into the executable. Packages use the
full runtime against which compatibility is checked. Read package resources
relative to __file__, and test the built executable after removing access to
the checkout. Cross-target builds reuse the pure wheel artifacts, but host
checks do not establish behavior on the destination runtime. Test the result
on that target. The single and executable modes use an external runtime,
which may differ from the embedded runtime recorded in the lock. See portable packaging.
First-version boundaries
- PyPI is the supported registry; private indexes and direct URL requirements are not supported.
- Version constraints use Python packaging version semantics. Extras and environment markers are rejected explicitly, including in transitive requirements, rather than silently ignored.
- Only pure-Python wheels with a supported
py3/none/anytag are accepted. Native extensions, source builds,.pthhooks,.pycfiles, and wheel.datainstallation schemes are unsupported. - Python version requirements are checked against the runtime's advertised
Python version, currently
3.11.0. That metadata check is separate from PocketPy compatibility. - Missing APIs, computed imports, plugin discovery, and optional code paths cannot all be established by compilation. An unverified package may install successfully and still fail an application test or the build's import check.
- The installed tree is limited to 1,024 files and 32 MiB in total, with at most 1 MiB per Python source and 4 MiB per other file. Application code and assets must also fit the combined bundle limits.
- Packages need a regular-package layout. Namespace packages without
__init__.pyare unsupported. Python source must use UTF-8.
Use the failure's package/version and dependency path to identify the blocker.
Prefer a tested version or a built-in module where appropriate; passing
--full-runtime does not install packages or provide CPython extensions.