Guide - AI & Automation

How to Run nanobot 24/7 on a Dedicated Mac mini (Self-Hosted AI Agent)

nanobot is an ultra-lightweight, open-source, self-hosted personal AI agent framework written in Python (MIT license, about 48.6k GitHub stars in September 2026) from the Data Intelligence Lab at the University of Hong Kong. It runs in a bundled WebUI, a terminal UI or your chat apps (Telegram, Discord, Slack, WhatsApp and a dozen more), schedules its own automations and speaks to 40+ model providers, including a local Ollama server. A dedicated Apple Silicon Mac mini is the natural always-on host: no laptop going to sleep, 1:1 physical hardware, a built-in macOS sandbox, and a flat price from $85/month.

20 min read Updated September 28, 2026

1. Why Run nanobot on a Mac mini?

nanobot is built around a long-lived gateway process: the official docs say to keep nanobot gateway running because it owns background delivery for chat apps, WebUI topics, scheduled automations, local triggers and the heartbeat. That only works on a machine that never sleeps. A dedicated Mac mini from MyRemoteMac gives you exactly that, a physical Apple Silicon Mac, yours alone, online 24/7 with a 99.9% SLA, full root, SSH and VNC access and a WireGuard VPN, for a flat monthly price instead of GPU-tier VPS billing. And because it is macOS, nanobot can use its built-in Seatbelt exec sandbox (sandbox-exec, shipped with macOS) and run a local Ollama model on the same box.

Feature Cloud VPS (AI tier) Mac mini (MyRemoteMac)
Monthly Cost GPU-tier pricing (varies) M4 from $85/mo · M6 from $149/mo (flat, USD)
Exec Sandbox bubblewrap (bwrap, to install) Seatbelt (sandbox-exec), built into macOS
Local LLM (Ollama) Extra cost / limited Native on Apple Silicon unified memory
Always-On Uptime Yes Yes (99.9% SLA)
Hardware Shared, virtualized Dedicated 1:1 physical Mac
Access SSH SSH + VNC + WireGuard VPN, full root

Key Advantage: nanobot's production recommendation is to combine the application-level workspace guard with an OS exec sandbox, bubblewrap on Linux, Seatbelt on macOS. On a Mac mini the sandbox is already there: a single config key confines the agent's shell commands to the workspace filesystem (no network restriction). Pair it with a local Ollama model and routine tasks never leave the machine.

2. Prerequisites

nanobot ships as the PyPI package nanobot-ai with platform wheels for macOS 13+ on Apple Silicon and Intel that bundle the WebUI and the native terminal UI. There is no Node.js, Homebrew or Git requirement for the standard install path. Here is what you need:

  • A dedicated Mac mini from MyRemoteMac, M4 from $85/mo (16 GB / 256 GB) or M6 from $149/mo. Both are Apple Silicon and covered by the macOS arm64 wheel.
  • SSH access to your Mac mini (provided with your MyRemoteMac subscription) and a standard, non-root user account to run nanobot, the project's SECURITY.md says never to run it as root.
  • Python 3.11 or newer and curl. The one-command installer aborts if it only finds an older python3; uv or pipx are optional but recommended when pip reports externally-managed-environment.
  • An LLM provider: an API key (Anthropic, OpenAI, OpenRouter, Gemini, DeepSeek, Groq, Mistral and about 40 others are built in) or a local OpenAI-compatible server such as Ollama running on the same Mac mini.
  • A messaging account on Telegram, Discord, Slack or WhatsApp to reach your agent (Telegram is the quickest: a bot token from @BotFather and no inbound port).

3. Step 1: Connect via SSH and Install nanobot

SSH into your Mac mini with the credentials from your MyRemoteMac dashboard. Run every command in this guide as a normal macOS user, never as root: the LaunchAgent you install later runs inside that user's session.

Connect via SSH and Check Python

# Connect to your Mac mini as a standard user (never root: SECURITY.md)
ssh admin@your-server-ip

# Confirm you are on Apple Silicon
uname -m
# arm64

# nanobot needs Python 3.11 or newer: install a current Python first if this is older
python3 --version
# Python 3.12.x

# curl is used to fetch the one-command installer
which curl

Install nanobot

The project's default path is a one-command installer that installs or upgrades nanobot-ai from PyPI using an active virtual environment, uv, pipx or a managed venv at ~/.nanobot/venv, and prints the exact command it used. Because SSH_CONNECTION is set, it skips the browser WebUI and runs the terminal wizard nanobot onboard --wizard instead. Preview it with --dry-run first. If you prefer to manage the install yourself, uv and pipx are the documented alternatives:

# Option A, official one-command installer: preview, then run
curl -fsSL https://raw.githubusercontent.com/HKUDS/nanobot/main/scripts/install.sh | sh -s -- --dry-run
curl -fsSL https://raw.githubusercontent.com/HKUDS/nanobot/main/scripts/install.sh | sh
# Over SSH it runs the terminal wizard `nanobot onboard --wizard` instead of opening the WebUI.
# The script reads NANOBOT_SKIP_WIZARD / PYTHON from sh's own environment, so set them on sh, not on curl:
# curl -fsSL https://raw.githubusercontent.com/HKUDS/nanobot/main/scripts/install.sh | NANOBOT_SKIP_WIZARD=1 sh
# curl -fsSL https://raw.githubusercontent.com/HKUDS/nanobot/main/scripts/install.sh | PYTHON=/path/to/python3.12 sh

# Option B: uv (isolated tool install, no externally-managed-environment errors)
uv tool install nanobot-ai

# Option C: pipx, or pip inside a virtual environment
pipx install nanobot-ai
# python3 -m pip install nanobot-ai
# pip says "externally-managed-environment"? Use Option A or B: never --break-system-packages

Verify the Installation

If nanobot is not on your PATH in a new shell, use the runner the installer printed (uv tool run, pipx run or the managed venv) or add ~/.local/bin to your PATH:

nanobot --version
# 0.3.5

# `nanobot` not found? Use the runner the installer printed:
uv tool run --from nanobot-ai nanobot --version
pipx run --spec nanobot-ai nanobot --version
~/.nanobot/venv/bin/python -m nanobot --version

4. Step 2: Configure a Model Provider (API or Local Ollama)

nanobot reads everything from ~/.nanobot/config.json (providers, model presets, channels, tools) and keeps memory, skills and generated files in ~/.nanobot/workspace/. The terminal wizard creates both. Config snippets in the official docs use camelCase keys and are meant to be merged into the file, not pasted as a whole. The file is read once at startup, so restart the gateway after every edit.

Run the Terminal Wizard

# Documented path for SSH / headless installs (the installer already ran it unless skipped)
nanobot onboard --wizard
# Creates ~/.nanobot/config.json and ~/.nanobot/workspace/

# Later, after an upgrade: merge new default fields without overwriting your values
nanobot onboard --refresh

Add a Provider and a Model Preset

A preset ties a provider to a model. The docs' example is Anthropic direct with claude-opus-4-5; the most common first-run failure is mixing an API key from one provider with a model ID from another, so always pin the provider in the preset. The official examples reference the key as ${ANTHROPIC_API_KEY}, resolved from the environment of the process that starts nanobot and never written back. That works for foreground sessions started from your shell (environment inheritance by the detached --background process is not documented), but the LaunchAgent generated in Step 4 carries no environment variables, so for a launchd deployment store the key in config.json and lock the file down as SECURITY.md describes:

# Merge into ~/.nanobot/config.json (key from console.anthropic.com)
{
  "providers": {
    "anthropic": { "apiKey": "sk-ant-YOUR_API_KEY_HERE" }
  },
  "modelPresets": {
    "primary": {
      "provider": "anthropic",
      "model": "claude-opus-4-5",
      "maxTokens": 8192,
      "contextWindowTokens": 200000
    }
  },
  "agents": { "defaults": { "modelPreset": "primary" } }
}

# Docs alternative for shell-started sessions: "apiKey": "${ANTHROPIC_API_KEY}"
# (resolved from the environment at startup; an unset variable fails fast with ConfigLoadError)

# Lock the config down (SECURITY.md)
chmod 700 ~/.nanobot && chmod 600 ~/.nanobot/config.json

Optional: Use a Local Model with Ollama

nanobot has a dedicated ollama provider. Start Ollama on the Mac mini separately (see our LLM on Mac mini guide), then point the provider at http://localhost:11434/v1, the model name is the raw Ollama tag, no prefix, and most Ollama setups need no API key. Fallback chains reference preset names, so you can keep a hosted frontier model as the primary and a local preset as fallback (or the reverse):

# Ollama must already be running on the Mac mini (started separately, outside nanobot)
# Merge into ~/.nanobot/config.json: model = raw Ollama tag, no prefix, no API key needed
{
  "providers": {
    "ollama": { "apiBase": "http://localhost:11434/v1" }
  },
  "modelPresets": {
    "primary": {
      "provider": "ollama",
      "model": "llama3.2",
      "maxTokens": 4096,
      "contextWindowTokens": 32768
    }
  },
  "agents": { "defaults": { "modelPreset": "primary" } }
}

# Fallback chains use preset names, not model IDs: context is sized for the smallest window in the chain
# "agents": { "defaults": { "modelPreset": "primary", "fallbackModels": ["localSmall"] } }

Check the Setup and Send a First Message

The docs are explicit: do not add chat apps, MCP servers, fallbacks or a service until this works.

# Check the setup without calling a model
nanobot status

# First one-shot message (since v0.3.5 a bare `nanobot` opens the terminal UI instead)
nanobot -m "Hello!"

5. Step 3: Connect Messaging Channels

nanobot's chat-apps documentation covers Telegram, Discord, Slack, WhatsApp, WeChat, WeCom, Feishu/Lark, DingTalk, QQ, Matrix, Email, Mattermost, Linear, Microsoft Teams, Signal and Mochat, plus the bundled WebUI, the terminal UI and an OpenAI-compatible API (nanobot serve). iMessage is not supported. Channel dependencies are optional features: enable them with nanobot plugins enable <channel> before switching the channel on in config. Telegram is the fastest to get working, long polling by default, so no inbound port on the Mac mini. The Telegram guide recommends pairing-only mode for first setup: omit allowFrom and approve your first DM from the trusted local CLI:

# 1. In Telegram, open @BotFather, send /newbot and copy the token (format: 1234567890:AAF...)

# 2. Enable the optional Telegram feature in the same Python environment as nanobot
nanobot plugins enable telegram

# 3. Merge into ~/.nanobot/config.json: omit allowFrom to use pairing-only mode
{ "channels": { "telegram": { "enabled": true, "token": "1234567890:AAF..." } } }

# 4. The channel must be listed, then run the gateway in the foreground for a first test
nanobot channels status
nanobot gateway

# 5. DM your bot once: it answers with a pairing code. Approve it from a second SSH session:
nanobot agent -m "/pairing approve ABCD-EFGH"

# 6. Stop the foreground gateway with Ctrl+C before installing the service in Step 4

Connect Discord, Slack or WhatsApp

Discord needs a bot token with the MESSAGE CONTENT INTENT enabled in the Developer Portal; keep the default groupPolicy mention so the bot only replies when @mentioned. Slack uses Socket Mode (a bot token plus an app-level token with connections:write) and needs no public URL, but DMs are open by default, set dm.policy to allowlist to get pairing codes. WhatsApp links via QR code and has been pure Python since v0.3.0 (no Node.js bridge); its session database equals full account access, so keep ~/.nanobot/whatsapp-auth at mode 0700 and use a separate number:

# Discord: bot token with MESSAGE CONTENT INTENT enabled in the Developer Portal
{ "channels": { "discord": { "enabled": true, "token": "YOUR_DISCORD_BOT_TOKEN",
    "groupPolicy": "mention", "allowChannels": [] } } }

# Slack, Socket Mode (xoxb bot token + xapp app-level token with connections:write), no public URL
nanobot plugins enable slack
{ "channels": { "slack": { "enabled": true, "botToken": "xoxb-...", "appToken": "xapp-...",
    "dm": { "policy": "allowlist" } } } }

# WhatsApp: the CLI prints a QR code; scan it from WhatsApp > Linked Devices
# (if the QR is not readable in your terminal, run the same command over VNC; our advice: use a separate number)
nanobot plugins enable whatsapp
nanobot channels login whatsapp
{ "channels": { "whatsapp": { "enabled": true, "allowFrom": ["33612345678"] } } }
chmod 700 ~/.nanobot/whatsapp-auth   # session DB = full account access

# Every channel: verify it is listed, then restart the gateway
nanobot channels status

Access Control: allowFrom and Pairing

Every DM-capable channel follows the same rule. With allowFrom omitted, the first DM returns a pairing code you approve from an already-approved chat or the CLI. A non-empty list is a strict allowlist: everyone else is ignored. The wildcard bypasses pairing and lets anyone who can reach the channel talk to the bot, the docs allow it only intentionally or temporarily in a private sandbox, never in production:

# channels.<name>.allowFrom semantics
#   omitted          → pairing-only mode: the first DM returns a code such as ABCD-EFGH
#   ["123456789"]    → static allowlist (your numeric Telegram/Discord ID), everyone else ignored
#   ["*"]            → anyone who can reach the channel: never in production

# Pairing management from the trusted local CLI
nanobot agent -m "/pairing approve ABCD-EFGH"
nanobot agent -m "/pairing deny ABCD-EFGH"
nanobot agent -m "/pairing revoke 123456789"

# Slack / Mattermost need "dm": { "policy": "allowlist" } to issue pairing codes;
# "dm": { "enabled": false } disables DMs where you do not need them

6. Step 4: Harden, Run 24/7 with launchd, Update

Stop the foreground gateway (Ctrl+C) before going further. nanobot documents three ways to keep the gateway alive on macOS: a LaunchAgent it writes itself, a detached background process managed from the CLI, or a plain foreground process for testing. For a headless 24/7 Mac mini use the LaunchAgent, it is the only option launchd supervises and restarts on failure. Harden the configuration first.

Harden Before Going Persistent

The official production recommendation is both the application-level workspace guard and the OS exec sandbox, Seatbelt on macOS. Seatbelt confines the agent's shell commands to the workspace (read-write), media (read-only) and required system paths, masks the ~/.nanobot config directory and points HOME and TMPDIR at the workspace. It does not restrict network access, and restrictToWorkspace alone is not an OS sandbox. If the agent does not need a shell at all, remove the tool entirely. Also keep tools.maxSessionMessagesPerMinute at its default of 6 and set a spending limit on your LLM provider:

# Official production recommendation on macOS: merge into ~/.nanobot/config.json
{
  "tools": {
    "restrictToWorkspace": true,
    "exec": { "sandbox": "seatbelt" }
  }
}

# Agent does not need a shell? Remove the tool entirely instead:
# { "tools": { "exec": { "enable": false } } }

# Seatbelt sets HOME and TMPDIR to the workspace and masks ~/.nanobot. Scripts that need
# extra paths get them via tools.exec.sandboxRoBinds / sandboxRwBinds (use sparingly).
# Neither Seatbelt nor bwrap restricts network access.

# Keep WebUI / API on localhost (defaults: WebUI 127.0.0.1:8765, health 127.0.0.1:18790, serve 127.0.0.1:8900)
# and leave tools.webuiAllowRemotePackageInstall = false and tools.ssrfWhitelist = []

Install the LaunchAgent

nanobot gateway install-service writes ~/Library/LaunchAgents/ai.nanobot.gateway.plist, which runs python -m nanobot gateway --foreground with your current Python, starts at load (RunAtLoad), restarts on crash (KeepAlive with SuccessfulExit false) and logs to ~/.nanobot/logs/. It fails with address already in use if a manual gateway is still running, so stop that first and preview with --dry-run:

# Stop any manually started gateway first (otherwise: "address already in use")
nanobot gateway stop

# Preview the plist, then install it
nanobot gateway install-service --manager launchd --dry-run
nanobot gateway install-service --manager launchd
# Writes ~/Library/LaunchAgents/ai.nanobot.gateway.plist
# Runs: python -m nanobot gateway --foreground  (RunAtLoad, KeepAlive on failure)
# Logs: ~/.nanobot/logs/

Manage the Service

The LaunchAgent lives in your user's gui domain, so it runs once that user's login session exists, the docs describe it as staying online after you log in. After a reboot of a headless Mac mini it only returns if your user logs in automatically; reboot-test once and check with launchctl list. Restart it after every config.json edit:

# Is it loaded?
launchctl list | grep ai.nanobot.gateway

# Restart after every config.json edit (config is read at startup only)
launchctl kickstart -k gui/$(id -u)/ai.nanobot.gateway

# Remove the service
nanobot gateway uninstall-service --manager launchd

# Second, isolated instance on the same Mac (own config, workspace, port and LaunchAgent).
# docs/multiple-instances.md: "Each instance must use a different port if they run at the same time"
# nanobot onboard --config ~/.nanobot-telegram/config.json --workspace ~/.nanobot-telegram/workspace
# Merge into ~/.nanobot-telegram/config.json (default gateway port is 18790; change the WebSocket
# channel port too if that instance also enables the WebUI, default 8765):
# { "gateway": { "host": "127.0.0.1", "port": 18792 },
#   "channels": { "websocket": { "port": 8766 } } }
# nanobot gateway install-service --manager launchd --name nanobot-telegram \
#   --config ~/.nanobot-telegram/config.json --workspace ~/.nanobot-telegram/workspace
# (for a one-off foreground run instead: nanobot gateway --config ~/.nanobot-telegram/config.json --port 18792)

Lighter Alternative: nanobot gateway --background

The README calls this the only command that promotes the shared gateway to persistent background mode. It is convenient for testing but not OS-supervised, so it does not come back after a reboot by itself, do not mix it with the LaunchAgent:

nanobot gateway --background
nanobot gateway status
nanobot gateway logs
nanobot gateway restart
nanobot gateway stop

Update nanobot

There is no nanobot update command: upgrade with the same method you used to install. The project asks you to check for updates weekly and published five security advisories in 2026, so upgrade promptly. Read the release notes first, v0.3.5 moved session files to sessions/<workspace-id>/ and tells you to back up configuration, workspaces and session storage and stop old processes first. So stop the gateway (uninstall the LaunchAgent, or nanobot gateway stop in background mode), back up, upgrade, then start it again, never let two versions write the same workspace concurrently:

# 1. Stop the old gateway first (v0.3.5 release notes: never let two versions write the same workspace)
nanobot gateway uninstall-service --manager launchd   # LaunchAgent (nanobot documents no plain launchd stop)
# nanobot gateway stop                                  # --background mode

# 2. Back up config, workspace and sessions
cp -R ~/.nanobot ~/nanobot-backup-$(date +%F)

# 3. Upgrade with the same method you installed with
curl -fsSL https://raw.githubusercontent.com/HKUDS/nanobot/main/scripts/install.sh | sh
# or: uv tool upgrade nanobot-ai
# or: pipx upgrade nanobot-ai
# or: python3 -m pip install -U nanobot-ai

nanobot --version
nanobot onboard --refresh      # merge new default config fields, keep your values

# 4. Start again so the new code and config are loaded
nanobot gateway install-service --manager launchd     # LaunchAgent: reinstall (RunAtLoad starts it)
# nanobot gateway --background                          # --background mode

7. Troubleshooting Common Issues

Installer aborts, pip refuses to install, or nanobot is not on PATH

The installer stops if python3 is older than 3.11, install a current Python and point the PYTHON variable at it. Never answer an externally-managed-environment error with --break-system-packages: use uv, pipx or a virtual environment. If the command is missing in a new shell, use the runner the installer printed:

# Python too old? Point the installer at a 3.11+ interpreter
python3 --version
PYTHON=/path/to/python3.12 sh -c "$(curl -fsSL https://raw.githubusercontent.com/HKUDS/nanobot/main/scripts/install.sh)"

# "externally-managed-environment" → isolated install, never --break-system-packages
uv tool install nanobot-ai
# or: pipx install nanobot-ai

# "curl: command not found" → skip the script
uv tool install nanobot-ai

# `nanobot` not on PATH in a new shell
uv tool run --from nanobot-ai nanobot --version
pipx run --spec nanobot-ai nanobot --version
~/.nanobot/venv/bin/python -m nanobot --version
export PATH="$HOME/.local/bin:$PATH"

First message fails: wrong model, ConfigLoadError or a provider error

A key from one provider with a model ID from another is the most common first-run failure. An unset ${VAR} placeholder makes startup fail fast with ConfigLoadError, under the LaunchAgent no environment is passed, so use a stored key there. Check the setup without calling a model, then retry with verbose logging:

# Validate without spending tokens
nanobot status

# Provider and model must match in the preset: provider "anthropic" ↔ "claude-opus-4-5",
# provider "openai" ↔ "gpt-5", provider "openrouter" ↔ "anthropic/claude-opus-4.5", provider "ollama" ↔ "llama3.2"

# ConfigLoadError at startup = a ${VAR} placeholder is unset in the starting process' environment
# (the generated LaunchAgent passes no environment → store the key in config.json + chmod 600)

# Watch the gateway with verbose logging (also verifies MCP servers)
nanobot gateway --verbose

Telegram bot stays silent

Usually one of three things: the telegram feature was never enabled in the same Python environment, your DM is still waiting for pairing approval, or you edited config.json without restarting the gateway (config is read at startup only). Check the channel list, approve pending pairings and restart:

# Is the channel enabled and listed?
nanobot plugins enable telegram
nanobot channels status

# Pending pairing? Approve it from the CLI
nanobot agent -m "/pairing approve ABCD-EFGH"

# Edited config.json? Restart the gateway
launchctl kickstart -k gui/$(id -u)/ai.nanobot.gateway
# or: nanobot gateway restart

# Token revoked? Generate a new one via @BotFather (/mybots > API Token) and update config.json
# WhatsApp "login expired"? nanobot channels login whatsapp

LaunchAgent will not start or the gateway is gone after a reboot

address already in use means a manually started gateway (foreground or --background) is still holding the port, stop it and reinstall. After a reboot, the gui-domain LaunchAgent only starts once your user is logged in. Logs are in ~/.nanobot/logs/; the WebUI is on port 8765 while 18790 is only the health endpoint:

# "address already in use" → a manual gateway still holds the port
nanobot gateway stop
nanobot gateway install-service --manager launchd

# Loaded? Logs?
launchctl list | grep ai.nanobot.gateway
ls ~/.nanobot/logs/

# Gone after a reboot: a gui-domain LaunchAgent starts once your user has logged in.
# If your setup allows automatic login for the nanobot user, enable it and reboot-test;
# WARNING: auto-login trades console-login security for reboot survival, confirm with your ops policy first.

# Ports: WebUI 8765 (localhost), health endpoint 18790, `nanobot serve` API 8900
# Generic SSH tip (not a nanobot feature): reach the localhost WebUI from your laptop
# ssh -N -L 8765:127.0.0.1:8765 admin@your-server-ip   → http://127.0.0.1:8765

8. Cost Analysis vs. Cloud VPS

nanobot itself is free (MIT). What you pay for is the host and the LLM usage. The host comparison below reuses the cloud VPS ranges from our OpenClaw and Hermes guides; LLM API usage is billed separately by your provider and is identical on either host, unless you run a local Ollama model on the Mac mini, in which case inference costs $0. nanobot publishes no RAM or CPU footprint figures (it only describes itself as ultra-lightweight), so plan sizing below is qualitative.

Use Case AI Calls/Month Cloud VPS Cost MyRemoteMac Cost Monthly Savings
Personal assistant (hosted API model) ~500 calls $120/mo (basic GPU VPS) $85/mo (Mac mini M4) $35/mo
Team bot + scheduled automations ~5,000 calls $200/mo $85/mo (Mac mini M4) $115/mo
Local Ollama model + agent on one box Unlimited (local) $350+/mo (GPU VPS) $149/mo (Mac mini M6) $201+/mo
Several isolated instances, heavy automation 10,000+ calls $600+/mo $149/mo (Mac mini M6) $451+/mo

Assumptions: VPS prices are the same ranges used across our guides for GPU-capable AI-tier instances and are not quotes from a specific provider; MyRemoteMac prices are the current monthly rates in USD (1 Gbps included, Mac mini M6 available since 22 September 2026). The M4/M6 split is a recommendation, not a measured requirement: a Mac mini M4 is plenty for a personal bot on hosted providers; pick the M6 when the same machine also serves a local Ollama model or several nanobot instances.

Bottom Line: A dedicated Mac mini costs less than a GPU VPS at every usage level, and nanobot's preset-based fallback chains let you route routine work to a free local Ollama preset while keeping a hosted frontier model for the hard questions, all on hardware that is yours alone.

9. nanobot vs. OpenClaw

Both are open-source (MIT), self-hosted, always-on personal AI agents driven from your chat apps, both run a long-lived gateway and both register their own launchd LaunchAgent (ai.nanobot.gateway vs ai.openclaw.gateway). nanobot's README even calls nanobot gateway the familiar entry point if you are coming from OpenClaw. The differences are in the stack and the pitch. OpenClaw is TypeScript on Node.js (26.1+ or 24.16+ via Homebrew) installed with npm; nanobot is Python 3.11+ from PyPI (nanobot-ai), installed with a one-line script, uv or pipx, with no Node.js at all. OpenClaw's pitch is breadth and the larger community; nanobot's is a small, readable core, per-channel pairing plus a built-in macOS Seatbelt exec sandbox (new in v0.3.5), multiple isolated instances on one Mac (multiple-instances.md) and a Python SDK plus an OpenAI-compatible API. OpenClaw supports iMessage; nanobot does not.

If you want the fullest-featured assistant and the larger community and channel list, read our OpenClaw on Mac mini guide. If you want a lightweight Python agent you can read end to end, several sandboxed instances, or Ollama on the same Mac mini, nanobot is the better fit. A third option, Hermes Agent, is covered in our Hermes on Mac mini guide. The Mac mini, the launchd service and the local Ollama option are the same for all three.

10. FAQ

Is nanobot free to use?

Yes. nanobot is MIT-licensed and free; you pay only for LLM usage from the provider you choose. A local Ollama model on your Mac mini is free to run. The Mac mini itself is from $85/month (M4) or $149/month (M6) at MyRemoteMac, billed in USD.

Which Mac mini configuration should I pick for nanobot?

nanobot publishes no RAM or CPU figures, so this is qualitative. For a personal bot on hosted providers (Anthropic, OpenAI, OpenRouter, etc.) the entry Mac mini M4 at $85/month (16 GB / 256 GB) is the sensible choice: the agent is described as ultra-lightweight. Pick the Mac mini M6 from $149/month when the same machine also runs a local Ollama model or several isolated nanobot instances, since local inference is what needs memory and compute.

Does nanobot survive a reboot of the Mac mini?

The LaunchAgent written by nanobot gateway install-service --manager launchd has RunAtLoad true and KeepAlive, so launchd starts it when your user session loads and restarts it after a crash. It lives in the gui domain, which means it comes back after a reboot only once your user logs in. If your setup allows automatic login for that user, enabling it restores the service after a reboot, but be aware that auto-login trades console-login security for reboot survival, so confirm it against your ops policy first, then reboot-test once and verify with launchctl list | grep ai.nanobot.gateway. nanobot gateway --background is not supervised and does not survive a reboot.

Can nanobot use a local model instead of an API?

Yes. nanobot has a dedicated ollama provider (default apiBase http://localhost:11434/v1) plus lm_studio, vllm and OVMS for other local OpenAI-compatible servers. Start Ollama on the Mac mini, set the preset's model to the raw Ollama tag (for example llama3.2) and pin provider to ollama. Most Ollama setups need no API key. If tool-using turns are slow, the docs say to check the model's chat template and prompt-cache reuse before touching memory or context settings.

Which messaging platforms does nanobot support?

The official chat-apps documentation lists Telegram, Discord, Slack, WhatsApp, WeChat/Weixin, WeCom, Feishu/Lark, DingTalk, QQ (and Napcat/OneBot), Matrix/Element, Email, Mattermost, Linear, Microsoft Teams, Signal and Mochat, served by one gateway, plus the bundled WebUI, the native terminal UI and an OpenAI-compatible HTTP API via nanobot serve. iMessage is not supported.

Is it safe to give an AI agent shell access on my Mac mini?

Only with the documented guardrails: run nanobot as a standard user (never root), set tools.restrictToWorkspace to true and tools.exec.sandbox to seatbelt (the project's production recommendation on macOS), or set tools.exec.enable to false if the agent does not need a shell at all. Keep pairing-only mode or a narrow allowFrom on every channel, never the wildcard, keep the WebUI and API bound to localhost, keep the default rate limit of 6 messages per minute, set a spending limit at your provider, and update weekly, five advisories were published in 2026, so run 0.3.5 or newer.

11. Sources and Further Reading

Every command, path and config key in this guide comes from the official nanobot repository (README and docs/ tree, read on 28 September 2026, v0.3.5) and its SECURITY.md. The repository docs can be newer than the latest package release, so re-check against the repo if a command behaves differently.

Related Guides

Ready to Run nanobot 24/7?

Deploy a dedicated Mac mini as your self-hosted AI agent host. Mac mini M4 from $85/month, Mac mini M6 from $149/month, 1 Gbps included.

Looking for more detail?

Browse the full documentation for step-by-step setup, configuration references, and troubleshooting.

Open the documentation →