eva venv Self-Bootstrap Re-exec
eva beginner 3 min read
ELI5
bin/eva checks which kitchen it’s in. If it sees the project’s own kitchen (.venv) on the floor but it’s currently cooking somewhere else, it teleports itself into the project kitchen and starts over. If there’s no project kitchen, it tries to use whatever utensils are nearby and tells you what’s missing.
Technical Deep Dive
Sequence
sequenceDiagram participant Sh as shell participant Py1 as system python3 participant Eva as bin/eva participant Py2 as .venv/bin/python3
Sh->>Py1: exec bin/eva …args Py1->>Eva: __main__ Eva->>Eva: _VENV_PY = <root>/.venv/bin/python3 alt _VENV_PY exists AND sys.prefix != .venv Eva->>Py2: os.execv(_VENV_PY, [_VENV_PY, __file__, *argv[1:]]) Py2->>Eva: re-enter __main__ inside venv else already in venv (sys.prefix == .venv) Eva->>Eva: continue without re-exec end Eva->>Eva: import ruamel.yaml alt import fails Eva-->>Sh: stderr "ruamel.yaml not installed - pip install -r requirements.txt" Eva->>Sh: exit 2 endWhy sys.prefix, not sys.executable
The comment at bin/eva:18-19 is explicit: pyenv venvs share the binary via symlink, so sys.executable already-resolved would still equal the system python’s real path even when running inside a venv. sys.prefix instead reflects the active environment root (<repo>/.venv), giving a stable equality check against _VENV and avoiding an infinite re-exec loop.
Failure Modes
| Condition | Behaviour |
|---|---|
.venv does not exist | re-exec is skipped; eva runs under whichever interpreter the shebang resolved |
.venv exists but ruamel.yaml missing | import fails, eva writes a one-shot install hint and exits 2 (bin/eva:32-40) |
Already inside .venv | re-exec block is bypassed entirely |
Key Terms
os.execv— replaces the current process image; argv[0] must be the executable path (passed as_VENV_PY).sys.prefix— root of the active Python environment; differs fromsys.base_prefixinside a venv.- shebang —
bin/evadeclares#!/usr/bin/env python3; the interpreter the shell finds first runs the bootstrap, then the bootstrap optionally relocates.
Q&A
Q: Why does bin/eva compare sys.prefix instead of sys.executable?
A: Pyenv-style venvs share the python binary via symlink, so sys.executable resolves to the same real path inside and outside the venv. sys.prefix reflects the active environment root and is the only reliable signal that the re-exec already happened (bin/eva:18-21).
Q: What happens when .venv/bin/python3 is missing?
A: The os.path.exists(_VENV_PY) check fails and eva runs under the system interpreter without re-execing. If ruamel.yaml is unavailable there too, the import error path emits the install hint and exits 2.
Q: Which third-party import would fail without the bootstrap?
A: ruamel.yaml — used for round-trip YAML editing throughout eva (bin/eva:32-34). The bootstrap exists primarily so users do not have to remember to source .venv/bin/activate.
Examples
$ which python3 ; bin/eva list/usr/bin/python3# bin/eva re-execs into ~/code/eva-hq/.venv/bin/python3 transparentlyneighbors on the map
- Prompt Artefact Directory Layout scaffolding a new prompt under prompts/
- Eleventy Catalog Site Build running the prompt catalog locally before publishing
- Python SDK & CLI writing Python scripts that interact with IRIS
- FNP WASM & Server-Side Proof Verification deploying FNP on mobile devices