Summoning

In plain words: Installation on a Linux host

Partial 14 min read 24 glossary terms 17 connected pages
The short version written for the Snayu team

The intended step-by-step procedure to install LychD on one Linux host with an NVIDIA GPU: build from source, create settings and data folders, bind one local llama.cpp model, start the system and get a first reply.

Why read it: Read this before attempting a real host install or acceptance test; it explains what each step should prove and where the procedure currently stops.
  1. 1Five stages: verify the host, build CLI and server image from one checkout, create Settings and Data Folders, bind a model, start and test.
  2. 2Build localhost/lychd:dev from your checkout; no published CLI/image pair matches the current source.
  3. 3The stop command currently refuses an active server, so you need a separate recovery plan before starting.

Partial Individual steps have evidence, but installation does not yet work end to end.

Words on this page, decoded click one for its card

Apply ConfigCommand Line (C…Installation
Where it sits in LychD

Installation Summoning

Setting up LychD on a real Linux machine and getting its first reply.

It's like: Moving into a new office and switching everything on for the first time.

Click a dot to open that part's card.

The original text Underlined words open their plain-English card.

The CircleTask Bubble is not yet whole

SummoningInstallation does not work end to end yet. This page describes how the rite is intended to work, not a supported installation path. Individual steps have repository evidence, but no maintained real-host receipt proves the complete sequence. Consult the State of Work before attempting it.

A model replying to a prompt is only part of bringing LychD to life. The application must start from the source you built, load the model you declared, retain its committed history, and return the answer through the intended workflow. This rite shows how to check those parts together on one Linux host.

Bring a source checkout, NVIDIA hardware, and a tool-capable GGUF model. You will work as your ordinary user in one shell; later commands reuse the paths and identities established earlier. This is a pre-alpha host acceptance procedure for someone familiar with Linux, TOML, systemd, and containers.

Before starting services, read Close the rite. The public stop command currently refuses an active VesselEngine Room. An acceptance attempt needs a separately authorized recovery plan; this guide does not supply a working end-to-end start/stop procedure.

Draw the Summoning Circle

The five movements establish which source, host, model, configuration, mounts, secrets, and capabilities the trial uses, and where the resulting services can be reached:

  1. The Grounds — establish the host and model.
  2. The Desecration — build the command and VesselEngine Room from one source.
  3. The Inscription — give configuration and durable state their homes.
  4. The First Soulstone — declare and bind the local model service.
  5. The Awakening — start the body and witness its First InvocationJob Request.

LychD calls the recurrent whole the LichAssistant. The model is one of its organs. These commands set up that organ and the services around it; the anatomy explains how memory, policy, authority, and identity contribute to the whole.

Use this revision's body

No published CLI/image pair matches this source revision. Build localhost/lychd:dev from the checkout used for the host command. A package or remote latest image is not a substitute. State of Work records repository evidence. You must still observe whether this combination works on your host.

Stage the acceptance campaign

Choose the question your trial will answer. If you only need to test an already running model, begin with the standalone vLLM probe. That probe does not qualify the complete LychD installation. The worked rite here uses llama.cpp. Using vLLM in its place needs a specific engine recipe and separate observations of its namespace, devices, cache, shared memory, and lifecycle.

Keep one trial record. Identify the source, configuration, images, and model; write down the permitted effects, case counts, deadlines, expected outcomes, receipt destination, stop conditions, and person responsible for recovery. Keep private host material and raw receipts outside the checkout. The gates below separate a model response from a composed installation, browser acceptance, and later use. Complete each gate before claiming the next:

Gate Required observation before continuing
Source and configuration Host command and VesselEngine Room image share a recorded source and lock; selected extensions and RunesService Config Files agree; dry-run binding validates paths, ports and separate secret references.
Warm model path Exact inventory and response identities, useful text, an actually executed harmless tool, finite request limits and released grants. This proves neither managed activation nor a persisted RunJob Record.
Composed body Owned startup, migration and restricted runtime role, queue processing, actual dispatch and a settled reply agree; settled session/RunJob Record evidence remains inspectable after restart.
Browser operation Dedicated local login and wrong-credential/foreign-Origin refusal, keyboard submission and cancellation, then exact RunJob Record → OrbRun Inspector → LoomWorkflow Viewer → return. Qualify the synthetic development fixture separately.
Daily pilot Predeclared repeated turns, startup/stop/restart, timeout/failure/cancellation and longer-session cases retain useful work and explain uncertain outcomes; measure latency, queues and resources. Complete authenticated lifecycle control before treating public CLI stop as supported.
Growth Add one measured application or resource demand at a time, preserve an exact baseline and regressions, verify extension-generation compatibility and recovery, and separately admit memory or code-change effects.

Begin the pilot with one fixed text model and sequential requests. Record those operating conditions: the lease ledger does not limit capacity for you. Set measurable latency and resource limits before the trial, then judge useful completed work on that profile. Arbitrary throughput, synthetic GPU arithmetic, or a large test count cannot establish that result.

For each case, record pass, failed, blocked, or unknown. If an acknowledgment is lost or a request times out, the external effect may still be running. Test interruption separately from retaining a settled reply through restart; they establish different behavior. Use the receipt requirements and the relevant delivery boundary to interpret what the observation supports.

Keep the first text pilot small. It needs no Phoenix, embedding model, ArchiveLong-term Memory, ScoutWeb Fetcher, TombSandbox, foreign coding runtime, training, federation, or public extension SDK. When adding one later, repeat the authority, custody, persistence, resource, and recovery checks affected by that addition.

The Grounds — verify the Linux host

The supported host policy requires a free and open-source Linux host stack under operator control. macOS and Windows are unsupported hosting platforms, including deployments in Linux guests on those hosts.

Before writing configuration, establish Linux with cgroup v2, rootless Podman 5.4 or newer, an effective Quadlet user generator 5.4 or newer, a responding systemd user manager, NVIDIA CDI, Git, and uv. Do not prefix LychD, Podman, or systemctl --user commands with sudo.

uname -s
systemctl --user status
loginctl show-user "$USER" --property=Linger
podman --version
podman info --format '{{.Host.Security.Rootless}}'
git --version
uv --version
nvidia-smi
nvidia-ctk cdi list

Look for Linux, Podman reporting rootless true, a visible NVIDIA device, and the CDI selector nvidia.com/gpu=all. The user manager must respond. If Linger=no, enable it and check again:

loginctl enable-linger "$USER"
loginctl show-user "$USER" --property=Linger

Require Linger=yes before proceeding. The initialization report below also checks cgroup v2 and the effective Quadlet user generator; the Podman CLI version alone cannot establish those requirements. An absent device, older Podman or Quadlet, or failed required host probe needs repair through the distribution or NVIDIA documentation before this rite can continue.

Name the four paths that the remaining commands will use:

CODEX_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/lychd"
CRYPT_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/lychd"
QUADLET_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/containers/systemd"
USER_UNIT_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user"
printf '%s\n' "$CODEX_DIR" "$CRYPT_DIR" "$QUADLET_DIR" "$USER_UNIT_DIR"

The model shelf is outside those LychD-owned roots. Bring a GGUF whose model card documents llama.cpp compatibility, a chat template, and tool calling. Establish it at the exact filename below; creating the directory does not supply the model. Its fit in VRAM is yours to verify. LychD has no capacity calculation that can prove it for you.

mkdir -p "$HOME/models"
realpath "$HOME/models"
test -r "$HOME/models/first-model.gguf" \
  && test -s "$HOME/models/first-model.gguf" \
  && echo "model readable and non-empty"
ls -lh "$HOME/models/first-model.gguf"
sha256sum "$HOME/models/first-model.gguf"

Keep the digest so the trial identifies the file it used. Readability and size establish that the file is present; loading it and running inference will test whether it works.

The Desecration — install LychD

The host command and containerized application must speak the same configuration and unit contracts. Build both from this checkout. If you already have it, begin at its root and skip only git clone and cd lychd:

git clone https://github.com/hexanomicon/lychd.git
cd lychd
uv sync --frozen
podman build --file Containerfile --tag localhost/lychd:dev .

Keep the checkout at a stable absolute path: the generated Host Reactor unit points into its .venv. Record the source and image identities, then inspect the installed grammar:

git rev-parse HEAD
uv run --extra postgres-binary lychd --help
podman image inspect localhost/lychd:dev --format '{{.Id}}'

Help exposes init, bind, start, stop, status (with exact alias st), logs, access, and del. There is no public run verb. Image inspection must return an ID. If construction fails, start with the first failed step and the supported Python range >=3.12,<3.16; a different package or image would abandon the source agreement this movement establishes.

The Inscription — create configuration and data homes

init gives editable intent a CodexSettings Folder and managed persistent material a CryptData Folder. This is a fresh-host procedure. Existing active RunesService Config Files or custom extensions change the installation being tested and need their own acceptance plan.

Preview the inscription. Resolve required HOST failures in its readiness report before continuing. The plan must also end with Initialization plan is safe; that message establishes layout safety and does not establish host readiness:

uv run --extra postgres-binary lychd init --dry-run
uv run --extra postgres-binary lychd init
vi "$CODEX_DIR/lychd.toml"

In the existing [server.web] table, replace its image value with:

image = "localhost/lychd:dev"

In the existing [extensions] table, replace its builtins value with:

builtins = ["animator/llamacpp"]

Leave crypt = [] unchanged. These are edits to existing tables, not additional tables to append. Run init again so the selected extension can supply its RuneService Config File anchor and inactive sample:

uv run --extra postgres-binary lychd init --dry-run
uv run --extra postgres-binary lychd init

Your edited settings file survives. The extension adds runes/animator/soulstones/llamacpp/ where needed. Now inspect the homes:

stat -c '%a %n' "$CODEX_DIR/lychd.toml"
stat -c '%a %n' \
  "$CRYPT_DIR/triggers/inbox" \
  "$CRYPT_DIR/triggers/journal"
ls -la "$CODEX_DIR/runes/animator/soulstones/llamacpp"

Settings must have mode 600; both Host Reactor directories must have mode 700; the llama.cpp anchor must exist. A malformed TOML value or unknown extension ID should be corrected before repeating init. The command refuses to overwrite existing settings. Preserve them yourself before deliberately replacing them with a fresh generated file.

The First Soulstone — bind one local model service

The SoulstoneLocal Model is the local model service. This one uses llama.cpp's router mode so its model can load without restarting the VesselEngine Room. Its RuneService Config File specifies which model shelf and NVIDIA device the service can use.

Secret references

This RuneService Config File names no non-core secret. bind creates absent lychd_app_secret_key and lychd_db_password, lychd_runtime_db_password, lychd_phoenix_db_password, and lychd_local_access_password secrets and preserves existing values. A later RuneService Config File naming an external secret must have that exact Podman-secret reference available before binding.

The administrative database credential is reserved for PostgreSQL and the migration gate. The VesselEngine Room/SAQ and optional Phoenix receive separate roles and credentials. Initialization creates the versioned HBA file; binding mounts it read-only so TCP authentication also applies to existing data. Restart PostgreSQL with that generated policy before the new migration gate runs. Preserve existing database secrets and data; replacing the administrator password does not reset an initialized PostgreSQL cluster.

Inscribe the Rune

Print the actual model directory and open the active RuneService Config File:

MODEL_DIR=$(realpath "$HOME/models")
printf '%s\n' "$MODEL_DIR"
vi "$CODEX_DIR/runes/animator/soulstones/llamacpp/atelier.toml"

Replace /home/YOU/models below with that exact directory. Keep the container path /models; TOML does not expand $HOME.

name = "atelier"
description = "First local llama.cpp router."
startup_mode = "router"
model_path = "/models/first-model.gguf"
models_dir = "/models"
models_autoload = false
volumes = ["/home/YOU/models:/models:ro,Z"]
devices = ["nvidia.com/gpu=all"]

[concurrency]
dedicated = true
persistent_resident = false
conflict_domains = ["gpu-main"]

[[models]]
id = "first-model"
path = "/models/first-model.gguf"

[models.capabilities]
families = ["chat"]
supports_tools = true

[quadlet]
image = "ghcr.io/ggml-org/llama.cpp:server-cuda"

Keep top-level model_path: it supplies the same first-model query identity the router loads. Explicit router mode determines the launch shape. The gpu-main conflict domain declares incompatibility; an empty list would claim coexistence and requires measured evidence.

Verify the mount, pull the engine image, record its resolved identity, and preview the binding:

grep -F "$MODEL_DIR:/models:ro,Z" \
  "$CODEX_DIR/runes/animator/soulstones/llamacpp/atelier.toml"
podman pull ghcr.io/ggml-org/llama.cpp:server-cuda
podman image inspect ghcr.io/ggml-org/llama.cpp:server-cuda \
  --format '{{.Id}} {{json .RepoDigests}}'
uv run --extra postgres-binary lychd bind --dry-run
uv run --extra postgres-binary lychd bind

Dry binding validates settings, RunesService Config Files, host, ports, mounts, and secret references without LychD-managed mutation. Real binding creates missing core secrets, writes the generated unit files, and reloads systemd once. Services are still stopped.

Check that the binding left the expected material:

podman secret exists lychd_app_secret_key && echo "application secret present"
podman secret exists lychd_db_password && echo "database secret present"
podman secret exists lychd_runtime_db_password && echo "runtime database secret present"
podman secret exists lychd_phoenix_db_password && echo "Phoenix database secret present"
podman secret exists lychd_local_access_password && echo "local access secret present"
test -f "$QUADLET_DIR/lychd-vessel.container" \
  && echo "Vessel Quadlet present"
test -f "$USER_UNIT_DIR/lychd-animator-atelier.target" \
  && echo "Animator target present"
test -f "$USER_UNIT_DIR/lychd-reactor.path" \
  && echo "Host Reactor path present"

A failed bind reports the first boundary it could not satisfy. Correct the cause and preview again. An absent RuneService Config File usually means the wrong extension selection or directory. A rejected mount must be an absolute host path outside CodexSettings Folder, CryptData Folder, systemd-unit, and Reactor control roots. Supply an external secret only under its exact reported name. Edit the RuneService Config File or settings that produced the generated units; LychD will regenerate the files from those declarations.

Retired host-native bindings

Core binds one managed container VesselEngine Room. The former --native-only and --uncaged options refuse before host inspection or effects. Existing native bindings remain preserved and block mutation; removal of support grants no conversion, stop or deletion authority. Reconcile such an installation separately under its actual ownership.

The Awakening — draw the Circle and make the First Invocation

The body is bound but still. Normal caged startup brings up the pod, PostgreSQL PhylacteryMemory Vault, migration gate, Host Reactor, and VesselEngine Room web process:

uv run --extra postgres-binary lychd start

Do not manually enable the generated units. Ask the PulseCommand Line (CLI) for its bounded inventory:

uv run --extra postgres-binary lychd status

That inventory does not establish migration success or model warmth. Inspect the core units and migration result directly:

systemctl --user is-active \
  lychd-pod.service \
  lychd-phylactery.service \
  lychd-reactor.path \
  lychd-vessel.service
systemctl --user show lychd-migrate.service \
  --property=Result --property=ExecMainStatus

Require four active results, migration Result=success, and ExecMainStatus=0. While startup is still converging, read the last 120 log lines:

uv run --extra postgres-binary lychd logs --lines 120

Temporary local-browser boundary

Use a dedicated browser profile on this host. Keep the listener on 127.0.0.1; do not publish, proxy, tunnel, or forward it. Keep the optional SAQ diagnostic UI disabled, do not expose /schema/scalar, and do not mix this profile with hostile sites. The two internal SAQ workers are required for normal RunJob Record execution.

Protected requests require a separate local credential before receiving the fixed magus:* SigilID Badge. This does not establish hostile-browser or remote safety. Close the trial under the recovery plan established before startup; the public stop limitation is explained below.

Retrieve the local login explicitly in a private terminal, then enter its displayed username and password in the browser's authentication dialog. Do not put the password in a URL or command line:

uv run --extra postgres-binary lychd access

Open the local AltarControl Panel:

http://127.0.0.1:7134/

The root opens BridgeChat. On a fresh PhylacteryMemory Vault, choose New Séance, then offer a simple IntentRequest:

Reply with one sentence confirming first light.

This is the First InvocationJob Request, a smaller living Circle within the boundary you have prepared. Its casting follows the exact admitted PatternWorkflow. The first request starts the SoulstoneLocal Model through the Host Reactor, loads first-model, waits for readiness, and asks DispatcherTraffic Controller again. The loaded model can then answer through the selected capability: the local Animus available to this casting. Declaring supports_tools = true permits admission, but a text reply does not demonstrate arbitrary tool use.

When a non-empty reply settles, ask the PulseCommand Line (CLI) again:

uv run --extra postgres-binary lychd status

Open http://127.0.0.1:7134/nexus and find atelier:chat:first-model. Its chip should read active: NexusModel Status Board's screen label for the backend warm phase. Raw phase and warm: true observations are available through /orchestrator/status; they are not additional card labels.

Four witnesses to first light

Witness Required observation
Binding status reports a coherent installation, with no unknown or changed ownership.
Body Exact owned inventory and migration observations agree on pod, PhylacteryMemory Vault, Reactor, VesselEngine Room, SoulstoneLocal Model activity, and successful migration.
Faculty NexusModel Status Board shows the exact atelier / chat / first-model capability as active after the turn.
Answer Bridge contains a non-empty settled reply.

Record all four observations with the source, configuration, image, model, host, and device identities. Together they document this installation and its first reply. They do not qualify another runtime combination or remove the local-browser restrictions above.

When the witnesses disagree

Begin with inventory, then narrow the log target to the component it names:

uv run --extra postgres-binary lychd status
uv run --extra postgres-binary lychd logs services --lines 120

If the core is healthy but inference fails, inspect the exact model filename, CDI selector, VRAM fit, and real chat-template/tool support. Correct the owning RuneService Config File and bind again. Current target names live in status --help and logs --help; hand-starting the SoulstoneLocal Model would create a second activation path and obscure the failure you are trying to observe.

Close the rite

lychd stop currently refuses to stop an active VesselEngine Room. The authenticated container admission and exact settlement needed to complete that lifecycle are not yet implemented and qualified. The historical native signed-stop receipts describe a different deployment and do not establish that this container can be stopped through the public command.

There is no automatic direct-manager fallback. A separately authorized operator recovery must identify the owned units and containers, close admission, establish their terminal state, and preserve dependencies while any outcome remains unknown. Follow the recovery plan agreed before startup. State of Work records what remains unqualified; completing the observations above does not certify a production lifecycle.

Stopping leaves configuration and history in place. You can inspect the destructive plan without applying it:

uv run --extra postgres-binary lychd del --dry-run

The plan must account for the edited CodexSettings Folder and durable PhylacteryMemory Vault. Retain any blocked recovery handoff and resolve its named condition before replanning. Do not remove those homes or generated units by hand.

The first answer is now tied to the machine and model that produced it, its committed RunJob Record, and the limits of the trial. If an observation is missing, return to The Awakening. When the observations agree and the trial has been closed, continue into Divination to follow what happens when the LichAssistant's answer begins a conversation.