Hologram Live

MCP serverFiles & storage

Find open models and get download links with the SHA-256 each file must have.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use Hologram Live

Install Hologram Live

The server’s own address, for the clients that take one directly. Or connect ahel onceand every client you use reads it from one address, with the account kept on ahel rather than in each client’s config.

  • Claude Code

    claude mcp add --transport http hologram-live 'https://hub.uor.foundation/mcp'

    Run it once in your project, then open /mcp to approve any sign-in the server asks for.

  • Claude Desktop

    https://hub.uor.foundation/mcp

    Add a custom connector in Settings, paste this address, and approve the sign-in.

  • Cursor

    cursor://anysphere.cursor-deeplink/mcp/install?name=hologram-live&config=eyJ1cmwiOiJodHRwczovL2h1Yi51b3IuZm91bmRhdGlvbi9tY3AifQ==

    Open the link and Cursor adds the server at that address.

  • ChatGPT

    https://hub.uor.foundation/mcp

    In Settings, enable Developer mode, create an MCP app, and paste this address. Your plan and workspace must allow custom apps.

  • Codex

    codex mcp add hologram-live --url 'https://hub.uor.foundation/mcp'

    Run it once, then sign in with codex mcp login hologram-live if the server asks for an account.

From the project's README

As published by Hologram-Technologies/hologram-live in README.md.

Hologram Live is a local-first module host for the Hologram ecosystem. This repository produces two independent products:

  • Hologram Server — the standalone hologram binary, containing the CLI and background service.
  • Hologram Desktop — a Tauri application that bundles hologram as a managed sidecar and embeds the shared .holo application executor.

The current desktop experience provides a Console dashboard, multi-thread Chat with archiving, content-addressed Files, watched .holo Applications, and module discovery in a responsive dark/light interface. A Cmd/Ctrl+K command palette reaches every action, and text size is adjustable with Cmd/Ctrl +/-/0. Chat routes through a configurable inference engine: the default echo engine repeats your message, while weightc (one-shot CLI over imported .wcpu artifacts) and Ollama-compatible HTTP endpoints serve real model completions.

Quick start

Desktop application

cd apps/desktop
npm ci
npm run dev

The preparation step builds the server sidecar before Tauri opens. The desktop app can:

  • start, restart, and stop the local Hologram service;
  • create and switch between chat threads with independent, durable histories;
  • upload, rename, list, and download local files;
  • watch application source directories, compile/import their .holo archives, and inspect verified archive metadata;
  • inspect the enabled module catalogue;
  • follow the system appearance or remember a light/dark choice; and
  • remain available from the system menu bar after the main window closes.

Build an installable desktop bundle with:

just desktop-build

The desktop UI's colours, type, and marks derive from the Hologram brand kit at a pinned revision; apps/desktop/BRANDING.md explains how to update the brand everywhere in three steps.

Standalone server

cargo build --release --locked --package hologram-live --bin hologram
./target/release/hologram init
./target/release/hologram start
./target/release/hologram status
./target/release/hologram modules list

Run the service in the foreground instead with:

./target/release/hologram serve

Every server advertises http://127.0.0.1:11435 by default and generates a 256-bit membership secret in its state directory at cluster.token. The file is reused across restarts and is owner-only on Unix. To form a multi-host cluster, securely give every node the same secret (at least 32 bytes), advertise the origin other nodes can reach, and seed a new node with any live member:

# first node; generates <state_dir>/cluster.token
hologram serve --advertise https://registry-a.example.com

# joining node; use the contents securely copied from the seed
HOLOGRAM_CLUSTER_TOKEN='<seed cluster.token contents>' \
  hologram serve \
    --advertise https://registry-b.example.com \
    --join https://registry-a.example.com

The joining node heartbeats immediately, learns the live membership set, and then heartbeats those peers directly. Failed seeds remain eligible for retry; members disappear from /api/v1/nodes after their TTL. Join messages use a short-lived keyed proof over the exact payload, so the cluster secret and the separate user authentication token are never sent over the wire. Non-loopback origins must use HTTPS.

The default configuration and local endpoint are:

~/.config/hologram/live.toml
http://127.0.0.1:11435

Open the endpoint for the built-in status page. API documentation is available at:

http://127.0.0.1:11435/docs
http://127.0.0.1:11435/openapi.json

/docs is the self-hosted Scalar reference; /openapi.json is the generated OpenAPI document. Native clients use the versioned Protobuf/gRPC service on the same endpoint.

A path no route claims is answered 404 with the daemon's error envelope (LIVE_NOT_FOUND). A caller that sends content-type: application/grpc gets gRPC UNIMPLEMENTED instead, as any gRPC server answers an unknown service.

Machine-readable CLI output

Global --json is supported by every CLI command and may appear before or after the subcommand. A successful command writes one JSON value to stdout, including lifecycle actions, downloads, generated files, accepted mutations, and run --output-format text. Diagnostics remain on stderr, while a runtime failure writes a JSON object with code and message to stdout and exits nonzero. This makes the complete CLI safe to compose with jq:

hologram status --json | jq -r '.status'
hologram files get blake3:... --output ./asset.bin --json | jq '.byte_length'
hologram run ./my-app --input-text 'hello' --output-format text --json | jq -r '.[]'
hologram run application.holo --output-format text --json | jq -r '.[]'

Help and shell-completion text retain Clap's human-readable format.

Demo workflows

Chat and conversation history

Create a thread, copy its returned ID, and send a message:

hologram --json history new "Demo chat"
hologram --json chat send <conversation-id> "Hello, Hologram"
hologram --json history show <conversation-id>

chat send records the user message and the assistant response as one persisted exchange. Threads retain separate histories and can be resumed from the desktop app.

The response comes from the inference engine selected in live.toml:

[inference]
engine = "echo"            # echo | weightc | ollama | llamacpp | candle | burn | vllm
default_model = ""         # imported id or remote served-model name
weightc_path = "weightc"
ollama_endpoint = "http://127.0.0.1:11434"
vllm_endpoint = "http://127.0.0.1:8000"
vllm_token_env = "VLLM_API_KEY"
model_path = ""            # GGUF (llamacpp/candle) or named-MPK checkpoint (burn)
tokenizer_path = ""        # tokenizer.json (candle) or tokenizer.model (burn)
model_architecture = ""    # candle: llama; burn: a supported Llama 3 variant
n_ctx = 4096
n_gpu_layers = 0
llamacpp_max_concurrent_requests = 1
request_timeout_secs = 300
resident_sessions = false  # weightc only: keep one resident enter session per conversation
max_resident_sessions = 4  # LRU cap on resident sessions

The default echo engine repeats the user message; it needs no model and no external process. The weightc engine shells out to weightc ask <artifact-dir> <prompt> --json against an imported .wcpu artifact. ollama proxies /api/generate, while vllm uses the OpenAI-compatible /v1/completions and /v1/models endpoints with native streaming and optional authentication from VLLM_API_KEY.

llamacpp loads a local GGUF model in-process and streams decoded pieces with exact token counts. Set model_path directly, or import a GGUF file and put its returned blake3:... id in default_model. It is off by default because it builds native C++ code and gives model execution the daemon's crash boundary. Build it with cargo build --release --features llamacpp; use llamacpp-metal or llamacpp-cuda for the corresponding GPU backend. These builds require CMake, Clang, and a C++ compiler.

candle is the Rust-native local GGUF alternative. The initial adapter supports Candle's quantized Llama-family implementation, requires a matching Hugging Face tokenizer.json, streams native deltas, and reports exact token counts. Set model_architecture = "llama"; use --features candle for CPU, candle-metal for Apple GPUs, or candle-cuda for NVIDIA GPUs. Candle is not a universal GGUF dispatcher: unsupported model families fail during startup instead of being guessed.

burn uses Tracel's Burn-LM Llama implementation on CPU. It requires a Burn named-MPK checkpoint, the matching Llama 3 tokenizer.model, and one of llama3.2-1b, llama3.2-3b, llama3.1-8b, or llama3-8b in model_architecture. Build with --features burn. Burn generation is currently buffered, so streaming API responses honestly report x-hologram-stream: emulated; GGUF files are not Burn checkpoints.

Run the live acceptance gate against real engines before releasing an inference build. It starts an isolated Hologram server and checks model discovery, buffered and native-streaming OpenAI/Ollama requests, usage, cancellation, and llama.cpp context overflow:

./scripts/check-inference-engine.sh llamacpp /models/tiny.gguf
HOLOGRAM_TOKENIZER_PATH=/models/tokenizer.json HOLOGRAM_MODEL_ARCHITECTURE=llama ./scripts/check-inference-engine.sh candle /models/tiny.gguf
HOLOGRAM_TOKENIZER_PATH=/models/tokenizer.model HOLOGRAM_MODEL_ARCHITECTURE=llama3.2-1b ./scripts/check-inference-engine.sh burn /models/llama3.2-1b.mpk
VLLM_ENDPOINT=http://127.0.0.1:8000 ./scripts/check-inference-engine.sh vllm org/model

VLLM_API_KEY is forwarded when set. Set HOLOGRAM_BIN to test an existing binary, or let the script build the required feature set.

With resident_sessions = true, the weightc engine instead keeps a supervised weightc enter --jsonl process per conversation, so turns reuse the live KV context instead of replaying a transcript, and only the new message crosses the wire each turn. Sessions are LRU-capped by max_resident_sessions; a crashed session is reported as a typed error and lazily respawned (starting fresh context) on the next turn. This mode needs a weightc build with enter --jsonl support. Models are managed with:

hologram models import ./tinyllama.wcpu
hologram models import ./tinyllama.gguf
hologram models list
hologram models remove blake3:...

Threads can be archived instead of deleted. Archived threads keep their messages and their updated_at_millis, but drop out of the default listing:

hologram --json history archive <conversation-id>
hologram --json history list          # archived threads are omitted
hologram --json history list --all    # archived threads included
hologram --json history unarchive <conversation-id>

In the desktop app, hovering a thread reveals an archive button, and archived threads collapse into an ARCHIVED group at the bottom of the thread list.

Configuration files use schema version 2, and a file written by an earlier build still starts. Missing sections and fields fall back to their documented defaults, and an older schema_version is upgraded and written back so the next start reads a current file; the rewrite records only what the file declares, never a value injected by an environment override. Unknown fields are still rejected rather than ignored, and a schema_version newer than the running build supports is refused rather than silently downgraded.

Removing a field from the schema comes with a schema_version bump and an entry in the retired-key table in src/config.rs. A file written before the bump keeps starting: the retired key is dropped during the upgrade, named in a warning, and gone from the rewritten file. Files already at the current version are not swept, so an unrecognised key there stays a startup error rather than being discarded as though it had been retired.

Files

hologram files put ./notes.txt --media-type text/plain
hologram files list
hologram files rename blake3:... meeting-notes.txt
hologram files get blake3:... --output ./meeting-notes.txt
hologram files search --filename-contains notes --limit 20

File bytes are addressed by their BLAKE3 content ID. Renaming changes only persisted filename metadata; the ID and bytes remain unchanged.

Object search

hologram registry search --kind file --limit 50
hologram registry search --media-type text/plain --min-size 1024
hologram --json registry search --limit 2 | jq -r '.next_cursor'
hologram registry search --limit 2 --cursor blake3:...

Search filters on stored metadata: --kind, --media-type, --filename-contains, --min-size, --max-size. It is not full-text and does not read object content.

Results are ordered ascending by object ID and paginated. --limit defaults to 100 and is clamped to 1000. A page carries next_cursor only while further matches remain; the cursor is opaque and valid only for the provider that issued it. truncated reports a page cut short by a provider-side scan bound, so a capped result is never presented as a complete one.

The same surface is available as GET /api/v1/objects/search and GET /api/v1/files/search, and as the registry.search and files.search native operations. hologram files search is the file-kind projection: the daemon fixes the kind, so --kind is not offered there.

Named artifacts

hologram push ./app.holo demo:v1
hologram serve demo:v1
hologram pull qwen3.5:4b
hologram pull host:5000/models/qwen3.5:4b
hologram run qwen3.5:4b --input-text "hello"
hologram --json pull qwen3.5:4b | jq '{archive_kappa, layers_fetched, bytes_transferred}'

A reference is [host[:port]/]namespace/name[:tag]. A bare name:tag expands against [registry].endpoint and [registry].namespace; an omitted tag means latest. Following OCI, the colon separates repository from tag, so qwen3.5:4b is repository qwen3.5, tag 4b.

An artifact is one OCI manifest whose layers are a thin .holo archive plus the kappa-addressed payload blobs it references, so two artifacts sharing weights transfer them once. Pull consults the local store first, fetches only what is missing, verifies every layer against its kappa on write, and confirms the whole set is present before reporting success — the registry itself does not check that a manifest's layers exist. Every step is content-addressed, so a pull is idempotent and an interrupted one resumes for free.

Tags are mutable, so a pull always re-resolves rather than caching by name, and records the resolved manifest digest — that digest, not the tag, is what makes a pull reproducible.

serve takes an optional reference. hologram serve alone is unchanged; hologram serve demo:v1 acquires the artifact, imports it, and makes it resident before the listener binds, so the daemon never reports ready with the named application not yet invocable. The argument joins whatever holo.resident already declares rather than replacing it.

That residency lasts for the life of that process. serve <ref> does not write to your configuration, so a daemon started any other way will not have it — put it in holo.resident if you want it every time.

run and serve resolve their argument in the same fixed order, so no existing invocation changes meaning:

  1. a blake3: id → the local catalog
  2. an existing filesystem path → a local archive
  3. anything else → a registry reference, pulled and then executed

Pulling grants no capabilities. A pulled archive receives the same ADR 020 baseline as a local file — no storage roots, no channels, no network scopes — and is executed by exactly the same path. Having come from a configured registry is not evidence about what an archive contains.

push is the inverse. The archive becomes the manifest's archive layer, and any payload a thin archive references without embedding is published alongside it — which is what lets a later pull deduplicate against blobs the registry already holds. A referenced payload that is not in the local store refuses the push before anything is written, rather than publishing a manifest whose content is missing. The archive is inspected first, so a file that is not a valid archive is rejected before the registry is touched.

Tags are mutable upstream, so push refuses to move a tag that already resolves unless given --force, and the result records whether a tag was moved. Silently repointing a name someone else is pulling is not a default worth having.

Progress is written to stderr and the result document to stdout, so --json stays usable in a pipeline; under --json the progress is JSONL events rather than a rendered bar.

Client library

Applications can talk to a daemon without depending on it. hologram-client is a standalone crate in this workspace:

use hologram_client::{HologramClient, ObjectQuery};

let client = HologramClient::new("http://127.0.0.1:11435")?;
let stored = client
    .put_file(b"hello".to_vec(), Some("notes.txt"), "text/plain")
    .await?;
let bytes = client.get_file(&stored.id).await?;

let page = client
    .search_files(&ObjectQuery {
        filename_contains: Some("notes".to_owned()),
        limit: 50,
        ..ObjectQuery::default()
    })
    .await?;

It depends on reqwest, rustls, serde, and serde_json only — taking hologram-live would pull wasmtime, axum, and tonic into every consumer's build. The cost of mirroring the wire shapes instead of importing them is drift, so a contract test in the daemon's suite serializes the server types and deserializes them with the client's; a renamed field fails a build rather than surfacing at runtime.

search_objects_all follows cursors to the end, stopping at a truncated page rather than looping, since truncation means the daemon stopped early.

.holo archives

Generate a validated source manifest interactively:

mkdir my-app
cd my-app
hologram app init

The generator prompts for ordered layers, their kind-specific entrypoint or surface information, the primary layer, an optional capability file, and optional child applications with delegated capability documents. It writes hologram.json atomically and prints the commands needed to compile and run it. For scripts and CI, provide the first layer as flags:

hologram app init ./my-app \
  --kind wasm \
  --path app.wasm \
  --entry holo_run

# Compose a previously compiled, self-contained child archive
hologram app init ./parent \
  --kind wasm --path parent.wasm --entry holo_run \
  --child worker.holo \
  --child-capabilities worker-capabilities.json

# A portable View source is a directory containing ui/index.html
hologram app init ./view-app \
  --kind view --path ui --surface portable

Use --yes for a minimal app.wasm/holo_run manifest. Existing manifests are preserved unless --force is explicit. Packaging remains a compiler choice: use hologram compile for a fat archive or add --thin for a manifest-only archive.

hologram holo fixture ./fixture.holo
hologram holo import ./fixture.holo
hologram holo list
hologram holo inspect ./application.holo
hologram holo plan ./application.holo
hologram holo verify ./application.holo
hologram holo inspect blake3:...
hologram holo plan blake3:...
hologram holo verify blake3:...
hologram holo remove blake3:...
Desktop watch loop

Open Applications in Hologram Desktop and choose Add directory, then select a project containing hologram.json. The desktop compiles it immediately, imports the successful archive into the normal local catalog, and recursively watches the project for later changes. Builds are debounced and written to the desktop cache rather than into the source directory.

Choose Run on a ready watched project to inspect its latest successful archive. Non-View applications accept a text input and execute once through the in-process executor. A portable View application instead offers Open application: it opens in its own native window outside the dashboard and keeps its prepared primary available across user messages until that window is closed, Stop application is chosen, or Desktop quits. Choose Add .holo to import an existing archive through the native file picker; catalog archives use the same Run panel. Unsupported providers and denied capabilities remain explicit runtime errors.

examples/wasm-view/ is the complete composed example. Its portable frontend posts one bounded application.invoke intent to an ASCII-uppercase Wasm primary:

hologram compile examples/wasm-view/hologram.json \
  --output target/wasm-view.holo

Import target/wasm-view.holo in Desktop and choose Open application. Its separate native window can submit any number of bounded messages to the same prepared Wasm primary. Closing the window or choosing Stop application detaches the View and stops the session in reverse layer order. The checked-in manifest is also compiled by display-independent lifecycle tests, which prove the persistent attachment, direct and View invocation, transactional window replacement, idempotent stop, and reverse shutdown without requiring a CI display. The CLI's hologram run remains deliberately one-shot and headless; it reports that no portable surface is available instead of changing its fresh-instance contract.

The Applications list is backed by the same holo list and holo inspect operations shown above, so its archive κ, application κ, layers, capabilities, physical sections, and verification state are not reconstructed by the web frontend. A failed rebuild is shown on the watched project while the last good immutable archive stays available. Stop watching removes only the persisted watch registration; it does not delete the last cataloged .holo archive.

The stable build creates and validates v4 .holo archives and rejects every other physical version. The physical file starts with HOLO, a version and section count, then fixed 24-byte section-table entries containing each section's kind, offset, and length. Logical layers do not have separate physical headers: their ordered descriptors live in the canonical AppManifest section and refer to payloads by κ. Every application archive contains exactly one verified application-directory extension.

.holo v4
├─ header + section table
├─ AppManifest       primary · requires · ordered layers · children
├─ Extension         verified, queryable application directory
├─ ContentBlob × N   κ71 · content bytes
├─ other sections    plans · weights · ports · certificates · metadata
└─ BLAKE3 footer

Shortened here. Read the whole README on GitHub.

Advanced
Delivery
model-hub MCP server → your ahel gateway (mcp.ahel.ai) → every connected AI client.
Catalog kind
mcp-server
Gateway key
foundation-uor-hub-model-hub
Source
github.com/Hologram-Technologies/hologram-live
Hosted endpoint
https://hub.uor.foundation/mcp