hepyy
A local HEP C++ package manager that downloads, compiles, and exposes packages as Python modules via cppyy — no ROOT, no conda, no system-wide installs required.
Supported packages out of the box: FastJet, Pythia8, HepMC3, fjcontrib, LHAPDF6.
Step-by-step examples for common setups (local, Colab, HPC, Jupyter, ROOT, shared packages): WORKFLOW-EXAMPLE.md
Requirements
- Python 3.9+ in a virtual environment (strongly recommended)
- A C++ compiler:
clang++(macOS) org++(Linux) cmake(for HepMC3)swig(for LHAPDF Python bindings — optional but recommended)- Internet access for first-time package downloads
On macOS with Homebrew:
brew install cmake swig
Installation
Create and activate a virtual environment, then install hepyy:
Short aliases:
heyyandherare registered as identical entry points alongsidehepyy— use whichever you prefer.heyy install fastjet her list hepyy config # all three are the same CLI
python -m venv myenv
source myenv/bin/activate
# From PyPI (the [cppyy] extra also installs cppyy itself — see note below):
pip install "hepyy[cppyy]"
# Or directly from GitHub (no clone needed):
pip install "hepyy[cppyy] @ git+https://github.com/matplo/hepyy.git"
# To update to the latest version (once inside an activated venv):
heyy upgrade
# Or manually with pip / uv:
pip install --force-reinstall "hepyy[cppyy] @ git+https://github.com/matplo/hepyy.git"
uv pip install --reinstall "hepyy[cppyy] @ git+https://github.com/matplo/hepyy.git"
# Or from a local clone (editable install for development):
git clone https://github.com/matplo/hepyy
cd hepyy
pip install -e ".[cppyy]"
Already have cppyy? (e.g. via conda/ROOT — see below) Just
pip install hepyy, no[cppyy]extra. cppyy isn't a hard dependency specifically so that pip never tries to install or upgrade it when a compatible one is already present — the[cppyy]extra is only needed when nothing already provides it.
Installing via conda (optional)
hepyy isn't on conda-forge, but it can still be installed straight from PyPI inside an activated conda/mamba environment:
# conda >=26.5: opt into the rattler solver, then install via the conda-pypi
# bridge channel (mirrors PyPI packages as installable conda packages)
conda config --set solver rattler
conda config --append channels conda-pypi
conda install hepyy
# Older conda: just use pip inside the activated conda env — no solver or
# channel setup needed, and it works on any conda version
pip install hepyy
Note: both routes above deliberately install plain
hepyy, nothepyy[cppyy]. If this conda env already has a working cppyy — for example because you installed CERN'srootpackage, which pulls in matched conda-forgecppyy/cppyy-backend/cppyy-cling/CPyCppyypackages — this leaves it alone rather than having pip try to install or upgrade its own copy (which risks an ABI mismatch against that matched set). If this conda env has no cppyy at all, usepip install hepyy[cppyy]instead (theconda-pypibridge only mirrors the base package, not extras) or install cppyy separately viaconda install -c conda-forge cppyy.Also: the
conda-pypichannel mirrors PyPI on its own schedule, so a release published minutes ago may not have propagated there yet.pip install -U hepyyinside the same conda env always gets the latest release immediately. See Configuration reference below for where hepyy stores its package builds inside a conda env.
Google Colab
hepyy works in Google Colab without any local setup.
Use ! to run shell commands from a notebook cell:
# Cell 1 — install hepyy (Colab has no cppyy preinstalled, so use the [cppyy] extra)
!pip install "hepyy[cppyy] @ git+https://github.com/matplo/hepyy.git"
# Cell 2 — initialise (creates package store, patches cppyy)
!hepyy init
# Cell 3 — build HEP packages (~10–20 min first time; Colab has 2+ cores)
!hepyy install fastjet hepmc3 lhapdf pythia8 fjcontrib --verbose
# Cell 4 — use them
import hepyy
hepyy.load('fastjet')
hepyy.load('fjcontrib')
hepyy.load('pythia8')
import cppyy, pythia8, fastjet, fjcontrib
# → ready to use
Notes:
- Each Colab runtime is ephemeral — packages must be reinstalled when the runtime resets.
The build takes ~10–20 min; avoid rebuilding every session by building once to persistent
storage (e.g. a mounted Drive folder) with
--to, then reusing it in any future session:# Session 1 — build once, straight to persistent storage from google.colab import drive drive.mount('/content/drive') !heyy install fastjet hepmc3 lhapdf pythia8 fjcontrib --to /content/drive/MyDrive/hepyy_packages --verbose # Session 2+ — any future runtime, no rebuild from google.colab import drive drive.mount('/content/drive') !heyy registry --add /content/drive/MyDrive/hepyy_packages/registry.json
--to <folder>makes<folder>a self-contained packages dir just for that install (its own<folder>/<name>/<version>/layout and<folder>/registry.json) — it doesn't touch this instance's own registry.heyy registry --addthen imports it wholesale into whichever fresh instance runs it, no per-packagehepyy registercalls needed. --verboseshows live build output, which is useful in Colab to confirm progress.- After
hepyy init, download the latest demo notebooks with:
This fetches all demo files from GitHub into!hepyy demos./hepyy_demos/. Re-run afterheyy upgradeto pick up new or updated demos. - See
demos/demo_softdrop_splitting.ipynbfor a complete worked example you can open directly in Colab.
Podman / containers
For a rootless, GPU-aware container setup (Python 3.11 + C++ + Fortran toolchain,
with hepyy-installed packages persisted on the host so adding a package never
needs an image rebuild), see contrib/podman/:
curl -fsSL https://raw.githubusercontent.com/matplo/hepyy/v0.2.30/contrib/podman/hepyy-pod.sh -o hepyy-pod.sh
chmod +x hepyy-pod.sh
./hepyy-pod.sh build
./hepyy-pod.sh run
See contrib/podman/README.md for details, including
automatic CUDA detection and GPU passthrough.
Initialise
Run once after installation to create the package store, fetch recipes, and check cppyy:
hepyy init
This creates the package store under your active venv and automatically clones the hepyy-recipes repository so the latest recipes are always available:
<venv>/hepyy_packages/
registry.json ← installed package index
src/ ← cached tarballs (safe to delete to free space)
logs/ ← build logs
recipe-cache/ ← cloned recipe repos
recipe-sources.json ← registered recipe sources
init also checks whether the cppyy backend (libCling) has broken library references
(common on macOS when the cppyy wheel was built against a different package manager).
When running inside a virtual environment, broken paths are patched automatically —
only files inside the venv are ever modified.
If the auto-fix cannot run (e.g. outside a venv, or install_name_tool / patchelf
is missing), inspect and patch manually:
# Inspect only:
hepyy fix-cppyy --check
# Patch:
hepyy fix-cppyy
To upgrade hepyy itself to the latest GitHub version from inside an active venv:
hepyy upgrade
This uses uv pip install --reinstall (or pip --force-reinstall) to bypass the
package cache. Re-enter the subshell after upgrading to pick up new entry points.
To refresh recipes at any time (e.g. after a new recipe is added upstream):
hepyy recipe update
Check where your packages will be installed:
hepyy config
Override the location at any time:
# Environment variable (shell session)
export HEPYY_PACKAGES_DIR=/opt/hep/packages
# Or permanently in .hepyy.toml at your project root:
# packages_dir = "/opt/hep/packages"
Installing packages
Recommended install order
Install order matters for Pythia8: it is built with optional support for FastJet, HepMC3, and LHAPDF6 only if those packages are already present in the registry at configure time. No explicit dependency is declared — if a package is installed, Pythia8 picks it up automatically; if not, that interface is simply omitted.
You can pass multiple package names to install and they are built sequentially in the
order given — which is all that is needed to satisfy the implicit Pythia8 dependencies:
hepyy install fastjet hepmc3 lhapdf pythia8 fjcontrib
Or one at a time:
hepyy install fastjet # (1) jet finding
hepyy install hepmc3 # (2) event record I/O
hepyy install lhapdf # (3) PDF sets
hepyy install pythia8 # (4) sees fastjet + hepmc3 + lhapdf → adds --with-* flags
hepyy install fjcontrib # (5) jet substructure (hard-requires fastjet)
During the Pythia8 build you will see which packages were detected:
[pythia8] FastJet : .../hepyy_packages/fastjet/3.5.1
[pythia8] HepMC3 : .../hepyy_packages/hepmc3/3.3.1
[pythia8] LHAPDF6 : .../hepyy_packages/lhapdf/6.5.4
[pythia8] configure: --with-fastjet3=... --with-hepmc3=... --with-lhapdf6=...
Version precedence
The registry stores one active entry per package name — the last-installed version.
If you install fastjet 3.4 and then fastjet 3.5, only 3.5 is visible to subsequent builds.
To control which version Pythia8 sees, install (or register) the desired fastjet version
before running hepyy install pythia8.
Useful flags
hepyy install fastjet --verbose # show build output live
hepyy install fastjet --force # re-extract and rebuild (keeps cached tarball)
hepyy install fastjet --redownload # delete tarball and start completely fresh
hepyy install fastjet --clean # wipe only build artifacts, keep extracted source
hepyy install fastjet -j 8 # use 8 parallel make jobs (overrides recipe default of 4)
# Flags apply to all packages when multiple names are given:
hepyy install fastjet hepmc3 lhapdf pythia8 fjcontrib --verbose
hepyy install fastjet hepmc3 lhapdf pythia8 fjcontrib -j 8
# --version and --recipe only take effect for a single-package install:
hepyy install fastjet --version 3.4.2
hepyy install mypackage --recipe /path/to/mypackage/1.0.yaml
--clean is useful on slow network mounts (e.g. Google Drive) where re-extracting
a large tarball is expensive: it removes cmake build dirs or runs make clean for
autotools packages, without touching the already-extracted source tree.
Inspecting what is installed
hepyy list # all installed packages with versions and prefixes
hepyy info fastjet # full details for one package
Using packages in Python
Loading with hepyy
# With the module system (recommended):
# module load fastjet pythia8 fjcontrib
# python myscript.py
# then in myscript.py just:
import fastjet, pythia8, fjcontrib # autoload hook has already set everything up
# Without the module system (Colab, bare venv):
import hepyy
hepyy.load("fastjet")
hepyy.load("pythia8")
hepyy.load("fjcontrib") # hepyy.load() is a no-op if already loaded
# Or pass a list — packages are loaded in order:
hepyy.load(["fastjet", "pythia8", "fjcontrib"])
import fastjet, pythia8, fjcontrib
# Either way, packages are available as cppyy proxies:
import cppyy
jet = fastjet.PseudoJet(1.0, 0.0, 1.0, 1.414)
print(jet.pt())
ROOT — PyROOT via native Python bindings
ROOT is available via the hepyy-recipes repository (not built-in). Install and use it with:
heyy recipe update # pull latest recipes including root
heyy install root # builds ROOT 6.40.00 (~30 min first time)
import hepyy
hepyy.load("root") # adds ROOT's lib/ to sys.path; does NOT import pip-cppyy
import ROOT
h = ROOT.TH1F("h", "h", 100, 0, 100)
h.Fill(42)
ROOT ships its own cppyy and cling — a different build from the pip-installed cppyy that hepyy uses for FastJet, Pythia8, etc. Because of this:
This is exactly the scenario the
cppyyextra (see Installation) exists for: if ROOT already provides a working cppyy — whether built viaheyy install rootabove, or via a conda-forgerootinstall (see Installing via conda) — install plainhepyy, nothepyy[cppyy], so pip never tries to install a second, separate cppyy alongside ROOT's.
-
hepyy.load("root")only adds ROOT'slib/directory tosys.path; it does not import pip-cppyy. ROOT's_facade.pythen finds ROOT's owncppyypackage (also inlib/) and initialises correctly. -
Mixing ROOT and pip-cppyy packages in the same session works for typical HEP workflows (generate/cluster with fastjet or pythia8, fill ROOT histograms) in ROOT 6.28+. The risk arises when passing C++ objects across the two cling contexts — e.g. handing a
fastjet::PseudoJet*directly to a ROOT-compiled function. -
With
module load, the auto-load hook handleshepyy.load()automatically so your script can go straight toimport fastjet; import ROOT. -
Recommended patterns:
# Pattern A — ROOT only session import ROOT # module load root handles hepyy.load('root') automatically # Pattern B — cppyy packages only session (module load fastjet pythia8) import fastjet, pythia8 # Pattern B+ROOT — typical mixed session (module load root fastjet pythia8) # autoload loads root FIRST → ROOT's cppyy wins → all packages share ROOT's cling import fastjet, pythia8 # loaded via ROOT's cppyy/cling import ROOT # same cling — works cleanly # fill histograms, write ROOT files — just avoid passing C++ objects between clings # Pattern C — ROOT owns cling, other libs loaded via ROOT's own interface import ROOT hepyy.gSystem_load('fastjet') # no pip-cppyy involved at all hepyy.gSystem_load('pythia8') p = ROOT.Pythia8.Pythia() j = ROOT.fastjet.PseudoJet(1, 0, 1, 1.4)
hepyy.gSystem_load(name) looks up the installed library path from the registry
and calls ROOT.gSystem.Load() for you — no hardcoded paths needed.
hepyy emits a UserWarning when ROOT and cppyy packages are loaded in the same
session so the potential conflict is visible at runtime.
module load rootwith the auto-load hook: when ROOT is among the module-loaded packages, hepyy loads it first so ROOT'slib/is insys.pathbefore the firstimport cppyy. ROOT's bundled cppyy is then used for all packages — one cling for everything. If ROOT is not module-loaded, hepyy strips ROOT'slib/fromDYLD_LIBRARY_PATHbefore loading pip-cppyy to prevent ROOT'slibcling.dylibfrom shadowing cppyy_backend's own cling.
HPC systems with GCC 14+ (NERSC Perlmutter, etc.): pip-cppyy ships a pre-built cling 16 that is incompatible with GCC 14 system headers — the PCH build fails and cppyy crashes. Installing ROOT via hepyy is the recommended fix: ROOT builds its own cling with the system's compiler, so on a GCC 14 system ROOT's cling is GCC 14 compatible. Loading ROOT first makes fastjet, pythia8, and all other packages share ROOT's cling instead of pip-cppyy's broken one.
heyy recipe update heyy install root # ~30 min first time; builds ROOT with system GCC 14import hepyy hepyy.load('root') # ROOT's cling — GCC 14 compatible, no PCH issues hepyy.load('fastjet') hepyy.load('pythia8') import ROOT, fastjet, pythia8 # all share ROOT's clingWith
module load, listingrootis enough — hepyy loads it first automatically:module load root fastjet pythia8 python script.py # fastjet and pythia8 use ROOT's cling
macOS with a current SDK: the same class of problem as above, different cause — pip-cppyy's
cling(LLVM 16) can't parse the C++ headers in current macOS SDKs, so the firstimport cppyycrashes building its PCH cache. hepyy warns about this before it happens (pointing here) instead of leaving you to decode the crash. Fix:heyy recipe update heyy install cppyy --force # ~10-30 min, one-time; builds cling pinned to # an older, compatible SDK — no runtime workaround # needed afterwardBuild it once into a shared
HEPYY_PACKAGES_DIRand everyhenv-created env can reuse it via--system-packages-dirinstead of rebuilding per env — see henv's Fixing a broken binary cppyy wheel.heyy install root(above) is also a valid alternative here, for the same reason: ROOT bundles its own, newercling.
LHAPDF — native Python bindings
LHAPDF is built with SWIG Python bindings. After hepyy install lhapdf the module
is installed directly into your venv — no hepyy.load() needed:
import lhapdf # works straight away
pdf = lhapdf.mkPDF("CT10nlo", 0)
xg = pdf.xfxQ(21, 0.01, 91.2) # gluon PDF at x=0.01, Q=91.2 GeV
print(f"xg(x=0.01, Q=Mz) = {xg:.4f}")
For C++ interop (passing LHAPDF::PDF* to other cppyy-loaded code):
hepyy.load("lhapdf") # loads the C++ library via cppyy
import cppyy
pdf = cppyy.gbl.LHAPDF.mkPDF("CT10nlo", 0)
Installing LHAPDF PDF sets
LHAPDF ships no PDF sets by default. Load the package first so lhapdf is on
your PATH, then install sets by name:
module load lhapdf
lhapdf install CT10nlo
lhapdf install NNPDF31_nnlo_as_0118
lhapdf install CT18NLO
lhapdf list --installed # what is already downloaded
PDF data files are stored under:
<packages_dir>/lhapdf/6.5.4/share/LHAPDF/<SetName>/
Add that directory to LHAPDF_DATA_PATH if you keep PDF sets elsewhere:
export LHAPDF_DATA_PATH=/data/pdfsets:$LHAPDF_DATA_PATH
Without
module load: use the full path directly:$(hepyy info lhapdf | awk '/^prefix/{print $2}')/bin/lhapdf install CT10nlo
One-line shell setup (recommended)
Add a single line to your shell config, once per machine, and completion +
module search path wire themselves up automatically every time you activate
a venv or conda env that has heyy installed — and stay out of the way
everywhere else (including after pip uninstall hepyy, with nothing left
behind to clean up, since it never writes anything into the env itself):
Bash — add to ~/.bashrc:
eval "$(heyy shell-init)"
Zsh — add to ~/.zshrc:
eval "$(heyy shell-init)"
Fish — add to ~/.config/fish/config.fish:
heyy shell-init --shell fish | source
This defines the module load/unload/list/avail shim (see
Shell module system below) and, on bash/zsh, checks on
every prompt whether the active venv/conda env changed (neither shell has a
native "env activated" event); fish uses its native --on-variable event
instead, so it fires exactly on activate/deactivate with no polling. Either
way, it only does anything once heyy is actually on PATH.
heyy completion and heyy modules (below) remain available standalone if
you'd rather wire them up yourself, or only want one of the two.
Shell completion
Enable tab completion for heyy, her, and hepyy in one line.
Zsh — add to ~/.zshrc:
eval "$(heyy completion)"
Bash — add to ~/.bashrc:
eval "$(heyy completion)"
The bash script uses complete -F / compgen -W and works with bash 3.2+,
including the macOS system bash. No version upgrade required.
Fish — add to ~/.config/fish/config.fish:
heyy completion --shell fish | source
After reloading your shell, pressing <Tab> completes commands, subcommands, and options:
heyy <Tab> # install list avail info env kernel recipe …
heyy install <Tab> # (available package names from recipes)
heyy kernel <Tab> # install list update uninstall
heyy kernel install --<Tab> # --name --display-name --sys-prefix
The --shell flag forces a specific shell if auto-detection is wrong:
heyy completion --shell bash
Shell module system
TCL modulefiles (Lmod / Environment Modules)
If your site uses Lmod or Environment Modules, hepyy can generate standard TCL modulefiles for all installed packages:
hepyy generate-modules # write/refresh modulefiles for all installed packages
Modulefiles are written to <packages_dir>/modulefiles/<name>/<version> and include
PATH, LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, PYTHONPATH (for packages with Python
bindings), and CPATH. Re-run after installing new packages to keep them up to date.
To add the directory to your active module search path:
eval "$(hepyy modules)" # runs: module use <packages_dir>/modulefiles
hepyy modules-path # print the modulefiles path only (no 'module use' prefix)
After that, standard module commands work as usual:
module load lhapdf/6.5.5
module load jewel/2.4.0
module list
Tip: add
eval "$(hepyy modules)"to your~/.bashrc/~/.zshrcso the modulefiles directory is always in the search path.
Python auto-load via module load
A hepyy_autoload.pth file ships with the package itself (installed straight
into site-packages by a regular pip install hepyy, and removed automatically
by pip uninstall hepyy — no separate step needed). Python processes .pth
files at startup, so any package loaded with module load before starting
Python is available to import directly — no hepyy.load() call needed.
(Editable/dev installs — pip install -e . — are the one case that still
needs heyy generate-modules once to write it.)
eval "$(heyy modules)" # register modulefiles dir (once, or in ~/.bashrc)
module load fastjet
module load pythia8
python -c "import fastjet, pythia8; print(fastjet.PseudoJet)"
For Jupyter notebooks or scripts that run without module load, the explicit call
still works as before:
import hepyy
hepyy.load("fastjet")
import fastjet
Note: the
.pthhook importshepyyat Python startup when anyHEPYY_LOADED_*env var is set. When no modules are loaded the check is a singleany()scan ofos.environ— effectively free.
Examples
Demo scripts live in the demos/ directory:
| Script | What it shows |
|---|---|
demos/demo_fastjet.py |
Basic FastJet jet finding |
demos/demo_pythia_fastjet.py |
Pythia8 + FastJet: event generation and jet clustering |
demos/demo_pythia_fastjet.ipynb |
Same as above in a Jupyter notebook |
demos/demo_pythia_fastjet_root.py |
Pythia8 + FastJet → ROOT TTree ntuple written to a .root file (requires root) |
demos/demo_fjcontrib.py |
SoftDrop, Nsubjettiness τ₂₁, EnergyCorrelator C₂ on Pythia8 dijets |
demos/demo_fjcontrib.ipynb |
Same as above in a Jupyter notebook with per-jet inspector table |
demos/demo_softdrop_splitting.ipynb |
SoftDrop splitting function: $z_g$ and $\theta_g$ distributions (open in Colab) |
Run:
hepyy install fastjet pythia8 fjcontrib # first time only
python demos/demo_fjcontrib.py
To get the latest demos after an upgrade (demos are not part of the installed package):
heyy demos # downloads all demos into ./hepyy_demos/
heyy demos --overwrite # re-download even if files already exist
For Jupyter / JupyterHub:
pip install jupyter matplotlib numpy ipykernel
heyy kernel install # register the venv as a selectable kernel
jupyter notebook demos/demo_fjcontrib.ipynb
Select the HEP (...) kernel when prompted, or use --kernel hepyy-<venv> on the
command line. After installing more packages, run heyy kernel update to refresh the
kernel spec. See the Jupyter kernel section for full options.
Jupyter kernel
Register the current venv as a Jupyter kernel so it can be selected in JupyterHub or JupyterLab:
pip install ipykernel # once, if not already installed
heyy kernel install
The kernel spec embeds PATH, DYLD_LIBRARY_PATH/LD_LIBRARY_PATH, PYTHONPATH, and
HEPYY_PACKAGES_DIR for every installed package, so notebooks can immediately do:
import hepyy
hepyy.load("fastjet")
import lhapdf # works directly — PYTHONPATH is already set
Kernel naming and multiple environments
Each venv gets an automatically distinct kernel name: hepyy-<venv-name>. If you
maintain separate environments for different projects — say henv-fastjet and
henv-pythia — running heyy kernel install from inside each one produces
hepyy-henv-fastjet and hepyy-henv-pythia as separate kernels with no extra
flags. You only need --name if you want something more descriptive than the venv
directory name.
The display name shown in JupyterLab defaults to HEP (<package list>) so you can
immediately tell what is available in each kernel without opening it.
Install options
heyy kernel install --name my-hep-env # custom kernel slug
heyy kernel install --display-name "HEP 2026" # custom label in JupyterHub/Lab
heyy kernel install --sys-prefix # install into sys.prefix (shared JupyterHub)
Updating after new package installs
After heyy install <pkg>, refresh the kernel to pick up the new paths:
heyy kernel update # refresh current venv's kernel
heyy kernel update hepyy-henv-dev # refresh a named kernel
kernel update is equivalent to re-running kernel install with the same name, but
it fails with a clear error (and a hint to run kernel install) if no kernel exists yet,
rather than silently creating one.
Listing and removing kernels
heyy kernel list # show all hepyy-managed kernels
heyy kernel uninstall hepyy-henv-dev # remove one (name from 'kernel list')
kernel list shows only kernels created by hepyy (identified by metadata written at
install time). kernel uninstall refuses to touch kernels not managed by hepyy.
Shared packages on a cluster
On an HPC cluster a single set of precompiled packages can be shared across user accounts. No one else needs to rebuild — they just point hepyy at the shared directory and generate their own kernel spec.
Option 1 — shared filesystem (NFS, GPFS, Lustre, …)
Admin / package builder (once):
export HEPYY_PACKAGES_DIR=/shared/hep/packages
heyy init
heyy install fastjet hepmc3 lhapdf pythia8 fjcontrib
heyy generate-modules # optional: write Lmod/TCL modulefiles into the same tree
Each user (no compilation needed):
export HEPYY_PACKAGES_DIR=/shared/hep/packages
heyy kernel install # writes a personal kernel.json pointing at the shared packages
Then in a notebook or script:
import hepyy
hepyy.load('fastjet')
hepyy.load('pythia8')
import fastjet, pythia8 # ready — no build, no wait
Tip: add
export HEPYY_PACKAGES_DIR=/shared/hep/packagesto~/.bashrc/~/.bash_profile, or set it from your site's module system, so it is always active.
Each user's heyy kernel install creates a kernel.json in their own
~/.local/share/jupyter/kernels/ that references the shared packages. The
packages themselves are never copied. To manage kernels:
heyy kernel list # show hepyy-managed kernels
heyy kernel update # refresh after the admin installs new packages
heyy kernel uninstall hepyy-myenv # remove (name from 'kernel list')
Option 2 — packages built by another tool
If your packages were compiled by yasp or another build system, register them without rebuilding:
export HEPYY_PACKAGES_DIR=/shared/hep/packages
heyy register fastjet --prefix /path/to/fastjet/3.5.1 --version 3.5.1
heyy register pythia8 --prefix /path/to/pythia8/8.317 --version 8.317
heyy kernel install # now embeds the registered prefixes
Option 3 — portable tarball (no shared filesystem)
Pack on the source machine:
tar -czf hep-packages.tar.gz -C /shared/hep/packages .
Unpack on the target machine (OS and Python version must be compatible):
mkdir -p ~/.henvs/default
tar -xzf hep-packages.tar.gz -C ~/.henvs/default
export HEPYY_PACKAGES_DIR=~/.henvs/default
heyy kernel install
Option 4 — merge another heyy instance's registry
If the prefixes are reachable from this instance (same machine, or a shared
filesystem) but you'd rather not point HEPYY_PACKAGES_DIR at someone else's
tree, import their whole registry in one shot instead of heyy register-ing
packages one at a time:
heyy registry --add /path/to/their/hepyy_packages/registry.json
Adds every package not already in this instance's registry; for one that
already exists here, it asks before overwriting (skipped automatically if
the existing entry is already identical) unless --yes is given.
Registering externally-built packages
If you already have a package built by another tool (e.g. yasp):
hepyy register fastjet --prefix /path/to/fastjet/3.5.1
hepyy register fastjet --prefix /path/to/fastjet/3.5.1 --version 3.5.1
External recipe sources
hepyy ships built-in recipes for FastJet, HepMC3, LHAPDF6, Pythia8, and fjcontrib. You can extend this with recipes from a GitHub repository or use a one-off recipe file from anywhere on disk.
GitHub recipe source
The matplo/hepyy-recipes repository
is registered automatically by hepyy init. You can add further repos the same way:
Point hepyy at a GitHub repo and it will clone it locally and search it automatically
on every install and avail call:
# Whole repo (recipes expected at <name>/<version>.yaml under the root)
hepyy recipe add https://github.com/user/my-hep-recipes
# Subdirectory of a repo
hepyy recipe add https://github.com/matplo/yasp/tree/main/recipes
Manage sources:
hepyy recipe list-sources # show all registered sources
hepyy recipe update # git pull on all sources (refresh)
hepyy recipe remove https://github.com/user/my-hep-recipes
Once added, packages from that source appear in hepyy avail and can be installed
by name like any built-in:
hepyy avail # shows built-in + remote recipes
hepyy install mypackage # finds recipe in remote source automatically
One-off recipe file
To use a single recipe file without registering a source:
hepyy install mypackage --recipe /path/to/mypackage/1.0.yaml
The --recipe flag accepts any absolute or relative path and overrides the built-in
and remote source search for that invocation.
Recipe format
Recipes are YAML files named <version>.yaml inside a <name>/ directory:
my-recipes/
fastjet/
3.5.1.yaml
mycustomlib/
2.0.yaml
See the built-in recipes under src/hepyy/recipes/ for the full format reference.
VCS-based recipes (git / svn)
If a package has no tarball (e.g. SVN-only like POWHEG, or a rolling git branch), omit
the url field. hepyy will skip the download step and run build_script directly
from an empty working directory — the script is responsible for fetching its own source:
name: powheg
version: "v2"
# no url — build_script fetches via SVN
build_system: script
build_script: |
svn co svn://powhegbox.mib.infn.it/trunk/POWHEG-BOX-V2 powheg-box
cd powheg-box
make -j{n_cores} pwhg_main
...
Recipe scripting gotchas
Build scripts are processed by Python's str.format_map() before being passed to bash.
This means any {...} in the script is treated as a template variable, including:
| Pattern | Problem | Fix |
|---|---|---|
${VAR:-default} |
{VAR:-default} consumed by format_map |
Use if [ -z "$VAR" ]; then VAR=default; fi |
find -exec cp {} \; |
{} is a positional field |
Escape as {{}} |
Comments containing {...} |
Also substituted | Remove or reword the comment |
Heppyyier template variables available in every script:
{prefix}, {version}, {n_cores}, {srcdir}, {builddir}, {CXX}, {CC},
and {<name>_prefix} for every package currently in the registry.
Configuration reference
| Method | Key | Example |
|---|---|---|
| Env var | HEPYY_PACKAGES_DIR |
export HEPYY_PACKAGES_DIR=/opt/hep |
.hepyy.toml |
packages_dir |
packages_dir = "/opt/hep" |
| Default (venv) | — | <venv>/hepyy_packages/ |
| Default (conda/mamba env, no venv) | — | <conda env>/share/hepyy_packages/ |
| Default (no venv, no conda) | — | ./packages/ |
Legacy env var HEPYY_BUILD_DIR and toml key build_dir are still accepted.
Metadata
Release files for hepyy 0.2.30
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| hepyy-0.2.30.tar.gz | 305.6 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| hepyy-0.2.30-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 372.3 kB
Release files / hepyy-0.2.30.tar.gz
| Download URL | hepyy-0.2.30.tar.gz |
|---|---|
| Size | 305.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b10f715949e09d17e0b88f27830a26044101742d21bfb4009a5548f3d2294c8d
|
|
BLAKE2b-256 checksum How to use checksums |
81f377a926c95984fbab3b4ffa4d75777bb1e3aaea6638ec746e7592a18bd692
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.
Transparency logRelease files / hepyy-0.2.30-py3-none-any.whl
| Download URL | hepyy-0.2.30-py3-none-any.whl |
|---|---|
| Size | 66.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8c5ce66b223d339ed19cd67c18f979ff17a9ea7c9f03c0141b669654fd3de9e5
|
|
BLAKE2b-256 checksum How to use checksums |
b32e2d4be0c64c7f7e119a6fbe07b6c5b7f60039b378a490795e944efd82cf9d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.
Transparency logSecurity for hepyy 0.2.30
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for hepyy-0.2.30.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.