Native Tool Integration

You want to use cargo, pip, and cmake the way you always have, but inside a HORUS project where horus.toml is the source of truth. HORUS transparently proxies these tools so commands are routed through the build pipeline: native build files are generated from horus.toml, the real tool runs against those files, and dependency changes sync back to horus.toml. Outside a HORUS project, the tools behave exactly as they normally would.

When To Use This

  • Using cargo add, cargo build, cargo test inside a HORUS project
  • Using pip install to add Python dependencies that sync to horus.toml
  • Using cmake for C++ components that integrate with the HORUS build
  • Working with third-party cargo subcommands (cargo audit, cargo nextest, cargo llvm-cov)

Use horus add instead if you prefer the HORUS-native command for adding dependencies directly.

Use the bypass (HORUS_NO_PROXY=1 cargo build) instead if you need to run the real tool without HORUS interception.

Prerequisites

  • HORUS installed (the installer sets up proxies automatically)
  • A project with horus.toml in the directory tree

How It Works

When you run a proxied command, here is what happens under the hood:

  1. You type a command — for example, cargo build.
  2. Shell function intercepts it — the HORUS installer adds thin shell functions that shadow the real cargo, pip, and cmake binaries.
  3. Project detection — the shell function calls horus _is-project to check whether the current directory (or any parent) contains a horus.toml.
  4. Delegation — if a HORUS project is detected, the command is delegated to horus cargo build (or horus pip ..., horus cmake ...).
  5. Build file generation — the proxy generates .horus/Cargo.toml (or .horus/pyproject.toml, .horus/CMakeLists.txt) from horus.toml.
  6. Real tool execution — the real cargo runs with --manifest-path .horus/Cargo.toml, pointing it at the generated build file.
  7. Sync back — if the command modified dependencies (e.g., cargo add serde), the proxy detects the change and syncs it back to horus.toml.

If no HORUS project is detected in step 3, the shell function passes the command straight to the real binary with no interception.

┌──────────────┐     ┌────────────────┐     ┌──────────────────┐
│  cargo build │────▶│ shell function │────▶│ horus _is-project│
└──────────────┘     └────────────────┘     └──────────────────┘
                                                     │
                              ┌───────────────────────┤
                              ▼                       ▼
                     ┌────────────────┐     ┌────────────────┐
                     │ horus project  │     │ not a project  │
                     │ horus cargo ..│     │ real cargo     │
                     └────────────────┘     └────────────────┘
                              │
                              ▼
                     ┌────────────────┐
                     │ generate       │
                     │ .horus/        │
                     │ Cargo.toml     │
                     └────────────────┘
                              │
                              ▼
                     ┌────────────────┐
                     │ run real cargo │
                     │ --manifest-path│
                     │ .horus/...     │
                     └────────────────┘
                              │
                              ▼
                     ┌────────────────┐
                     │ sync changes   │
                     │ back to        │
                     │ horus.toml     │
                     └────────────────┘

Setup

The HORUS installer sets up native tool proxying automatically. After installing HORUS, open a new terminal and verify:

type cargo
# Should show: cargo is a function

If you see cargo is a function, the proxy is active.

Manual Setup

If you installed HORUS without the installer, or need to re-initialize:

# Write shell environment and register proxies
horus env --init

This does two things:

  1. Writes ~/.horus/env.sh containing the shell functions for cargo, pip, and cmake.
  2. Adds a source ~/.horus/env.sh line to your ~/.bashrc and/or ~/.zshrc.

Restart your shell (or source ~/.horus/env.sh) to activate.

Removing Proxies

To uninstall the shell proxies and restore the original tool behavior:

horus env --uninstall

This removes the source line from your shell config and deletes ~/.horus/env.sh. The original cargo, pip, and cmake binaries are untouched.


Cargo

All standard cargo commands work transparently inside a HORUS project:

# Building
cargo build                # builds from .horus/Cargo.toml
cargo build --release      # release build
cargo build -p member      # workspace member selection

# Dependencies
cargo add serde            # adds to .horus/Cargo.toml, syncs to horus.toml
cargo add tokio -F full    # features work too
cargo remove serde         # removes from both

# Testing and quality
cargo test                 # runs tests
cargo clippy               # linting
cargo fmt                  # formatting
cargo bench                # benchmarks

# Documentation
cargo doc                  # generate docs
cargo doc --open           # generate and open in browser

# Third-party subcommands
cargo audit                # security audit (if installed)
cargo nextest run          # alternative test runner
cargo llvm-cov             # code coverage

Workspace Members

If your horus.toml defines workspace members, the -p flag works as expected:

cargo build -p my_driver   # build only the driver crate
cargo test -p my_algorithm # test only the algorithm crate

Pip

Python dependency management syncs bidirectionally with horus.toml:

# Installing packages
pip install numpy          # installs + syncs to horus.toml [dependencies]
pip install "requests>=2"  # version constraints preserved
pip install -e .           # editable install (rewrites paths to .horus/)

# Removing packages
pip uninstall numpy        # removes package + syncs removal from horus.toml

# Read-only commands (no sync needed)
pip list                   # pass-through, no sync
pip freeze                 # pass-through
pip show numpy             # pass-through

Editable Installs

When you run pip install -e ., the proxy rewrites the path to point at .horus/pyproject.toml so the editable install references the correct generated build file.


CMake

CMake integration rewrites build paths to keep generated files inside .horus/:

# Configure — source dir is rewritten to .horus/
cmake .                    # configures with -B .horus/cpp-build

# Build
cmake --build .horus/cpp-build

# Install
cmake --install .horus/cpp-build

# Common options pass through
cmake . -DCMAKE_BUILD_TYPE=Release
cmake . -G Ninja

The proxy ensures that CMakeLists.txt in .horus/ is generated from the [cmake] section of your horus.toml before running the real cmake.


How Sync Works

The proxy uses fingerprinting to detect and merge changes between horus.toml and native build files.

Fingerprinting

Each time the proxy generates a .horus/Cargo.toml (or other native file), it computes a SHA-256 hash of the generated content and stores it in .horus/.fingerprints. On the next invocation, it compares:

  • Current horus.toml against the last-generated fingerprint.
  • Current native file against the last-generated fingerprint.

Detecting External Changes

If the native file changed but horus.toml did not, the proxy knows the native tool modified the file (e.g., cargo add wrote to .horus/Cargo.toml). It parses the diff and applies matching changes to horus.toml.

If horus.toml changed but the native file did not, the proxy regenerates the native file from horus.toml.

If both changed, horus.toml wins and the native file is regenerated.

Internal Dependencies

Dependencies on HORUS workspace crates (horus_core, horus_library, horus_macros, etc.) are never synced back to horus.toml. These are injected by the build pipeline based on your project configuration and should not appear in user-facing dependency lists.


Bypassing the Proxy

If you ever need to run the real tool directly, bypassing the HORUS proxy:

# Use the full path
/usr/bin/cargo build
$(which -a cargo | tail -1) build

# Or use command to skip the shell function
command cargo build

# Or temporarily disable
HORUS_NO_PROXY=1 cargo build

Common Errors

SymptomCauseFix
cargo not being proxied (type cargo shows binary path)Shell proxy not installed or sourcedRun horus env --init then source ~/.horus/env.sh
cargo add does not update horus.tomlFingerprint state out of syncRun horus build to force regeneration and sync
Native file conflicts with horus.tomlBoth files modified independentlyhorus.toml always wins; run horus build to regenerate .horus/ files
Proxy not detecting HORUS projectNo horus.toml in current or parent directoriesVerify with horus _is-project, ensure horus.toml exists in project root
pip install not syncing to horus.tomlRead-only pip commands (list, freeze, show) do not trigger syncOnly install/uninstall commands trigger sync; verify with horus param list

The rule is simple: horus.toml always wins. If there is a conflict between horus.toml and the generated .horus/ build files, the native files are regenerated from horus.toml and conflicting native-side changes are discarded.


See Also