# Embed holger in your own process — guide
> **Class:** `guide` · **Function:** `embed`. Architecture: [`embed-design.md`](embed-design.md).
> You don't have to run holger as a server — link `holger-server-lib`, parse (or generate)
> a RON config, and drive it through the `Holger` functional API. No gRPC, no socket. This
> is exactly what nornir's `embed-holger` feature does.
## Generate the dev-pair config and wire it
```rust
use holger_server_lib::{read_ron_config, wire_holger, Holger};
use holger_server_lib::dev_pair_ron; // re-exported from lib root
use std::path::Path;
// One writable cache mirror (/cache) + one rehearsal registry (/sparring),
// both backed by on-disk .znippy archives under `data_dir`.
let ron = dev_pair_ron(Path::new("/tmp/holger-dev"), "127.0.0.1:50051", "127.0.0.1:8080");
std::fs::write("/tmp/holger-dev/holger.ron", &ron)?;
let mut holger: Holger = read_ron_config("/tmp/holger-dev/holger.ron")?;
wire_holger(&mut holger)?; // resolves the repo→endpoint→storage graph
```
## Drive it directly — no network
```rust
use holger_server_lib::ArtifactId; // re-exported for in-process consumers
// names of the configured repos: ["crates-io", "cache", "sparring"]
for name in holger.list_repositories() { println!("repo: {name}"); }
// store + fetch bytes through a writable repo's backend
let id = ArtifactId { namespace: None, name: "serde".into(), version: "1.0.0".into() };
holger.put("sparring", &id, b"...crate bytes...")?;
let bytes = holger.fetch("sparring", &id)?; // Some(...) — read-only repos error on put
```
## Enumerate a repo's contents (the viz-pane path)
`fetch`/`put` are by-id. To *list* what's in a repo, reach the backend directly — it's an
`Arc<dyn RepositoryBackendTrait>`, and the trait + entry types are re-exported so you need no
separate `holger-traits` dep:
```rust
use holger_server_lib::{RepositoryBackendTrait, ArtifactEntry};
for repo in &holger.repositories {
if let Some(backend) = &repo.backend_repository {
let entries: Vec<ArtifactEntry> = backend.list(None, 100)?; // crates in the .znippy
let files: Vec<String> = backend.archive_files(None)?; // raw archive paths
// ...
}
}
```
> Writable-repo gotcha (fixed in `8c9e458`): `list`/`archive_files` now read via
> `open_reader()`, so a **writable** dev-mode repo (`/cache`, `/sparring`) enumerates its
> on-disk crates. If you fork an older holger, port that fix or your dev-pair will look empty.
## When to embed vs run a server
Embed when the consumer *is* the security boundary (a single process that wants a registry
without a socket) — the host owns auth/transport. Run `holger-server` when independent
clients over the network must reach it. The embedded path adds no egress of its own unless
the embedded config wires a writable+upstream repo (the dev-pair `/cache` deliberately does,
for the dev-mirror use case).