Start
Install
Install Omnesis yourself with one command, or ask a local coding agent to guide you across the devices you choose. The gateway usually runs on an always-on computer. Its installer installs the CLI, sets up TLS, registers the gateway and a collector as services, and downloads an embedding model. A second machine that only collects, or one running an agent harness, uses the same installer with a role flag.
The installer can deliver Omnesis in two ways:
| Method | Flag | The host needs | Choose it when |
|---|---|---|---|
| Source | (default) | Node 24.16 or newer within Node 24, or Node 26.1 or newer; git; about 3.5 GB of memory; a C/C++ toolchain on Linux and Intel macOS | You want the default: a checkout of the release, built on the machine. |
| Docker | --docker |
Docker with the Compose plugin, v2.24.0 or later | You want containers and no Node on the host. See Docker for image selection, storage and networking. |
Requirements
-
macOS, Apple silicon or Intel. Every source is available, and local
embeddings use Metal acceleration on Apple silicon. Intel Macs also need Xcode Command
Line Tools (
xcode-select --install): installation checks the native vector engine and builds it locally when its bundled binary is incompatible. -
Linux, amd64 or arm64. Source installs need glibc 2.35 or newer; Docker
hosts do not. Cloud and cross-platform sources work; the Apple, Things and Screen Time
sources need a Mac, which can run a collector for a Linux
gateway. Local embeddings use a CUDA or Vulkan GPU when one is present and the CPU
otherwise;
OMNESIS_LLAMA_GPU=falseforces the CPU. - Windows is not supported.
- Node.js 24.16 or newer within Node 24, or Node.js 26.1 or newer, for a source install. Node 25 and Node 24.0 to 24.15 are not supported. When no supported Node is on your PATH, the installer installs Node 24. A Docker host does not need Node.
- git, for a source install only.
-
About 3.5 GB of memory for a source install, which builds Omnesis on
the machine. The installer refuses a smaller machine before it fetches or builds
Omnesis, though it may already have installed Node 24. On a machine with swap to spare,
OMNESIS_BUILD_MEMORY_MB=4096builds anyway.
macOS The Apple sources read local databases, so the collector needs Full Disk Access. The installer opens the settings pane for it; you can also grant it later. See Full Disk Access.
Guided install with an agent
If you have a coding agent with terminal access on the computer where you want to begin, copy this prompt into it. The full install prompt asks the agent to inspect the machine, help you choose a gateway and any additional collectors, then walk through Tailscale, phones, and browser capture one step at a time. It uses the same installer and checks each part before moving on. You choose which devices and sources to add.
Help me install Omnesis across the devices I choose. Read https://omnesis.dev/install-prompt.md and follow it.
You can also read the agent instructions before pasting the prompt. The agent will need you for account sign-ins, permissions, and steps on other devices.
One-command install
❯ curl -fsSL https://omnesis.dev/install.sh | sh
The script runs as your user. It uses sudo only for Linux prerequisites (Node, git and
build tools) when they are missing, and on Linux to make you the machine's Tailscale
operator when tailscale cert refuses your user. Before it changes anything,
it prints the role, delivery method and release it is about to install;
--dry-run stops there. Then it:
- Checks the platform: macOS or Linux, amd64 or arm64. Anything else is refused.
- Installs Node 24 when no supported Node is on your PATH: Homebrew on macOS, NodeSource on Linux.
- For a Linux source install, installs make, C/C++ compilers and Python 3 if they are missing.
-
Installs the newest stable release of the
omnesisCLI (a checkout in~/omnesis), with the command at~/.local/bin/omnesis. If that directory is not on your PATH, it adds it once to the profile file your shell reads, marked as added by the installer, and tells you the command that makes it available in the current terminal. -
Sets up TLS. When Tailscale is running it asks
Tailscale detected — set up a trusted HTTPS certificate for <name>? [Y/n], Yes by default, and mints the certificate for the machine's MagicDNS name; without a
terminal it mints it unasked unless you pass
--no-tls. When the tailnet has HTTPS certificates switched off, it says so instead of asking.--mkcertuses a mkcert certificate instead. Otherwise the gateway keeps its own self-signed certificate. Certificates explains what each one means for browsers and phones. - Sets up encryption at rest when the machine has a usable OS keyring, and asks what to do when it has none (see First run).
- Registers the gateway and the collector as user services (launchd agents on macOS, systemd user units on Linux) and starts them.
- Downloads the embedding model you chose, so semantic search works from the start.
-
If
codexis installed, offers to set up the agent with a ChatGPT sign-in; then, if the agent is still unassigned andclaudeis installed, offers to set it up with Claude Code (see First run). - Prints the exact command another machine runs to join this gateway, as a collector or an agent-harness host, with the gateway's URL and certificate fingerprint, and how to mint the pairing code that command asks for.
-
Ends with the portal address. On a terminal that address carries a one-time login code
(
?token=…) the installer mints for you, which signs you in once, within 10 minutes. Without a terminal, the code is never printed. On a self-signed gateway, the closing summary leads with a warning that browsers and the Chrome extension cannot connect, and names the one command that fixes it. It also names the AI agents that cannot connect to the certificate it serves.
SSL_CERT_FILE, which the portal shows. With a mkcert certificate, Claude Code
and Codex each need a one-time trust setting.
ChatGPT and the Claude apps connect from their providers' servers, so they also need the
gateway published. To move to a Tailscale
certificate later, set up Tailscale with MagicDNS and HTTPS certificates, then run
omnesis tls provision; on a Docker install, run the installer again.
Roles
With no role flag the installer sets up the gateway machine, as above. Each run installs one role.
| Role | What it installs |
|---|---|
| (no flag) | The gateway machine: gateway, collector, TLS, encryption at rest, embedding model, services. |
--collector |
A collector for a gateway on another machine: the CLI, a pairing with that gateway, and the collector service. No gateway, embedding model or index. |
--openclaw / --hermes |
An agent-harness machine: the CLI, then a pairing with a gateway on another machine and the harness's Omnesis plugin. The harness must already be installed; the installer never installs it. On a machine that already runs Omnesis, the role uses the CLI that is there and leaves the install and its services as they are. See OpenClaw and Hermes. |
--client-only |
The CLI alone, for a machine you only query from. |
--docker |
The gateway machine as containers, or with --collector a collector in
a container. The harness roles are refused, because their plugin runs inside the
harness itself. See Docker.
|
The collector and harness roles take the gateway's address and ask for a pairing code,
which you mint on the gateway host with
omnesis devices pair --kind collector (or --kind agent for a
harness), or in the portal under Settings → Devices:
❯ curl -fsSL https://omnesis.dev/install.sh | sh -s -- --collector --gateway-url https://gateway.example.io:7600 --trust-fingerprint sha256:<fingerprint>
Pairing code:
Collector studio-mini is online.
Leave out --gateway-url and the installer looks for a gateway on the local
network, shows you what answered and its certificate fingerprint, and asks before pairing.
If nothing answers, or there is no terminal to confirm with, it stops and asks you to name
the gateway. Setup → Collector on another machine explains
each step and the commands underneath.
Installer flags
Pass flags after sh -s --, as in the examples above. The role flags are in
Roles.
| Flag | Effect |
|---|---|
--version X.Y.Z |
Install an exact release (source tag or Docker image). |
--commit <full-sha> |
Source installs only: install an exact 40-character commit available from the configured repository. Intended for controlled testing between releases. |
--edge |
Install the main branch from source. Docker installs release images
only, so it refuses this flag.
|
--source-dir <dir> |
Where a source install is checked out (environment:
OMNESIS_SOURCE_DIR). Default ~/omnesis.
|
--force |
Allow an existing checkout to move to an older release. |
--reconfigure |
On a machine this installer already set up from source, run the full install again (certificate, keyring, model, pairing, services) instead of updating the install in place. See Updating. |
--port <port> |
Gateway port. Default 7600. Moving an installed gateway to another port names every device paired from another machine, which still dials the old port, and prints what points each one at the new port. |
--mkcert |
Use a mkcert certificate instead of Tailscale, covering the host name and its current network addresses. |
--no-tls |
Skip TLS setup: no Tailscale certificate is offered or minted, natively or with
--docker, and the gateway keeps its self-signed certificate. A
certificate an earlier run set up stays.
|
--tls-cert <path>, --tls-key <path>,
--tls-ca <path>
|
With --docker: serve a certificate you issued. See
TLS in Docker.
|
--build |
With --docker: build the images from the checkout this script came
from instead of pulling published ones. They are tagged with the checkout's own
version and -local (for example 0.7.3-local), never as a
published release, so a later omnesis update moves the install onto
the published images. --version may only repeat the checkout's
version. The build needs about 25 GB free where Docker stores images; the
installer checks before writing anything.
|
--combined, --gateway-only,
--docker-network host|bridge
|
With --docker: run the gateway and collector in one container, or the
gateway alone, and choose the network mode. See
Choose a topology.
|
--hardened, --no-hardened |
Linux with systemd: run the gateway under a dedicated system account, with its own
state in /var/lib/omnesis-gateway. The installer prints the root
command that does it and does not run it. Refused while a gateway service of yours
is registered. --no-hardened keeps the gateway under your account
without asking. See Hardened gateway.
|
--embedder <id> |
Install this embedding model instead of asking. List the ids with
omnesis model catalog --role embed, which needs no running gateway.
|
--no-model |
Install no embedding model; search is keyword-only until you add one. |
--no-keyring |
Don't set up encryption at rest. |
--keyring-passphrase-file <path> |
When no OS keyring is usable, set up encryption at rest with the passphrase in this file instead of asking. |
--no-service |
Don't register services; you start the daemons yourself. Refused with
--docker, which registers none.
|
--no-modify-path |
Leave your shell profile alone and print the PATH line to add instead. Without it,
a profile that already puts ~/.local/bin on PATH is left as it is.
|
--gateway-url <url> |
With a collector or harness role: the gateway to pair with. Without it, the local network is searched and you confirm what answered. |
--trust-fingerprint sha256:… |
With a collector or harness role: accept the gateway only if its certificate has this fingerprint. |
--code <code> |
With a collector or harness role: the pairing code, for an unattended install. Without it you are asked, which keeps the code out of shell history. |
--dry-run |
Check the flags and platform, print what would be installed, and exit without changing anything. |
--no-prompt |
Never ask. Optional choices take their default, and a required choice stops and names the flag it needs. A sudo password prompt also fails immediately. |
OMNESIS_NETWORK_TIMEOUT_SECONDS |
Environment variable: how long a download may stall before it is retried or fails. Default 300 seconds, at most one day. |
scripts/install.sh
documents every flag in its header.
First run
The installer may ask up to six questions. It reads the answers from your terminal, not
from standard input, because under curl … | sh standard input is the script
itself. Each has a flag, so an unattended install can answer in advance.
| Question | When it is asked | Answer it in advance with |
|---|---|---|
| Run the gateway as a dedicated account? | First, on a Linux host with systemd that has no gateway yet. Optional. | --hardened or --no-hardened |
| Which embedding model? | Every gateway install except a hardened one, unless the model is served by an HTTP backend. Without a terminal, the default is installed. | --embedder <id> or --no-model |
| What to do without a keyring? |
Only when the machine has no usable OS keyring. Required, except under
--docker, where a run without a terminal encrypts with a generated
passphrase file.
|
--keyring-passphrase-file <path> or
--no-keyring
|
| Set up the agent with Codex? |
When codex is installed and the agent has no model yet. Optional.
|
Nothing; an unattended install skips it. |
| Set up the agent with Claude Code (Haiku)? |
When claude is installed and the agent still has no model after the
Codex offer. Optional.
|
Nothing; an unattended install skips it. |
| Which address should other machines use? | After a self-signed or mkcert gateway starts. Optional. | Nothing; an unattended install keeps the default. |
Embedding model. The installer lists the models built into the CLI, marks
a default (the model this machine already uses, or the recommended one), and takes a
number. You answer before anything is downloaded, registered or started.
--no-model leaves search keyword-only.
No usable keyring. This happens on a headless Linux machine with no
unlocked login keyring, or on a Mac whose login keychain is locked. Encryption at rest
needs a key the machine can keep, so the installer offers three answers: continue without
encryption at rest, protect the key with a generated passphrase file, or stop so you can
unlock a keyring first. Under --docker no keyring on the machine could reach
a container, so there are two answers, and pressing Enter takes the generated passphrase
file.
The passphrase option creates an owner-only passphrase file, prints a recovery code once
(write it down), and configures the services to use it. An install without encryption at
rest can add it later with omnesis secure, which backs up, encrypts what is
on disk and restarts the gateway. See
Encryption at rest.
Codex. The offer appears once an ordinary gateway is healthy, when a
codex command is on your PATH and the agent has no model. The installer never
runs that command; it only takes it as a sign the offer is relevant. If you accept,
Omnesis signs in to ChatGPT with a device code in its own private Codex home, never
copying another installation's credentials. It assigns codex/gpt-5.6-luna
to the agent only if your account's model list includes it. A failed sign-in or check
leaves the agent unassigned and prints how to retry.
Accepting turns on remote inference for the whole gateway: conversation context, relevant
Omnesis data and tool results are sent to OpenAI, and any other remote model you configure
later is allowed too. Collector, harness, client-only, Docker and hardened installs, and
installs with
--no-service, never make this offer.
Claude Code. The offer appears once an ordinary gateway is healthy, when
a claude command is on your PATH and the agent still has no model after the
Codex offer. If you accept, the installer asks the gateway for its view of Claude Code.
Only when the gateway reports Claude Code installed but signed out does the installer run
your own claude auth login in the terminal; the login belongs to that Claude
Code installation, and Omnesis never stores or reads it. A Claude Code too old for the
gateway gets a hint to update it with claude update instead. The installer
assigns claude-code/haiku to the agent only if your account's model list
includes it. A status the gateway cannot report, a failed sign-in or a failed check leaves
the agent unassigned and prints how to retry with
omnesis claude-code setup-agent.
Accepting turns on remote inference for the whole gateway: conversation context, relevant Omnesis data and tool results are sent to Anthropic through Claude Code, and any other remote model you configure later is allowed too. The same installs that never make the Codex offer never make this one, and an unattended install skips it.
Address for other machines. The installer lists the names and network
addresses in the gateway's certificate. Choose one the other machine can reach. It is
saved as OMNESIS_GATEWAY_URL and used in the join commands it prints. The
default is omnesis.local for a self-signed certificate and
<hostname>.local for mkcert; an IP address works on a network without
mDNS.
Without a terminal (a container build, a provisioning script, an AI agent running it for you), the installer asks nothing. A question with a default takes it and says which flag changes it; a required one refuses rather than choosing for you. Pass its flag and it runs unattended.
Open the portal
Open the portal at the address the installer printed:
https://<magicdns-name>:7600/portal/ after a Tailscale certificate,
otherwise https://localhost:7600/portal/. On a terminal the installer prints
it with a one-time login code, /portal/?token=<code>: opening it signs
you in, and the portal removes the code from the address bar. The code works once, within
10 minutes. With the self-signed certificate your browser warns once; accept it. For a
fresh code, or to sign in from another browser, mint one in a terminal on the gateway
host, Docker installs included, and paste it into the portal's login screen:
# the code the portal asks for
❯ omnesis devices pair --kind portal
# are the services up?
❯ omnesis service status
# follow the gateway log
❯ omnesis service logs gateway -f
The CLI on the gateway host needs no login: it uses the gateway's
bootstrap admin token. On a Docker install the daemons
are containers, so use the docker compose commands under
Docker in place of omnesis service.
A phone and a browser are optional. Pair the iOS or Android app by scanning a code from
omnesis devices pair --kind ios (or --kind android); see
Setup → Phones. The
Omnesis Browser Capture
extension pairs with omnesis devices pair --kind browser and needs a
certificate the browser trusts; see
Setup → Browser extension.
Add your first source
❯ omnesis sources add gmail
# or run it bare for an interactive picker across all sources
❯ omnesis sources add
For Google, a wizard walks you through creating your own OAuth client, which takes about five minutes once per install. There is no shared client: your credentials and tokens stay on your machines.
In the portal, use + Add source on the Sources page. Adding, pausing and removing sources is covered in Managing sources, and the full catalogue, with what each source needs, is on Available sources.
Docker
The Docker install is the same installer with a flag. The gateway and the collector run as
containers from published images tagged by release:
ghcr.io/omnesis-dev/omnesis-gateway and omnesis-collector, or
omnesis-combined for both in one container, with
omnesis-updater for updates. The host needs Docker with the Compose plugin at
v2.24.0 or later (docker compose version prints it; the installer refuses an
older one), curl and a POSIX shell; no Node, checkout or compiler. On Linux
the account that installs must be able to use the Docker daemon without sudo: in the
docker group (sudo usermod -aG docker $USER, then log in again),
which the installer names when the socket refuses it. Pulling the images needs about 4 GB
free where Docker stores them; the installer checks before writing anything (OMNESIS_DOCKER_PULL_DISK_GB=0
skips the check). The installer uses release images only, so it refuses
--edge; --version X.Y.Z selects an exact release. From a
checkout, sh scripts/install.sh --docker --build builds the images locally,
tagged <version>-local after the checkout's version. The
omnesis command it writes finds Docker where Docker Desktop, OrbStack and
Colima put it even when PATH does not include it, as in a non-login
ssh session, cron or launchd.
❯ curl -fsSL https://omnesis.dev/install.sh | sh -s -- --docker
It writes ~/.config/omnesis/docker-compose.yml, pulls the images, starts the
gateway, waits for it to answer /health, and starts the collector, which
pairs itself. The config directory is mounted into the containers
at the same absolute path, so the data, the token, the certificate and the
compose file are all readable on the host, and a path means the same thing inside and
outside the containers. A first install that stops before its containers start (the images
will not pull, a pairing code is refused) removes the compose file, install marker and
omnesis command it wrote, so the re-run starts clean; the images it pulled
stay for that re-run, and a keyring it armed stays with its .env.
omnesis on this host is a wrapper that runs the CLI inside the container: the
gateway's, or the collector's on a machine that only collects. On a gateway host, the
source, device, model, TLS, query and update commands on this site work unchanged. A
machine that only collects holds its collector's token, not the gateway's admin token, so
there its omnesis runs update and uninstall;
source, device and status commands run on the gateway host or in the portal. A few
commands act on the containers themselves, which no container can do, so the wrapper runs
them on the host: update, uninstall, folders share,
the restart secure needs,
restore, which stops the containers around the restore and starts them again, and
service, whose start, stop, restart,
status and logs run their
docker compose equivalents:
❯ omnesis sources add gmail
❯ omnesis status
# the containers themselves
❯ omnesis service status
❯ omnesis service logs gateway --follow
❯ omnesis service restart
In an install that runs the gateway and the collector in one container,
omnesis service logs collector shows that container, and the collector stops
and starts with it.
With no version flag, the installer asks the image registry for its tags, picks the
highest stable release available for every image the stack needs, and records that tag so
updates and rollbacks are repeatable. OMNESIS_IMAGE_REPO changes the registry
used for both the lookup and the pull. Updating is
omnesis update, as on any other install.
Tag discovery works only on registries that allow anonymous reads. For a private registry,
log Docker in first, then pin an exact release with
--version. Paste the token only at Docker's password prompt, never on the
installer's command line:
❯ docker login registry.example.com
# enter the registry credentials at Docker's password prompt
❯ curl -fsSL https://omnesis.dev/install.sh | OMNESIS_IMAGE_REPO=registry.example.com/omnesis sh -s -- --docker --version X.Y.Z
The account you log in with must itself have access to the image. If access is denied, the
installer prints the docker login <registry> command to run; it never
runs that command or reads the token itself.
Without a terminal, as in a provisioning script or an AI agent running it for you, the
installer asks nothing and takes the answer Enter would give: the default embedding model,
and encryption at rest from a passphrase file it generates in the config directory,
readable only by you. It prints each default with the flag that changes it, and the
recovery code. A Docker collector's pairing code has no default; the installer checks for
--code before it pulls anything.
❯ curl -fsSL https://omnesis.dev/install.sh | sh -s -- --docker
To answer otherwise, pass --embedder <id> or --no-model,
and --no-keyring or --keyring-passphrase-file naming a
passphrase file you created inside the config directory. A container has no OS keyring, so
a passphrase file is the only way to encrypt at rest, and the containers see only that
directory:
❯ mkdir -m 700 -p ~/.config/omnesis
❯ (umask 077; od -An -N32 -tx1 /dev/urandom | tr -d ' \n' > ~/.config/omnesis/keyring.pass)
❯ curl -fsSL https://omnesis.dev/install.sh | sh -s -- --docker --embedder nomic-embed-text-v1.5.Q8_0 --keyring-passphrase-file ~/.config/omnesis/keyring.pass
The installer prints no recovery code for a passphrase file you supply; create one once
the gateway runs, with omnesis keyring export-recovery --backend passphrase,
and store it away from the server.
A second machine that only collects can run its collector in a container too:
❯ curl -fsSL https://omnesis.dev/install.sh | sh -s -- --docker --collector --gateway-url https://<gateway-host>:7600 --trust-fingerprint sha256:<fingerprint>
It asks for a pairing code minted on the gateway host (omnesis devices pair --kind collector); without a terminal, pass it with --code. Re-running the line on a
collector that is paired already keeps its device and needs no code; a new
--code, or another --gateway-url, pairs it again as a new
device.
Choose a topology
The default --docker install runs a gateway and a collector as separate
containers. Use --docker --combined for one container running both, or
--docker --gateway-only when every collector will run elsewhere. A combined
container stops both processes if either fails and drains the collector before stopping
the gateway. Every topology accepts additional native collectors: on a Mac, run the
installer with --collector --gateway-url https://<server>:7600
and redeem a fresh collector pairing code from the gateway. macOS sources need a native
Mac collector; mounting Mac files into a Linux container does not supply macOS APIs. On
the machine that runs Docker itself, the native collector installs
beside the Docker install.
On Linux, add --docker-network host for Bonjour/mDNS discovery on the LAN.
Host networking shares the host interfaces and ports, including UDP 5353; allow multicast
on the trusted LAN in the host firewall. Port mappings are unnecessary in this mode.
Bridge mode is the default and needs an explicit gateway URL on other devices. Phones are
offered the host's own addresses at the published port, which the host's
omnesis command records on every run, never the container's. Publishing UDP
5353 alone does not bridge multicast discovery. Docker Desktop runs inside a VM; use an
explicit URL there. Only run one gateway on each chosen port.
OAuth callback ports 3000–3003 are published on host loopback in bridge mode. A provider
redirect to localhost refers to the computer running the browser. For a headless server
use the portal authentication flow where offered, or forward each needed port over SSH
(for example ssh -L 3000:127.0.0.1:3000 user@<server>) before opening
the authorization URL locally. Do not expose callback ports to the internet.
A collector sees only files mounted into its container. For a filesystem source, add a
read-only bind mount to the collector service (or gateway in
combined mode), such as /srv/source-data:/sources/data:ro, then configure the
source with its container path, /sources/data. Grant the container UID read
and directory traversal permissions on that source directory. Mount only the directories
that source needs. Store credentials, writable source caches and databases inside the
persistent config directory, rather than in the image or the read-only source mount.
Ordinary updates preserve Compose edits; rerunning the installer regenerates the file, so
retain and reapply your additional mounts when reconfiguring.
Standalone Compose
The repository includes compose.yaml for a combined container, independent of
the installer. Set OMNESIS_IMAGE_TAG to an exact published version and
OMNESIS_PASSPHRASE_PATH to an absolute path outside the repository containing
a strong random passphrase. The container runs as UID/GID 10001:10001; grant that identity
read access to the file without making it readable by other users. Compose file secrets
are bind mounts, not an encrypted secret store. Set OMNESIS_TLS_EXTRA_NAMES
to the server DNS names/IP addresses clients will use before first boot.
Before starting the daemons, run
docker compose run --rm --no-deps --entrypoint omnesis gateway keyring init --backend
passphrase, then
docker compose run --rm --no-deps --entrypoint omnesis gateway keyring export-recovery
--backend passphrase. Store the recovery material offline, then run docker compose up -d. The
named state volume contains the complete configuration directory. Stop with
docker compose down; adding --volumes destroys it. This
standalone example is managed through Compose; use the installer for its host CLI wrapper
and transactional omnesis update integration.
On Linux Docker Engine, add the included compose.host.yaml override for host
networking: docker compose -f compose.yaml -f compose.host.yaml up -d. Use
both -f flags on subsequent Compose commands, including run and
down. The override removes bridge port mappings, honors
OMNESIS_PORT for the gateway, and keeps OAuth callback listeners on host
loopback. It is not a Docker Desktop networking configuration.
Unraid
Enable Docker in Unraid Settings, then open the server terminal. Choose a persistent
appdata directory on a local pool, such as /mnt/cache/appdata/omnesis; keep
SQLite databases off SMB/NFS shares and do not let a mover relocate active database files.
Check the pool name on your server. Run
curl -fsSL https://omnesis.dev/install.sh |
OMNESIS_CONFIG_DIR=/mnt/cache/appdata/omnesis sh -s -- --docker --combined
--docker-network host. Follow the encryption prompts and store recovery material away from the server.
The generated Compose file stays in appdata. Manage it with
docker compose -f /mnt/cache/appdata/omnesis/docker-compose.yml and use
omnesis update for updates. If Compose is unavailable, install the Compose
plugin through your Unraid administration tooling before running the installer. A manual
Unraid Docker template can use the combined image, host networking, UID/GID 10001:10001
and an appdata mount at /var/lib/omnesis. Set
OMNESIS_OAUTH_CALLBACK_HOST=127.0.0.1 with host networking to keep callback
listeners on loopback; initialize its passphrase keyring before starting, as in the
standalone Compose instructions. Never enable privileged mode or mount the Docker socket
into the daemon.
Persist the entire config directory: all databases and sidecars, attachments, source caches, credentials, tokens, TLS keys/certificates, sealed keyring, configuration and Compose metadata. The optional backup command captures the gateway's data; filesystem snapshots require both daemons to be stopped for consistency. Separately mounted passphrase files and supplied TLS material live outside that directory. A passphrase stored beside encrypted data protects neither against theft of that complete directory nor a host administrator. Losing both unlock and recovery material loses encrypted data.
Tailscale can run on the Docker host (including the Unraid host); no privileged VPN container is required. Pair other machines using its reachable DNS name and the TLS configuration below. External MCP clients use the same gateway HTTPS endpoint as native installs. A self-signed certificate needs explicit client trust; clients that require publicly trusted HTTPS need a Tailscale or domain certificate and a reachable route.
A native collector beside a Docker install
The usual Mac setup runs the gateway in Docker and a native collector for the Apple
sources on the same Mac. Run the --collector line the Docker install printed
on that machine. The installer finds the Docker install and puts the collector beside it,
sharing nothing with it:
| Docker install | Native collector beside it | |
|---|---|---|
| Command | omnesis |
omnesis-collector |
| Config directory | ~/.config/omnesis |
~/.config/omnesis-collector |
| Code | the images | a source checkout at ~/omnesis-collector |
| Daemons | containers | a collector service (LaunchAgent or systemd user unit) |
| Device | the container's collector, <host>-collector |
a device of its own, with its own token:
<host>-mac-collector on a Mac (<host>-native-collector
on Linux)
|
When the gateway is the one on this machine, the collector dials it at
https://localhost:<port> unless --gateway-url names
another address, and on a terminal the installer mints the pairing code with
omnesis itself. Without a terminal, run
omnesis devices pair --kind collector on the same machine and pass the code
with --code.
<host> is the machine's short name, lowercased, without the
.local a Mac adds: Maya-MacBook.local pairs as
maya-macbook-mac-collector. A code minted with a name keeps that name, and a
collector paired before keeps the one it has. The installer prints the name the gateway
registered, which is what --device takes.
❯ curl -fsSL https://omnesis.dev/install.sh | sh -s -- --collector
# sources, devices and status: the Docker gateway, as before
❯ omnesis sources add apple-notes --device 'maya-macbook-mac-collector'
# the native collector itself
❯ omnesis-collector service status
❯ omnesis-collector update
❯ omnesis-collector uninstall
Sources, devices and status stay on omnesis, which holds the gateway's admin
token; omnesis-collector manages the collector's own service, update and
removal, talks to the gateway the collector is paired with, and names itself in every hint
it prints. Each uninstall removes only its own install.
omnesis-collector uninstall offers to revoke its device on this machine's
Docker gateway (yes by default; --yes accepts it): the sources it hosts stay,
with their data, but stop syncing until you move or detach them. With
--purge it also deletes ~/.config/omnesis-collector and its keys
in the OS keyring, keeping the keyring's root key while another native install of yours
uses it; the Docker install keeps its own keys in its config directory. The reverse order
is refused: a Docker install does not take over the omnesis command and
config directory of a native install whose service is still registered. Remove that one
first (omnesis uninstall), install Docker, then the native collector beside
it. The collector beside a Docker install is installed from source;
--method package is not available for it.
Host folders
A container sees the install's config directory and nothing else of the machine. A source
that reads a folder, such as an Obsidian vault or a Maildir, needs that folder shared with
the collector's container. When you add one, ~ and relative paths mean the
machine you type on, not the container. On a terminal, a folder the container cannot see
is offered for sharing; the collector's container is then recreated with it, and the add
continues:
❯ omnesis sources add obsidian-notes ~/Documents/Vault
/Users/maya/Documents/Vault is a folder on this machine. The collector runs in a container that sees only the folders shared with it. Share /Users/maya/Documents/Vault with the collector, read-only? [Y/n]
A shared folder is mounted read-only at the same absolute path, so the source's settings
name the path you know. Manage them directly with omnesis folders (the list),
omnesis folders share <path> and
omnesis folders unshare <path>. The list is kept in
shared-folders in the config directory; re-running the installer and
omnesis update keep every share.
Without a terminal there is nobody to offer the share to: the add fails, naming the
omnesis folders share command to run. Share the folder first, then add the
source with its settings as flags (see
adding a source from a script). Sharing
recreates the collector's container (on --combined, the gateway's too) and
returns once it is back; the add waits for the collector to reconnect.
❯ omnesis folders share ~/Documents/Vault
❯ omnesis sources add obsidian-notes --set vaultPath=~/Documents/Vault
TLS in Docker
Under Docker the gateway serves its own self-signed certificate unless it is given one. That is enough for the CLI, the phone apps and collectors. It is not enough for browsers or the browser extension, which cannot connect through it at all. The container cannot reach the host's Tailscale daemon, so the installer issues the certificate on the host, the machine that runs Docker, as it does for a native install:
-
When Tailscale is running on the host (on a Mac, the app counts, including the App Store
one), it asks
Tailscale detected — set up a trusted HTTPS certificate for <name>? [Y/n], Yes by default. Without a terminal it goes ahead unasked unless you pass
--no-tls. -
It runs
tailscale certfor the host's MagicDNS name, writes the pair to~/.config/omnesis/tls/tailscale.crtandtailscale.key, and wires it as if you had passed it with--tls-certand--tls-key. The containers dial the gateway by that name. The banner, the pairing addresses and the join command for another machine use it too. -
It registers a job on the host that renews the certificate daily: a launchd agent
(
dev.omnesis.tls-renew) on macOS, and a systemd timer (omnesis-tls-renew.timer) on Linux. That is a user timer, or a system timer when Docker runs as root. The job runs~/.local/share/omnesis/omnesis-tls-renew.sh, which lives outside the config directory the containers can write. The gateway picks each renewal up within the hour, or at once, since the job also runsomnesis tls reload. -
A re-run keeps the certificate and its job without asking again, even while Tailscale is
down.
omnesis uninstallremoves the job with the install.
The host needs what a native install needs: it has joined
the tailnet, with MagicDNS and HTTPS certificates turned on in the admin console. When
HTTPS certificates are off, the installer says so and keeps the self-signed certificate.
On Linux, tailscale cert needs your user to be the machine's Tailscale
operator; the installer asks sudo for that permission, which changes nothing
on the tailnet. Without Tailscale, or when you decline, the closing banner warns that
browsers and the extension cannot connect, and names the re-run that fixes it. The
installer refuses --mkcert under --docker, because the container
cannot install a mkcert authority in your browser. To use your own certificate instead,
issue it on the host and hand it over, as below.
The self-signed certificate covers localhost, the gateway's mDNS names, the
service name gateway that the collector container dials, and the host names
and LAN addresses the installer passes in. The banner prints the join command for another
machine with --trust-fingerprint. A certificate minted earlier is kept,
because paired phones and collectors pin it. If it no longer covers the host's name or
addresses, omnesis tls renew --force mints a new one, and every phone and
collector paired with the old one must pair again.
-
Issue on the hostTailscale or mkcert writes the certificate, its key and, for a private authority,
the root CA into
~/.config/omnesis/tls/ -
Installer checksThe
--tls-*files sit in the config directory, the key matches, and the certificate is valid and names a host - Mounted into the containersthe config directory, at the same path
- Gateway container serves itand answers to every name the certificate covers
Inside the compose network
-
Collector and updaterdial
https://<name>:7600and verify the name, trustingrootCA.pemwhen you passed--tls-ca
From outside
-
Browser, extension, phonesdial
https://<name>:<published port>; a browser trusts it through a public chain or the authority you installed
A certificate you renew yourself has to keep the container account's read access. Keep
private keys mode 0600 and owned by the daemon UID/GID (10001:10001 for root-run Docker
installs), or use an equally restricted group grant. A renewal command running as root can
replace a key with a root-owned file the container cannot read. Replace the files
atomically, and check omnesis tls status after renewing.
With mkcert, issue the certificate for the names you will use and pass the authority's
root with --tls-ca. Your browser needs that root installed once, and phones
pair against the certificate by fingerprint.
❯ mkcert -cert-file ~/.config/omnesis/tls/mkcert.crt -key-file ~/.config/omnesis/tls/mkcert.key studio-northstar.local localhost
❯ cp "$(mkcert -CAROOT)/rootCA.pem" ~/.config/omnesis/tls/
❯ curl -fsSL https://omnesis.dev/install.sh | sh -s -- --docker --tls-cert ~/.config/omnesis/tls/mkcert.crt --tls-key ~/.config/omnesis/tls/mkcert.key --tls-ca ~/.config/omnesis/tls/rootCA.pem
The installer refuses a file outside the config directory or linked from elsewhere, the
gateway's own tls/cert.pem and key.pem, a key that does not
match, an expired certificate, one that chains to no trusted root (unless
--tls-ca names its authority), and one that names no specific host. A host
that only collects (--docker --collector) takes --tls-ca alone,
to verify a gateway behind a private authority.
Renewing a certificate you handed over is up to you: re-issue into the same files with the
tool that made them. The gateway picks the new certificate up within the hour, or at once
after omnesis tls reload, without a restart. A later run of the installer
without the flags keeps the certificate it recorded. Handing over a certificate of your
own removes the Tailscale renewal job an earlier run registered. What a renewal means for
paired clients is in
Clients that pinned the old certificate.
What a container cannot do
-
The Apple sources need a Mac. Apple Notes, Messages, Calendar,
Reminders, Contacts, Things and Screen Time read macOS databases that do not exist in a
Linux container. The usual setup is a Docker gateway with a native collector on the Mac,
installed with the
--collectorcommand the gateway's install prints; on the Docker machine itself it installs beside the Docker install. Sources that sync over the network work fully in the container. - Host folders are shared one by one. The containers see the config directory; a folder a source reads is shared read-only with the collector's container.
-
Discovery does not cross the Docker bridge. A container collector
cannot search the LAN for a gateway, so
--docker --collectorrequires--gateway-url, naming the gateway by a name its certificate covers. -
Certificates are issued on the host. The container cannot run
tailscale certormkcert. The installer issues a Tailscale certificate on the host and a host job renews it; any other certificate is one you hand it. The gateway renews only its own self-signed default. -
There is no OS keyring in a container. Encryption at rest uses a
passphrase file instead: the installer generates one by default, readable only by you,
at
~/.config/omnesis/keyring.pass, and the containers read it at start. Keep that file; without it the data cannot be opened. An install without encryption at rest adds it later withomnesis secureon the same machine (see Encryption in Docker). -
The OAuth callback ports stay published. A provider redirects your
browser to
http://localhost:3000–3003, so the collector container publishes those host ports; they cannot move without re-registering every OAuth client. If something else holds one, free it. A host that will never complete an OAuth sign-in can let the kernel pick the ports withOMNESIS_OAUTH_HOST_PORTS=ephemeral.
From source
For development, use the Node version recorded in .nvmrc. Source builds
require Node 24.16 or newer within Node 24, or Node 26.1 or newer. Run the two daemons
directly from a checkout:
❯ git clone https://github.com/omnesis-dev/Omnesis.git
❯ cd Omnesis && npm install
# terminal 1
❯ npm run gateway
# terminal 2
❯ npm run collector
# any CLI command
❯ npm run cli -- status
npm run gateway and npm run collector are the checkout's
equivalents of omnesis gateway serve and omnesis collector run.
npm run collector and npm run cli trust the gateway's
self-signed certificate for you. To run them as supervised services instead of in two
terminals, use npm run cli -- service install.
To change Omnesis rather than only run it, read the contribution guide first. It covers the repository layout, the checks a pull request must pass, and the tests each kind of change needs.
For an isolated test gateway from a development checkout, use
scripts/dev-instance.sh start --session "Codex: navigation" --purpose "Try the new
navigation". Session and purpose are optional, but strongly recommended when several agents or test
gateways run in parallel. The portal shows them in a Test gateway card in its left menu.
Choose a separate OMNESIS_CONFIG_DIR and available
OMNESIS_GATEWAY_PORT for each instance. Use --bare for an empty
synthetic instance or --real to add real sources yourself.
scripts/dev-instance.sh info prints a portal login link with its token; treat
it as a credential and share it only with the person testing the feature.
Uninstall
omnesis uninstall removes Omnesis from the machine it runs on: everything it
finds, or only the parts you name. Your data stays in the config directory unless you add
--purge, which deletes it.
# see what would go, then remove it
❯ omnesis uninstall --dry-run
❯ omnesis uninstall
# only the OpenClaw integration
❯ omnesis uninstall openclaw
# everything, with the data and keys
❯ omnesis uninstall --purge
Without a component it lists what it found, lets you pick, and asks before it changes anything. Name components to remove only those:
| Component | What it removes |
|---|---|
gateway |
The gateway service: the systemd user unit or LaunchAgent, a
hardened gateway (its service, releases
and admin command, through sudo), or a Docker install.
|
collector |
The collector service. |
openclaw, hermes |
The agent integration omnesis connect installed: the plugin
(unregistered through OpenClaw's own command), the skill, the integration's state
and credentials, and the Omnesis entries in the harness's config and
.env. Everything else in those files stays as it was.
|
claude-code, codex |
The Omnesis plugin, its marketplace and the omnesis MCP server,
through each tool's own plugin and mcp commands.
|
cli |
The omnesis command: the installer's source checkout, the global
package, ~/.local/bin/omnesis, ~/.local/lib/omnesis, and
the installer's PATH line (marked # Added by the Omnesis installer)
when nothing else lives in ~/.local/bin.
|
Flags:
-
--purgealso deletes the config directory (data, tokens, credentials and keys), the service logs and thedev.omnesisentries in the macOS Keychain or Linux Secret Service, and a hardened gateway's/var/lib/omnesis-gatewayand/etc/omnesis-gateway. It is refused while anything that uses the config directory would stay. The keyring's root key is shared by every Omnesis config directory of your account, so it stays while another one remains, such as a named instance's. --dry-runprints the plan and changes nothing.-
--yesskips the confirmation; without a terminal it is required.--jsonreports every step and its outcome. -
--instance <name>removes a named parallel instance instead of the default one;--dir <path>names a harness home outside its default, withopenclaworhermes. -
--discard-local-changesremoves the installer's source checkout even when it has local changes. A checkout the installer did not clone, a git worktree, and a launcher or PATH line of your own are never removed.
Every step is independent and safe to repeat: a step that fails is reported with what is
left and how to finish it, the others still run, and running the command again picks up
where it stopped. It waits for nothing on the network and works with the gateway gone. If
the installed omnesis no longer starts, run
npm run cli -- uninstall in a checkout of the repository (after
npm ci): it finds the install from what is on disk and removes it the same
way.
Docker. On a Docker host, omnesis uninstall runs in the
launcher on the host, not in a container: it takes the containers down and removes every
local image of the install's repositories (omnesis-gateway,
omnesis-collector, omnesis-combined and
omnesis-updater under its registry), older releases included, then removes
the compose file, the launcher and the installer's PATH line (kept, and said, when other
programs live in ~/.local/bin), and with --purge the config
directory. An install is removed as a whole. On a machine that only collects, it ends by
reminding you to remove its device on the gateway host, as a native collector's does. A
native collector beside it stays; remove that one
with omnesis-collector uninstall, which in turn never touches the Docker
install.
What only you can do. The command says which of these apply when it finishes:
-
On a second machine, remove its device from the gateway as well. For a collector, first
move or detach the sources it hosts (see
Managing sources); then, on the gateway host, run
omnesis devices revoke <device> --forget; the uninstall prints the device's name. Revoking a harness machine's device also signs its agent out of its connection. - Restart OpenClaw or Hermes so the running harness stops loading the plugin.
- On a Mac, remove the collector from Full Disk Access in System Settings.
-
The prerequisites the installer may have added (Node, git, build tools) and the
mkcertcertificate authority stay;mkcert -uninstallremoves the authority if nothing else uses it.