Skip to content
Apothem
Architecture

Self-contained runtime

How Apothem's engine runs from any checkout — vendored dependencies, the PYTHONPATH=src invocation model, and the plugin-tree bootstrap.

Self-Contained Runtime

Apothem's engine is a self-contained runtime: it runs registry-free, directly from any checkout or placed source tree, because its third-party dependencies travel with it. Two pieces make that work — a vendored dependency tree and a python -m invocation model that needs no installed console scripts.

Vendored dependency tree

The validation and serialization stack is vendored as pure-Python source under src/apothem/_vendor/, each package alongside its upstream license file:

  • yaml (the pure-Python parser/emitter; the optional libyaml C extension is not carried)
  • jsonschema, with its dependency chain attrs (and its attr alias), referencing, and jsonschema_specifications
  • rpds — a pure-Python shim that reimplements the HashTrieMap, HashTrieSet, and List surface jsonschema and referencing use, backed by builtin types, so the stack runs with zero compiled extensions
  • typing_extensions

Vendored copies take precedence over any system-installed version: the plugin bootstrap, the npm shim, the installers, and the python -m apothem entry point itself each put the vendor directory on sys.path ahead of site-packages. The selection policy — what is vendored, what is not, and how vendored packages are refreshed — is documented in the dependency vendoring strategy.

Two dependencies stay outside the tree: click and rich, the terminal-facing libraries the CLI imports. They must be importable under the interpreter that runs the engine; the installers check both, name any that is missing, and offer to install it for you — with your confirmation, or automatically with --yes / APOTHEM_AUTO_INSTALL_DEPS=1. On every other channel the entry point checks both with the standard library before it imports the CLI, and a missing one stops it with an error that names the exact pip command for the running interpreter (a JSON envelope with code runtime.dependency_missing under --json).

The python -m invocation model

Apothem intentionally declares no console scripts in pyproject.toml — console scripts only exist when a package manager places them on PATH, and the self-contained runtime never assumes one. The engine has two invocation surfaces instead:

SurfaceInvocationContext
Engine CLIpython -m apothem <command>A source tree with src/ on PYTHONPATH (checkout, npx cache, plugin tree)
Hook runtime<resolved CPython> "<harness-root>/.apothem/support/hooks/dispatch.py" <event>The Claude Code materialization: the copy under the harness root's shared .apothem/support/ tree, by absolute path
  • python -m apothem runs src/apothem/__main__.py, which puts src/apothem/_vendor on sys.path, checks that click and rich are importable, then calls apothem.cli:main — the Click command group.
  • Hook entries in the materialized settings.json / hooks.json invoke the dispatcher (and, for Claude Code, the conformity gate at <harness-root>/.apothem/support/conformity/gate.py) by absolute script path. Both are standalone stdlib scripts that bootstrap their own sys.path, and the gate's schema fixtures ride beside it at <harness-root>/.apothem/support/schemas/, so hooks run with no importable apothem package on the host. The templates carry a ${HARNESS_ROOT} token that apothem install renders to the real harness-root path in forward-slash form.
  • From a source checkout, the module forms python -m apothem.hooks.dispatch and python -m apothem.conformity.gate run the same code for development.

The package directory becomes importable by prepending the checkout's src/ directory to PYTHONPATH:

PYTHONPATH="$HOME/.apothem/src" python -m apothem <command>

When the apothem launcher is not on PATH, install.sh prints this form at completion, with the vendored directory ahead of src/ and the CPython it resolved in place of python. install.ps1 prints the same two settings in PowerShell form: a $env:PYTHONPATH assignment that joins the vendored and src/ directories with ;, then & '<CPython>' -m apothem <command>.

Plugin-tree bootstrap

The Claude Code plugin bundles the engine under <plugin_root>/lib/apothem rather than relying on PYTHONPATH. The bootstrap module apothem.lib.plugin_bootstrap exposes bootstrap_syspath, which idempotently prepends <plugin_root>/lib and the vendor directory to sys.path so import apothem and every vendored dependency resolve from the plugin tree. A malformed tree (missing lib/) raises PluginBootstrapError rather than silently importing a stale system copy.

What the installer places on disk

The script installers place a git clone of the source tree at ~/.apothem (override with APOTHEM_HOME) and run the engine from it — no Python packages are installed into site-packages beyond the optional click / rich prerequisite offer. The clone is the full repository, including the test suite and documentation site the runtime never imports, for two deliberate reasons: the engine materializes its cohorts — rules, skills, commands, and templates — directly from the tree into each harness, so the tree is the live source of truth rather than only a runtime; and the .git directory stays in place so apothem update checks out the release tag in the existing clone instead of re-downloading.

This run-from-source layout is the same pattern tools like nvm, pyenv, and oh-my-zsh use — a few megabytes of source plus history, removable in one step with the uninstaller (there is no system state to unwind). A slimmer footprint — a shallow or sparse checkout that omits tests/ and site/ — is possible but would trade away the in-place, signature-verified git-based update path; the current layout favours a simple, verifiable update over minimal disk.

How the runtime finds Python

The one-shot installers and the npx shim probe different names and apply the same rules. The installers probe python3, python, and the versioned names (python3.14 through python3.10). The npx shim probes APOTHEM_PYTHON when it is set, then python3, python, and py -3; it has no versioned names. Both reject Microsoft Store launcher shims and accept the first candidate reporting version 3.10 or newer. When run from a source tree, the installers reuse the bundled hooks/lib/find-python locator, which applies the same floor.

Run python -m apothem --help with the checkout's src/ directory on PYTHONPATH to confirm the self-contained CLI path resolves on your host.

On this page