Commands, package names, and image names on this page come from the open-source project that Mibyan Desktop is built on, and can differ from the Mibyan Desktop installer. For the supported Mibyan install and update path, see Install and update.
What’s different from the standard installThe
curl | bash installer manages Python, Node, and dependencies itself. The Nix flake replaces all of that — every Python dependency is a Nix derivation built by uv2nix, and runtime tools (Node.js, git, ripgrep, ffmpeg) are wrapped into the binary’s PATH. There is no runtime pip, no venv activation, no npm install.For non-NixOS users, this only changes the install step. Everything after (mibyan setup, mibyan gateway install, config editing) works identically to the standard install.For NixOS module users, the entire lifecycle is different: configuration lives in configuration.nix, secrets go through sops-nix/agenix, the service is a systemd unit, and CLI config commands are blocked. You manage mibyan the same way you manage any other NixOS service.Runtime pins
PM’s tool lock is also a Nix build input.nix/npm-pinned.nix reads the npm
pin, and nix/pm-packages.nix exposes matching archives as pm-NAME derivations:
nix/pythonLock.nix reads Python’s major/minor from pm/lock.json.
The uv2nix environment, package overrides, plugin packages, and developer shell
use that interpreter family. If the pinned nixpkgs lacks that family, evaluation
stops instead of selecting a different Python.
Native Nix evaluation and builds remain CI gates. Update through Nix. Do not
repair a Nix store path with pip.
Prerequisites
- Nix with flakes enabled — Determinate Nix recommended (enables flakes by default)
- API keys for the services you want to use (at minimum: an OpenRouter or Anthropic key)
Quick Start (Any Nix User)
No clone needed. Nix fetches, builds, and runs everything:nix profile install, mibyan, mibyan-agent, and mibyan-acp are on your PATH. From here, the workflow is identical to the standard installation — mibyan setup walks you through provider selection, mibyan gateway install sets up a launchd (macOS) or systemd user service, and config lives in ~/.mibyan/.
NixOS Module
The flake exportsnixosModules.default — a full NixOS service module that declaratively manages user creation, directories, config generation, secrets, documents, and service lifecycle.
This module needs NixOS. Mibyan is an agent for one person. If you want an agent for one person and not a system service, use the Home Manager module. That module runs on NixOS and on each other system that Home Manager supports.
Add the Flake Input
Minimal Configuration
nixos-rebuild switch creates the mibyan user, generates config.yaml, wires up secrets, and starts the gateway — a long-running service that connects the agent to messaging platforms (Telegram, Discord, etc.) and listens for incoming messages.
Container-aware CLI
When Users listed in The CLI auto-detects when sudo is needed and uses it transparently. Without this, you’ll need to run
container.enable = true and addToSystemPackages = true, every mibyan command on the host automatically routes into the managed container. This means your interactive CLI session runs inside the same environment as the gateway service — with access to all container-installed packages and tools.- The routing is transparent:
mibyan chat,mibyan sessions list,mibyan --version, etc. all exec into the container under the hood - All CLI flags are forwarded as-is
- If the container isn’t running, the CLI retries briefly (5s with a spinner for interactive use, 10s silently for scripts) then fails with a clear error — no silent fallback
- For developers working on the mibyan codebase, set
mibyan_DEV=1to bypass container routing and run the local checkout directly
container.hostUsers to create a ~/.mibyan symlink to the service state directory, so the host CLI and the container share sessions, config, and memories:hostUsers are automatically added to the mibyan group for file permission access.Podman users: The NixOS service runs the container as root. Docker users get access via the docker group socket, but Podman’s rootful containers require sudo. Grant passwordless sudo for your container runtime:sudo mibyan chat manually.Verify It Works
Afternixos-rebuild switch, check that the service is running:
Choosing a Deployment Mode
The module supports two modes, controlled bycontainer.enable:
To enable container mode, add one line:
Container mode auto-enables
virtualisation.docker.enable via mkDefault. If you use Podman instead, set container.backend = "podman" and virtualisation.docker.enable = false.Cron on a native install needs a lingering service userScheduled cron jobs are launched in a transient
systemd-run --user --scope so a gateway restart cannot kill a running job. That needs a systemd user manager for the service uid, which a system service only gets when the uid lingers. With createUser = true the module sets users.users.<user>.linger = true (nixpkgs ≥ 25.05), orders the gateway after linger-users.service, and waits briefly for /run/user/<uid>/bus before starting. If you declare the user yourself (createUser = false), set linger = true on it or run sudo loginctl enable-linger <user> once; otherwise cron degrades to unscoped workers (or fails closed under cron.require_restart_safe_scope: true).Configuration
Declarative Settings
Thesettings option accepts an arbitrary attrset that is rendered as config.yaml. It supports deep merging across multiple module definitions (via lib.recursiveUpdate), so you can split config across files:
config.yaml on disk, but user-added keys that Nix doesn’t touch are preserved. This means if the agent or a manual edit adds keys like skills.disabled or streaming.enabled, they survive nixos-rebuild switch.
Model naming
settings.model.default uses the model identifier your provider expects. With OpenRouter (the default), these look like "anthropic/claude-sonnet-4" or "google/gemini-3-flash". If you’re using a provider directly (Anthropic, OpenAI), set settings.model.base_url to point at their API and use their native model IDs (e.g., "claude-sonnet-4-20250514"). When no base_url is set, Mibyan defaults to OpenRouter.Escape Hatch: Bring Your Own Config
If you’d rather manageconfig.yaml entirely outside Nix, use configFile:
settings entirely — no merge, no generation. The file is copied as-is to $mibyan_HOME/config.yaml on each activation.
Customization Cheatsheet
Quick reference for the most common things Nix users want to customize:Secrets Management
Bothenvironment (non-secret vars) and environmentFiles (secret files) are merged into $mibyan_HOME/.env at activation time (nixos-rebuild switch). Mibyan reads this file on every startup, so changes take effect with a systemctl restart mibyan-agent — no container recreation needed.
sops-nix
agenix
OAuth / Auth Seeding
For platforms requiring OAuth (e.g., Discord), useauthFile to seed credentials on first deploy:
auth.json doesn’t already exist (unless authFileForceOverwrite = true). Runtime OAuth token refreshes are written to the state directory and preserved across rebuilds.
Documents
Mibyan reads files from two directories. Thus there are two options. Use the option for the directory that the file must go into.documents installs into the working directory of the agent, which is workingDirectory. The agent reads its project context from that workspace:
mibyanHomeFiles installs into mibyan_HOME. Mibyan reads the identity file and the memory files of the agent from that directory. SOUL.md and memories/ work only from there. A SOUL.md in documents makes a workspace file. Mibyan does not load that file as the identity:
mibyanHomeFiles needs no workingDirectory, because the module owns the mibyan_HOME directory. Most users want mibyanHomeFiles.
MCP Servers
ThemcpServers option declaratively configures MCP (Model Context Protocol) servers. Each server uses either stdio (local command) or HTTP (remote URL) transport.
Stdio Transport (Local Servers)
HTTP Transport (Remote Servers)
HTTP Transport with OAuth
Setauth = "oauth" for servers using OAuth 2.1. Mibyan implements the full PKCE flow — metadata discovery, dynamic client registration, token exchange, and automatic refresh.
$mibyan_HOME/mcp-tokens/<server-name>.json and persist across restarts and rebuilds.
Sampling (Server-Initiated LLM Requests)
Some MCP servers can request LLM completions from the agent:Managed Mode
When mibyan runs via the NixOS module, the following CLI commands are blocked with a descriptive error pointing you toconfiguration.nix:
This prevents drift between what Nix declares and what’s on disk. Detection uses two signals:
- The
mibyan_MANAGEDenvironment variable. The service sets it, and the gateway process reads it. - The
.managedmarker file inmibyan_HOME. The activation script writes it, and an interactive shell reads it. Thus the CLI also blocks a command such asdocker exec -it mibyan-agent mibyan config set ....
sudo nixos-rebuild switch. The Home Manager module gives home-manager switch.
Home Manager Module
The flake also exportshomeManagerModules.default. Mibyan is an agent for one person. The credentials, the memory, the sessions and the cron jobs all belong to that person. Thus a user service is the correct shape on a personal machine. It runs on each distribution that Home Manager supports, and not only on NixOS.
The option set is the same set that the NixOS module uses. It is services.mibyan-agent, with the same settings, environmentFiles, documents, mcpServers, extraPlugins and backend options. Each example above works here without a change. Only the necessary parts are different:
Add the Flake Input
home-manager.users.<name> in a NixOS or nix-darwin configuration:
home-manager switch makes ~/.mibyan, writes config.yaml, builds .env and starts the gateway as a user service.
Running the Desktop / Dashboard Backend
gateway.enable runs the messaging gateway for Telegram, Discord, Slack and the other platforms. Mibyan Desktop and the web dashboard connect to a different process, which is mibyan serve or mibyan dashboard. backend.mode runs that process with the gateway:
serve runs without a user interface. It gives the /api/ws and /api/pty sockets that Mibyan Desktop connects to, and it does not build the web application. dashboard gives all of that, and also serves the browser admin panel. Both processes use one mibyan_HOME with the gateway. Thus the sessions, the skills, the memory and the cron jobs are the same for all of them. backend.mode works in the same way on the NixOS module, but not in container mode.
Verify It Works
Container Architecture
This section is only relevant if you’re using
container.enable = true. Skip it for native mode deployments./nix/store is bind-mounted — it brings its own interpreter and all dependencies, so there’s no reliance on the container’s system libraries. The container entrypoint resolves through a current-package symlink: /data/current-package/bin/mibyan gateway run --replace. On nixos-rebuild switch, only the symlink is updated — the container keeps running.
What Persists Across What
The container is only recreated when its identity hash changes. The hash covers: schema version, image,
extraVolumes, extraOptions, and the entrypoint script. Changes to environment variables, settings, documents, or the mibyan package itself do not trigger recreation.
GC Root Protection
ThepreStart script creates a GC root at ${stateDir}/.gc-root pointing to the current mibyan package. This prevents nix-collect-garbage from removing the running binary. If the GC root somehow breaks, restarting the service recreates it.
Plugins
The NixOS module supports declarative plugin installation — no imperativemibyan plugins install needed.
Directory Plugins (extraPlugins)
For plugins that are just a source tree with plugin.yaml + __init__.py (e.g., mibyan-lcm):
$mibyan_HOME/plugins/ at activation time. Mibyan discovers them via its normal directory scan. Removing a plugin from the list and running nixos-rebuild switch removes the symlink.
Entry-Point Plugins (extraPythonPackages)
For pip-packaged plugins that register via [project.entry-points."mibyan_agent.plugins"] (e.g., rtk-mibyan):
site-packages is added to PYTHONPATH in the mibyan wrapper. importlib.metadata discovers the entry point at session start.
Optional Dependency Groups (extraDependencyGroups)
For optional extras declared in mibyan-agent’s pyproject.toml, use extraDependencyGroups to include them in the sealed venv at build time. This is required for any extra not in the default [all] set — on Nix, runtime installation into the read-only store is not possible.
pyproject.toml is authoritative for the complete list and platform markers.
Memory providers that live in the plugin catalog rather than in the Mibyan tree (e.g. Hindsight) are not extras. Install them like any catalog plugin with
mibyan plugins install hindsight, or declaratively via extraPlugins pointing at the plugin’s source tree.
Or use the pre-built #messaging or #full flake packages instead of per-extra configuration (see Quick Start).
When to use which:
Combining Both
A directory plugin with third-party Python dependencies needs both options:Using the Overlay
External flakes can override the package directly:Plugin Configuration
Plugins still need to be enabled inconfig.yaml. Add them via the declarative settings:
A build-time collision check prevents plugin packages from shadowing core mibyan dependencies. If a plugin provides a package already in the sealed venv,
nixos-rebuild fails with a clear error.Development
Dev Shell
The flake provides an editable Python environment with the lock-derived interpreter and thedev dependency group. mibyan_PYTHON points to its interpreter. It does not install
Python dependencies into a repository-local .venv. The shell also provides
Node.js and runtime tools. Its npm hook refreshes JS workspaces when their inputs change.
direnv (Recommended)
The included.envrc activates the dev shell automatically:
Flake Checks
The flake includes build-time verification that runs in CI and locally:Options Reference
Core
Configuration
Secrets & Environment
Documents
MCP Servers
Service Behavior
Backend (mibyan serve / mibyan dashboard)
This option runs the process that Mibyan Desktop and the web dashboard connect to, with the gateway. You cannot use it with container.enable.
Home Manager only
programs.mibyan-agent (Home Manager only)
Home Manager separates “install this application for me” from “run this
daemon”. services.mibyan-agent keeps the state, the configuration and the
daemons. programs.mibyan-agent installs what you use, and reads
mibyanHome and the backend address from the services.
mibyan_HOME itself. A desktop menu reads no shell
profile, so the value that programs.mibyan-agent.enable exports with
home.sessionVariables reaches an interactive shell only. Without the
value in the launcher, the application opens ~/.mibyan while the
services use mibyanHome, and you see no sessions and no keys.
With backend.sessionTokenFile, the application connects to the backend
of the service instead of starting one of its own. Both sides read the
file at start time, so the token enters no Nix store path. Without the
option, each side runs its own backend.
services.mibyan-agent.installPackage was removed by this split. A
configuration that still sets it gets an error that names the
replacement.
Container (NixOS only)
Directory Layout
Native Mode
Home Manager
Container Mode
Same layout, mounted into the container:Updating
current-package symlink is updated and the agent picks up the new binary on restart. No container recreation, no loss of installed packages.
Troubleshooting
Service Logs
Container Inspection
Force Container Recreation
If you need to reset the writable layer (fresh Ubuntu):Verify Secrets Are Loaded
If the agent starts but can’t authenticate with the LLM provider, check that the.env file was merged correctly:

