Core Concepts
This page explains the mental model behind IVPM. Understanding these concepts makes the rest of the documentation easier to navigate.
Project-Local Management
IVPM stores all dependencies inside each project, making projects self-contained and portable. There is no global package database and no shared state between projects.
A typical IVPM-enabled project has this structure:
my-project/
├── ivpm.yaml # Package configuration
├── packages/ # Dependencies directory
│ ├── python/ # Python virtual environment (if needed)
│ ├── dependency-1/ # Source package (editable)
│ ├── dependency-2/ # Cached package (symlink, read-only)
│ └── ...
├── src/ # Your project source
└── ...
The packages/ directory is created by ivpm update and is typically
listed in .gitignore. Deleting it and re-running ivpm update
recreates the entire environment from scratch.
The Update Pipeline
When you run ivpm update, IVPM executes a three-stage pipeline:
┌───────────────────────────────────────────────────────┐
│ Stage 1: Resolution │
│ Read ivpm.yaml, resolve variables (${var}), │
│ select dependency set, │
│ resolve sub-dependencies recursively │
└──────────────────────┬────────────────────────────────┘
│
┌──────────────────────▼────────────────────────────────┐
│ Stage 2: Fetch │
│ Fetch each package by source type │
│ (git, pypi, http, gh-rls, dir, file) │
│ │
│ As each package lands on disk, leaf handlers │
│ inspect it concurrently │
└──────────────────────┬────────────────────────────────┘
│
┌──────────────────────▼────────────────────────────────┐
│ Stage 3: Build Views │
│ Root handlers build project views (by phase number) │
│ - Direnv handler: environment view │
│ - Modules handler: module-load view │
│ - Python handler: Python venv view │
│ - Node handler: Node.js environment view │
│ - Agents handler: agent skills view │
│ - FuseSoC handler: FuseSoC library view │
│ │
│ Lock file written (packages/package-lock.json) │
└───────────────────────────────────────────────────────┘
Stage 1 – Resolution:
IVPM reads ivpm.yaml, resolves any ${var} references from the
vars: block (see Variables), selects the active dependency
set (via -d flag
or default-dep-set), and walks sub-package ivpm.yaml files
recursively to build a complete dependency graph.
Stage 2 – Fetch:
Each package is fetched according to its source type – git clones a
repository, pypi downloads from PyPI, http fetches an archive, and
so on. Fetches run in parallel. As each package becomes available on disk,
registered handlers run their leaf callbacks
concurrently to detect and classify the package.
Stage 3 – Build Views: After all packages are fetched, handlers run their root callbacks on the main thread. Each handler builds a view – a coherent projection of the dependency graph into one domain. The Python handler builds a virtual environment view; the direnv handler builds an environment-variable view; the agents handler builds a skills-directory view; the Node handler builds a Node.js environment view. Finally, the lock file is written.
For details on the handler mechanism, see Package Handlers.
Source Types and Content Types
Every package has two key attributes:
Source type – how to fetch the package:
git– clone a Git repositorypypi– install from the Python Package Indexnpm– install from the npm registryhttp– download an archive via HTTP/HTTPSgh-rls– download from a GitHub Releasedir– symlink a local directoryfile– use a local archive file
Content type – what the package contains and how to process it:
python– a Python package (installed into the venv by the Python handler)node– a Node.js package (installed into the Node environment by the Node handler)raw– data, HDL, or other files (placed inpackages/with no further processing)
These attributes are independent: a git source can contain a python
package or a raw package. IVPM auto-detects both in most cases.
For complete attribute reference and auto-detection rules, see Package Types & Sources.
Dependency Sets
Dependency sets are named collections of dependencies that let you maintain different profiles for different scenarios:
package:
name: my-project
default-dep-set: default-dev
dep-sets:
- name: default # Release: runtime dependencies only
deps:
- name: core-lib
url: https://github.com/org/core-lib.git
- name: default-dev # Development: adds test tools
uses: default
deps:
- name: pytest
src: pypi
Common uses: separating dev from release dependencies, creating different build-target profiles, and controlling which sub-dependencies get loaded.
For complete dependency set documentation, see Dependency Sets.
Recursive Sub-Dependencies
When a fetched package has its own ivpm.yaml, IVPM resolves its
dependencies recursively. By default, sub-packages inherit the parent’s
dependency set name. You can override this per-package:
deps:
- name: library-a
url: https://github.com/org/library-a.git
dep-set: default # Use release deps even when parent uses default-dev
This prevents a third-party library’s development tools from being pulled into your project.
Lock File and Reproducibility
Every ivpm update writes packages/package-lock.json, recording the
exact resolved identity of every fetched package (git commit hashes, release
tags, pip versions, HTTP ETags). This file enables exact workspace
reproduction:
# Reproduce an archived workspace
$ ivpm update --lock-file ./ivpm.lock
For full details, see Package Lock File.
Next Steps
Package Handlers – How handlers build project views (Python, Node, Direnv, Agents, and more)
Getting Started with IVPM – Install IVPM and set up your first project
Dependency Sets – Dependency set patterns and inheritance
Package Types & Sources – All source types, content types, and attributes