Skip to content
Apothem
Arquitetura

Runtime autocontido

Como o motor do Apothem roda a partir de qualquer checkout — dependências internalizadas, o modelo de invocação PYTHONPATH=src e o bootstrap da árvore do plugin.

Runtime autocontido

O motor do Apothem é um runtime autocontido: ele roda sem registro de pacotes, diretamente a partir de qualquer checkout ou árvore de código-fonte posicionada, porque suas dependências de terceiros viajam com ele. Duas peças fazem isso funcionar — uma árvore de dependências internalizadas e um modelo de invocação python -m que não precisa de scripts de console instalados.

Árvore de dependências internalizadas

A pilha de validação e serialização é internalizada como código-fonte em Python puro sob src/apothem/_vendor/, cada pacote ao lado do arquivo de licença do seu projeto original:

  • yaml (o parser/emissor em Python puro; a extensão C opcional libyaml não é incluída)
  • jsonschema, com sua cadeia de dependências attrs (e seu alias attr), referencing e jsonschema_specifications
  • rpds — um shim em Python puro que reimplementa a superfície HashTrieMap, HashTrieSet e List que jsonschema e referencing usam, apoiado em tipos embutidos, de modo que a pilha roda com zero extensões compiladas
  • typing_extensions

As cópias internalizadas têm precedência sobre qualquer versão instalada no sistema: o bootstrap do plugin, o shim do npm, os instaladores e o próprio ponto de entrada python -m apothem colocam, cada um, o diretório vendor no sys.path à frente de site-packages. A política de seleção — o que é internalizado, o que não é e como os pacotes internalizados são atualizados — está documentada na estratégia de internalização de dependências.

Duas dependências ficam fora da árvore: click e rich, as bibliotecas voltadas ao terminal que a CLI importa. Elas precisam ser importáveis no interpretador que roda o motor; os instaladores verificam ambas, nomeiam qualquer uma que esteja faltando e oferecem instalá-la para você — com sua confirmação, ou automaticamente com --yes / APOTHEM_AUTO_INSTALL_DEPS=1. Em todos os outros canais, o ponto de entrada verifica ambas com a biblioteca padrão antes de importar a CLI, e a falta de uma delas o interrompe com um erro que nomeia o comando pip exato para o interpretador em execução (um envelope JSON com o código runtime.dependency_missing sob --json).

O modelo de invocação python -m

O Apothem intencionalmente não declara scripts de console no pyproject.toml — scripts de console só existem quando um gerenciador de pacotes os coloca no PATH, e o runtime autocontido nunca pressupõe um. Em vez disso, o motor tem duas superfícies de invocação:

SuperfícieInvocaçãoContexto
CLI do motorpython -m apothem <command>Uma árvore de código-fonte com src/ em PYTHONPATH (checkout, cache do npx, árvore do plugin)
Runtime de hooks<resolved CPython> "<harness-root>/.apothem/support/hooks/dispatch.py" <event>A materialização do Claude Code: a cópia sob a árvore compartilhada .apothem/support/ da raiz do harness, por caminho absoluto
  • python -m apothem executa src/apothem/__main__.py, que coloca src/apothem/_vendor no sys.path, verifica se click e rich são importáveis e então chama apothem.cli:main — o grupo de comandos do Click.
  • As entradas de hook no settings.json / hooks.json materializado invocam o despachante (e, para o Claude Code, o conformity gate em <harness-root>/.apothem/support/conformity/gate.py) por caminho absoluto de script. Ambos são scripts autônomos da biblioteca padrão que fazem o bootstrap do próprio sys.path, e os fixtures de schema do gate ficam ao lado dele em <harness-root>/.apothem/support/schemas/, de modo que os hooks rodam sem nenhum pacote apothem importável no host. Os templates carregam um token ${HARNESS_ROOT} que o apothem install renderiza como o caminho real da raiz do harness, com barras normais.
  • A partir de um checkout do código-fonte, as formas de módulo python -m apothem.hooks.dispatch e python -m apothem.conformity.gate executam o mesmo código para desenvolvimento.

O diretório do pacote se torna importável ao antepor o diretório src/ do checkout ao PYTHONPATH:

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

Quando o lançador apothem não está no PATH, o install.sh imprime esta forma ao concluir, com o diretório de dependências incorporadas antes de src/ e o CPython que ele resolveu no lugar de python. O install.ps1 imprime as mesmas duas configurações na forma do PowerShell: uma atribuição a $env:PYTHONPATH que une os diretórios de dependências incorporadas e src/ com ;, seguida de & '<CPython>' -m apothem <command>.

Bootstrap da árvore do plugin

O plugin do Claude Code empacota o motor sob <plugin_root>/lib/apothem em vez de depender do PYTHONPATH. O módulo de bootstrap apothem.lib.plugin_bootstrap expõe bootstrap_syspath, que antepõe, de forma idempotente, <plugin_root>/lib e o diretório vendor ao sys.path, para que import apothem e cada dependência internalizada sejam resolvidos a partir da árvore do plugin. Uma árvore malformada (sem lib/) lança PluginBootstrapError em vez de importar silenciosamente uma cópia desatualizada do sistema.

O que o instalador coloca em disco

Os instaladores por script colocam um clone git da árvore de código-fonte em ~/.apothem (substituível com APOTHEM_HOME) e rodam o motor a partir dele — nenhum pacote Python é instalado em site-packages além da oferta opcional do pré-requisito click / rich. O clone é o repositório completo, incluindo a suíte de testes e o site de documentação que o runtime nunca importa, por duas razões deliberadas: o motor materializa seus cohorts — regras, skills, comandos e templates — diretamente da árvore em cada harness, de modo que a árvore é a fonte da verdade viva, e não apenas um runtime; e o diretório .git permanece no lugar para que o apothem update faça checkout da tag de release no clone existente em vez de baixá-lo novamente.

Este layout de execução a partir do código-fonte é o mesmo padrão que ferramentas como nvm, pyenv e oh-my-zsh usam — alguns megabytes de código-fonte mais o histórico, removíveis em um único passo com o desinstalador (não há estado de sistema a desfazer). Uma pegada menor — um checkout raso ou esparso que omita tests/ e site/ — é possível, mas abriria mão do caminho de atualização no local, verificado por assinatura e baseado em git; o layout atual privilegia uma atualização simples e verificável em vez de um uso mínimo de disco.

Como o runtime encontra o Python

Os instaladores de uma única etapa e o shim do npx sondam nomes diferentes e aplicam as mesmas regras. Os instaladores sondam python3, python e os nomes versionados (python3.14 até python3.10). O shim do npx sonda APOTHEM_PYTHON quando ele está definido e, em seguida, python3, python e py -3; ele não tem nomes versionados. Ambos rejeitam os shims do lançador da Microsoft Store e aceitam o primeiro candidato que informar a versão 3.10 ou mais recente. Quando executados a partir de uma árvore de código-fonte, os instaladores reutilizam o localizador empacotado hooks/lib/find-python, que aplica o mesmo piso.

Próximo passo recomendado

Execute python -m apothem --help com o diretório src/ do checkout no PYTHONPATH para confirmar que o caminho da CLI autocontida é resolvido no seu host.

On this page