Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
Added
- Skill Editing & Forking: Edit personal skills or fork repo skills into personal skills directly from the web UI
- “Edit” button on personal/project skills opens an inline editor for name, description, allowed tools, and body
- “Fork & Edit” button on repo skills copies the skill to personal skills for customization
- Confirmation hint in chat after skill creation/update with link to the skills page
Changed
Deprecated
Removed
Fixed
Security
[0.10.18] - 2026-03-09
Added
- [gateway] Make provider discovery startup non-blocking
- [monitoring] Track memory history and improve local-llm memory reporting (#325)
- [ios] Add local llama cpp memory field to GraphQL schema
- [providers] Include reasoning fields for kimi models (#323)
- [chat] Tabs to filter chats between sessions and cron (#338)
- [oauth] Support pasted callback URL fallback (#365)
- [providers] Add reasoning effort support for models with extended thinking (#363)
Changed
- Externalize web/wasm assets and reduce memory footprint (#321)
- [web] Move chat history hydration to paged HTTP
- [web] Paginate sessions and auto-load older history
Removed
- [web] Remove nested onboarding scroll and restore settings nav icons
- [web] Declutter chat controls and fix dropdown positioning
Fixed
- [gateway] Speed up startup by deferring tailscale and log scan
- [gateway] Improve browser warmup integration
- [scripts] Run local nextest with ci timeout profile
- [ci] Build macOS app arm64 in fast path
- [web] Move session history off websocket and cap payload size
- [web] Use combo select for session header selectors
- [web] Externalize SVG icons and restore empty-chat centering
- [web] Align e2e with controls modal and daily model refresh
- [ci] Stage wasm assets for cargo-deb packaging
- [packaging] Use cli-relative web assets in cargo-deb
- Install rustls CryptoProvider before channel startup (#336)
- [ci,tools] Unblock dependabot and support wasmtime 36
- [auth] Honor forwarded host for proxy session cookies
- [config] Include tmux in default sandbox packages
- [mdns] Use stable host label to avoid mDNSResponder conflict and double-.local suffix (#349)
- [web] Prevent Enter key from triggering actions during IME composition (#341)
- [biome] Update schema to 2.4.6 and move noUnusedExpressions to suspicious
- [ci] Update biome version to 2.4.6 in CI workflows
- [macos] Extract makeTextView to fix function body length lint violation
- [providers] Report compatible client_version for Codex model discovery (#359)
- [prompt] Omit sandbox/node info from runtime prompt when disabled (#362)
- [web] Allow deleting cron sessions from chat sidebar (#357)
- [chat] Skip duplicate text fallback when TTS disabled and voice streamed (#373)
- [web] Break redirect loop when accessing via Tailscale Serve (#356)
Security
- [nodes] Add multi-node support with device pairing, remote exec, and UI (#291)
- [security] Add direct nginx websocket proxy example (#364)
[0.10.17] - 2026-03-05
Fixed
- [config] Include tmux in default sandbox packages
[0.10.16] - 2026-03-05
Fixed
- [ci,tools] Unblock dependabot and support wasmtime 36
- [auth] Honor forwarded host for proxy session cookies
[0.10.15] - 2026-03-05
Fixed
- Install rustls CryptoProvider before channel startup (#336)
[0.10.14] - 2026-03-05
Fixed
- [packaging] Use cli-relative web assets in cargo-deb
[0.10.13] - 2026-03-04
Fixed
- [ci] Stage wasm assets for cargo-deb packaging
[0.10.12] - 2026-03-04
Added
- [ci] Add release dry-run mode
- [browser] Add container_host for Docker-in-Docker connectivity (#300)
- [ios] Auto-discover server identity and show emojis (#297)
- [website] Migrate cloudflare website into monorepo (#302)
- [local-llm] Allow arbitrary HuggingFace model IDs for MLX models
- [web,tools] AOT WASM pre-compilation and Shiki CDN loading
- [cli] Remove wasm from default features to reduce memory
- [gateway] Make provider discovery startup non-blocking
- [monitoring] Track memory history and improve local-llm memory reporting (#325)
- [ios] Add local llama cpp memory field to GraphQL schema
Changed
- [web] Move settings nav icons from JS to CSS
- Externalize web/wasm assets and reduce memory footprint (#321)
- [web] Move chat history hydration to paged HTTP
- [web] Paginate sessions and auto-load older history
Removed
- [web] Remove nested onboarding scroll and restore settings nav icons
- [web] Declutter chat controls and fix dropdown positioning
Fixed
- [config] Support provider url alias for remote Ollama config (#299)
- [ci] Make release dry-run job conditions valid
- [providers] Use Ollama capabilities for tool support detection (#301)
- [scripts] Roll back heavy local validation parallelism
- [web] Skip npm install when TAILWINDCSS binary is provided
- [ci] Update website/releases.json on release
- [web] Add missing i18n button key for preferredModels
- [local-llm] Use sampler API for mlx-lm >= 0.20
- [gateway] Break redirect loop when onboarded but auth not configured (#310)
- [gateway] Reduce idle CPU from metrics loop and log broadcast feedback
- [gateway] Speed up startup by deferring tailscale and log scan
- [gateway] Improve browser warmup integration
- [scripts] Run local nextest with ci timeout profile
- [ci] Build macOS app arm64 in fast path
- [web] Move session history off websocket and cap payload size
- [web] Use combo select for session header selectors
- [web] Externalize SVG icons and restore empty-chat centering
- [web] Align e2e with controls modal and daily model refresh
Security
- [nodes] Add multi-node support with device pairing, remote exec, and UI (#291)
[0.10.11] - 2026-03-02
[0.10.10] - 2026-03-02
Fixed
- [swift-bridge] Stabilize gateway migration and stream tests
[0.10.9] - 2026-03-02
Fixed
- [ci] Harden tailwindcss cli downloads
[0.10.8] - 2026-03-02
Changed
- [gateway] Fetch updates from releases manifest instead of GitHub API
Fixed
- [ci] Add Tailwind CSS build step to release workflow, Dockerfile, and snapcraft
- [e2e] Wait for session history render before DOM injection in chat-abort
[0.10.7] - 2026-03-02
Added
- [sandbox] Add GitHub runner parity packages and enable corepack (#284)
- [providers] Add first-class LM Studio provider (#286)
- [agents] Enrich spawn_agent presets with identity, policies, memory (#271)
- [web] Show running version at bottom of identity settings
- [channels] Channel architecture phase 5, contract suites, and observability baseline (#289)
Changed
- [channels] Registry-driven dispatch for cheap new channels (#277)
Fixed
- [e2e] Make sandboxes container tests deterministic
- [e2e] Replace remaining racy waitForResponse with route interceptors
- [mcp] Make optional MCP tool params nullable to prevent empty string errors (#283)
- [provider-setup] Reorder validation probes to prefer fast models (#280)
- [sandbox] Resolve host gateway IP for Podman < 5.0 (#287)
- [e2e] Fix flaky “deleting unmodified fork” test
- [ci] Stale lockfile, missing Tailwind in macOS job, OAuth e2e setup
- [ci] Use standalone Tailwind binary for macOS app job
- [e2e] Fix OAuth token-exchange failure test and add error-context capture
- [web] Auto-install node_modules in Tailwind build script
- [web] Retry openclaw onboarding scan until ws is ready
Security
- [macos] Wire settings UI to rust config backend (#267)
- [channels] Shared channel webhook middleware pipeline (#290)
[0.10.6] - 2026-03-01
Fixed
- [web] Fix Shiki highlighter init failures in E2E tests
- [web] Make thinking stop button smaller with left spacing
- [chat] Surface error when LLM returns empty response with zero tokens
- [providers] Emit StreamEvent::Error on non-success finish_reason
[0.10.5] - 2026-03-01
Fixed
- [web] Lazy-load Shiki to prevent blocking page mount
[0.10.4] - 2026-03-01
Added
- [web] Add Shiki syntax highlighting to code blocks
[0.10.3] - 2026-03-01
Added
- Add channel-aware heartbeat delivery and send_message agent tool (#270)
- [memory] Add tree-sitter code splitter and RRF search merge
Changed
- [ffi] Tighten unsafe_code allowances
Fixed
- [sandbox] Make apple container keepalive portable (#269)
- [local-llm] Combine compile-time and runtime Metal detection
- [auth] Auto-detect new WebAuthn hosts and prompt passkey refresh (#268)
- [web] Replace rg with grep in changelog guard and deduplicate passkey status refresh
[0.10.2] - 2026-02-28
Added
Changed
Deprecated
Removed
Fixed
- Release packaging now installs cross-compilation targets on the active nightly toolchain in the Homebrew binary job, fixing
error[E0463]: can't find crate for coreduring macOS binary builds. - Docker release builds now copy
apps/courierinto the image build context so Cargo workspace metadata resolves correctly during WASM component builds.
Security
[0.10.1] - 2026-02-28
Added
Changed
Deprecated
Removed
Fixed
Security
[0.10.0] - 2026-02-28
Added
- Gemini first-class provider: Google Gemini is now registered via the OpenAI-compatible endpoint with native tool calling, vision/multimodal support, streaming, and model discovery. Replaces the previous genai-backed fallback that lacked tool support. Supports both
GEMINI_API_KEYandGOOGLE_API_KEYenvironment variables - Podman sandbox backend — Podman as a first-class sandbox backend. Set
backend = "podman"or let auto-detection prefer it over Docker (Apple Container → Podman → Docker → restricted-host). Uses thepodmanCLI directly (no socket compatibility needed) - Trusted network mode: sandbox containers now default to
sandbox.network = "trusted", routing outbound traffic through an HTTP CONNECT proxy with full audit logging. Whentrusted_domainsis empty (the default), all domains are allowed (audit-only mode); when configured, only listed domains pass without approval. Includes real-time network audit log with domain, protocol, and action filtering via Settings > Network Audit. Configurable viasandbox.trusted_domainsinmoltis.toml. Proxy env vars (HTTP_PROXY,HTTPS_PROXY,NO_PROXY) are now automatically injected into both Docker and Apple Container sandboxes, and the proxy binds to0.0.0.0so it is reachable from container VMs. The proxy rejects connections from non-private IPs (only loopback, RFC 1918, link-local, and CGNAT ranges are accepted) - New
moltis-network-filtercrate: domain filtering, proxy, and audit buffer logic extracted frommoltis-toolsandmoltis-gatewayinto a standalone crate with feature flags (proxy,service,metrics). The macOS app can now depend on it directly for network audit log display viamoltis-swift-bridge - macOS Network Audit pane: new Settings > Network Audit section with real-time log display, action filtering (allowed/denied), search, pause/resume, clipboard export, and JSONL download — matching the web UI pattern. New FFI callback
moltis_set_network_audit_callbackbridges Rust audit entries to Swift - Proxy-compliant HTTP tools: all HTTP tools (
web_fetch,web_search,location,map) now route through the trusted-network proxy when active, so their traffic appears in the Network Audit log and respects domain filtering. The sharedreqwestclient is initialized with proxy config at gateway startup;web_fetchuses a per-tool proxy setting for its custom redirect-following client - Network policy rename:
sandbox.network = "open"has been renamed to"bypass"to make explicit that traffic bypasses the proxy entirely (no audit logging) - Real WASM sandbox (
wasmfeature, default on) — Wasmtime + WASI sandbox with filesystem isolation, fuel metering, epoch-based timeouts, and ~20 built-in coreutils (echo, cat, ls, mkdir, rm, cp, mv, etc.). Two execution tiers: built-in commands operate on a sandboxed directory tree;.wasmmodules run via Wasmtime with preopened dirs and captured I/O. Backend:"wasm"in config - Restricted-host sandbox — new
"restricted-host"backend (extracted from the oldWasmtimeSandbox) providing honest naming for what it does: env clearing, restricted PATH, andulimitresource wrappers without containers or WASM. Always compiled (no feature gate) - Docker security hardening — containers now launch with
--cap-drop ALL,--security-opt no-new-privileges, tmpfs mounts for/tmpand/run, and--read-onlyroot filesystem for prebuilt images - Generic sandbox failover chain — auto-detection now tries Apple Container → Docker → Restricted Host. Failover uses restricted-host as the final fallback instead of NoSandbox
- Discord channel integration via new
moltis-discordcrate using serenity Gateway API (persistent WebSocket, no public URL required). Supports DM and group messaging with allowlist/OTP gating, mention mode, guild allowlist, and 2000-char message chunking. Web UI: connect/edit/remove Discord bots in Settings > Channels and onboarding flow - Discord reply-to-message support: set
reply_to_message = trueto have the bot send responses as Discord threaded replies to the user’s message - Discord ack reactions: set
ack_reaction = "👀"to add an emoji reaction while processing (removed on completion) - Discord bot token import from OpenClaw installations during onboarding (both flat and multi-account configs)
- Discord bot presence/activity: configure
activity,activity_type(playing/listening/watching/competing/custom), andstatus(online/idle/dnd/invisible) in bot config - Discord OTP self-approval for DMs: non-allowlisted users receive a 6-digit challenge code (visible in web UI) to self-approve access, matching Telegram’s existing OTP flow
- Discord native slash commands:
/new,/clear,/compact,/context,/model,/sessions,/agent,/helpregistered as Discord application commands with ephemeral responses - OTP module moved from
moltis-telegramto sharedmoltis-channelscrate for cross-platform reuse - Real-time session sync between macOS app and web UI via
SessionEventBus(tokio::sync::broadcast). Sessions created, deleted, or patched in one UI instantly appear in the other. New FFI callbackmoltis_set_session_event_callbackand WebSocket"session"events for create/delete/fork operations. - Swift bridge: persistent session storage via FFI —
moltis_list_sessions,moltis_switch_session,moltis_create_session,moltis_session_chat_streamfunctions backed by JSONL files and shared SQLite metadata (moltis.db) across all UIs (macOS app, web, TUI) - Internationalization (i18n): web UI now supports runtime language switching via
i18nextwith English and French locales. Error codes use structured constants with locale-aware error messages across API handlers, terminal, chat, and environment routes. Onboarding step labels, navigation buttons, and page strings use translation keys (t()calls) - Vault UI: recovery key display during onboarding password setup, vault status/unlock controls in Settings > Security, encrypted/plaintext badges on environment variables
- Encryption-at-rest vault (
vaultfeature, default on) — environment variables are encrypted with XChaCha20-Poly1305 AEAD using Argon2id-derived keys. Vault is initialized on first password setup and auto-unsealed on login. Recovery key provided at initialization for emergency access. API:/api/auth/vault/status,/api/auth/vault/unlock,/api/auth/vault/recovery send_imagetool for sending local image files (PNG, JPEG, GIF, WebP) to channel targets like Telegram, with optional caption support- GraphQL API at
/graphql(GET serves GraphiQL playground and WebSocket subscriptions, POST handles queries/mutations) exposing all RPC methods as typed operations - New
moltis-graphqlcrate with queries, mutations, subscriptions, customJsonscalar, andServiceCallertrait abstraction - New
moltis-providerscrate that owns provider integrations and model registry/catalog logic (OpenAI, Anthropic, OpenAI-compatible, OpenAI Codex, GitHub Copilot, Kimi Code, local GGUF, local LLM) graphqlfeature flag (default on) in gateway and CLI crates for compile-time opt-out- Settings > GraphQL page embedding GraphiQL playground at
/settings/graphql - Gateway startup now seeds a built-in
dcg-guardhook in~/.moltis/hooks/dcg-guard/(manifest + handler), so destructive command guarding is available out of the box oncedcgis installed - Swift embedding POC scaffold with a new
moltis-swift-bridgestatic library crate, XcodeGen YAML project (apps/macos/project.yml), and SwiftLint wiring for SwiftUI frontend code quality - New
moltis-openclaw-importcrate for detecting OpenClaw installations and selectively importing identity, providers, skills, memory files, Telegram channels, sessions, and MCP servers - New onboarding RPC methods:
openclaw.detect,openclaw.scan, andopenclaw.import - New
moltis importCLI commands (detect,all,select) with--dry-runand--jsonoutput options - Onboarding now includes a conditional OpenClaw Import step with category selection, import execution, and detailed per-category results/TODO reporting
- Settings now includes an OpenClaw Import section (shown only when OpenClaw is detected) for scan-and-import workflows after onboarding
- Microsoft Teams channel integration via new
moltis-msteamsplugin crate with webhook ingress and OAuth client-credentials outbound messaging - Teams channel management in the web UI (add/edit/remove accounts, sender review, session/channel badges)
- Guided Teams bootstrap tooling via
moltis channels teams bootstrapplus an in-UI endpoint generator in Settings → Channels - Multi-agent personas with per-agent workspaces (
data_dir()/agents/<id>/),agents.*RPC methods, and session-levelagent_idbinding/switching across web + Telegram flows chat.peekRPC method returning real-time session state (active flag, thinking text, active tool calls) for any session key- Active tool call tracking per-session in
LiveChatServicewith camelCase-serializedActiveToolCallstructs - Web UI: inline red “Stop” button inside thinking indicator,
abortedbroadcast handler that cleans up streaming state - Channel commands:
/peek(shows thinking text and active tool calls) and/stop(aborts active generation)
Changed
- Crate restructure: gateway crate reduced from ~42K to ~29K lines by extracting
moltis-chat(chat engine, agent orchestration),moltis-auth(password + passkey auth),moltis-tls(TLS/HTTPS termination),moltis-service-traits(shared service interfaces), and moving share rendering intomoltis-web - Provider wiring now routes through
moltis-providersinstead ofmoltis-agents::providers, and local LLM feature flags (local-llm,local-llm-cuda,local-llm-metal) now resolve viamoltis-providers - Voice now auto-selects the first configured TTS/STT provider when no explicit provider is set.
- Default voice template/settings now favor OpenAI TTS and Whisper STT in onboarding-ready configs.
- Updated the
dcg-guardexample hook docs and handler behavior to gracefully no-op whendcgis missing, instead of hard-failing - Automatic model/provider selection now prefers subscription-backed providers (OpenAI Codex, GitHub Copilot) ahead of API-key providers, while still honoring explicit model priorities
- GraphQL gateway now builds its schema once at startup and reuses it for HTTP and WebSocket requests
- GraphQL resolvers now share common RPC helper macros and use typed response objects for
node.describe,voice.config,voice.voxtral_requirements,skills.security_status,skills.security_scan, andmemory.config - GraphQL
logs.ackmutation now matches backend behavior and no longer takes anidsargument - Gateway startup diagnostics now report OpenClaw detection status and pass detection state to web gon data for conditional UI rendering
- Gateway and CLI now enable the
openclaw-importfeature in default builds - Providers now support
stream_transport = "sse" | "websocket" | "auto"in config. OpenAI can stream via Responses API WebSocket mode, andautofalls back to SSE when WebSocket setup is unavailable. - Agent Identity emoji picker now includes 🐰 🐹 🦀 🦞 🦝 🦭 🧠 🧭 options
- Added architecture docs for a native Swift UI app embedding Moltis Rust core through a C FFI bridge (
docs/src/native-swift-embedding.md) - Channel persistence and message-log queries are now channel-type scoped (
channel_type + account_id) so Telegram and Teams accounts can share the same account IDs safely - Chat/system prompt resolution is now agent-aware, loading
IDENTITY.md,SOUL.md,MEMORY.md,AGENTS.md, andTOOLS.mdfrom the active session agent workspace with backward-compatible fallbacks - Memory tool operations and compaction memory writes are now agent-scoped, preventing cross-agent memory leakage during search/read/write flows
- Default sandbox package set now includes
golang-go, and pre-built sandbox images install the latestgog(steipete/gogcli) asgogandgogcli - Sandbox config now supports
/home/sandboxpersistence strategies (off,session,shared), withsharedas the default and a shared host folder mounted fromdata_dir()/sandbox/home/shared - Settings → Sandboxes now includes shared-home controls (enabled + folder path), and sandbox config supports
tools.exec.sandbox.shared_home_dirfor custom shared persistence location
Deprecated
Removed
Fixed
- OpenAI Codex OAuth in Docker: the web UI no longer overrides the provider’s pre-registered
redirect_uri, which caused OpenAI to reject the authorization request withunknown_error. The OAuth callback server now also respects the gateway bind address (0.0.0.0in Docker) so the callback port (1455) is reachable from the host. Docker image now exposes port 1455 for OAuth callbacks (#207) - Slow SQLite writes:
moltis.dbandmemory.dbnow usejournal_mode=WALandsynchronous=NORMAL(matchingmetrics.db), eliminating multi-second write contention that caused 3–10 s INSERT times under concurrent access - Channel image delivery now parses the actual MIME type from data URIs instead of hardcoding
image/png - Docker image now installs Docker CLI from Docker’s official Debian repository (
docker-ce-cli), avoiding API mismatches with newer host daemons during sandbox builds/exec - Chat UI now shows a first-run sandbox preparation status message before container/image setup begins, so startup delays are visible while sandbox resources are created
- OpenAI TTS and Whisper STT now correctly reuse OpenAI credentials from
voice config,
OPENAI_API_KEY, or the LLM OpenAI provider config. - Voice provider parsing now accepts
openai-ttsandgoogle-ttsaliases sent by the web UI. - Chat welcome card is now hidden as soon as the thinking indicator appears.
- Onboarding summary loading state now keeps modal sizing stable with a centered spinner.
- Onboarding voice provider rows now use a dedicated
needs-keybadge class and styling, with E2E coverage to verify the badge pill rendering - OpenAI Codex OAuth token handling now preserves account context across refreshes and resolves
ChatGPT-Account-Idfrom additional JWT/auth.json shapes to avoid auth failures with Max-style OAuth flows - Onboarding/provider setup now surfaces subscription OAuth providers (OpenAI Codex, GitHub Copilot) as configured when local OAuth tokens are present, even if they are omitted from
providers.offered - GraphQL WebSocket upgrade detection now accepts clients that provide
Upgrade/Sec-WebSocket-KeywithoutConnection: upgrade - GraphQL channel and memory status bridges now return schema-compatible shapes for
channels.status,channels.list, andmemory.status - Provider errors with
insufficient_quotanow surface as explicit quota/billing failures (with the upstream message) instead of generic retrying/rate-limit behavior - Linux
aarch64builds now skipjemallocto prevent startup aborts on 16 KiB page-size kernels (for example Raspberry Pi 5 Debian images) - Gateway startup now blocks the common reverse-proxy TLS mismatch (
MOLTIS_BEHIND_PROXY=truewith Moltis TLS enabled) and explains using--no-tls; HTTPS-upstream proxy setups can explicitly opt in withMOLTIS_ALLOW_TLS_BEHIND_PROXY=true - WebSocket same-origin checks now accept proxy deployments that rewrite
Hostby usingX-Forwarded-Hostin proxy mode, and treat implicit:443/:80as equivalent to default ports
Security
[0.9.10] - 2026-02-21
Added
Changed
Deprecated
Removed
Fixed
Security
[0.9.9] - 2026-02-21
Added
Changed
Deprecated
Removed
Fixed
Security
[0.9.8] - 2026-02-21
Added
Changed
Deprecated
Removed
Fixed
Security
[0.9.7] - 2026-02-20
Added
Changed
Deprecated
Removed
Fixed
Security
[0.9.6] - 2026-02-20
Added
- Cron jobs can now deliver agent turn output to Telegram channels via the
deliver,channel, andtopayload fields
Changed
Deprecated
Removed
Fixed
- Accessing
http://on the HTTPS port now returns a 301 redirect tohttps://instead of a garbled TLS handshake page - SQLite metrics store now uses WAL journal mode and
synchronous=NORMALto fix slow INSERT times (1-3s) on Docker/WSL2
Security
[0.9.5] - 2026-02-20
Added
Changed
Deprecated
Removed
Fixed
- Skip jemalloc on Windows (platform-specific dependency gate)
Security
[0.9.4] - 2026-02-20
Added
Changed
Deprecated
Removed
Fixed
Security
[0.9.3] - 2026-02-20
Added
Changed
Deprecated
Removed
Fixed
Security
[0.9.2] - 2026-02-20
Added
- Event-driven heartbeat wake system: cron jobs can now trigger immediate
heartbeat runs via a
wakeModefield ("now"or"nextHeartbeat"). - System events queue: in-memory bounded buffer that collects events (exec completions, cron triggers) and drains them into the heartbeat prompt so the agent sees what happened while it was idle.
- Exec completion callback: command executions automatically enqueue a summary event and wake the heartbeat, giving the agent real-time awareness of background task results.
Changed
Deprecated
Removed
Fixed
Security
[0.9.1] - 2026-02-19
Added
lightweightfeature profile for memory-constrained devices (Raspberry Pi, etc.) with only essential features:jemalloc,tls,web-ui.- jemalloc allocator behind
jemallocfeature flag for lower memory fragmentation. - Configurable
history_points(metrics) andlog_buffer_size(server) settings to tune in-memory buffer sizes. - Persistent browser profiles: cookies, auth state, and local storage now persist
across sessions by default. Disable with
persist_profile = falsein[tools.browser], or set a custom path withprofile_dir. (#162) - Added
examples/docker-compose.coolify.ymlplus Docker/cloud deploy docs for self-hosted Coolify (e.g. Hetzner), including reverse-proxy defaults and Docker socket mount guidance for sandboxed exec support. - Markdown and ANSI table rendering in chat messages.
- Provider-aware
show_maplinks for multi-provider map display. - Session history caching with visual switch loader for faster session transitions.
Changed
- MetricsHistory default reduced from 60,480 to 360 points (~170x less memory).
- LogBuffer default reduced from 10,000 to 1,000 entries.
- Shared
reqwest::Clientsingleton inmoltis-agentsandmoltis-toolsreplaces per-call client creation, saving connection pools and TLS session caches. - WebSocket client channels changed from unbounded to bounded (512), adding backpressure for slow consumers.
- Release profile:
panic = "abort"andcodegen-units = 1for smaller binaries.
Deprecated
Removed
Fixed
- Onboarding identity save now captures browser timezone and persists it to
USER.mdviauser_timezone, so first-run profile setup records the user’s timezone alongside their name. - Runtime prompt host metadata now prefers user/browser timezone over server
local fallback and includes an explicit
today=YYYY-MM-DDfield so models can reliably reason about the user’s current date. - Skills installation now supports Claude marketplace repos that define skills
directly via
.claude-plugin/marketplace.jsonplugins[].skills[]paths (for exampleanthropics/skills), including loadingSKILL.mdentries underskills/*and exposing them through the existing plugin-skill workflow. - Web search no longer falls back to DuckDuckGo by default when search API keys
are missing, avoiding repeated CAPTCHA failures; fallback is now opt-in via
tools.web.search.duckduckgo_fallback = true. - Terminal: force tmux window resize on client viewport change to prevent stale dimensions after reconnect.
- Browser: profile persistence now works correctly on Apple Container (macOS containerized sandbox).
- Browser: centralized stale CDP connection detection prevents ghost browser sessions from accumulating. (#172)
- Gateway: deduplicate voice replies on Telegram channels to prevent echo loops. (#173)
- Cron job editor: fix modal default validation and form reset when switching schedule type. (#181)
- MCP: strip internal metadata from tool call arguments before forwarding to MCP servers.
- Web search: load runtime env keys and improve Brave search response parsing robustness.
- Prompt: clarify sandbox vs
data_dirpath semantics in system prompts. - Gateway: align
show_maplisting ratings to the right for consistent layout.
Security
[0.9.0] - 2026-02-17
Added
- Settings > Cron job editor now supports per-job LLM model selection and
execution target selection (
hostorsandbox), including optional sandbox image override when sandbox execution is selected.
Changed
- Configuration documentation examples now match the current schema
(
[server],[identity],[tools],[hooks.hooks],[mcp.servers.<name>], and[channels.telegram.<account>]), including updated provider and local-LLM snippets.
Deprecated
Removed
Fixed
- Agent loop iteration limit is now configurable via
tools.agent_max_iterationsinmoltis.toml(default25) instead of being hardcoded at runtime.
Security
[0.8.38] - 2026-02-17
Added
show_mapnow supports multi-point maps viapoints[], rendering all destinations in one screenshot with auto-fit zoom/centering, while keeping legacy single-point fields for backward compatibility.- Telegram channel reply streaming via edit-in-place updates, with per-account
stream_modegating sooffkeeps the classic final-message delivery path. - Telegram per-account
stream_notify_on_completeoption to send a final non-silent completion message after edit-in-place streaming finishes. - Telegram per-account
stream_min_initial_charsoption (default30) to delay the first streamed message until enough text has accumulated.
Changed
Deprecated
Removed
Fixed
Security
[0.8.37] - 2026-02-17
Added
- Settings > Terminal now includes tmux window tabs for the managed
moltis-host-terminalsession, plus a+ Tabaction to create new tmux windows from the UI. - New terminal window APIs:
GET /api/terminal/windowsandPOST /api/terminal/windowsto list and create host tmux windows. - Host terminal websocket now supports
?window=<id|index>targeting and returnsactiveWindowIdin the ready payload.
Changed
- Web chat now supports
/shcommand mode: entering/shtoggles a dedicated command input state, command sends are automatically prefixed with/sh, and the token bar shows effective execution route (sandboxedvshost) plus prompt symbol (#for root,$for non-root). - Settings > Terminal now polls tmux windows and updates tabs automatically,
so windows created inside tmux (for example
Ctrl-b c) appear in the web UI. - Host terminal tmux integration now uses a dedicated tmux socket and applies a Moltis-friendly profile (status off, mouse off, stable window naming).
- Settings > Terminal subtitle now omits the prompt symbol hint so it does not
show stale
$/#information after privilege changes inside the shell.
Deprecated
Removed
Fixed
- Apple Container sandbox startup now pins
--workdir /tmp, bootstraps/home/sandboxbeforesleep infinity, and uses explicit exec workdirs to avoidWORKDIRchdir failures when image metadata directories are missing. - Cron tool job creation/update now accepts common shorthand schedule/payload shapes (including cron expression strings) and normalizes them before validation, reducing model-side schema mismatch failures.
- Force-exec fallback now triggers only for explicit
/sh ...input (including/sh@bot ...), preventing casual chat messages likeheyfrom being treated as shell commands while still allowing normal model-driven exec tool use. - Tool-mode system prompt guidance is now conversation-first and documents the
/shexplicit shell prefix. - Chat auto-compaction now uses estimated next-request prompt tokens (current context pressure) instead of cumulative session token totals, and chat context UI now separates cumulative usage from current/estimated request context.
- Settings > Terminal tab switching now uses in-band tmux window switching over
the active websocket, reducing redraw/cursor corruption when switching
between tmux windows (including fullscreen apps like
vim). - Host terminal tmux attach now resets window sizing to auto (
resize-window -A) to prevent stale oversized window dimensions across reconnects. - Settings > Terminal tmux window polling now continues after tab switches, so
windows closed with
Ctrl-Dare removed from the tab strip automatically. - Settings > Terminal now recovers from stale
?window=reconnect targets after a tmux window is closed, attaching to the current window instead of getting stuck in a reconnect loop. - Settings > Terminal host PTY output is now transported as raw bytes
(base64-encoded over websocket) instead of UTF-8-decoded text, fixing
rendering/control-sequence corruption in full-screen terminal apps like
vim. - Settings > Terminal now force-syncs terminal size on connect/window switch so newly created tmux windows attach at full viewport size instead of a smaller default geometry.
- Settings > Terminal now ignores OSC color/palette mutation sequences from
full-screen apps to avoid invisible-text redraw glitches when switching tmux
tabs (notably seen with
vim). - Settings > Terminal now re-sends forced resize updates during a short post-connect settle window, fixing initial page-reload cases where tmux windows stayed at stale dimensions until a manual tab switch.
Security
[0.8.36] - 2026-02-16
Added
- OAuth 2.1 support for remote MCP servers — automatic discovery (RFC 9728/8414), dynamic client registration (RFC 7591), PKCE authorization code flow, and Bearer token injection with 401 retry
McpOAuthOverrideconfig option for servers that don’t implement standard OAuth discoverymcp.reauthRPC method to manually trigger re-authentication for a server- Persistent storage of dynamic client registrations at
~/.config/moltis/mcp_oauth_registrations.json - SSRF allowlist:
tools.web.fetch.ssrf_allowlistconfig field to exempt trusted CIDR ranges from SSRF blocking, enabling Docker inter-container networking. - Memory config: add
memory.disable_ragto force keyword-only memory search while keeping markdown indexing and memory tools enabled - Generic OpenAI-compatible provider support: connect any OpenAI-compatible endpoint via the provider setup UI, with domain-derived naming (
custom-prefix), model auto-discovery, and full model selection
Changed
Deprecated
Removed
Fixed
- Telegram queued replies: route channel reply targets per queued message so
chat.message_queue_mode = "followup"delivers replies one-by-one instead of collapsing queued channel replies into a single batch delivery. - Queue mode default: make one-by-one replay (
followup) explicit as theChatConfigdefault, with config-level tests to prevent regressions. - MCP OAuth dynamic registration now uses the exact loopback callback URI selected for the current auth flow, improving compatibility with providers that require strict redirect URI matching (for example Linear).
- MCP manager now applies
[mcp.servers.<name>.oauth]override settings when building the OAuth provider for SSE servers. - Streamable HTTP MCP transport now persists and reuses
Mcp-Session-Id, parsestext/event-streamresponses, and sends best-effortDELETEon shutdown to close server sessions. - MCP docs/config examples now use the current table-based config shape and
/mcpendpoint examples for remote servers. - Memory embeddings endpoint composition now avoids duplicated path segments like
/v1/v1/embeddingsand accepts base URLs ending in host-only,/v1, versioned paths (for example/v4), or/embeddings
Security
[0.8.35] - 2026-02-15
Added
- Add memory target routing guidance to
memory_saveprompt hint — core facts go to MEMORY.md, everything else tomemory/<topic>.mdto keep context lean
Changed
Deprecated
Removed
Fixed
Security
[0.8.34] - 2026-02-15
Added
- Add explicit
memory_savehint in system prompt so weaker models (MiniMax, etc.) call the tool when asked to remember something - Add anchor text after memory content so models don’t ignore known facts when
memory_searchreturns empty - Add
zaito default offered providers in config template
Changed
Deprecated
Removed
Fixed
Security
[0.8.33] - 2026-02-15
Added
Changed
Deprecated
Removed
Fixed
- CI: remove unnecessary
std::path::qualification in gateway server flagged by nightly clippy.
Security
[0.8.32] - 2026-02-15
Added
Changed
Deprecated
Removed
Fixed
- CI: gate macOS-only sandbox helper functions with
#[cfg]to fix dead-code errors on Linux CI.
Security
[0.8.31] - 2026-02-15
Added
-
Sandbox toggle notification: when the sandbox is enabled or disabled mid-session, a system message is injected into the conversation history so the LLM knows the execution environment changed. A chat notice also appears in the UI immediately.
-
Config
[env]section: environment variables defined in[env]inmoltis.tomlare injected into the Moltis process at startup. This makes API keys (Brave, OpenRouter, etc.) available to features that read fromstd::env::var(). Process env vars (docker -e, host env) take precedence. Closes #107. -
Browser auto-detection and install: automatically detect all installed Chromium-family browsers (Chrome, Chromium, Edge, Brave, Opera, Vivaldi, Arc) and auto-install via the system package manager when none is found. Requests can specify a preferred browser (
"browser": "brave") or let the system pick the first available one. -
Z.AI provider: add Z.AI (Zhipu) as an OpenAI-compatible provider with static model catalog (GLM-5, GLM-4.7, GLM-4.6, GLM-4.5 series) and dynamic model discovery via
/modelsendpoint. Supports tool calling, streaming, vision (GLM-4.6V/4.5V), and reasoning content. -
Running Containers panel: the Settings > Sandboxes page now shows a “Running Containers” section listing all moltis-managed containers with live state (running/stopped/exited), backend type (Apple Container/Docker), resource info, and Stop/Delete actions. Includes disk usage display (container/image counts, sizes, reclaimable space) and a “Clean All” button to stop and remove all stale containers at once.
-
Startup container GC: the gateway now automatically removes orphaned session containers on startup, preventing disk space accumulation from crashed or interrupted sessions.
-
Download full context as JSONL: the full context panel now has a “Download” button that exports the conversation (including raw LLM responses) as a timestamped
.jsonlfile. -
Sandbox images in cached images list: the Settings > Images page now merges sandbox-built images into the cached images list so all container images are visible in one place.
Changed
- Sandbox image identity: image tags now use SHA-256 instead of
DefaultHasherfor deterministic, cross-run hashing of base image + packages.
Deprecated
Removed
Fixed
- Thinking indicator lost on reload: reloading the page while the model
was generating no longer loses the “thinking” dots. The backend now includes
replyingstate insessions.listandsessions.switchRPC responses so the frontend can restore the indicator after a full page reload. - Thinking text restored after reload: reloading the page during extended
thinking (reasoning) now restores the accumulated thinking text instead of
showing only bouncing dots. The backend tracks thinking text per session and
returns it in the
sessions.switchresponse. - Apple Container recovery: simplify container recovery to a single flat
retry loop (3 attempts max, down from up to 24). Name rotation now only
triggers on
AlreadyExistserrors, preventing orphan containers. AddednotFounderror matching so exec readiness probes retry correctly. Diagnostic info (running container count, service health, container logs) is now included in failure messages. Detect stale Virtualization.framework state (NSPOSIXErrorDomain EINVAL) and automatically restart the daemon (container system stop && container system start) before retrying; bail with a clear remediation message only if automatic restart fails. Exec-level recovery retries reduced from 3 to 1. - Ghost Apple Containers: failed container deletions are now tracked in a zombie set and filtered from list output, preventing stale entries from reappearing in the Running Containers panel.
- Container action errors preserved: failed delete/clean/restart operations now surface the original error message to the UI instead of silently swallowing it.
- Usage parsing across OpenAI-compatible providers: token counts now
handle Anthropic-style (
input_tokens/output_tokens), camelCase variants, cache token fields, and multiple response nesting structures across diverse providers. - Think tag whitespace: leading whitespace after
</think>close tags is now stripped, preventing extra blank lines in streamed output. - Token bar visible at zero: the token usage bar no longer disappears when all counts are zero; it stays visible as a baseline indicator.
Security
[0.8.30] - 2026-02-15
Added
Changed
- Assistant reasoning persistence: conversation reasoning is now persisted in assistant messages and shared snapshots so resumed sessions retain reasoning context instead of dropping it after refresh/share operations.
Deprecated
Removed
Fixed
Security
[0.8.29] - 2026-02-14
Added
- Memory bootstrap: inject
MEMORY.mdcontent directly into the system prompt (truncated at 20,000 chars) so the agent always has core memory available without needing to callmemory_searchfirst. Matches OpenClaw’s bootstrap behavior - Memory save tool: new
memory_savetool lets the LLM write to long-term memory files (MEMORY.mdormemory/<name>.md) with append/overwrite modes and immediate re-indexing for search
Changed
- Memory writing:
MemoryManagernow implements theMemoryWritertrait directly, unifying read and write paths behind a single manager. The silent memory turn andMemorySaveToolboth delegate to the manager, which handles path validation, size limits, and automatic re-indexing after writes
Deprecated
Removed
Fixed
- Memory file watcher: the file watcher now covers
MEMORY.mdat the data directory root, which was previously excluded because the filter only matched directories
Security
[0.8.28] - 2026-02-14
Added
Changed
- Browser sandbox resolution:
BrowserToolnow resolves sandbox mode directly fromSandboxRouterinstead of relying on a_sandboxflag injected via tool call params.
Deprecated
Removed
Fixed
- E2E onboarding failures: Fixed missing
saveProviderKeyexport inprovider-validation.jsthat was accidentally left unstaged in the DRY refactoring commit.
Security
[0.8.27] - 2026-02-14
Added
Changed
- DRY voice/identity/channel utils: Extracted shared RPC wrappers and
validation helpers from
onboarding-view.jsandpage-settings.js/page-channels.jsinto dedicatedvoice-utils.js,identity-utils.js, andchannel-utils.jsmodules.
Deprecated
Removed
Fixed
- Config test env isolation: Fixed spurious
save_config_to_path_removes_stale_keys_when_values_are_clearedtest failure caused byMOLTIS_IDENTITY__NAMEenvironment variable leaking into the test viaapply_env_overrides.
Security
[0.8.26] - 2026-02-14
Added
- Rustls/OpenSSL migration roadmap: Added
plans/2026-02-14-rustls-migration-and-openssl-reduction.mdwith a staged plan to reduce OpenSSL coupling, isolate feature gates, and move default TLS networking paths toward rustls.
Changed
Deprecated
Removed
Fixed
- Windows release build reliability: The
.exerelease workflow now forces Strawberry Perl (OPENSSL_SRC_PERL/PERL) so vendored OpenSSL builds do not fail due to missing Git Bash Perl modules. - OpenAI tool-call ID length: Remap tool-call IDs that exceed OpenAI’s 40-character limit during message serialization, and generate shorter synthetic IDs in the agent runner to prevent API errors.
- Onboarding credential persistence: Provider credentials are now saved before opening model selection during onboarding, aligning behavior with the Settings > LLM flow.
Security
[0.8.25] - 2026-02-14
Added
Changed
Deprecated
Removed
Fixed
Security
[0.8.24] - 2026-02-13
Added
Changed
Deprecated
Removed
Fixed
Security
[0.8.23] - 2026-02-13
Added
- Multi-select preferred models per provider: The LLMs page now has a
“Preferred Models” button per provider that opens a multi-select modal.
Selected models are pinned at the top of the session model dropdown.
New
providers.save_modelsRPC accepts multiple model IDs at once. - Multi-select model picker in onboarding: The onboarding provider step now uses a multi-select model picker matching the Settings LLMs page. Toggle models on/off, see per-model probe status badges, and batch-save with a single Save button. Previously-saved preferred models are pre-selected when re-opening the model selector.
Changed
- Model discovery uses
DiscoveredModelstruct: Replaced(String, String)tuples with a typedDiscoveredModelstruct across all providers (OpenAI, GitHub Copilot, OpenAI Codex). The struct carries an optionalcreated_attimestamp from the/v1/modelsAPI, enabling discovered models to be sorted newest-first. Preferred/configured models remain pinned at the top. - Removed OpenAI-specific model name filtering from discovery: The
/v1/modelsresponse is no longer filtered by OpenAI naming conventions (gpt-*,o1, etc.). All valid model IDs from any provider are now accepted. This fixes model discovery for third-party providers like Moonshot whose model IDs don’t follow OpenAI naming. - Disabled automatic model probe at startup: The background chat completion probe that checked which models are supported is now triggered on-demand by the web UI instead of running automatically 2 seconds after startup. With dynamic model discovery, the startup probe was expensive and noisy (non-chat models like image, audio, and video would log spurious warnings).
- Model test uses streaming for faster feedback: The “Testing…” probe when selecting a model now uses streaming and returns on the first token instead of waiting for a full non-streaming response. Timeout reduced from 20s to 10s.
- Chosen models merge with config-defined priority: Models selected via the UI are prepended to the saved models list and merged with config-defined preferred models, so both sources contribute to ordering.
- Dynamic cross-provider priority list: The model dropdown priority
is now a shared
Arc<RwLock<Vec<String>>>updated at runtime when models are saved, instead of a staticHashMapbuilt once at startup. - Replaced hardcoded Ollama checks with
keyOptionalmetadata: JS files no longer checkprovider.name === "ollama"for behavior. Instead, the backend exposes akeyOptionalfield on provider metadata, making the UI provider-agnostic.
Fixed
- Settings UI env vars now available process-wide: environment variables set via Settings > Environment were previously only injected into sandbox commands. They are now also injected into the Moltis process at startup, making them available to web search, embeddings, and provider API calls.
[0.8.14] - 2026-02-11
Security
- Disconnect all WS clients on credential change: WebSocket connections
opened before auth setup are now disconnected when credentials change
(password set/changed, passkey registered during setup, auth reset, last
credential removed). An
auth.credentials_changedevent notifies browsers to redirect to/login. Existing sessions are also invalidated on password change for defense-in-depth.
Fixed
- Onboarding test for SOUL.md clear behavior: Fixed
identity_update_partialtest to match the new empty-file behavior from v0.8.13.
[0.8.13] - 2026-02-11
Added
- Auto-create SOUL.md on first run:
SOUL.mdis now seeded with the default soul text when the file doesn’t exist, mirroring howmoltis.tomlis auto-created. If deleted, it re-seeds on next load.
Fixed
- SOUL.md clear via settings: Clearing the soul textarea in settings no longer re-creates the default on the next load. An explicit clear now writes an empty file to distinguish “user cleared soul” from “file never existed”.
- Onboarding WS connection timing: Deferred WebSocket connection until authentication completes, preventing connection failures during onboarding.
Changed
- Passkey auth preselection: Onboarding now preselects the passkey authentication method when a passkey is already registered.
- Moonshot provider: Added Moonshot to the default offered providers list.
[0.8.12] - 2026-02-11
Fixed
- E2E test CI stability:
NoopChatService::clear()now returns Ok instead of an error when no LLM providers are configured, fixing 5 e2e test failures in CI environments. Hardened websocket, chat-input, and onboarding-auth e2e tests against startup race conditions and flaky selectors.
[0.8.8] - 2026-02-11
Changed
- Sessions sidebar layout: Removed the top
Sessionstitle row and moved the new-session+action next to the session search field for a more compact list header. - Identity autosave UX: Name fields in Settings > Identity now autosave on input blur, matching the quick-save behavior used for emoji selection.
- Favicon behavior by browser: Identity emoji changes now update favicon live; Safari-specific reload guidance is shown only when Safari is detected.
- Page title format: Browser title now uses the configured assistant name
only, without appending
AI assistantsuffix text.
[0.8.7] - 2026-02-11
Added
- Model allowlist probe output support: Model allowlist matching now handles provider probe output more robustly and applies stricter matching semantics.
- Ship helper command: Added a
just shiptask andscripts/ship-pr.shhelper to streamline commit, push, PR update, and local validation workflows.
Changed
- Gateway titles and labels: Login/onboarding page titles now consistently
use configured values and identity emoji; UI copy now labels providers as
LLMwhere appropriate. - Release binary profile: Enabled ThinLTO and binary stripping in the release profile to reduce artifact size.
- SPA route handling: Centralized SPA route definitions and preserved TOML comments during config updates.
Fixed
- Auth setup hardening: Enforced authentication immediately after password or passkey setup to prevent unintended post-setup unauthenticated access.
- Streaming event ordering: Preserved gateway chat stream event ordering to avoid out-of-order UI updates during streaming responses.
- Sandbox fallback pathing: Exec fallback now uses the host data directory when no container runtime is available.
[0.8.6] - 2026-02-11
Changed
- Release workflow gates E2E tests: Build Packages workflow now runs E2E tests and blocks all package builds (deb, rpm, arch, AppImage, snap, Homebrew, Docker) if they fail.
Added
- XML tag stripping: Strip internal XML tags from LLM responses to prevent tag leakage in chat (thinking, reasoning, scratchpad, etc.)
- Runtime model metadata: Fetch model metadata from provider APIs for accurate context window detection during auto-compaction
- Run detail UI: Panel showing tool calls and message flow for agent runs, accessible via expandable button on assistant messages
Fixed
- Docker TLS setup: All Docker examples now expose port 13132 for CA certificate download with instructions to trust the self-signed cert, fixing HTTPS access in Safari and other strict browsers.
- E2E onboarding-auth test: The
authPlaywright project’stestMatchregex/auth\.spec/also matchedonboarding-auth.spec.js, causing it to run against the default gateway (wrong server) instead of the onboarding-auth gateway. Tightened regex to/\/auth\.spec/.
[0.8.5] - 2026-02-11
Added
- CLI
--versionflag:moltis --versionnow prints the version. - Askama HTML rendering: SPA index and social metadata templates use Askama instead of string replacement.
Fixed
- WebSocket reconnect after remote onboarding auth: Connection now reconnects immediately after auth setup instead of waiting for the backoff timer, fixing “WebSocket not connected” errors during identity save.
- Passkeys on Fly.io: Auto-detect WebAuthn RP ID from
FLY_APP_NAMEenvironment variable (constructs{app}.fly.dev). - PaaS proxy detection: Added explicit
MOLTIS_BEHIND_PROXY=truetorender.yamlandfly.tomlso auth middleware reliably detects remote connections behind the platform’s reverse proxy. - WebAuthn origin scheme on PaaS: Non-localhost RP IDs now default to
https://origin since PaaS platforms terminate TLS at the proxy.
Security
- Compaction prompt injection hardening: Session compaction now passes
typed
ChatMessageobjects to the summarizer LLM instead of concatenated{role}: {content}text, preventing role-spoofing prompt injection where user content could mimic role prefixes (similar to GHSA-g8p2-7wf7-98mq).
[0.8.4] - 2026-02-11
Changed
- Session delete UX: Forked sessions with no new messages beyond the fork point are deleted immediately without a confirmation dialog.
Fixed
- Localhost passkey compatibility: Gateway startup URLs and TLS redirect
hints now use
localhostfor loopback hosts, while WebAuthn also allowsmoltis.localhostas an additional origin when RP ID islocalhost.
[0.8.3] - 2026-02-11
Fixed
- Linux clippy
unused_mutfailure: Fixed a target-specificunused_mutwarning in browser stale-container cleanup that failed release clippy on Linux with-D warnings.
[0.8.2] - 2026-02-11
Fixed
- Release clippy environment parity: The release workflow clippy job now
runs in the same CUDA-capable environment as main CI, includes the llama
source git bootstrap step, and installs
rustfmtalongsideclippy. This fixes release clippy failures caused by missing CUDA toolchain/runtime.
[0.8.1] - 2026-02-11
Fixed
- Clippy validation parity: Unified local validation, CI (main), and
release workflows to use the same clippy command and flags
(
--workspace --all-features --all-targets --timings -D warnings), which prevents release-only clippy failures from command drift.
[0.8.0] - 2026-02-11
Added
- Instance-scoped container naming: Browser and sandbox container/image prefixes now derive from the configured instance name, so multiple Moltis instances do not collide.
Changed
- Stale container cleanup targeting: Startup cleanup now removes only containers that belong to the active instance prefix instead of sweeping unrelated containers.
- Apple container runtime probing: Browser container backend checks now use
the modern Apple container CLI flow (
container image pull --help) without legacy fallback behavior.
Fixed
- Release workflow artifacts: Disabled docker build record artifact uploads in release CI to avoid release workflow failures from missing artifact paths.
- Release preflight consistency: Pinned nightly toolchain and aligned release preflight checks with CI formatting/lint gates.
[0.7.1] - 2026-02-11
Fixed
- Release format gate: Included missing Rust formatting updates in release
history so the release workflow
cargo fmt --all -- --checkpasses for tagged builds.
[0.7.0] - 2026-02-11
Added
- HTTP endpoint throttling: Added gateway-level per-IP rate limits for
login (
/api/auth/login), auth API routes, general API routes, and WebSocket upgrades, with429responses,Retry-Afterheaders, and JSONretry_after_seconds. - Login retry UX: The login page now disables the password Sign In button
while throttled and shows a live
Retry in Xscountdown.
Changed
- Auth-aware throttling policy: IP throttling is now bypassed when auth is not required for the current request (authenticated requests, auth-disabled mode, and local Tier-2 setup mode). This keeps brute-force protection for unauthenticated/auth-required traffic while avoiding localhost friction.
- Login error copy: During throttled login retries, the error message stays static while the retry countdown is shown only on the button.
Documentation
- Added throttling/security notes to
README.md,docs/src/index.md,docs/src/authentication.md, anddocs/src/security.md.
[0.6.1] - 2026-02-10
Fixed
- Release clippy: Aligned release workflow clippy command with nightly
flags (
-Z unstable-options,--timings). - Test lint attributes: Fixed useless outer
#[allow]on test moduleusestatement; replaced.unwrap()with.expect()in auth route tests.
[0.6.0] - 2026-02-10
Added
- CalDAV integration: New
moltis-caldavcrate providing calendar CRUD operations (list calendars, list/create/update/delete events) via the CalDAV protocol. Supports Fastmail, iCloud, and generic CalDAV servers with multi-account configuration under[caldav.accounts.<name>]. Enabled by default via thecaldavfeature flag. BeforeLLMCall/AfterLLMCallhooks: New modifying hook events that fire before sending prompts to the LLM provider and after receiving responses (before tool execution). Enables prompt injection filtering, PII redaction, and response auditing via shell hooks.- Config template: The generated
moltis.tomltemplate now lists all 17 hook events with correct PascalCase names and one-line descriptions. - Hook event validation:
moltis config checknow warns on unknown hook event names in the config file. - Authentication docs: Comprehensive
docs/src/authentication.mdwith decision matrix, credential types, API key scopes, session endpoints, and WebSocket auth documentation.
Fixed
- Browser container lifecycle: Browser containers (browserless/chrome)
now have proper lifecycle management — periodic cleanup removes idle
instances every 30 seconds, graceful shutdown stops all containers on
Ctrl+C, and
sessions.clear_allimmediately closes all browser sessions. ADropsafety net ensures containers are stopped even on unexpected exits.
Changed
- Unified auth gate: All auth decision logic is now in a single
check_auth()function called by oneauth_gatemiddleware. This fixes the split-brain bug where passkey-only setups (no password) were treated differently by 4 out of 5 auth code paths — the middleware usedis_setup_complete()(correct) while the others usedhas_password()(incorrect for passkey-only setups). - Hooks documentation: Rewritten
docs/src/hooks.mdwith complete event reference, correctedToolResultPersistclassification (modifying, not read-only), and new “Prompt Injection Filtering” section with examples. - Logs level filter UI: Settings -> Logs now shows
DEBUG/TRACElevel options only when they are enabled by the active tracing filter (including target-specific directives). Default view remainsINFOand above. - Logs level filter control: Settings -> Logs now uses the same combo dropdown pattern as the chat model selector for consistent UX.
- Branch favicon contrast: Non-main branches now use a high-contrast purple
favicon variant so branch sessions are visually distinct from
main.
Security
- Content-Security-Policy header: HTML pages now include a nonce-based CSP
header (
script-src 'self' 'nonce-<UUID>'), preventing inline script injection (XSS defense-in-depth). The OAuth callback page also gets a restrictive CSP. - Passkey-only auth fix: Fixed authentication bypass where passkey-only
setups (without a password) would incorrectly allow unauthenticated access
on local connections, because the
has_password()check returned false even thoughis_setup_complete()was true.
[0.5.0] - 2026-02-09
Added
moltis doctorcommand: Comprehensive health check that validates config, audits security (file permissions, API keys in config), checks directory and database health, verifies provider readiness (API keys via config or env vars), inspects TLS certificates, and validates MCP server commands on PATH.
Security
- npm install –ignore-scripts: Skill dependency installation now passes
--ignore-scriptsto npm, preventing supply chain attacks via malicious postinstall scripts in npm packages. - API key scope enforcement: API keys with empty/no scopes are now denied access instead of silently receiving full admin privileges. Keys must specify at least one scope explicitly (least-privilege by default).
[0.4.1] - 2026-02-09
Fixed
- Clippy lint in map test: Replace
is_some()/unwrap()withif let Someto fixclippy::unnecessary_unwrapthat broke the v0.4.0 release build.
[0.4.0] - 2026-02-09
Added
- Auto-import external OAuth tokens: At startup, auto-detected provider
tokens (e.g. Codex CLI
~/.codex/auth.json) are imported into the centraloauth_tokens.jsonstore so users can manage all providers from the UI. - Passkey onboarding: The security setup step now offers passkey registration (Touch ID, Face ID, security keys) as the recommended default, with password as a fallback option.
providers.validate_keyRPC method: Test provider credentials without saving them — builds a temporary registry, probes with a “ping” message, and returns validation status with available models.providers.save_modelRPC method: Save the preferred model for any configured provider without changing credentials.models.testRPC method: Test a single model from the live registry with a real LLM request before committing to it.- Model selection for auto-detected providers: The Providers settings page
now shows a “Select Model” button for providers that have available models but
no preferred model set. This lets users pick their favorite model for
auto-detected providers (e.g. OpenAI Codex detected from
~/.codex/auth.json). show_maptool: New LLM-callable tool that composes a static map image from OSM tiles with red/blue marker pins (destination + user location), plus clickable links to Google Maps, Apple Maps, and OpenStreetMap. Supportsuser_latitude/user_longitudeto show both positions with auto-zoom. Solves the “I can’t share links” problem in voice mode.- Location precision modes: The
get_user_locationtool now accepts aprecisionparameter —"precise"(GPS-level, default) for nearby places and directions, or"coarse"(city-level, faster) for flights, weather, and time zones. The LLM picks the appropriate mode based on the user’s query.
Changed
- Show “No LLM Providers Connected” card instead of welcome greeting when no providers are configured.
- Onboarding provider setup: Credentials are now validated before saving. After successful validation, a model selector shows available models for the provider. The selected model is tested with a real request before completing setup. Clear error messages are shown for common failures (invalid API key, rate limits, connection issues).
- Settings provider setup: The main Providers settings page now uses the same validate-first flow as onboarding. Credentials are validated before saving (bad keys are never persisted), a model selector appears after validation, and OAuth flows show model selection after authentication.
Fixed
- Docker RAM detection: Fall back to
/proc/meminfowhensysinforeturns 0 bytes for memory inside Docker/cgroup environments. - MLX model suggested on Linux: Use backend-aware model suggestion so MLX models are only suggested on Apple Silicon, not on Linux servers.
- Host package provisioning noise: Skip
apt-getwhen running as non-root with no passwordless sudo, instead of failing with permission denied warnings. - Browser image pull without runtime: Guard browser container image pull to skip when no usable container runtime is available (backend = “none”).
- OAuth token store logging: Replace silent
.ok()?chains with explicitwarn!/info!logging inTokenStoreload/save/delete for diagnosability. - Provider warning noise: Downgrade “tokens not found” log from
warn!todebug!for unconfigured providers (GitHub Copilot, OpenAI Codex). - models.detect_supported noise: Downgrade UNAVAILABLE RPC errors from
warn!todebug!since they indicate expected “not ready yet” states.
[0.3.8] - 2026-02-09
Changed
- Release CI parallelization: Split clippy and test into separate parallel jobs in the release workflow for faster feedback on GitHub-hosted runners.
Fixed
- CodSpeed workflow zizmor audit: Pinned
CodSpeedHQ/action@v4to commit SHA to satisfy zizmor’sunpinned-usesaudit.
[0.3.7] - 2026-02-09
Fixed
- Clippy warnings: Fixed
MutexGuardheld across await in telegram test,field assignment outside initializerin provider setup test, anditems after test modulein gateway services.
[0.3.6] - 2026-02-09
Fixed
- Release CI zizmor audit: Removed
rust-cachefrom the release workflow’s clippy-test job entirely instead of usingsave-if: false, which zizmor does not recognize as a cache-poisoning mitigation.
[0.3.5] - 2026-02-09
Fixed
- Release CI cache-poisoning: Set
save-if: falseonrust-cachein the release workflow to satisfy zizmor’s cache-poisoning audit for tag-triggered workflows that publish artifacts.
[0.3.4] - 2026-02-09
Fixed
- Session file lock contention: Replaced non-blocking
try_write()with blockingwrite()inSessionStore::append()andreplace_history()so concurrent tool-result persists wait for the file lock instead of failing withEAGAIN(OS error 35).
Changed
- Release CI quality gates: The Build Packages workflow now runs biome, format, clippy, and test checks before building any packages, ensuring code correctness before artifacts are produced.
[0.3.3] - 2026-02-09
Fixed
- OpenAI Codex token refresh panic: Made
get_valid_token()async to fixblock_oninside async runtime panic when refreshing expired OAuth tokens. - Channel session binding: Ensure session row exists before setting channel
binding, fixing
get_user_locationfailures on first Telegram message. - Cargo.lock sync: Lock file now matches workspace version.
[0.3.0] - 2026-02-08
Added
-
Silent replies: The system prompt instructs the LLM to return an empty response when tool output speaks for itself, suppressing empty chat bubbles, push notifications, and channel replies. Empty assistant messages are not persisted to session history.
-
Persist TTS audio to session media: When TTS is enabled and the reply medium is
voice, the server generates TTS audio, saves it to the session media directory, and includes the media path in the persisted assistant message. On session reload the frontend renders an<audio>player from the media API instead of re-generating audio via RPC. -
Per-session media directory: Screenshots from the browser tool are now persisted to
sessions/media/<key>/and served viaGET /api/sessions/:key/media/:filename. Session history reload renders screenshots from the API instead of losing them. Media files are cleaned up when a session is deleted. -
Process tool for interactive terminal sessions: New
processtool lets the LLM manage interactive/TUI programs (htop, vim, REPLs, etc.) via tmux sessions inside the sandbox. Supports start, poll, send_keys, paste, kill, and list actions. Includes a built-intmuxskill with usage instructions. -
Runtime host+sandbox prompt context: Chat system prompts now include a
## Runtimesection with host details (hostname, OS, arch, shell, provider, model, session, sudo non-interactive capability) andexecsandbox details (enabled state, mode, backend, scope, image, workspace mount, network policy, session override). Tool-mode prompts also add routing guidance so the agent asks before requesting host installs or changing sandbox mode. -
Telegram location sharing: Telegram channels now support receiving shared locations and live location updates. Live locations are tracked until they expire or the user stops sharing.
-
Telegram reply threading: Telegram channel replies now use
reply_to_message_idto thread responses under the original user message, keeping conversations visually grouped in the chat. -
get_user_locationtool: New browser-based geolocation tool lets the LLM request the user’s current coordinates via the Geolocation API, with a permission prompt in the UI. -
sandbox_packagestool: New tool for on-demand package discovery inside the sandbox, allowing the LLM to query available and installable packages at runtime. -
Sandbox package expansions: Pre-built sandbox images now include expanded package groups — GIS/OpenStreetMap, document/office/search, image/audio/media/data-processing, and communication packages. Mise is also available for runtime version management.
-
Queued message UI: When a message is submitted while the LLM is already responding, it is shown in a dedicated bottom tray with cancel support. Queued messages are moved into the conversation only after the current response finishes rendering.
-
Full context view: New “Context” button in the chat header opens a panel showing the full LLM messages array sent to the provider, with a Copy button for easy debugging.
-
Browser timezone auto-detection: The gateway now auto-detects the user’s timezone from the browser via
Intl.DateTimeFormatand includes it in session context, removing the need for manual timezone configuration. -
Logs download: New Download button on the logs page streams the JSONL log file via
GET /api/logs/downloadwith gzip/zstd compression. -
Gateway middleware hardening: Consolidated middleware into
apply_middleware_stack()with security and observability layers:- Replace
allow_origin(Any)with dynamic host-based CORS validation reusing the WebSocket CSWSHis_same_originlogic, safe for Docker/cloud deployments with unknown hostnames CatchPanicLayerto convert handler panics to 500 responsesRequestBodyLimitLayer(16 MiB) to prevent memory exhaustionSetSensitiveHeadersLayerto redact Authorization/Cookie in traces- Security response headers (
X-Content-Type-Options,X-Frame-Options,Referrer-Policy) SetRequestIdLayer+PropagateRequestIdLayerforx-request-idcorrelation across HTTP request logs- zstd compression alongside gzip for better ratios
- Replace
-
Message run tracking: Persisted messages now carry
run_idandseqfields for parent/child linking across multi-turn tool runs, plus a client-side sequence number for ordering diagnostics. -
Cache token metrics: Provider responses now populate cache-hit and cache-miss token counters in the metrics subsystem.
Changed
- Provider auto-detection observability: When no explicit provider settings are present in
moltis.toml, startup now logs each auto-detected provider with its source (env, config file key, OAuth token file, provider key file, or Codex auth file). Addedserver.http_request_logs(Axum HTTP traces) andserver.ws_request_logs(WebSocket RPC request/response traces) config options (both defaultfalse) for on-demand transport debugging without code changes. - Dynamic OpenAI Codex model catalog: OpenAI Codex providers now load model IDs from
https://chatgpt.com/backend-api/codex/modelsat startup (with fallback defaults), and the gateway refreshes Codex models hourly so long-running sessions pick up newly available models (for examplegpt-5.3) without restart. - Model availability probing UX: Model support probing now runs in parallel with bounded concurrency, starts automatically after provider connect/startup, and streams live progress (
start/progress/complete) over WebSocket so the Providers page can render a progress bar. - Provider-scoped probing on connect: Connecting a provider from the Providers UI now probes only that provider’s models (instead of all providers), reducing noise and startup load when adding accounts one by one.
- Configurable model ordering: Added
chat.priority_modelsinmoltis.tomlto pin preferred models at the top of model selectors without rebuilding. Runtime model selectors (models.list, chat model dropdown, Telegram/model) hide unsupported models, while Providers diagnostics continue to show full catalog entries (including unsupported flags). - Configurable provider offerings in UI: Added
[providers] offered = [...]allowlist inmoltis.tomlto control which providers are shown in onboarding/provider-picker UI. New config templates default this to["openai", "github-copilot"]; settingoffered = []shows all known providers. Configured providers remain visible for management.
Fixed
-
Web search DuckDuckGo fallback: When no search API key (Brave or Perplexity) is configured,
web_searchnow automatically falls back to DuckDuckGo HTML search instead of returning an error and forcing the LLM to ask the user about using the browser. -
Web onboarding flash and redirect timing: The web server now performs onboarding redirects before rendering the main app shell. When onboarding is incomplete, non-onboarding routes redirect directly to
/onboarding; once onboarding is complete,/onboardingredirects back to/. The onboarding route now serves a dedicated onboarding HTML/JS entry instead of the full app bundle, preventing duplicate bootstrap/navigation flashes in Safari. -
Local model cache path visibility: Startup logs for local LLM providers now explicitly print the model cache directory and cached model IDs, making
MOLTIS_DATA_DIRbehavior easier to verify without noisy model-catalog output. -
Kimi device-flow OAuth in web UI: Kimi OAuth now uses provider-specific headers and prefers
verification_uri_complete(or synthesizes?user_code=fallback) so mobile-device sign-in links no longer fail with missinguser_code. -
Kimi Code provider authentication compatibility:
kimi-codeis now API-key-first in the web UI (KIMI_API_KEY, default base URLhttps://api.moonshot.ai/v1), while still honoring previously stored OAuth tokens for backward compatibility. Provider errors now include a targeted hint to switch to API-key auth when Kimi returnsaccess_terminated_error. -
Provider setup success feedback: API-key provider setup now runs an immediate model probe after saving credentials. The onboarding and Providers modal only show success when at least one model validates, and otherwise display a validation failure message instead of a false-positive “configured” state.
-
Heartbeat/cron duplicate runs: Skip heartbeat LLM turn when no prompt is configured, and fix duplicate cron job executions that could fire the same scheduled run twice.
-
Onboarding finish screen removed: Onboarding now skips the final “congratulations” screen and redirects straight to the chat view.
-
User message footer leak: Model name footer and timestamp are no longer incorrectly attached to user messages in the chat UI.
-
TTS counterpart auto-enable on STT save: Saving an ElevenLabs or Google Cloud STT key now automatically enables the matching TTS provider, mirroring the onboarding voice-test behavior.
-
Voice-generating indicator removed: The separate “voice generating” spinner during TTS playback has been removed in favor of the unified response indicator.
-
Config restart crash loop prevention: The gateway now validates the configuration file before restarting, returning an error to the UI instead of entering a crash loop when the config is invalid.
-
Safari dev-mode cache busting: Development mode now busts the Safari asset cache on reload, and fixes a missing border on detected-provider cards.
Refactored
- McpManager lock consolidation: Replaced per-field
RwLocks inMcpManagerwith a singleRwLock<McpManagerInner>to reduce lock contention and simplify state management. - GatewayState lock consolidation: Replaced per-field
RwLocks inGatewayStatewith a singleRwLock<GatewayInner>for the same reasons. - Typed chat broadcast payloads: Chat WebSocket broadcasts now use typed
Rust structs instead of ad-hoc
serde_json::Valuemaps.
Documentation
- Expanded default
SOUL.mdwith the full OpenClaw reference text for agent personality bootstrapping.
[0.2.9] - 2026-02-08
Added
- Voice provider policy controls: Added provider-list allowlists so config templates and runtime voice setup can explicitly limit shown/allowed TTS and STT providers.
- Typed voice provider metadata: Expanded voice provider metadata and preference handling to use typed flows across gateway and UI paths.
Changed
- Reply medium preference handling: Chat now prefers the same reply medium when possible and falls back to text when a medium cannot be preserved.
Fixed
- Chat UI reply badge visibility: Assistant footer now reliably shows the selected reply medium badge.
- Voice UX polish: Improved microphone timing behavior and preserved settings scroll state in voice configuration views.
[0.2.8] - 2026-02-07
Changed
- Unified plugins and skills into a single system: Plugins and skills were separate
systems with duplicate code, manifests, and UI pages. They are now merged into one
unified “Skills” system. All installed repos (SKILL.md, Claude Code
.claude-plugin/, Codex) are managed through a singleskills-manifest.jsonandinstalled-skills/directory. The/pluginspage has been removed — everything is accessible from the/skillspage. A one-time startup migration automatically moves data from the old plugins manifest and directory into the new unified location. - Default config template voice list narrowed: New generated configs now include a
[voice]section with provider-list allowlists limited to ElevenLabs for TTS and Mistral + ElevenLabs for STT.
Fixed
- Update checker repository configuration: The update checker now reads
server.update_repository_urlfrommoltis.toml, defaults new configs tohttps://github.com/moltis-org/moltis, and treats an omitted/commented value as explicitly disabled. - Mistral and other providers rejecting requests with HTTP 422: Session metadata fields
(
created_at,model,provider,inputTokens,outputTokens) were leaking into provider API request bodies. Mistral’s strict validation rejected the extracreated_atfield. ReplacedVec<serde_json::Value>with a typedChatMessageenum in theLlmProvidertrait — metadata can no longer leak because the type only contains LLM-relevant fields (role,content,tool_calls). Conversion from persisted JSON happens once at the gateway boundary viavalues_to_chat_messages(). - Chat skill creation not persisting new skills: Runtime tool filtering incorrectly
applied the union of discovered skill
allowed_toolsto all chat turns, which could hidecreate_skill/update_skilland leave only a subset (for exampleweb_fetch). Chat runs now use configured tool policy for runtime filtering without globally restricting tools based on discovered skill metadata.
Added
-
Voice Provider Management UI: Configure TTS and STT providers from Settings > Voice
- Auto-detection of API keys from environment variables and LLM provider configs
- Toggle switches to enable/disable providers without removing configuration
- Local binary detection for whisper.cpp, piper, and sherpa-onnx
- Server availability checks for Coqui TTS and Voxtral Local
- Setup instructions modal for local provider installation
- Shared Google Cloud API key between TTS and STT
-
Voice provider UI allowlists: Added
voice.tts.providersandvoice.stt.providersconfig lists to control which TTS/STT providers are shown in the Settings UI. Empty lists keep current behavior and show all providers. -
New TTS Providers:
- Google Cloud Text-to-Speech (380+ voices, 50+ languages)
- Piper (fast local neural TTS, runs offline)
- Coqui TTS (high-quality neural TTS with voice cloning)
-
New STT Providers:
- ElevenLabs Scribe (90+ languages, word timestamps, speaker diarization)
- Mistral AI Voxtral (cloud-based, 13 languages)
- Voxtral Local via vLLM (self-hosted with OpenAI-compatible API)
-
Browser Sandbox Mode: Run browser in isolated Docker containers for security
- Automatic container lifecycle management
- Uses
browserless/chromeimage by default (configurable viasandbox_image) - Container readiness detection via HTTP endpoint probing
- Browser sandbox mode automatically follows the session’s sandbox mode
(no separate
browser.sandboxconfig - sandboxed sessions use sandboxed browser)
-
Memory-Based Browser Pool Limits: Browser instances now limited by system memory
max_instances = 0(default) allows unlimited instances, limited only by memorymemory_limit_percent = 90blocks new instances when system memory exceeds threshold- Idle browsers cleaned up automatically before blocking
- Set
max_instances > 0for hard limit if preferred
-
Automatic Browser Session Tracking: Browser tool automatically reuses sessions
- Session ID is tracked internally and injected when LLM doesn’t provide one
- Prevents pool exhaustion from LLMs forgetting to pass session_id
- Session cleared on explicit “close” action
-
HiDPI Screenshot Support: Screenshots scale correctly on Retina displays
device_scale_factorconfig (default: 2.0) for high-DPI rendering- Screenshot display in UI scales according to device pixel ratio
- Viewport increased to 2560×1440 for sharper captures
-
Enhanced Screenshot Lightbox:
- Scrollable container for viewing long/tall screenshots
- Download button at top of lightbox
- Visible ✕ close button instead of text hint
- Proper scaling for HiDPI displays
-
Telegram Screenshot Support: Browser screenshots sent to Telegram channels
- Automatic retry as document when image dimensions exceed Telegram limits
- Error messages sent to channel when screenshot delivery fails
- Handles
PHOTO_INVALID_DIMENSIONSandPHOTO_SAVE_FILE_INVALIDerrors
-
Telegram Tool Status Notifications: See what’s happening during long operations
- Tool execution messages sent to Telegram (e.g., “🌐 Navigating to…”,
“💻 Running:
git status”, “📸 Taking screenshot…”) - Messages sent silently (no notification sound) to avoid spam
- Typing indicator automatically re-sent after status messages
- Supports browser, exec, web_fetch, web_search, and memory tools
- Tool execution messages sent to Telegram (e.g., “🌐 Navigating to…”,
“💻 Running:
-
Log Target Display: Logs now include the crate/module path for easier debugging
- Example:
INFO moltis_gateway::chat: tool execution succeeded tool=browser
- Example:
-
Contributor docs: local validation: Added documentation for the
./scripts/local-validate.shworkflow, including published local status contexts, platform behavior, and CI fallback expectations. -
Hooks Web UI: New
/hookspage to manage lifecycle hooks from the browser- View all discovered hooks with eligibility status, source, and events
- Enable/disable hooks without removing files (persisted across restarts)
- Edit HOOK.md content in a monospace textarea and save back to disk
- Reload hooks at runtime to pick up changes without restarting
- Live stats (call count, failures, avg latency) from the hook registry
- WebSocket-driven auto-refresh via
hooks.statusevent - RPC methods:
hooks.list,hooks.enable,hooks.disable,hooks.save,hooks.reload
-
Deploy platform detection: New
MOLTIS_DEPLOY_PLATFORMenv var hides local-only providers (local-llm, Ollama) on cloud deployments. Pre-configured in Fly.io, DigitalOcean, and Render deploy templates. -
Telegram OTP self-approval: Non-allowlisted DM users receive a 6-digit verification code instead of being silently ignored. Correct code entry auto-approves the user to the allowlist. Includes flood protection (non-code messages silently ignored), lockout after 3 failed attempts (configurable cooldown), and 5-minute code expiry. OTP codes visible in web UI Senders tab. Controlled by
otp_self_approval(default: true) andotp_cooldown_secs(default: 300) config fields. -
Update availability banner: The web UI now checks GitHub releases hourly and shows a top banner when a newer version of moltis is available, with a direct link to the release page.
Changed
- Documentation safety notice: Added an upfront alpha-software warning on the docs landing page, emphasizing careful deployment, isolation, and strong auth/network controls for self-hosted AI assistants.
- Release packaging: Derive release artifact versions from the Git tag (
vX.Y.Z) in CI, and sync package metadata during release jobs to prevent filename/version drift. - Versioning: Bump workspace and snap baseline version to
0.2.0. - Onboarding auth flow: Route first-run setup directly into
/onboardingand remove the separate/setupweb UI page. - Startup observability: Log each loaded context markdown (
CLAUDE.md/AGENTS.md/.claude/rules/*.md), memory markdown (MEMORY.mdandmemory/*.md), and discoveredSKILL.mdto make startup/context loading easier to audit. - Workspace root pathing: Standardize workspace-scoped file discovery/loading on
moltis_config::data_dir()instead of process cwd (affects BOOT.md, hook discovery, skill discovery, and compaction memory output paths). - Soul storage: Move agent personality text out of
moltis.tomlinto workspaceSOUL.md; identity APIs/UI still edit soul, but now persist it as a markdown file. - Identity storage: Persist agent identity fields (
name,emoji,creature,vibe) to workspaceIDENTITY.mdusing YAML frontmatter; settings UI continues to edit these fields through the same RPC/API. - User profile storage: Persist user profile fields (
name,timezone) to workspaceUSER.mdusing YAML frontmatter; onboarding/settings continue to use the same API/UI while reading/writing the markdown file. - Workspace markdown support: Add
TOOLS.mdprompt injection from workspace root (data_dir), and keep startup injection sourced fromBOOT.md. - Heartbeat prompt precedence: Support workspace
HEARTBEAT.mdas heartbeat prompt source with precedenceheartbeat.prompt(config override) →HEARTBEAT.md→ built-in default; log when config prompt overridesHEARTBEAT.md. - Heartbeat UX: Expose effective heartbeat prompt source (
config,HEARTBEAT.md, or default) viaheartbeat.statusand display it in the Heartbeat settings UI. - BOOT.md onboarding aid: Seed a default workspace
BOOT.mdwith in-file guidance describing startup injection behavior and recommended usage. - Workspace context parity: Treat workspace
TOOLS.mdas general context (not only policy) and add workspaceAGENTS.mdinjection support fromdata_dir. - Heartbeat token guard: Skip heartbeat LLM turns when
HEARTBEAT.mdexists but is empty/comment-only and there is no explicitheartbeat.promptoverride, reducing unnecessary token consumption. - Exec approval policy wiring: Gateway now initializes exec approval mode/security level/allowlist from
moltis.toml(tools.exec.*) instead of always using hardcoded defaults. - Runtime tool enforcement: Chat runs now apply configured tool policy (
tools.policy) and skillallowed_toolsconstraints when selecting callable tools. - Skill trust lifecycle: Installed marketplace skills/plugins now track a
trustedstate and must be trusted before they can be enabled; the skills UI now surfaces untrusted status and supports trust-before-enable. - Git metadata via gitoxide: Gateway now resolves branch names, repo HEAD SHAs, and commit timestamps using
gix(gitoxide) instead of shelling out togitfor those read-only operations.
Fixed
- OAuth callback on hosted deployments: OpenAI Codex OAuth now uses the web app origin callback (
/auth/callback) in the UI flow instead of hardcoded localhost loopback, allowing DigitalOcean/Fly/Render deployments to complete OAuth successfully. - Sandbox startup on hosted Docker environments: Skip sandbox image pre-build when sandbox mode is off, and require Docker daemon accessibility (not just Docker CLI presence) before selecting the Docker sandbox backend.
- Homebrew release automation: Run the tap update in the release workflow after all package/image jobs complete so formula publishing does not race missing tarball assets.
- Docker runtime: Install
libgomp1in the runtime image to satisfy OpenMP-linked binaries and prevent startup failures withlibgomp.so.1missing. - Release CI validation: Add a Docker smoke test step (
moltis --help) after image build/push so missing runtime libraries fail in CI before release. - Web onboarding clarity: Add setup-code guidance that points users to the process log (stdout).
- WebSocket auth (remote deployments): Accept existing session/API-key auth from WebSocket upgrade headers so browser connections don’t immediately close after
connecton hosted setups. - Sandbox UX on unsupported hosts: Disable sandbox controls in chat/images when no runtime backend is detected, with a tooltip explaining cloud deploy limitations.
- Telegram OTP code echoed to LLM: After OTP self-approval, the verification code message was re-processed as a regular chat message because
sender_approverestarted the bot polling loop (resetting the Telegram update offset). Sender approve/deny now hot-update the in-memory config without restarting the bot. - Empty allowlist bypassed access control: When
dm_policy = Allowlistand all entries were removed, the empty list was treated as “allow everyone” instead of “deny everyone”. An explicit Allowlist policy with an empty list now correctly denies all access. - Browser sandbox timeout: Sandboxed browsers now use the configured
navigation_timeout_ms(default 30s) instead of a shorter internal timeout. Previously, sandboxed browser connections could time out prematurely. - Tall screenshot lightbox: Full-page screenshots now display at proper size with vertical scrolling instead of being scaled down to fit the viewport.
- Telegram typing indicator for long responses: Channel replies now wait for outbound delivery tasks to finish before chat completion returns, so periodic
typing...updates continue until the Telegram message is actually sent. - Skills dependency install safety:
skills.install_depnow requires explicit user confirmation and blocks host installs when sandbox mode is disabled (unless explicitly overridden in the RPC call).
Security
- Asset response hardening: Static assets now set
X-Content-Type-Options: nosniff, and SVG responses include a restrictiveContent-Security-Policy(script-src 'none',object-src 'none') to reduce stored-XSS risk if user-controlled SVGs are ever introduced. - Archive extraction hardening: Skills/plugin tarball installs now reject unsafe archive paths (
.., absolute/path-prefix escapes) and reject symlink/hardlink archive entries to prevent path traversal and link-based escapes. - Install provenance: Installed skill/plugin repo manifests now persist a pinned
commit_sha(resolved from clone or API fallback) for future trust drift detection. - Re-trust on source drift: If an installed git-backed repo’s HEAD commit changes from the pinned
commit_sha, the gateway now marks its skills untrusted+disabled and requires trust again before re-enabling; the UI surfaces this assource changed. - Security audit trail: Skill/plugin install, remove, trust, enable/disable, dependency install, and source-drift events are now appended to
~/.moltis/logs/security-audit.jsonlfor incident review. - Emergency kill switch: Added
skills.emergency_disableto immediately disable all installed third-party skills and plugins; exposed in the Skills UI as a one-click emergency action. - Risky dependency install blocking:
skills.install_depnow blocks suspicious install command patterns by default (e.g. piped shell payloads, base64 decode chains, quarantine bypass) unless explicitly overridden withallow_risky_install=true. - Provenance visibility: Skills UI now displays pinned install commit SHA in repo and detail views to make source provenance easier to verify.
- Recent-commit risk warnings: Skill/plugin detail views now include commit links and commit-age indicators, with a prominent warning banner when the pinned commit is very recent.
- Installer subprocess reduction: Skills/plugins install paths now avoid
gitsubprocess clone attempts and use GitHub tarball installs with pinned commit metadata. - Install resilience for rapid multi-repo installs: Skills/plugins install now auto-clean stale on-disk directories that are missing from manifest state, and tar extraction skips link entries instead of failing the whole install.
- Orphaned repo visibility: Skills/plugins repo listing now surfaces manifest-missing directories found on disk as
orphanedentries and allows removing them from the UI. - Protected seed skills: Discovered template skills (
template-skill/template) are now marked protected and cannot be deleted from the web UI. - License review links: Skill/plugin license badges now link directly to repository license files when detectable (e.g.
LICENSE.txt,LICENSE.md,LICENSE). - Example skill seeding: Gateway now seeds
~/.moltis/skills/template-skill/SKILL.mdon startup when missing, so users always have a starter personal skill template. - Memory indexing scope tightened: Memory sync now indexes only
MEMORY.md/memory.mdandmemory/content by default (instead of scanning the entire data root), reducing irrelevant indexing noise from installed skills/plugins. - Ollama embedding bootstrap: When using Ollama for memory embeddings, gateway now auto-attempts to pull missing embedding models (default
nomic-embed-text) via Ollama HTTP API.
Documentation
- Added
docs/src/skills-security.mdwith third-party skills/plugin hardening guidance (trust lifecycle, provenance pinning, source-drift re-trust, risky install guards, emergency disable, and security audit logging).
[0.1.10] - 2026-02-06
Changed
- CI builds: Build Docker images natively per architecture instead of QEMU emulation, then merge into multi-arch manifest
[0.1.9] - 2026-02-06
Changed
- CI builds: Migrate all release build jobs from self-hosted to GitHub-hosted runners for full parallelism (
ubuntu-latest,ubuntu-latest-arm,macos-latest), remove all cross-compilation toolchain steps
[0.1.8] - 2026-02-06
Fixed
- CI builds: Fix corrupted cargo config on all self-hosted runner jobs, fix macOS runner label, add llama-cpp build deps to Docker and Snap builds
[0.1.7] - 2026-02-06
Fixed
- CI builds: Use project-local
.cargo/config.tomlfor cross-compilation instead of appending to global config (fixes duplicate key errors on self-hosted runners)
[0.1.6] - 2026-02-06
Fixed
- CI builds: Use macOS GitHub-hosted runners for apple-darwin binary builds instead of cross-compiling from Linux
- CI performance: Run lightweight lint jobs (zizmor, biome, fmt) on GitHub-hosted runners to free up self-hosted runners
[0.1.5] - 2026-02-06
Fixed
- CI security: Use GitHub-hosted runners for PRs to prevent untrusted code from running on self-hosted infrastructure
- CI security: Add
persist-credentials: falseto docs workflow checkout (fixes zizmor artipacked warning)
[0.1.4] - 2026-02-06
Added
-
--no-tlsCLI flag:--no-tlsflag andMOLTIS_NO_TLSenvironment variable to disable TLS for cloud deployments where the provider handles TLS termination -
One-click cloud deploy: Deploy configs for Fly.io (
fly.toml), DigitalOcean (.do/deploy.template.yaml), Render (render.yaml), and Railway (railway.json) with deploy buttons in the README -
Config Check Command:
moltis config checkvalidates the configuration file, detects unknown/misspelled fields with Levenshtein-based suggestions, warns about security misconfigurations, and checks file references -
Memory Usage Indicator: Display process RSS and system free memory in the header bar, updated every 30 seconds via the tick WebSocket broadcast
-
QMD Backend Support: Optional QMD (Query Memory Daemon) backend for hybrid search with BM25 + vector + LLM reranking
- Gated behind
qmdfeature flag (enabled by default) - Web UI shows installation instructions and QMD status
- Comparison table between built-in SQLite and QMD backends
- Gated behind
-
Citations: Configurable citation mode (on/off/auto) for memory search results
- Auto mode includes citations when results span multiple files
-
Session Export: Option to export session transcripts to memory for future reference
-
LLM Reranking: Use LLM to rerank search results for improved relevance (requires QMD)
-
Memory Documentation: Added
docs/src/memory.mdwith comprehensive memory system documentation -
Mobile PWA Support: Install moltis as a Progressive Web App on iOS, Android, and desktop
- Standalone mode with full-screen experience
- Custom app icon (crab mascot)
- Service worker for offline support and caching
- Safe area support for notched devices
-
Push Notifications: Receive alerts when the LLM responds
- VAPID key generation and storage for Web Push API
- Subscribe/unsubscribe toggle in Settings > Notifications
- Subscription management UI showing device name, IP address, and date
- Remove any subscription from any device
- Real-time subscription updates via WebSocket
- Client IP detection from X-Forwarded-For, X-Real-IP, CF-Connecting-IP headers
- Notifications sent for both streaming and agent (tool-using) chat modes
-
Safari/iOS PWA Detection: Show “Add to Dock” instructions when push notifications require PWA installation (Safari doesn’t support push in browser mode)
-
Browser Screenshot Thumbnails: Screenshots from the browser tool now display as clickable thumbnails in the chat UI
- Click to view fullscreen in a lightbox overlay
- Press Escape or click anywhere to close
- Thumbnails are 200×150px max with hover effects
-
Improved Browser Detection: Better cross-platform browser detection
- Checks macOS app bundles before PATH (avoids broken Homebrew chromium wrapper)
- Supports Chrome, Chromium, Edge, Brave, Opera, Vivaldi, Arc
- Shows platform-specific installation instructions when no browser found
- Custom path via
chrome_pathconfig orCHROMEenvironment variable
-
Vision Support for Screenshots: Vision-capable models can now interpret browser screenshots instead of having them stripped from context
- Screenshots sent as multimodal image content blocks for GPT-4o, Claude, Gemini
- Non-vision models continue to receive
[base64 data removed]placeholder supports_vision()trait method added toLlmProviderfor capability detection
-
Session state store: per-session key-value persistence scoped by namespace, backed by SQLite (
session_statetool). -
Session branching:
branch_sessiontool forks a conversation at any message index into an independent copy. -
Session fork from UI: Fork button in the chat header and sidebar action buttons let users fork sessions without asking the LLM. Forked sessions appear indented under their parent with a branch icon.
-
Skill self-extension:
create_skill,update_skill,delete_skilltools let the agent manage project-local skills at runtime. -
Skill hot-reload: filesystem watcher on skill directories emits
skills.changedevents via WebSocket when SKILL.md files change. -
Typed tool sources:
ToolSourceenum (Builtin/Mcp { server }) replaces string-prefix identification of MCP tools in the tool registry. -
Tool registry metadata:
list_schemas()now includessourceandmcpServerfields so the UI can group tools by origin. -
Per-session MCP toggle: sessions store an
mcp_disabledflag; the chat header exposes a toggle button to enable/disable MCP tools per session. -
Debug panel convergence: the debug side-panel now renders the same seven sections as the
/contextslash command, eliminating duplicated rendering logic. -
Documentation pages for session state, session branching, skill self-extension, and the tool registry architecture.
Changed
-
Memory settings UI enhanced with backend comparison and feature explanations
-
Added
memory.qmd.statusRPC method for checking QMD availability -
Extended
memory.config.getto includeqmd_feature_enabledflag -
Push notifications feature is now enabled by default in the CLI
-
TLS HTTP redirect port now defaults to
gateway_port + 1instead of the hardcoded port18790. This makes the Dockerfile simpler (both ports are adjacent) and avoids collisions when running multiple instances. Override via[tls] http_redirect_portinmoltis.tomlor theMOLTIS_TLS__HTTP_REDIRECT_PORTenvironment variable. -
TLS certificates use
moltis.localhostdomain. Auto-generated server certs now includemoltis.localhost,*.moltis.localhost,localhost,127.0.0.1, and::1as SANs. Banner and redirect URLs usehttps://moltis.localhost:<port>when bound to loopback, so the cert matches the displayed URL. Existing certs are automatically regenerated on next startup. -
Certificate validity uses dynamic dates. Cert
notBefore/notAfterare now computed from the current system time instead of being hardcoded. CA certs are valid for 10 years, server certs for 1 year from generation. -
McpToolBridgenow stores and exposesserver_name()for typed registration. -
mcp_service::sync_mcp_tools()usesunregister_mcp()/register_mcp()instead of scanning tool names by prefix. -
chat.rsusesclone_without_mcp()instead ofclone_without_prefix("mcp__")in all three call sites.
Fixed
- Push notifications not sending when chat uses agent mode (run_with_tools)
- Missing space in Safari install instructions (“usingFile” → “using File”)
- WebSocket origin validation now treats
.localhostsubdomains (e.g.moltis.localhost) as loopback equivalents per RFC 6761. - Browser tool schema enforcement: Added
strict: trueandadditionalProperties: falseto OpenAI-compatible tool schemas, improving model compliance with required fields - Browser tool defaults: When model sends URL without action, defaults to
navigateinstead of erroring - Chat message ordering: Fixed interleaving of text and tool cards when streaming; messages now appear in correct chronological order
- Tool passthrough in ProviderChain: Fixed tools not being passed to fallback providers when using provider chains
- Fork/branch icon in session sidebar now renders cleanly at 16px (replaced complex git-branch SVG with simple trunk+branch path).
- Deleting a forked session now navigates to the parent session instead of an unrelated sibling.
- Streaming tool calls for non-Anthropic providers:
OpenAiProvider,GitHubCopilotProvider,KimiCodeProvider,OpenAiCodexProvider, andProviderChainnow implementstream_with_tools()so tool schemas are sent in the streaming API request and tool-call events are properly parsed. Previously onlyAnthropicProvidersupported streaming tool calls; all other providers silently dropped the tools parameter, causing the LLM to emit tool invocations as plain text instead of structured function calls. - Streaming tool call arguments dropped when index ≠ 0: When a provider
(e.g. GitHub Copilot proxying Claude) emits a text content block at
streaming index 0 and a tool_use block at index 1, the runner’s argument
finalization used the streaming index as the vector position directly.
Since
tool_callshas only 1 element at position 0, the condition1 < 1was false and arguments were silently dropped (empty{}). Fixed by mapping streaming indices to vector positions via a HashMap. - Skill tools wrote to wrong directory:
create_skill,update_skill, anddelete_skillusedstd::env::current_dir()captured at gateway startup, writing skills to<cwd>/.moltis/skills/instead of~/.moltis/skills/. Skills now write to<data_dir>/skills/(Personal source), which is always discovered regardless of where the gateway was started. - Skills page missing personal/project skills: The
/api/skillsendpoint only returned manifest-based registry skills. Personal and project-local skills were never shown in the navigation or skills page. The endpoint now discovers and includes them alongside registry skills.
Documentation
- Added voice.md with TTS/STT provider documentation and setup guides
- Added mobile-pwa.md with PWA installation and push notification documentation
- Updated CLAUDE.md with cargo feature policy (features enabled by default)
- Updated browser-automation.md with browser detection, screenshot display, and model error handling sections
- Rewrote session-branching.md with accurate fork details, UI methods, RPC API, inheritance table, and deletion behavior.