# Clone dwarves and build it — on a machine that has nothing else
**`git clone dwarves && cargo build` DOES NOT WORK, and it never has.** It does not fail
at link time or on a missing system library — it fails before cargo resolves a single
crate:
```
error: failed to load manifest for workspace member `…/dwarves/crates/dwarves`
Caused by: failed to load manifest for dependency `autonom`
Caused by: failed to read `…/edda/crates/autonom/Cargo.toml`
Caused by: No such file or directory (os error 2)
```
Measured on a fresh clone of `main` 6052d02 (2026-08-07) into an empty directory.
That is not a bug in the clone. dwarves is one repo of a **constellation** that is wired
with `path` dependencies to its siblings, and `path` deps are not optional: cargo reads
every one of them to build the dependency graph. A `path` that is not there is a hard
error, so **the siblings are a build dependency exactly like a crate is** — they are just
not something cargo can fetch for you.
There is no `--offline`, no feature flag and no `[patch]` trick that avoids this. The only
fix is to have the siblings on disk, side by side.
## The layout — this is the whole secret
Every `path` is relative (`../edda/...`, `../facett/...`), so the repos must be **siblings
in ONE parent directory**. The parent's name does not matter; `dwarves` must not be nested
inside another repo.
```
<parent>/
├── dwarves/ ← the one you actually wanted
├── edda/ ← 53 path deps point here (the most load-bearing sibling)
├── facett/ ← 37 path deps (the UI framework)
├── nornir/
├── holger/
├── modgunn/ ← TRANSITIVE: nothing in dwarves names it; holger-server-lib does
├── znippy/
├── znippy-zoomies/
├── skade/
├── draupnir/
├── Skidbladnir/ ← capital S, and the directory name must match
├── tunnr/
└── funnel-core/
```
**Twelve repos, dwarves included.** Verified sufficient: with exactly these,
`cargo metadata` on a fresh `main` clone exits 0. Verified necessary the honest way — by
adding them one at a time and re-reading the error, which is how `modgunn` was found.
## Do it
```sh
mkdir -p ~/git && cd ~/git
git clone git@codeberg.org:nordisk/dwarves.git
git clone git@codeberg.org:nordisk/edda.git
git clone git@codeberg.org:nordisk/facett.git
git clone git@codeberg.org:nordisk/nornir.git
git clone git@codeberg.org:nordisk/holger.git
git clone git@codeberg.org:nordisk/modgunn.git
git clone git@codeberg.org:nordisk/znippy.git
git clone git@codeberg.org:nordisk/znippy-zoomies.git
git clone git@codeberg.org:nordisk/skade.git
git clone git@codeberg.org:nordisk/draupnir.git
git clone git@codeberg.org:nordisk/Skidbladnir.git
git clone git@codeberg.org:nordisk/funnel-core.git
# ⚠ tunnr is NOT under nordisk. It is mikronova, and it is an ssh:// URL.
git clone ssh://git@codeberg.org/mikronova/tunnr.git
```
Then check the wiring BEFORE starting a long build, because this is the step that tells
you a sibling is missing in one second instead of twenty minutes:
```sh
cd dwarves && cargo metadata --format-version 1 >/dev/null && echo "constellation OK"
```
`warning: patch … was not used in the crate graph` on that command is **normal** — the
`[patch.crates-io]` block in `dwarves/Cargo.toml` covers the fat/`holger` build, and a
default build does not resolve all of it. Warnings are not the verdict; the exit code is.
### Two traps that are not about dwarves
* **Do not clone every sibling at a tag or a pinned SHA.** These repos move together, and
the `path` deps mean you compile whatever is checked out — not what `Cargo.lock` says.
Clone the default branch and leave it alone.
* **The canonical branch is not `main` everywhere.** `znippy`'s is `master`. `git clone`
gets this right on its own (it follows `origin/HEAD`); a script that hard-codes
`-b main` gets it wrong. If you need to know, ask the repo, never a document:
`git symbolic-ref refs/remotes/origin/HEAD`.
## Then build
`cargo build` is not the entry point either — what gets built comes from
`.nornir/build-variants.toml`, so the declaration cannot drift from the build:
```sh
cargo xtask build --suite ORIGINAL --list # the five declared variants
cargo xtask build --suite ORIGINAL --variant dwarves-ui
```
(`--atom` is the deprecated spelling of `--variant`; it still works.)
The five variants are `dwarves-server` (the service), `dwarves` (the fat CLI), `dwarves-cli`
(the thin CLI), `dwarves-ui` (the thin desktop UI) and `dwarves-solo` (the UI with the
server compiled in). Pick the one you want; `dwarves-ui` is the desktop app.
Disk: the fat `dwarves-server` artifact alone is ~300 MB and the shared `target/` for the
whole constellation runs to tens of GB. On a laptop, point `CARGO_TARGET_DIR` at a disk
that can take it.
## Robot UI tests are WAYLAND ONLY
Do not reach for `Xvfb`, and do not set `DISPLAY`. The robot-UI drive supports Wayland and
nothing else — see `dwarves-gui/src/robot_mode.rs` and the `nornir-robotui` display
backend. On a Wayland session the visible replay is:
```sh
cargo xtask build --suite ORIGINAL --variant dwarves-ui
dwarves-ui --robot-mode headless # off-screen, no window, exits non-zero on a red step
dwarves-ui --robot-mode watch # a real window, replays the recorded tab tour
```
`--robot-mode headless` needs `--features robot-remote`; `watch` needs `--features watch`.
A binary built without them **refuses the flag and exits 2** rather than opening a plain
GUI window that drives nothing.