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 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:

  1. Checks the platform: macOS or Linux, amd64 or arm64. Anything else is refused.
  2. Installs Node 24 when no supported Node is on your PATH: Homebrew on macOS, NodeSource on Linux.
  3. For a Linux source install, installs make, C/C++ compilers and Python 3 if they are missing.
  4. Installs the newest stable release of the omnesis CLI (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.
  5. 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. --mkcert uses a mkcert certificate instead. Otherwise the gateway keeps its own self-signed certificate. Certificates explains what each one means for browsers and phones.
  6. 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).
  7. Registers the gateway and the collector as user services (launchd agents on macOS, systemd user units on Linux) and starts them.
  8. Downloads the embedding model you chose, so semantic search works from the start.
  9. If codex is installed, offers to set up the agent with a ChatGPT sign-in; then, if the agent is still unassigned and claude is installed, offers to set it up with Claude Code (see First run).
  10. 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.
  11. 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.
Choose the certificate for the agents you want to connect. Without a Tailscale certificate or a domain of your own, the gateway serves its self-signed certificate, and Claude Code, ChatGPT and the Claude apps cannot connect to it. OpenClaw, Hermes and the phone apps work as they are, and Codex works with one setting, 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:

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.

  1. Issue on the hostTailscale or mkcert writes the certificate, its key and, for a private authority, the root CA into ~/.config/omnesis/tls/
  2. Installer checksThe --tls-* files sit in the config directory, the key matches, and the certificate is valid and names a host
  3. Mounted into the containersthe config directory, at the same path
  4. Gateway container serves itand answers to every name the certificate covers

Inside the compose network

  1. Collector and updaterdial https://<name>:7600 and verify the name, trusting rootCA.pem when you passed --tls-ca

From outside

  1. Browser, extension, phonesdial https://<name>:<published port>; a browser trusts it through a public chain or the authority you installed
You issue the certificate on the host; the installer checks it, the containers see it through the mounted config directory, and every client, inside or outside Docker, reaches the gateway by a name the certificate covers.

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

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:

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: