A personal AI gateway written in Rust. One binary, no runtime, no npm.
Features • Installation • Build • Cloud Deployment • How It Works • Hooks • Discord
Inspired by OpenClaw — just build it and run it.
# One-liner install script (macOS / Linux)
curl -fsSL https://www.moltis.org/install.sh | sh
# macOS / Linux via Homebrew
brew install moltis-org/tap/moltis
# Docker (multi-arch: amd64/arm64)
docker pull ghcr.io/moltis-org/moltis:latest
# Or build from source
cargo install moltis --git https://github.com/moltis-org/moltis- Multi-provider LLM support — OpenAI Codex, GitHub Copilot, and Local LLM through a trait-based provider architecture
- Streaming responses — real-time token streaming for a responsive user experience, including when tools are enabled (tool calls stream argument deltas as they arrive)
- Communication channels — Telegram integration with an extensible channel abstraction for adding others
- Web gateway — HTTP and WebSocket server with a built-in web UI
- Session persistence — SQLite-backed conversation history, session management, and per-session run serialization to prevent history corruption
- Agent-level timeout — configurable wall-clock timeout for agent runs (default 600s) to prevent runaway executions
- Sub-agent delegation —
spawn_agenttool lets the LLM delegate tasks to child agent loops with nesting depth limits and tool filtering - Message queue modes —
followup(replay each queued message as a separate run) orcollect(concatenate and send once) when messages arrive during an active run - Tool result sanitization — strips base64 data URIs and long hex blobs, truncates oversized results before feeding back to the LLM (configurable limit, default 50 KB)
- Memory and knowledge base — embeddings-powered long-term memory
- Skills — extensible skill system with support for existing repositories
- Hook system — lifecycle hooks with priority ordering, parallel dispatch
for read-only events, circuit breaker, dry-run mode, HOOK.md-based discovery,
eligibility checks, bundled hooks (boot-md, session-memory, command-logger),
CLI management (
moltis hooks list/info), and web UI for editing, enabling/disabling, and reloading hooks at runtime - Web browsing — web search (Brave, Perplexity) and URL fetching with readability extraction and SSRF protection
- Voice support — Text-to-speech (TTS) and speech-to-text (STT) with multiple cloud and local providers. Configure and manage voice providers from the Settings UI.
- Scheduled tasks — cron-based task execution
- OAuth flows — built-in OAuth2 for provider authentication
- TLS support — automatic self-signed certificate generation
- Observability — OpenTelemetry tracing with OTLP export
- MCP (Model Context Protocol) support — connect to MCP tool servers over stdio or HTTP/SSE (remote servers), with health polling, automatic restart on crash (exponential backoff), and in-UI server config editing
- Parallel tool execution — when the LLM requests multiple tool calls in
one turn, they run concurrently via
futures::join_all, reducing latency - Sandboxed execution — Docker and Apple Container backends with pre-built images, configurable packages, and per-session isolation
- Authentication — password and passkey (WebAuthn) authentication with session cookies, API key support, and a first-run setup code flow
- Endpoint throttling — built-in per-IP request throttling for
unauthenticated traffic when auth is enforced, with strict limits for
password login attempts and sensible caps for API/WS traffic (
429+Retry-Afteron limit hit) - WebSocket security — Origin validation to prevent Cross-Site WebSocket Hijacking (CSWSH)
- Onboarding wizard — guided setup for agent identity (name, emoji, creature, vibe, soul) and user profile
- Config validation —
moltis config checkvalidates the configuration file, detects unknown/misspelled fields with suggestions, and reports security warnings - Default config on first run — writes a complete
moltis.tomlwith all defaults so you can edit packages and settings without recompiling - Random port per installation — each fresh install picks a unique available port, avoiding conflicts when multiple users run moltis on the same machine
- Zero-config startup —
moltisruns the gateway by default; no subcommand needed - Configurable directories —
--config-dir/--data-dirCLI flags andMOLTIS_CONFIG_DIR/MOLTIS_DATA_DIRenvironment variables - Cloud deployment — one-click deploy configs for Fly.io, DigitalOcean,
and Render with
--no-tlsflag for cloud TLS termination - Tailscale integration — expose the gateway over your tailnet via Tailscale
Serve (private HTTPS) or Funnel (public HTTPS), with status monitoring and
mode switching from the web UI (optional
tailscalefeature flag)
# Clone and build
git clone https://github.com/moltis-org/moltis.git
cd moltis
cargo build --release
# Start the gateway (gateway is the default command)
cargo run --releaseOpen https://moltis.localhost:3000
Moltis uses Docker for sandboxed command execution — when the LLM runs shell commands, they execute inside isolated containers. When running Moltis itself in a container, you need to give it access to the host's container runtime.
# Docker / OrbStack
docker run -d \
--name moltis \
-p 13131:13131 \
-p 13132:13132 \
-v moltis-config:/home/moltis/.config/moltis \
-v moltis-data:/home/moltis/.moltis \
-v /var/run/docker.sock:/var/run/docker.sock \
ghcr.io/moltis-org/moltis:latest
# Podman (rootless)
podman run -d \
--name moltis \
-p 13131:13131 \
-p 13132:13132 \
-v moltis-config:/home/moltis/.config/moltis \
-v moltis-data:/home/moltis/.moltis \
-v /run/user/$(id -u)/podman/podman.sock:/var/run/docker.sock \
ghcr.io/moltis-org/moltis:latest
# Podman (rootful)
podman run -d \
--name moltis \
-p 13131:13131 \
-p 13132:13132 \
-v moltis-config:/home/moltis/.config/moltis \
-v moltis-data:/home/moltis/.moltis \
-v /run/podman/podman.sock:/var/run/docker.sock \
ghcr.io/moltis-org/moltis:latestOpen https://localhost:13131 in your browser and complete the setup.
Moltis generates a self-signed TLS certificate on first run. To trust it and
remove browser warnings, download the CA certificate from
http://localhost:13132/certs/ca.pem and add it to your system trust store
(Keychain on macOS, update-ca-certificates on Linux).
Important notes:
- Socket mount is required — Without mounting the container runtime socket, Moltis cannot execute sandboxed commands. The agent will still work for chat-only interactions, but any tool that runs shell commands will fail.
- Security consideration — Mounting the Docker socket gives the container full access to the Docker daemon. This is necessary for Moltis to create sandbox containers. Only run Moltis containers from trusted sources.
- OrbStack — Works identically to Docker; use the same socket path
(
/var/run/docker.sock). - Podman — Moltis talks to the Podman socket using the Docker API
(Podman's compatibility layer). Use the rootless socket path
(
/run/user/$(id -u)/podman/podman.sock) or rootful path (/run/podman/podman.sock) depending on your setup. You may need to enable the Podman socket service:systemctl --user enable --now podman.socket - Persistence — Mount volumes to preserve data across container restarts:
/home/moltis/.config/moltis— configuration (moltis.toml, mcp-servers.json)/home/moltis/.moltis— data (databases, sessions, memory)
Deploy the pre-built Docker image to your favorite cloud provider:
| Provider | Deploy |
|---|---|
| DigitalOcean |
Fly.io (CLI):
fly launch --image ghcr.io/moltis-org/moltis:latest
fly secrets set MOLTIS_PASSWORD="your-password"All cloud configs use --no-tls because the provider handles TLS termination.
See Cloud Deploy docs for
per-provider setup details, persistent storage notes, and authentication.
Moltis is a local-first AI gateway — a single Rust binary that sits between you and multiple LLM providers. Everything runs on your machine; no cloud relay required.
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Web UI │ │ Telegram │ │ Discord │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└────────┬───────┴────────┬───────┘
│ WebSocket │
▼ ▼
┌─────────────────────────────────┐
│ Gateway Server │
│ (Axum · HTTP · WS · Auth) │
├─────────────────────────────────┤
│ Chat Service │
│ ┌───────────┐ ┌─────────────┐ │
│ │ Agent │ │ Tool │ │
│ │ Runner │◄┤ Registry │ │
│ └─────┬─────┘ └─────────────┘ │
│ │ │
│ ┌─────▼─────────────────────┐ │
│ │ Provider Registry │ │
│ │ Multiple providers │ │
│ │ (Codex · Copilot · Local)│ │
│ └───────────────────────────┘ │
├─────────────────────────────────┤
│ Sessions │ Memory │ Hooks │
│ (JSONL) │ (SQLite)│ (events) │
└─────────────────────────────────┘
│
┌───────▼───────┐
│ Sandbox │
│ Docker/Apple │
│ Container │
└───────────────┘
When moltis gateway runs, it loads moltis.toml, initializes the credential
store (passwords, passkeys, API keys), registers LLM providers and tools,
discovers hooks and skills, optionally starts the memory manager, and
pre-builds a sandbox image if configured. An Axum HTTP server then listens for
WebSocket and REST connections.
- Connect — A client (web UI, Telegram bot, API key bearer) opens a WebSocket. The server validates auth and Origin headers, then assigns a connection ID.
- Send — The client calls the
chat.sendRPC method with message text and an optional model override. The gateway resolves the session, persists the user message to a JSONL file, loads conversation history, and builds a system prompt (agent identity, project context, discovered skills). - Agent loop — If the chosen provider supports tool calling, an agent
loop runs (up to 25 iterations). Each iteration calls the LLM, inspects the
response for tool calls, fires
BeforeToolCall/AfterToolCallhooks, executes tools inside the sandbox, appends results, and loops until the LLM produces a final text answer. If tools are not available, the provider streams tokens directly. - Broadcast — Every step (thinking, tool start/end, text deltas, final response) is broadcast over the WebSocket as sequenced events. The web UI renders them in real time.
- Channel replies — If the message originated from Telegram or another channel, the final response is delivered back through that channel's outbound interface.
Conversations are stored as append-only JSONL files under
~/.moltis/agents/<agent>/sessions/. A SQLite database tracks metadata
(message counts, model selection, project bindings, channel bindings).
When token usage approaches 95% of the context window, the session is
auto-compacted: history is summarized and important facts are persisted to the
memory store.
The optional memory manager watches memory/ directories for Markdown files,
chunks them by heading, embeds the chunks, and stores vectors in SQLite for
hybrid (vector + full-text) search. Memory context is injected into the system
prompt automatically.
Lifecycle hooks let you observe, modify, or block actions at key points.
Modifying events (BeforeToolCall, BeforeCompaction, MessageSending) run
sequentially — a hook can rewrite arguments or block execution. Read-only
events (AfterToolCall, SessionEnd, GatewayStart, …) run in parallel.
Hooks are discovered from HOOK.md files and include a circuit breaker that
auto-disables after repeated failures.
Moltis applies defense in depth across several layers:
- Authentication — On first run a one-time setup code is printed to the terminal. The user enters it to set a password or register a WebAuthn passkey. Subsequent requests are authenticated via session cookies or API key bearer tokens. Connections from loopback addresses (localhost, 127.0.0.1, ::1) are allowed without credentials as a safe default for local use.
- WebSocket Origin validation — The WebSocket upgrade handler rejects cross-origin requests to prevent Cross-Site WebSocket Hijacking (CSWSH). A malicious webpage cannot connect to your local gateway from the browser.
- SSRF protection — The
web_fetchtool resolves DNS before making HTTP requests and blocks any target IP in loopback, private, link-local, or CGNAT ranges. This prevents the LLM from reaching internal services. - Secret handling — Passwords, API keys, and tokens are stored as
secrecy::Secret<String>, which redactsDebugoutput, prevents accidentalDisplay, and zeroes memory on drop. Environment variable values injected into sandbox sessions are redacted from command output (including base64 and hex encoded forms). - No unsafe code —
unsafe_codeis denied workspace-wide. The only exception is an opt-in FFI wrapper behind thelocal-embeddingsfeature flag. - Hook gating —
BeforeToolCallhooks can inspect, modify, or block any tool invocation before it executes, giving you a programmable policy layer over what the agent is allowed to do.
User commands never run directly on the host. They execute inside isolated containers using either Docker or Apple Container as the backend.
At startup the gateway builds a deterministic image from the configured base
image (ubuntu:25.10 by default) and the package list in moltis.toml. The
image tag is a hash of the base image + sorted packages — if you add or remove
a package, the tag changes and a rebuild is triggered automatically.
Each command invocation gets a per-session container. Environment variables configured for the agent are injected into the container, but their values are redacted from any output the LLM sees (plain text, base64, and hex forms) to prevent leaking secrets through tool results.
cargo build # Debug build
cargo build --release # Optimized buildcargo run # Start the gateway server (default command)On first run, a setup code is printed to the terminal. Open the web UI and enter this code to set your password or register a passkey.
Optional flags:
cargo run -- --config-dir /path/to/config --data-dir /path/to/datacargo test --all-featuresMoltis includes a hook dispatch system that lets you react to lifecycle events with native Rust handlers or external shell scripts. Hooks can observe, modify, or block actions.
BeforeToolCall, AfterToolCall, BeforeAgentStart, AgentEnd,
MessageReceived, MessageSending, MessageSent, BeforeCompaction,
AfterCompaction, ToolResultPersist, SessionStart, SessionEnd,
GatewayStart, GatewayStop, Command
Hooks are discovered from HOOK.md files in these directories (priority order):
<workspace>/.moltis/hooks/<name>/HOOK.md— project-local~/.moltis/hooks/<name>/HOOK.md— user-global
Each HOOK.md uses TOML frontmatter:
+++
name = "my-hook"
description = "What it does"
events = ["BeforeToolCall"]
command = "./handler.sh"
timeout = 5
[requires]
os = ["darwin", "linux"]
bins = ["jq"]
env = ["SLACK_WEBHOOK_URL"]
+++moltis hooks list # List all discovered hooks
moltis hooks list --eligible # Show only eligible hooks
moltis hooks list --json # JSON output
moltis hooks info <name> # Show hook details- boot-md — reads
BOOT.mdfrom workspace onGatewayStart - session-memory — saves session context on
/newcommand - command-logger — logs all
Commandevents to JSONL
Shell hooks receive the event payload as JSON on stdin and communicate their action via exit code and stdout:
| Exit code | Stdout | Action |
|---|---|---|
| 0 | (empty) | Continue |
| 0 | {"action":"modify","data":{...}} |
Replace payload data |
| 1 | — | Block (stderr used as reason) |
[[hooks]]
name = "audit-tool-calls"
command = "./examples/hooks/log-tool-calls.sh"
events = ["BeforeToolCall"]
[[hooks]]
name = "block-dangerous"
command = "./examples/hooks/block-dangerous-commands.sh"
events = ["BeforeToolCall"]
timeout = 5
[[hooks]]
name = "notify-discord"
command = "./examples/hooks/notify-discord.sh"
events = ["SessionEnd"]
env = { DISCORD_WEBHOOK_URL = "https://discord.com/api/webhooks/..." }See examples/hooks/ for ready-to-use scripts (logging, blocking dangerous
commands, content filtering, agent metrics, message audit trail,
Slack/Discord notifications, secret redaction, session saving).
moltis sandbox list # List pre-built sandbox images
moltis sandbox build # Build image from configured base + packages
moltis sandbox clean # Remove all pre-built sandbox images
moltis sandbox remove <tag> # Remove a specific imageThe gateway pre-builds a sandbox image at startup from the base image
(ubuntu:25.10) plus the packages listed in moltis.toml. Edit the
[tools.exec.sandbox] packages list and restart — a new image with a
different tag is built automatically.
Moltis is organized as a Cargo workspace with the following crates:
| Crate | Description |
|---|---|
moltis |
Command-line interface and entry point |
moltis-gateway |
HTTP/WebSocket server and web UI |
moltis-agents |
LLM provider integrations |
moltis-channels |
Communication channel abstraction |
moltis-telegram |
Telegram integration |
moltis-config |
Configuration management |
moltis-sessions |
Session persistence |
moltis-memory |
Embeddings-based knowledge base |
moltis-skills |
Skill/plugin system |
moltis-mcp |
MCP client, transport, and tool bridge |
moltis-plugins |
Plugin formats, hook handlers, and shell hook runtime |
moltis-tools |
Tool/function execution |
moltis-routing |
Message routing |
moltis-projects |
Project/workspace management |
moltis-onboarding |
Onboarding wizard and identity management |
moltis-oauth |
OAuth2 flows |
moltis-protocol |
Serializable protocol definitions |
moltis-common |
Shared utilities |
MIT