Skip to content
Apothem
Architecture

Runtime autonome

Comment le moteur d'Apothem s'exécute depuis n'importe quel checkout — dépendances vendorisées, le modèle d'invocation PYTHONPATH=src et le bootstrap de l'arbre du plugin.

Runtime autonome

Le moteur d'Apothem est un runtime autonome : il s'exécute sans registre, directement depuis n'importe quel checkout ou arbre de code source déposé, parce que ses dépendances tierces voyagent avec lui. Deux pièces rendent cela possible — un arbre de dépendances vendorisées et un modèle d'invocation python -m qui n'a besoin d'aucun script de console installé.

Arbre de dépendances vendorisées

La pile de validation et de sérialisation est vendorisée sous forme de code source en Python pur sous src/apothem/_vendor/, chaque paquet accompagné du fichier de licence de son projet amont :

  • yaml (le parseur/émetteur en Python pur ; l'extension C optionnelle libyaml n'est pas embarquée)
  • jsonschema, avec sa chaîne de dépendances attrs (et son alias attr), referencing et jsonschema_specifications
  • rpds — un shim en Python pur qui réimplémente la surface HashTrieMap, HashTrieSet et List qu'utilisent jsonschema et referencing, adossé à des types intégrés, de sorte que la pile s'exécute sans aucune extension compilée
  • typing_extensions

Les copies vendorisées priment sur toute version installée sur le système : le bootstrap du plugin, le shim npm, les installateurs et le point d'entrée python -m apothem lui-même placent chacun le répertoire vendor dans sys.path devant site-packages. La politique de sélection — ce qui est vendorisé, ce qui ne l'est pas et comment les paquets vendorisés sont rafraîchis — est documentée dans la stratégie de vendorisation des dépendances.

Deux dépendances restent hors de l'arbre : click et rich, les bibliothèques orientées terminal qu'importe la CLI. Elles doivent être importables sous l'interpréteur qui exécute le moteur ; les installateurs vérifient les deux, nomment celle qui manque et proposent de l'installer pour vous — avec votre confirmation, ou automatiquement avec --yes / APOTHEM_AUTO_INSTALL_DEPS=1. Sur tous les autres canaux, le point d'entrée vérifie les deux avec la bibliothèque standard avant d'importer la CLI, et une dépendance manquante l'arrête avec une erreur qui nomme la commande pip exacte pour l'interpréteur en cours d'exécution (une enveloppe JSON avec le code runtime.dependency_missing sous --json).

Le modèle d'invocation python -m

Apothem ne déclare intentionnellement aucun script de console dans pyproject.toml — les scripts de console n'existent que lorsqu'un gestionnaire de paquets les place sur le PATH, et le runtime autonome n'en suppose jamais un. Le moteur dispose plutôt de deux surfaces d'invocation :

SurfaceInvocationContexte
CLI du moteurpython -m apothem <command>Un arbre de code source avec src/ sur le PYTHONPATH (checkout, cache npx, arbre du plugin)
Runtime des hooks<resolved CPython> "<harness-root>/.apothem/support/hooks/dispatch.py" <event>Matérialisation Claude Code : la copie située sous l'arborescence partagée .apothem/support/ de la racine de l'environnement, par chemin absolu
  • python -m apothem exécute src/apothem/__main__.py, qui place src/apothem/_vendor dans sys.path, vérifie que click et rich sont importables, puis appelle apothem.cli:main — le groupe de commandes Click.
  • Les entrées de hook du settings.json / hooks.json matérialisé invoquent le répartiteur (et, pour Claude Code, le portail de conformité à <harness-root>/.apothem/support/conformity/gate.py) par chemin de script absolu. Tous deux sont des scripts autonomes de la bibliothèque standard qui amorcent leur propre sys.path, et les fixtures de schéma du portail voyagent à côté de lui dans <harness-root>/.apothem/support/schemas/, de sorte que les hooks s'exécutent sans aucun paquet apothem importable sur l'hôte. Les templates portent un jeton ${HARNESS_ROOT} qu'apothem install rend en chemin réel de la racine de l'environnement, sous forme à barres obliques.
  • Depuis un checkout du code source, les formes de module python -m apothem.hooks.dispatch et python -m apothem.conformity.gate exécutent le même code pour le développement.

Le répertoire du paquet devient importable en plaçant le répertoire src/ du checkout en tête de PYTHONPATH :

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

Lorsque le lanceur apothem ne figure pas dans le PATH, install.sh affiche cette forme à la fin, avec le répertoire vendorisé placé avant src/ et le CPython qu'il a résolu à la place de python. install.ps1 affiche les deux mêmes réglages sous forme PowerShell : une affectation $env:PYTHONPATH qui joint les répertoires vendorisé et src/ avec ;, puis & '<CPython>' -m apothem <command>.

Bootstrap de l'arbre du plugin

Le plugin Claude Code embarque le moteur sous <plugin_root>/lib/apothem plutôt que de s'appuyer sur PYTHONPATH. Le module de bootstrap apothem.lib.plugin_bootstrap expose bootstrap_syspath, qui place de façon idempotente <plugin_root>/lib et le répertoire vendor en tête de sys.path afin qu'import apothem et chaque dépendance vendorisée se résolvent depuis l'arbre du plugin. Un arbre malformé (sans lib/) lève PluginBootstrapError plutôt que d'importer silencieusement une copie système périmée.

Ce que l'installateur dépose sur le disque

Les installateurs par script déposent un clone git de l'arbre de code source à ~/.apothem (remplaçable par APOTHEM_HOME) et exécutent le moteur depuis lui — aucun paquet Python n'est installé dans site-packages au-delà de la proposition optionnelle des prérequis click / rich. Le clone est le dépôt complet, y compris la suite de tests et le site de documentation que le runtime n'importe jamais, pour deux raisons délibérées : le moteur matérialise ses cohortes — règles, skills, commandes et templates — directement depuis l'arbre dans chaque environnement, de sorte que l'arbre est la source de vérité vivante et pas seulement un runtime ; et le répertoire .git reste en place pour qu'apothem update extraie le tag de version dans le clone existant au lieu de le retélécharger.

Cette disposition d'exécution depuis le code source suit le même motif que des outils comme nvm, pyenv et oh-my-zsh — quelques mégaoctets de code source plus l'historique, supprimables en une seule étape avec le désinstallateur (il n'y a aucun état système à défaire). Une empreinte plus légère — un checkout superficiel ou partiel qui omet tests/ et site/ — est possible, mais sacrifierait le chemin de mise à jour sur place, vérifié par signature et fondé sur git ; la disposition actuelle privilégie une mise à jour simple et vérifiable plutôt qu'un espace disque minimal.

Comment le runtime trouve Python

Les installateurs en une étape et le shim npx sondent des noms différents et appliquent les mêmes règles. Les installateurs sondent python3, python et les noms versionnés (python3.14 jusqu'à python3.10). Le shim npx sonde APOTHEM_PYTHON lorsqu'elle est définie, puis python3, python et py -3 ; il n'a aucun nom versionné. Tous deux rejettent les shims du lanceur Microsoft Store et acceptent le premier candidat signalant la version 3.10 ou une version plus récente. Lorsqu'ils sont exécutés depuis un arbre de code source, les installateurs réutilisent le localisateur embarqué hooks/lib/find-python, qui applique le même plancher.

Prochaine étape recommandée

Exécutez python -m apothem --help avec le répertoire src/ du checkout sur le PYTHONPATH pour confirmer que le chemin de la CLI autonome se résout sur votre hôte.

On this page