# How Herdr Built-In Agent Integrations Report State

> Learn how Herdr built-in agent integrations report state by checking versioned installation files and comparing against compiled constants for Current, Outdated, or NotInstalled status.

- Repository: [Can Celik/herdr](https://github.com/ogulcancelik/herdr)
- Tags: internals
- Published: 2026-05-31

---

**TLDR:** Herdr built-in agent integrations report state by checking for versioned installation files at well-known paths, parsing the `HERDR_INTEGRATION_VERSION` marker, and comparing it against compiled constants to determine if the integration is Current, Outdated, or NotInstalled.

Herdr is an open-source tool that manages AI agent workflows by installing hooks for popular coding assistants like Claude, Codex, and Pi. Understanding how Herdr built-in agent integrations report state is essential for developers building custom UIs or diagnosing installation issues. The system uses a file-based versioning approach defined in [`src/integration/mod.rs`](https://github.com/ogulcancelik/herdr/blob/main/src/integration/mod.rs) to track the health of every supported agent.

## The State Reporting Pipeline

Herdr determines the state of each built-in integration—Pi, Omp, Claude, Codex, Opencode, Hermes, and Qodercli—through a deterministic three-step process.

### Locating Installation Files

Each integration has a well-known path generated by `integration_specs()`. For example, the Claude integration expects its state file at `~/.config/claude/hooks/herdr-agent-state.sh`. The function `integration_status_at` ([`src/integration/mod.rs`](https://github.com/ogulcancelik/herdr/blob/main/src/integration/mod.rs#L106)‑L138) performs the actual filesystem check to verify the file exists.

### Parsing Version Markers

When the installation file exists, Herdr reads its contents to locate the line starting with `HERDR_INTEGRATION_VERSION=`. The helper `parse_integration_version` ([`src/integration/mod.rs`](https://github.com/ogulcancelik/herdr/blob/main/src/integration/mod.rs#L39)‑L52) extracts the numeric version from this marker.

### Determining Integration Status

Each integration defines a constant such as `PI_INTEGRATION_VERSION = 2`. The logic compares the installed version against the expected version:

- If installed version ≥ expected: **Current**
- If installed version < expected: **Outdated**  
- If file missing: **NotInstalled**

## The IntegrationStatus Data Structure

The result is encapsulated in the `IntegrationStatus` struct defined in [`src/integration/mod.rs`](https://github.com/ogulcancelik/herdr/blob/main/src/integration/mod.rs) (lines 87‑94):

```rust
pub(crate) struct IntegrationStatus {
    pub target: crate::api::schema::IntegrationTarget,
    pub path: PathBuf,
    pub state: IntegrationStatusKind,
    pub installed_version: Option<u32>,
    pub expected_version: u32,
}

```

This structure provides a type-safe representation of the integration's health, including the target agent, filesystem path, and version metadata.

## Programmatically Querying Integration State

The `ogulcancelik/herdr` repository exposes several helper functions to access these statuses in Rust code.

### Retrieving All Integration Statuses

To fetch a vector containing the current status for every built-in integration:

```rust
use crate::integration;

let statuses = integration::installed_integration_statuses();

for status in statuses {
    println!(
        "{} → {} (installed: {:?}, expected: {})",
        status.target,
        status.state_label(),
        status.installed_version,
        status.expected_version
    );
}

```

### Generating UI Recommendations

For CLI or TUI applications that need user-friendly labels and availability information:

```rust
use crate::integration;

let recommendations = integration::integration_recommendations();

for rec in recommendations {
    println!(
        "{} [{}] – {}",
        rec.label,
        rec.path.display(),
        rec.status_label()
    );
}

```

### Checking a Single Agent Integration

To manually verify the state of a specific agent like Claude:

```rust
use crate::integration;
use crate::api::schema::IntegrationTarget;

let path = integration::claude_dir()
    .unwrap()
    .join("hooks")
    .join(integration::CLAUDE_HOOK_INSTALL_NAME);

let status = integration::integration_status_at(
    IntegrationTarget::Claude,
    path,
    integration::CLAUDE_INTEGRATION_VERSION,
);

println!("Claude integration is {:?}", status.state);

```

## Core Implementation Files

The state reporting logic spans several key files in the repository:

| File | Purpose |
|------|---------|
| [`src/integration/mod.rs`](https://github.com/ogulcancelik/herdr/blob/main/src/integration/mod.rs) | Core logic for locating, installing, and reporting the state of agent integrations. Contains `integration_status_at`, `parse_integration_version`, and the `IntegrationStatus` struct. |
| [`src/api/schema.rs`](https://github.com/ogulcancelik/herdr/blob/main/src/api/schema.rs) | Defines the `IntegrationTarget` enum used to identify each built-in integration. |
| `src/integration/assets/*` | Sample integration assets containing the `HERDR_INTEGRATION_VERSION=` marker parsed at runtime. |

## Summary

- Herdr built-in agent integrations report state through versioned files at well-known paths like `~/.config/claude/hooks/herdr-agent-state.sh`.
- The `integration_status_at` function checks file existence and parses the `HERDR_INTEGRATION_VERSION` marker to determine if the state is Current, Outdated, or NotInstalled.
- Version constants such as `PI_INTEGRATION_VERSION` define the minimum required version for each integration.
- The `IntegrationStatus` struct encapsulates the target agent, path, state, and version metadata for type-safe access.
- Helper functions `installed_integration_statuses()` and `integration_recommendations()` provide high-level APIs for consumption by the CLI and TUI.

## Frequently Asked Questions

### How does Herdr determine if an agent integration is outdated?

Herdr compares the numeric version parsed from the `HERDR_INTEGRATION_VERSION` line in the installation file against a compiled constant (e.g., `CLAUDE_INTEGRATION_VERSION`). If the installed version is less than the expected version, the integration is marked as **Outdated**; if greater or equal, it is **Current**.

### Where are Herdr integration state files stored?

Each integration follows a well-known path generated by `integration_specs()`. For example, Claude integrations reside at `~/.config/claude/hooks/herdr-agent-state.sh`, while other agents use their respective configuration directories under `~/.config/`.

### Can I programmatically check a specific integration's state?

Yes. Use the `integration_status_at` function from [`src/integration/mod.rs`](https://github.com/ogulcancelik/herdr/blob/main/src/integration/mod.rs), providing the `IntegrationTarget`, the specific `PathBuf`, and the expected version constant. This returns an `IntegrationStatus` struct containing the state and version metadata for that specific agent.

### What happens if the integration file does not exist?

If `integration_status_at` cannot locate the file at the expected path, it returns an `IntegrationStatus` with the `state` field set to **NotInstalled** and `installed_version` set to `None`, allowing the UI to prompt for installation.