Configuration Reference

Complete guide to configuring HORUS projects via horus.toml and understanding the auto-managed .horus/ directory.

Quick Reference

Minimal horus.toml:

[package]
name = "my_robot"
version = "0.1.0"

Full horus.toml:

[package]
name = "my_robot_controller"
version = "1.2.3"
description = "Advanced mobile robot controller with navigation"
authors = ["Robotics Team <team@example.com>"]
license = "Apache-2.0"
edition = "1"
repository = "https://github.com/team/my-robot-controller"
package-type = "app"
categories = ["control", "navigation"]

[drivers]
camera = "opencv"
lidar = true

enable = ["cuda", "editor"]

[ignore]
files = ["debug_*.rs", "**/temp/**"]
directories = ["experiments/", "old/"]
packages = ["ipython"]

Project Metadata

All project metadata fields live under the [package] table. horus.toml is a config-only manifest -- it does not contain dependencies or language settings. Dependencies live in native build files (Cargo.toml for Rust, pyproject.toml for Python), and language is auto-detected from which build files exist.

name (Required)

Project name used for identification and package management.

Type: String Required: Yes Constraints:

  • Must be unique within your organization
  • Use lowercase with hyphens (kebab-case)
  • No spaces or special characters except hyphens and underscores

Examples:

[package]
name = "temperature-monitor"
# or
name = "mobile_robot_controller"
# or
name = "warehouse-navigation"

version (Required)

Project version following semantic versioning.

Type: String Required: Yes Format: MAJOR.MINOR.PATCH (semantic versioning)

Examples:

[package]
version = "0.1.0"    # Initial development
# or
version = "1.0.0"    # First stable release
# or
version = "2.3.1"    # Mature project

edition (Optional)

Manifest schema version. Controls which fields and features are available in horus.toml.

Type: String Required: No Default: "1"

Examples:

[package]
edition = "1"

description (Optional)

Human-readable description of your project.

Type: String Required: No Default: None

Examples:

[package]
description = "Temperature monitoring system with alerts"
# or
description = "Autonomous mobile robot for warehouse operations"

authors (Optional)

Project authors list.

Type: Array of strings Required: No Default: None

Examples:

[package]
authors = ["Robotics Team <team@example.com>"]
# or
authors = ["John Doe <john@example.com>", "Jane Smith <jane@example.com>"]

license (Optional)

Project license identifier.

Type: String Required: No Default: None Common Values: Apache-2.0, MIT, GPL-3.0, BSD-3-Clause

Examples:

[package]
license = "Apache-2.0"
# or
license = "MIT"
# or
license = "Proprietary"

repository (Optional)

URL to the project's source repository.

Type: String Required: No Default: None

Examples:

[package]
repository = "https://github.com/team/my-robot"

package-type (Optional)

Classification of the package for registry discovery.

Type: String Required: No Default: None Values: node, driver, tool, algorithm, model, message, app

Examples:

[package]
package-type = "app"
# or
package-type = "node"
# or
package-type = "driver"

categories (Optional)

Categories for package discovery in the registry.

Type: Array of strings Required: No Default: None

Examples:

[package]
categories = ["control", "navigation", "perception"]

Language Auto-Detection

HORUS automatically detects the project language from native build files present in the project directory:

Build FileDetected Language
Cargo.tomlRust
pyproject.tomlPython

No language field is needed in horus.toml. When you run horus new, both horus.toml and the appropriate native build file (Cargo.toml or pyproject.toml) are created.

Dependencies

Dependencies are managed through native build files, not through horus.toml:

LanguageBuild FileAdd Dependencies With
RustCargo.tomlhorus add <crate> (delegates to cargo add)
Pythonpyproject.tomlhorus add <package> (delegates to pip install)

HORUS registry packages are also added with horus add, which updates the appropriate native build file.

Rust Dependencies (Cargo.toml)

For Rust projects, dependencies live in Cargo.toml alongside your horus.toml:

# Cargo.toml (managed by cargo / horus add)
[package]
name = "my-robot"
version = "0.1.0"
edition = "2021"

[dependencies]
horus = { path = "..." }
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }

Adding dependencies:

# Add a crate (delegates to cargo add)
horus add serde --features derive
horus add tokio --features full

# Add from HORUS registry
horus add pid-controller

# Add with specific version
horus add serde@1.0.200

Python Dependencies (pyproject.toml)

For Python projects, dependencies live in pyproject.toml:

# pyproject.toml
[project]
name = "my-robot"
version = "0.1.0"
dependencies = [
    "horus-robotics",
    "numpy>=1.24",
    "opencv-python>=4.8",
]

Adding dependencies:

# Add a package (delegates to pip install)
horus add numpy
horus add opencv-python

# Add from HORUS registry
horus add pid-controller

HORUS Registry Packages

HORUS registry packages (horus add <name>) are added to the appropriate native build file based on the detected project language.

# Install from HORUS registry
horus add pid-controller
horus add sensor-fusion
horus add motion-planner

Ignore Patterns

ignore (Optional)

Exclude files and directories from HORUS processing.

Type: Table with optional files and directories arrays Required: No Default: None

ignore.files

Exclude specific files from detection and execution.

Type: Array of glob patterns Patterns: * (wildcard), **/ (recursive directories)

Examples:

[ignore]
files = [
  "debug_*.py",          # Ignore debug_test.py, debug_node.py
  "test_*.rs",           # Ignore all test files
  "**/experiments/**",   # Ignore files in any experiments/ directory
  "scratch.rs",          # Ignore specific file
]

ignore.directories

Exclude entire directories.

Type: Array of directory names or paths

Examples:

[ignore]
directories = ["old/", "experiments/", "tests/", "benchmarks/"]

ignore.packages

Skip specific packages during auto-install.

Type: Array of package name strings

Examples:

[ignore]
packages = ["ipython", "debugpy"]

Complete Ignore Example

[package]
name = "robot_controller"
version = "0.1.0"

[ignore]
# Don't run debug files
files = ["debug_*.py", "test_*.rs", "**/temp/**"]

# Don't process these directories
directories = ["old_controllers/", "experiments/", "docs/"]

Feature Flags

enable (Optional)

Enable optional feature flags for your project.

Type: Array of strings (at the top level, outside any table)

Examples:

enable = ["cuda", "editor"]

Hooks

[hooks] (Optional)

Declare commands that run automatically before or after horus run, horus build, and horus test. Eliminates manual horus fmt && horus lint && horus run pipelines.

Fields:

FieldTypeDescription
pre_runstring[]Run before horus run
pre_buildstring[]Run before horus build
pre_teststring[]Run before horus test
post_teststring[]Run after horus test

Built-in hook names: fmt, lint, check. Any other name is looked up in [scripts].

Example:

[hooks]
pre_run = ["fmt", "lint"]       # Auto-format and lint before every run
pre_test = ["lint"]             # Lint before testing
post_test = ["clean --shm"]    # Clean shared memory after tests (if defined in [scripts])

Skipping hooks:

horus run --no-hooks      # Skip all hooks for this run
horus test --no-hooks     # Skip hooks for this test

How it works: When you run horus run, the scheduler checks [hooks].pre_run. For each entry, it calls the corresponding command function (fmthorus fmt, linthorus lint). If any hook fails, the run is aborted. Use --no-hooks to bypass when debugging.


Driver Configuration

[drivers] (Optional)

Configure hardware drivers. Three forms supported:

Simple — enable a driver or specify a backend (feature flags only):

[drivers]
camera = "opencv"
lidar = true

Terra — connect to hardware via the Terra HAL. Auto-adds the correct Terra crate to your build:

[drivers.arm]
terra = "dynamixel"
port = "/dev/ttyUSB0"
baudrate = 1000000
servo_ids = [1, 2, 3, 4, 5, 6]

[drivers.lidar]
terra = "rplidar"
port = "/dev/ttyUSB1"

[drivers.imu]
terra = "bno055"
bus = "i2c-1"
address = 0x28

Registry package — use a community or vendor driver package:

[drivers.force_sensor]
package = "horus-driver-ati-netft"
address = "192.168.1.100"
filter_hz = 500

Local code — reference your own driver registered via register_driver!:

[drivers.conveyor]
node = "ConveyorDriver"
port = "/dev/ttyACM0"
baudrate = 57600

All forms can be mixed in the same file. The terra, package, and node keys determine the driver source. All other keys become params passed to the driver at runtime.

Supported Terra drivers:

NameCrateHardware
dynamixelterra-serialDynamixel servos
rplidarterra-serialSLAMTEC RPLiDAR
vescterra-serialVESC motor controllers
modbusterra-serialModbus RTU devices
realsenseterra-realsenseIntel RealSense cameras
webcamterra-webcamV4L2 cameras
velodyne, ouster, livoxterra-lidar3D LiDAR
mpu6050, bno055terra-embeddedI2C IMU sensors
odrive, canopenterra-canCAN bus devices
ethercatterra-ethercatEtherCAT servos/PLCs
i2c, spi, serial, can, gpio, pwmterra-Raw bus access
virtualterra-virtualMock devices for testing

See the Driver API reference for the runtime API.

The .horus/ Directory

The .horus/ directory is automatically managed by HORUS. You should never manually edit files inside it.

Structure

my_project/
├── horus.toml              # Project config (edit this)
├── Cargo.toml              # Rust dependencies (edit this)
├── main.rs                 # Your code (edit this)
└── .horus/                 # Build cache (don't touch)
    ├── target/             # Build artifacts
    └── packages/           # Cached registry packages

For Python projects:

my_project/
├── horus.toml              # Project config (edit this)
├── pyproject.toml          # Python dependencies (edit this)
├── main.py                 # Your code (edit this)
└── .horus/                 # Build cache (don't touch)
    └── packages/           # Cached registry packages

What's Inside .horus/

.horus/ is a build cache only:

target/ (Rust projects):

  • Cargo build artifacts
  • Can be large (ignore in git)

packages/:

  • Cached HORUS registry packages
  • Symlinks to global cache when possible

Git Configuration

Always add to .gitignore:

# HORUS build cache
.horus/

The horus new command automatically creates this .gitignore for you.

When .horus/ is Created

.horus/ is created automatically when you run:

  • horus run
  • horus install
  • horus build

You never need to create it manually.

Cleaning .horus/

Remove local environment:

rm -rf .horus/

Regenerate on next run:

horus run  # Automatically recreates .horus/

Complete Examples

Rust Application

horus.toml:

[package]
name = "temperature-monitor"
version = "0.1.0"
description = "Simple temperature monitoring system"
authors = ["Robotics Team"]
license = "Apache-2.0"

[ignore]
files = ["debug_*.rs"]

Cargo.toml (alongside horus.toml):

[package]
name = "temperature-monitor"
version = "0.1.0"
edition = "2021"

[dependencies]
horus = { path = "..." }
serde = { version = "1", features = ["derive"] }

Rust Application with Drivers

horus.toml:

[package]
name = "robot-backend"
version = "1.0.0"
description = "Robot control backend with sensor processing"
authors = ["ACME Robotics"]
license = "Apache-2.0"

[drivers]
camera = "opencv"
lidar = true

enable = ["cuda"]

[ignore]
directories = ["tests/"]

Cargo.toml:

[package]
name = "robot-backend"
version = "1.0.0"
edition = "2021"

[dependencies]
horus = { path = "..." }
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }

[dev-dependencies]
criterion = "0.5"

Note: HORUS uses a flat namespace (like ROS), so multiple processes automatically share topics when using the same topic names. No configuration needed!

Python Application

horus.toml:

[package]
name = "vision-processor"
version = "0.2.0"
description = "Computer vision processing node"
authors = ["Vision Team"]
license = "MIT"

[ignore]
directories = ["notebooks/", "experiments/"]

pyproject.toml (alongside horus.toml):

[project]
name = "vision-processor"
version = "0.2.0"
dependencies = [
    "horus-robotics",
    "numpy>=1.24",
    "opencv-python>=4.8",
    "pillow",
]

Best Practices

Version Your Configuration

Always commit horus.toml and your native build file to version control:

git add horus.toml Cargo.toml   # Rust project
git add horus.toml pyproject.toml  # Python project

Use Semantic Versioning

Follow semver for your project version:

  • 0.x.y - Initial development
  • 1.0.0 - First stable release
  • x.y.z - Major.Minor.Patch

Keep horus.toml Minimal

horus.toml is config only. Dependencies go in native build files:

# Good (minimal horus.toml)
[package]
name = "my_robot"
version = "0.1.0"

Add optional fields only when needed:

# With optional metadata
[package]
name = "my_robot"
version = "0.1.0"
description = "A temperature monitoring robot"
authors = ["Team"]
license = "MIT"

Validation

HORUS validates horus.toml on every command. Common errors:

Missing Required Fields

Error: Missing required field 'name' in horus.toml

Fix: Add name and version fields under [package].

Invalid TOML Syntax

Error: Failed to parse horus.toml: invalid TOML syntax at line 5

Fix: Check TOML syntax (key-value pairs use =, strings must be quoted, tables use [brackets]).

Invalid Version Format

Error: Invalid version format: '1.0'. Expected semantic version (e.g., '1.0.0')

Fix: Use format "MAJOR.MINOR.PATCH".

Next Steps