Package Management
Note: Publishing packages requires the registry backend to be deployed. Installing public packages works immediately.
HORUS provides a comprehensive package management system for sharing and discovering robotics components. Create reusable nodes, message types, and algorithms that the community can use.
Quick Reference
| Task | Command |
|---|---|
| Add a dependency | horus add serde |
| Add with version | horus add serde@1.0 --features derive |
| Install a tool/plugin | horus install horus-sim3d |
| Remove a package | horus remove pid-controller |
| Search registry | horus search slam |
| List installed | horus list |
| Update all | horus update |
| Authenticate | horus auth login |
| Publish | horus publish |
Overview
The package system allows you to:
- Install packages from multiple sources (HORUS registry, crates.io, PyPI)
- Publish your work for others to use
- Manage dependencies automatically
- Version control with semantic versioning
- Search and discover community packages
Package Sources
HORUS supports packages from multiple sources:
| Source | Description | Command |
|---|---|---|
| HORUS Registry | Curated robotics packages | horus add pid-controller or horus install pid-controller |
| crates.io | Rust ecosystem packages | horus add serde |
| PyPI | Python ecosystem packages | horus add numpy |
| Git | Git repositories | horus add https://github.com/org/repo |
| Local Path | Local filesystem | horus add ./path/to/pkg |
horus add vs horus install
| Command | Like | Purpose | Modifies horus.toml? |
|---|---|---|---|
horus add serde | cargo add | Add project dependency | Yes |
horus install slam-toolbox | cargo install | Install standalone tool/plugin globally | No |
Use horus add for libraries your project depends on. Use horus install for standalone tools, plugins, and CLI extensions.
Quick Start
Adding Project Dependencies
# Add from crates.io (auto-detected for Rust projects)
horus add serde
horus add tokio
# Add from PyPI (auto-detected for Python projects)
horus add numpy
horus add opencv-python
# Add with specific version and features
horus add serde@1.0 --features derive
# Add from HORUS registry
horus add pid-controller
Installing Standalone Packages
# Install a standalone tool or plugin globally
horus install horus-sim3d
horus install rplidar-driver@1.2.0
horus install horus-visualizer --plugin
Automatic Source Detection
HORUS automatically detects the package source:
- First checks HORUS registry
- Then checks both PyPI and crates.io
- If found in multiple sources, prompts you to choose:
Package 'package_name' found in BOTH PyPI and crates.io
Which package source do you want to use?
[1] [PYTHON] PyPI (Python package)
[2] [RUST] crates.io (Rust binary)
[3] [FAIL] Cancel installation
Choice [1-3]:
System Package Detection
If a package is already installed system-wide, HORUS offers to reuse it:
Package 'ripgrep' v14.0.0 already installed system-wide
[1] Use system package (no download)
[2] Install fresh copy to HORUS
[3] Cancel
Choice [1-3]:
What happens during installation:
- Detects package source (HORUS registry, crates.io, or PyPI)
- Downloads package from the appropriate source
- Resolves dependencies automatically
- Caches locally in
~/.horus/cache/or.horus/packages/ - Makes package available for use
Using an Installed Package
// In your main.rs or any file
use pid_controller::PIDNode;
use horus::prelude::*;
fn main() -> Result<()> {
let mut scheduler = Scheduler::new();
// Use the installed package
let pid = PIDNode::new(1.0, 0.1, 0.01);
scheduler.add(pid).order(5).build()?;
scheduler.run()?;
Ok(())
}
Publishing Your Package
# 1. Authenticate first (one-time)
horus auth login
# 2. Navigate to your project
cd my-awesome-controller
# 3. Publish
horus publish
Package Locations
Local Packages
Project-local (default):
my_project/
── .horus/
── packages/
── pid-controller@1.0.0/ # HORUS registry
── serde@1.0.200/ # crates.io
── pypi_numpy@1.24.0/ # PyPI (prefixed with pypi_)
── src/
── main.rs
Why use local:
- Different projects can use different versions
- Clean separation per project
- Easy to delete with project
Global Packages
System-wide (installed with -g flag):
~/.horus/
── cache/
── pid-controller@1.0.0/ # HORUS registry
── serde@1.0.200/ # crates.io
── pypi_numpy@1.24.0/ # PyPI packages
── git_abc123/ # Git dependencies
Naming conventions by source:
| Source | Directory Format | Example |
|---|---|---|
| HORUS Registry | <name>@<version>/ | pid-controller@1.0.0/ |
| crates.io | <name>@<version>/ | serde@1.0.200/ |
| PyPI | pypi_<name>@<version>/ | pypi_numpy@1.24.0/ |
| Git | git_<hash>/ | git_abc123def/ |
Why use global:
- Share common packages across all projects
- Save disk space (one copy for everything)
- Faster install after first download
Priority Order & Smart Dependency Resolution
When resolving packages, HORUS checks in this order:
1. Project-local .horus/packages/ (highest priority)
- Checked first, ALWAYS wins
- Can be symlink to global OR real directory
- Enables local override of broken global packages
2. Global cache ~/.horus/cache/
- Only checked if not found locally
- Shared across all projects
- Version-specific directories (e.g.,
serde@1.0.228/)
3. System install /usr/local/lib/horus/ (if available)
- Last resort fallback
Smart Dependency Resolution:
When you run horus add, HORUS auto-detects the source and writes to horus.toml:
# Add a dependency (auto-detects source)
horus add serde # Rust project → crates.io
horus add numpy # Python project → PyPI
horus add pid-controller # → horus registry
# Dependencies are fetched on next horus build/run
Local Package Cache:
Project dependencies installed from the horus registry are cached in .horus/packages/ with symlinks to the global cache (~/.horus/cache/) for disk efficiency. Local copies always take precedence over global ones.
Benefits:
- Local override - Bypass broken global packages
- Version isolation - Different projects can use different versions
- Disk efficient - Shares global cache when possible
- Zero config - Works automatically
Commit horus.lock to git so teammates get identical dependency versions with horus build.
Package Commands
horus add
Add a project dependency to horus.toml. Auto-detects the source (crates.io, PyPI, horus registry) from your project language. Like cargo add.
Usage:
horus add <package[@version]> [OPTIONS]
Options:
-s, --source <SOURCE>- Override source:crates-io,pypi,system,registry,git,path-F, --features <FEATURES>- Enable features (comma-separated)--dev- Add to[dev-dependencies]--driver- Add to[hardware]
Examples:
# Auto-detected source based on project language
horus add serde # Rust project → crates.io
horus add numpy # Python project → PyPI
horus add pid-controller # → horus registry
# With version and features
horus add serde@1.0 --features derive
horus add tokio --features full
# Explicit source override
horus add opencv --source system
# Dev dependencies
horus add criterion --dev
# Drivers
horus add camera --driver
horus install
Install a standalone package or plugin globally. Like cargo install — does NOT modify horus.toml.
Usage:
horus install <package[@version]> [OPTIONS]
Options:
--plugin- Install as CLI plugin-t, --target <NAME>- Target workspace/project name
Examples:
# Install standalone tool/plugin
horus install horus-sim3d
horus install rplidar-driver@1.2.0
horus install horus-visualizer --plugin
Installing from crates.io
When installing Rust packages from crates.io, HORUS uses cargo install under the hood:
horus install ripgrep
Output:
Installing ripgrep from crates.io...
Compiling ripgrep...
Installing with cargo...
Package installed: ripgrep@14.0.0
Location: ~/.horus/cache/ripgrep@14.0.0/
Requirements:
- Rust toolchain must be installed (
rustup) cargomust be available in PATH
Adding PyPI Dependencies
Add Python packages as project dependencies with horus add:
horus add numpy
horus add opencv-python
This writes to horus.toml [dependencies] with source = "pypi". The package is installed via pip on the next horus build or horus run.
Requirements:
- Python 3.x must be installed
pipmust be available in PATH
When using horus run, Python package paths are automatically configured — no manual sys.path needed.
HORUS Registry Output:
Installing pid-controller@1.2.0...
Downloaded (245 KB)
Extracted to .horus/packages/pid-controller@1.2.0/
Installed dependencies: control-utils@1.0.0
Build successful
Package installed: pid-controller@1.2.0
Location: .horus/packages/pid-controller@1.2.0/
Usage:
use pid_controller::PIDNode;
horus remove
Uninstall a package.
Usage:
horus remove <package>
Options:
-g, --global- Remove from global cache-t, --target <NAME>- Target workspace/project name
Examples:
# Remove local package
horus remove motion-planner
# Remove from global cache
horus remove common-utils -g
# Remove from specific workspace
horus remove pid-controller -t my-project
Output:
Removing pid-controller@1.2.0...
Removed from .horus/packages/
Freed 892 KB
Package removed: pid-controller@1.2.0
horus list
List installed packages or search the registry.
Usage:
horus list [QUERY] [OPTIONS]
Options:
-g, --global- List global cache packages-a, --all- List all (local + global)
List Local Packages:
horus list
Output:
Local packages:
pid-controller 1.2.0
motion-planner 2.0.1
sensor-drivers 1.5.0
List Global Cache:
horus list -g
Search Registry:
# Search by keyword
horus list sensor
Output:
Found 3 package(s):
sensor-fusion 2.1.0 - Kalman filter fusion
sensor-drivers 1.5.0 - LIDAR/IMU/camera drivers
sensor-calibration 1.0.0 - Calibration tools
horus update
Update installed packages to their latest versions.
Usage:
horus update [PACKAGE] [OPTIONS]
Options:
-g, --global- Update global cache packages--dry-run- Show what would be updated without making changes
Examples:
# Update all local packages
horus update
# Update a specific package
horus update pid-controller
# Update global packages
horus update -g
# Preview updates without applying
horus update --dry-run
horus search
Search the registry for packages.
Usage:
horus search <query> [OPTIONS]
Options:
--category <CATEGORY>- Filter by category (driver, algorithm, plugin, tool)
Examples:
horus search slam
horus search lidar --category driver
Dependency Management
Version Constraints
horus add pid-controller@1.2.0 # Exact version
horus add motion-planner@^2.0 # Compatible (2.x.x, not 3.0.0)
horus add sensor-drivers@~1.5.0 # Patch updates (1.5.x)
Automatic Resolution
HORUS automatically resolves and installs transitive dependencies:
horus add robot-controller
Resolving dependencies...
robot-controller@1.0.0
├── motion-planner@2.0.1
│ └── pathfinding-utils@1.2.0
└── pid-controller@1.2.0
└── control-utils@1.0.0
Installing 5 packages...
✓ All dependencies installed
Specifying Dependencies
Use horus add for all dependency sources:
# HORUS registry
horus add pid-controller
horus add motion-planner
# crates.io
horus add serde --source crates-io
# PyPI
horus add numpy --source pypi
# System library
horus add opencv --source system
See Configuration Reference for details on horus.toml dependency syntax.
Common Workflows
Using Multiple Packages
# Add dependencies
horus add pid-controller
horus add motion-planner
horus add sensor-fusion
use pid_controller::PIDController;
use motion_planner::AStarPlanner;
use sensor_fusion::KalmanFilter;
use horus::prelude::*;
fn main() -> Result<()> {
let mut scheduler = Scheduler::new();
// Combine multiple packages into your system
Ok(())
}
Updating Dependencies
# Update all packages to latest versions
horus update
# Update a specific package
horus update pid-controller
# Preview updates without applying
horus update --dry-run
Publishing
To publish packages to the HORUS registry, see the Registry Author Guide on the registry website. It covers:
- Authentication (
horus auth login) - Publishing workflow (
horus publish) - CI/CD integration (GitHub Actions, GitLab CI)
- Package versioning and lifecycle (
yank,deprecate,owner) - API key management
Quick start:
horus auth login # One-time GitHub OAuth
cd my-package
horus publish # Publish to registry
Troubleshooting
Package Not Found
Error: Package 'nonexistent-package' not found in registry
# Check spelling / search for the correct name
horus search sensor
Version Conflict
Error: Version conflict
robot-controller requires motion-planner ^2.0
sensor-fusion requires motion-planner ^1.5
# Update the conflicting package to a compatible version
horus add sensor-fusion@2.0.0
Build Failures
# Clean and retry
horus remove my-package
horus add my-package
# Check the registry for known issues
horus info my-package
Registry Unavailable
# Use cached packages for offline development
horus list -g
# Check connectivity
horus doctor
Next Steps
- Using Prebuilt Nodes — Install and use community packages
- Configuration — horus.toml dependency syntax
- Lockfile — Reproducible builds with horus.lock
- CLI Reference — Complete command documentation
- Registry Guide — Publishing packages to the registry
See Also
- horus.toml — Project manifest
- Lockfile — Reproducible builds
- CLI Reference —
horus add,horus install