A private, adaptive AI runtime that's yours. It orchestrates models, memory, tools, grounded work, and optional adapter training on hardware you control.
Important
Sonder is a runtime, not a foundation model and not a set of base-model
weights. Ollama is the local model server: it stores
model artifacts, loads the selected weights into system RAM/VRAM, and performs
inference. Sonder sits around that server. It selects an Ollama model,
builds grounded prompts, manages memory and tools, applies runtime policy, and
validates/deploys optional trained adapters. The sonder:latest and
sonder-personal:latest names are Ollama model aliases, not models embedded
in this Git repository.
Sonder is not trying to turn a small local model into a frontier model, and this README will not pretend otherwise. It is built for privacy, ownership, grounded work, and personalization. Local operation works offline; web and cloud tiers are separate, explicit opt-ins.
The project uses sonder commands, SONDER_* environment variables, Sonder
state paths, and sonder:* Ollama aliases. These are runtime identifiers; the
actual base-model files remain managed by Ollama rather than this repository.
See ARCHITECTURE.md for the complete component and model
lifecycle boundary.
What it is
- A model-agnostic runtime. Sonder provides the API, REPL, apps, memory, retrieval, tools, policies, activity evidence, training workflow, and guarded automation around a selected inference model.
- Local & private by default. Ollama serves the selected model through a loopback endpoint on your CPU/GPU. With cloud and web opt-ins disabled, prompts, files, memory, and lessons stay on your machine.
- Self-improving on your context. Every coding interaction can be captured, scored by real outcomes (did it compile? pass tests?), and distilled into short "lessons" it retrieves next time. Over time it learns your patterns, not the internet's average.
- Yours to own. You keep the Ollama model files, optional adapter weights, runtime state, memory, and lessons. Nothing in Sonder Runtime requires renting a hosted model.
What it isn't
- Not a standalone or pretrained model. Cloning this repository does not download Qwen weights. Setup asks Ollama to use an installed or downloaded compatible model, or imports a separately built sealed model bundle.
- Not a frontier model. A local 7B served through the runtime is genuinely weaker than a hosted giant. If you just want the smartest possible answer with zero setup, use ChatGPT/Claude — honestly.
- Not "for literally everyone" yet. Today it needs a decent machine and some setup. See the Roadmap for how that changes.
Who it's for: privacy-conscious people, offline/field use, tinkerers and the on-device AI crowd, and organizations that need a private assistant on their own data (a clinic, a firm, a studio) — anyone who values owning their AI over squeezing out the last IQ point.
The moat isn't the weights — a generically fine-tuned model just re-derives what you'd get from Google, and the base model already knows it. The moat is your private, grounded data: your code, your bugs and fixes, your conventions. Sonder is built to accumulate exactly that.
Sonder is a mostly Python orchestration runtime. Ollama is a separate local inference service, and Qwen2.5-Coder is one supported default model family—not the Sonder project itself:
Android / desktop / REPL / MCP
|
v
Sonder Runtime: policy + memory + tools + grounding + training control
|
v
Ollama model server: model storage + RAM/VRAM loading + token inference
|
v
Selected base or personal model weights (for example Qwen2.5-Coder)
An optional, off-by-default NPU utility sidecar can accelerate bounded routing
and compatible embedding work below those model tiers; it is never a generative
model tier, and Ollama's CPU/GPU path remains responsible for token generation.
Hardware/session claims stay separate and no current device is assumed. See
NPU.md; the MCP surface exposes npu_status for bounded diagnostics.
For a normal response, the runtime's learning loop is:
your task ─► retrieve relevant lessons ─► augment prompt ─► local model ─► answer
▲ │
│ ▼
distill a lesson ◄── (if good) ── you record the outcome (compiled? tests passed?)
- Retrieval — hybrid lexical (SQLite FTS5) + semantic (local embeddings), with a relevance threshold so only genuinely on-topic lessons are injected (irrelevant lessons hurt, so it injects nothing when nothing fits).
- Capture — every learning call is logged locally to
memory.db. - Grounding — you (or your fleet) call
record_outcomewith a real signal; execution outcomes are the reward. - Reflection — a good outcome distills a deduped one-line lesson future prompts can retrieve.
The loop is model-agnostic: point it at a compatible Ollama model. The selected
local code model is memory-augmented; a stronger paid/cloud model can answer
without local-lesson injection while its grounded good outcomes are distilled into
lessons and fine-tuning data the local model retrieves later. Which
tiers learn is configurable (SONDER_LEARN_TIERS, default local aliases:
fast,code,general). Memory, capture, and distillation stay on the runtime host.
A cloud-tier prompt leaves only after SONDER_ALLOW_CLOUD=1. The fast, code,
and general aliases use loopback Ollama by default; pointing OLLAMA_HOST at a
non-loopback server is blocked unless SONDER_ALLOW_REMOTE_OLLAMA=1 explicitly
acknowledges that prompts and embeddings leave this machine. Remote Ollama and
hosted/cloud consent are separate gates. Their shared mappings
and each execution lane's preferred alias live in the hot-reloadable runtime
policy described below. Environment values seed the first policy file; cloud
aliases and cloud opt-in remain separate host-owned configuration.
Loopback model requests use one bounded, same-model retry by default for narrowly
transient transport failures and HTTP 408/429/502/503/504 responses. The retry
shares the original timeout budget, checks fleet cancellation before resending,
and never changes endpoint, model, or tier. Hosted/cloud calls are always
single-attempt to avoid silently duplicating metered work. Set
SONDER_LOCAL_RETRIES=0..2 and SONDER_LOCAL_RETRY_DELAY_MS=0..1000 to tune the
loopback policy. Explicit remote Ollama and hosted/cloud calls are single-attempt.
Good-outcome lesson reflection does not queue another model request behind an
active fleet: the outcome is committed immediately and its lesson remains
retryable. When the fleet is idle, reflection uses a separate shared generation
and embedding budget (SONDER_DISTILLATION_TIMEOUT, default 20 seconds,
bounded by SONDER_TIMEOUT) so record_outcome cannot inherit the normal
five-minute model-call ceiling.
The learning loop above is cross-task memory. On top of it Sonder also has:
- Conversation memory (ON by default). Successive
sondercalls remember each other, so follow-ups have context. With nosession, calls share thedefaultthread; pass a distinctsessionid to isolate a conversation, orsession="none"for a one-off single turn. Threads persist inmemory.dbacross restarts and are auto-titled. A database-backed, live-process-owned turn claim serializes each remembered session across MCP, serve, and REPL processes until code verification and persistence finish, so no concurrent turn can consume a response still being repaired. After upgrading from a pre-claim runtime, reconnect/restart each runtime process once before concurrent use. Older turns are rolled into a running summary so a thread never overflows the local context window. (The 7B is a ~32K-context model on a 6 GB GPU — memory is carrying the right turns + summarizing the rest, not a giant window.) List/resume threads withsonder_sessions()/ REPL/sessions//resume. - Semantic recall. Each call also surfaces the most similar past good-outcome solutions from the same project (vector search over prior interactions), not just distilled lessons. Cross-project raw-solution recall is never implicit.
- Project facts.
sonder_remember_fact(text, project=…)stores durable facts (toolchain, conventions, key paths) that are injected into every call for that project — a mini-brief the model carries itself. Scope a call withproject=…. - Dynamic user preferences. Sonder now captures clear preference statements
like "I prefer concise status updates" during normal chat, stores them with
evidence counts, and injects active preferences into future local-model
prompts. Use
/prefer,/prefer <text>, or/prefer forget <id-or-key>to inspect, teach, or disable them explicitly. - Visible activity. Each response tracks observable work: model calls, tool
calls, active response count, file creates/edits/deletes, and line deltas. Tool
results retain a bounded, secret-redacted action transcript (
Viewed Image,Ran Script,Edited File, etc.), while/workmaintains a persistent ordered checklist and emits an evidence-backed end report. Use/activity,/report,/checklist, or the app's Workbench Activity panel while work runs. - Inspectable learning quality.
/learningandlearning_health_status()report distinct outcome coverage, positive/negative signal mix, lesson source provenance, grounded distillation yield, lesson and raw-interaction task-vector provenance/integrity, embedding coverage, duplicate rows, search-index drift, missing sources, and redacted privacy-flag counts. The Flutter System page renders the same metrics as live meters and source/signal chips instead of reducing self-improvement to one opaque score.
- Local, in your terminal —
sonder(like launchingclaude). Interactive REPL routed through the full loop, with/work,/report,/checklist,/inventory,/tree,/search,/programs,/scripts,/image,/mkdir,/runprogram,/runscript,/trace,/strict,/run,/train,/master,/agents,/capacity,/agentcancel,/agentretry,/asset,/artifactcheck,/forge,/game,/gamefleet,/todo,/commands,/activity,/runtime,/mcp,/learning,/dump,/permissions,/compact,/debug,/pass,/fail,/stats,/context,/quality,/privacy,/embeddings,/emotion, and/improve, plus conversation commands/new,/sessions,/resume,/project,/fact,/facts. Concrete natural-language workspace requests route to the same guarded workbench. Each REPL launch is its own remembered thread. - Hosted on your own server + a thin client anywhere — run
deploy_sonder.sh --serveon your box (systemd service, API key), then any machine runs the single-filesonder_client.pypointed at it. The serve layer threads the chat UI's own conversation history. - Integrated with Claude/Codex — the MCP
sonder-runtimetools includeworkbench_agent,npu_status, budgeted workspace inventory, guarded tree/range/text/script/program/image inspection, argv-only program/script execution, persistent checklists, exact activity reports, agent/master orchestration, universal artifact generation, grounded game generation, bounded code/project runners, workflows, web tools, self-healing, privacy-safe memory review, local embedding backfill, and the remaining learning/memory surfaces.master_orchestratecan delegate to parallel subagents and audit their outputs; artifact and game tools create persistent assets/projects and accept only grounded checks. Local tiers remain the default for private workspace code. - Mobile & desktop app (GUI) — a cross-platform Flutter client with a shared Windows/Android/Linux/macOS System experience. Android and other client-only builds can start, stop, and restart the configured computer through a bounded authenticated host launcher; long first-run starts continue as persistent, resumable host operations and never expose a remote shell. See app/README.md and mobile host control.
Concrete natural-language work requests now pass through a visible execution
decision before any model answer. A small task runs in the guarded foreground
workbench; explicit fleet, swarm, spawn-as-many, or parallel-agent language
uses the hardware-bounded fleet; explicit keep working, end-to-end,
autonomously, or background language starts persistent Autopilot. For an
ambiguous compound request, a small local model may choose only between foreground
and Autopilot and may select one bounded local alias (fast, code, or
general). The response reports its mode, tier/model, source, reason, and
confidence.
foreground only, plan only, and no tools are deterministic overrides. The
router runs only for local-open or developer/admin-authorized requests, never
enables cloud or location, and defers instead of starting a second concurrent
Autopilot run. Slash commands remain explicit overrides.
/autopilot run <objective> turns one outcome into a durable, model-planned task
ledger. A local planner selects measurable success criteria and ordered tasks;
the guarded workbench executes one task at a time; successful inspection and
research tasks trigger evidence-aware checkpoints where a local reviewer may
keep or replace the remaining pending plan. Deterministic host code alone
enforces tool/root allowlists, local-only tiers, cycle/task/failure/replan budgets,
mutation validation, pause/cancel, and the completion gate. Superseded tasks stay
in the audit ledger. Runs live in a process-safe private autopilot.db and survive
server replacement. Stale owners become interrupted and are never silently
replayed.
The tool agent retains the complete evidence ledger while compacting only its model-facing observation window. It repairs malformed JSON decisions twice, blocks unchanged failing tool-call loops, and reserves a final-only synthesis pass after the tool-step budget is exhausted. Negative existence claims receive an extra local evidence review; explicit literals and named headings must be searched exactly, and the host may run only a guarded read-only recovery action before asking the model to synthesize again.
/autopilot status [id]
/autopilot plan [--observe] [--no-web] [--static] <objective>
/autopilot run [--observe] [--no-web] [--static] <objective>
/autopilot resume|pause|cancel <id>
Workspace mode can inspect, create, and edit through bounded tools, but cannot
delete files, change accounts/permissions/memory, launch fleets, use cloud tiers,
or infer location. Observe mode is read-only. The Flutter System page exposes the
same goal composer, adaptive/static selector, checkpoint and replan counters,
persisted checklist, budgets, events, end report, and lifecycle controls. Use
--static to opt out of adaptive checkpoints. Starting, resuming, pausing, or
cancelling through hosted HTTP requires a developer/admin account; status remains
read-only.
artifact_generate(name, brief) turns a free-form request into a deterministic,
stdlib-only creative pack. It is not game-specific: requests can produce icons,
logos, backgrounds, textures, tilesets, sprite sheets, SVG vectors and diagrams,
brand palettes, Markdown briefs, editable DOCX reports, JSON/CSV sample data,
editable XLSX workbooks, standalone HTML mockups, editable PPTX slide decks, PCM
WAV sound effects and music loops, editable MIDI scores, animated GIF previews,
uncompressed AVI video with synchronized PCM audio, SRT/WebVTT captions,
CMX-style EDL timelines, OBJ/MTL models, self-contained textured,
humanoid-rigged/morphing GLB 2.0 characters with named clip sequences, and JSON
scenes. The generator uses deterministic in-house OOXML/ZIP, RIFF/AVI, GIF/LZW, MIDI-event,
caption/timecode, PNG/PPM, waveform, and procedural-geometry writers, bounded
sizes, safe workspace paths, idempotent regeneration, and SHA-256 manifests.
artifact_verify(path) checks every file before downstream use.
Generation now fails closed unless every manifest size/hash and every recognized
format contract passes. artifact_ground(path, recipe, requirements_json) and
/artifactcheck <path> [| recipe] apply the same guarded recipes to arbitrary
workspace outputs: writing/Markdown structure, JSON fields, CSV columns and row
shape, DOCX paragraphs, XLSX rows/sheets, PPTX slides, OOXML relationships and
package safety, AVI streams/frames/index/audio synchronization, animated GIF
frames/LZW/duration, MIDI tracks/notes/tempo, caption timing and cue text, EDL
event/timecode continuity and local-media references, self-contained HTML/UI
references, SVG geometry, PNG chunks/CRCs, PPM dimensions, WAV frames/duration,
OBJ vertices/faces/index bounds, GLB containers/buffers/accessors/scenes,
embedded PNG CRCs/pixel streams, texture/sampler/material references, UV sets,
triangle indices, unit normals, joint indices, normalized skin weights,
affine inverse-bind matrices, canonical humanoid hierarchy, nonzero morph
position/normal/tangent frames, default weights/names, exact animation clip
metadata and durations, valid named clip sequences, skeletal and blend-shape
timelines, quaternion normalization, and complete bundle manifests. Custom
requirements can pin headings, text, fields, columns, files, kinds, sizes,
paragraph/row/slide/frame/note/cue/event/vertex/triangle/joint/animation counts,
sheets, and dependency policy.
game_reference_suite is the known-good default baseline: persistent Python 2D,
JavaScript 2.5D, C++ 3D, and C# 2D projects consume generated assets, simulate
bounded gameplay, software-render frame.ppm, print GAME_OK, and exit. Verified
fallbacks cover every combination of Python, JavaScript, C++, and C# with 2D,
2.5D, and 3D labels. Projects resolve assets beside their script or executable,
so they remain runnable when launched from another working directory. The
model-driven game_generate_and_test and game_generation_campaign surfaces use
the same contract, reject third-party engine tokens and placeholders, compile/run
the candidate, repair failures, and record grounded outcomes. If the local model
cannot satisfy the contract, a clearly labeled verified reference fallback leaves
a runnable project while the model attempt remains recorded as failed.
Concrete /master requests containing an explicit build verb plus a game or
artifact target now route directly through these grounded forges. Language,
dimension, theme, and campaign intent are inferred conservatively; fleet,
multiple, and various requests use the hardware-bounded campaign path. Design
questions and explanation requests remain ordinary conversation instead of
creating files unexpectedly. Explicit campaign constraints are sticky: a C++
2.5D fleet stays C++/2.5D, while an unconstrained multi-language request rotates
through the verified default matrix. The direct command form is
/gamefleet <name> | <concept> [| language | dimension].
Use Sonder Runtime to orchestrate a local junior implementer, not as the final authority:
- Start substantial work with
status()ordiagnostics()so you know model, VRAM, context, and memory-quality state before launching a batch. - Prefer
offload(tier="code")for one self-contained coding draft,run_code/parallel_generate_runfor bounded experiments, andmaster_orchestrateonly when independent perspectives are actually useful. For repository tasks, passproject="<existing repository root>"(or put an absoluteRepository:root in the task).master_orchestratebinds every child, ledger row, and aggregate to that one canonical root, switches to guarded read-only tool agents, and requires a host-issued file-evidence receipt before accepting an answer. It never falls back to Sonder's process cwd; a missing, conflicting, or escaped scope returns EVIDENCE_REQUIRED. - Keep prompts narrow and complete. Include the relevant files, constraints, acceptance checks, and what "done" means; the local model cannot see the caller's hidden context.
- Treat every answer as a draft. The caller must audit APIs, edge cases, file operations, security, and project style before applying changes.
- Use agent fan-out deliberately: 1-3 agents for normal work and 4-6 for useful
diversity. Explicit
fleet,swarm,workflow,parallel agents, or spawn-as-many requests queue the hardware-derived breadth ceiling when the caller omitsagents(or passes zero). A positiveagentsvalue is always honored up to the configured ceiling, including in fleet mode and when fleet keywords trigger that mode automatically. The automatic ceiling is two candidates per logical CPU, capped at 64 and overridable withSONDER_MAX_AGENTS. A separate scheduler bounds simultaneous model calls from CPU and currently available RAM (8 automatic slots maximum). Inspect it with/capacity [requested-agents]; use/agentcancel <id|prefix|all>for cooperative cancellation. Queued work stops immediately. Already-running Ollama/HTTP calls return naturally and their late results are discarded. Fleet state is shared through a private per-user SQLite ledger, so the app, REPL, API, and MCP processes see the same work. Crashed/stale owners becomeinterruptedafter a heartbeat grace period and are never replayed automatically; explicitly rerun one with/agentretry <master-id|prefix> [tier](localcodeby default). - Record outcomes only after grounded evidence: compile, tests, direct use, or explicit rejection. Good labels improve retrieval; vague labels pollute it.
- Run
memory_quality_report()periodically andmemory_quality_repair(apply=True)after reviewing duplicate plans. Retrieval quality is part of model quality. - Keep cloud tiers opt-in. Local tiers are the default for private code and user-specific memory; cloud tiers are metered and prompts leave the machine.
- Dogfood automatically. When normal Sonder use reveals a bug, missing
feature, weak procedure, confusing docs, bad default, flaky test, or other
fixable issue in this repo, the assistant working with the user is authorized
to implement the fix, run the relevant tests, commit, and push to
Krilliac/Sonder-runtimewithout waiting for a separate planning round.
Do not offload secrets, credential material, final security review, subtle correctness decisions, hot-path performance work, or changes whose failure mode cannot be checked locally. Do not auto-apply changes that weaken security, broaden permissions/cloud access, delete user data, rewrite history, or require privilege escalation beyond normal repository development; surface those for explicit approval.
On a server (start the runtime and its Ollama-backed model):
git clone https://github.com/Krilliac/Sonder-runtime.git && cd Sonder-runtime
bash deploy_sonder.sh # installs Ollama, picks a model that fits your RAM, creates the alias
# or: bash deploy_sonder.sh --serve # also host it as a public API service (prints URL + API key)Local dev:
python -m venv venv && venv/Scripts/pip install -r requirements-dev.txt
venv/Scripts/python -m pytest -q # run the test suite
python sonder_repl.py # interactive sessionBundled desktop engine setup: run bootstrap-engine.cmd on Windows,
./bootstrap-engine.sh on Linux/macOS, or press Setup engine in the app.
It starts Ollama if needed, detects RAM, chooses an available qwen2.5-coder
size, and creates the sonder alias. Lightweight packages use installed
Python/Ollama and may install mcp or download missing models on first setup.
For a network-independent package, assemble and include a sealed platform
engine bundle. The manifest pins the platform/architecture, portable Python and
Ollama executables, every runtime/model file size and SHA-256, available base
models, RAM thresholds, and the embedding model. Setup verifies the complete
Ollama manifest/blob graph before copying models into writable shared state;
offline mode never invokes pip or ollama pull.
# Build a reusable Windows bundle from this machine's installed Ollama models.
venv\Scripts\python.exe scripts\assemble_engine_bundle.py `
--out app\build\engine-bundles\windows-x86_64
# Reuse that verified bundle and build the local Flutter release.
powershell -NoProfile -File .\scripts\build_flutter_local.ps1 -Target windows
# Or assemble/refresh the bundle and build in one command.
powershell -NoProfile -File .\scripts\build_flutter_local.ps1 `
-Target windows -AssembleOfflineEngine
# Audit without changing state or allowing network access.
bootstrap-engine.cmd --bundle app\build\engine-bundles\windows-x86_64 --dry-runThe assembler defaults to the compact installed qwen2.5-coder:1.5b plus
nomic-embed-text; repeat --base-model NAME=MIN_RAM_GB to seal additional
installed sizes. Linux/macOS use the same format and launchers but should pass a
relocatable platform Python distribution with --python-runtime.
Headless server/console mode: the chat app is optional. On Windows run
sonder-headless.cmd start to launch Ollama and sonder_serve.py
without a visible app, sonder-headless.cmd status to inspect it, and
sonder-headless.cmd stop to stop the Sonder API process. Use
--stop-ollama with stop if you also want to shut down the Ollama daemon.
Cross-platform equivalent:
python sonder_headless.py start --port 11435 --context-size 32k.
Then connect with sonder_client.py, any OpenAI-compatible client pointed at
http://127.0.0.1:11435/v1, the REPL, Claude MCP, or the Flutter app later.
HTTP clients used by more than one conversation or device should send a stable,
unique session value per conversation. Session state is isolated by the
authenticated principal plus that explicit ID; a blank session is intentionally
ephemeral and should not be used when multiple clients need continuity.
Calling sonder from a Windows terminal now follows the same local-first
startup path as the app: it sets the shared state home, bootstraps the engine on
first run, starts the background API server, then opens the REPL. Set
SONDER_TERMINAL_BOOTSTRAP=0 to skip first-run setup or
SONDER_TERMINAL_START_SERVER=0 to open only the REPL. If
SONDER_SERVER is set, the same command opens the hosted/API client after
warming up the local fallback server; set SONDER_TERMINAL_REMOTE=0 to force
the local REPL.
Use the hosted model from any PC: see CLIENT.md.
HTTP auth and hosted/admin mode: SONDER_AUTH_MODE accepts api-key,
account, both, or either. If it is unset, configuring
SONDER_API_KEY selects API-key mode, SONDER_REQUIRE_ACCOUNT=1 selects
account mode, and a credential-free server remains local-open only on
loopback. both requires the API key in Authorization: Bearer ... and the
account session token in X-Sonder-Account-Token; either accepts either
credential. A non-loopback bind is refused unless authentication is explicitly
strong: API keys must be at least 24 characters, account signing secrets in
SONDER_AUTH_SECRET at least 32, and both/either require both strengths.
The first HTTP admin registration is a one-time bootstrap: configure a
SONDER_BOOTSTRAP_SECRET of at least 16 characters and send it in
X-Sonder-Bootstrap-Secret. Successful creation consumes that bootstrap.
Later HTTP registration is disabled unless SONDER_ALLOW_REGISTRATION=1
and the request is authenticated as an admin. /login returns an account
session token; /accounts and /setaccount manage roles, tiers, dev flags and
bans. /debug exposes only safe inspectable state. /cot remains denied; use
/trace, /debug, /agents, retrieved lessons, tool calls and status logs.
Browser origins are denied unless they exactly match a comma-separated entry in
SONDER_CORS_ORIGINS; * is intentionally ignored. HTTP POST bodies must
have Content-Type: application/json and an explicit Content-Length.
SONDER_MAX_REQUEST_BYTES defaults to 1 MiB and is capped at 16 MiB.
Workbench/filesystem tools: guarded /inventory, /tree, /search, /programs,
/scripts, /image, /mkdir, /runprogram, /runscript, /files, /read,
/write, /append, /edit, and dry-run /delete operate inside approved
local roots. Program execution is argv-only (no shell command strings), bounded
by time/output limits, and kills timed-out process trees. Scripts use known
interpreters; direct inline PowerShell/cmd execution is rejected. The matching
server tools are available to agents and reusable workflows. The default roots
are the checkout and SONDER_HOME;
file_roots.local now defaults to SONDER_HOME/file_roots.local, not the
checkout. Override that file with SONDER_FILE_ROOTS_FILE, or add roots with
SONDER_FILE_ROOTS. Control-plane files (root policy/config/state files,
the memory database, credential-like files, and root-level Python modules) may
be read under the guarded policy but mutation requires an authenticated
developer/admin token; an approval code or broad root alone does not bypass
that protection. SONDER_FILE_APPROVAL_CODE and
SONDER_FILE_BYPASS=1 remain local-owner controls for ordinary broader
paths. Deletes require the exact DELETE <resolved path> confirmation string
returned by the dry-run.
workspace_inventory reads metadata only and reports manifests, extension and
area sizes, largest files, exclusions, elapsed time, and a concrete truncation
reason. Inventory, text search, and script discovery enforce both an entry
budget and a wall-clock deadline, never follow symlinks, and skip hidden and
generated/tooling directories unless explicitly included.
Selectable context: use /contextsize 32k, /contextsize 256k, or
/contextsize 1m to select the requested virtual context. Ollama receives a
safe native num_ctx clamped by SONDER_NATIVE_CONTEXT_MAX (default around
256k), while Sonder represents larger budgets with summaries, retrieval,
facts, and recent-turn selection. App Settings has the same Context size field;
env defaults are SONDER_CONTEXT_SIZE, SONDER_NATIVE_CONTEXT_MAX, and
SONDER_VIRTUAL_CONTEXT_MAX.
Sonder sends Ollama local-runtime options on every local model call so it uses the machine instead of idling on conservative defaults:
OLLAMA_HOST- Ollama origin with an explicit port (default127.0.0.1:11434). Exact0.0.0.0/[::]bind addresses andlocalhostare dialed through numeric loopback. Changing the origin requires restarting or reconnecting the runtime because the base URL is loaded at process start.SONDER_ALLOW_REMOTE_OLLAMA- set1only when intentionally sending model prompts and embeddings to a non-loopback Ollama host. It does not enable hosted/cloud model tiers; those separately requireSONDER_ALLOW_CLOUD=1. Prefer HTTPS or a trusted private LAN: opting into a remotehttp://origin acknowledges the destination but does not encrypt transport.SONDER_NUM_THREAD- CPU threads per request. Defaults to all detected CPU threads (%NUMBER_OF_PROCESSORS%on Windows,nprocon Linux).SONDER_NUM_GPU- model layers to offload to GPU. Defaults to999, which asks Ollama to place all supported layers on the GPU. Set0for CPU-only, orauto/noneto let Ollama decide.SONDER_NUM_BATCH- inference batch size. Defaults to512.SONDER_MAX_AGENTS- queued breadth cap for delegated orchestration. Defaults to two candidates per logical CPU (minimum 16), hard-bounded at 64. Raising it adds perspectives; it does not increase simultaneous model calls.SONDER_PARALLEL_WORKERS- explicit concurrent model-call override, bounded to 1..16 and never above the requested agent count. Without it, Sonder derives 1..8 slots from CPU count and available physical RAM.SONDER_SESSION_CLAIM_WAIT_SECONDS- how long a second runtime waits for the same remembered session before returning a retryable busy error (default5, bounded to0..30). Claims bind the owner PID plus process-start identity, cannot expire under a live owner, and are reclaimed only after confirmed death; an unknown OS probe stays busy rather than risking split-brain session writes.SONDER_FLEET_DB- optional path for the private process-shared fleet ledger. Defaults toSONDER_HOME/fleet.db.SONDER_FLEET_HEARTBEAT- set0to disable owner heartbeats (primarily for deterministic tests). Production defaults to a five-second heartbeat.SONDER_RUNTIME_POLICY- optional path to the shared JSON policy for local aliases and execution lanes. By default it isSONDER_HOME/runtime_policy.json.SONDER_FAST,SONDER_CODE,SONDER_CODE_LOCAL, andSONDER_GENERALseed only its first creation.OLLAMA_FLASH_ATTENTION- enabled as1by the launch scripts when they start Ollama.
Check the active values with diagnostics() or REPL /diagnostics; check VRAM
residency with status().
A fresh Sonder installation uses an unpersonalized base model through Ollama. The runtime becomes useful to you by accumulating grounded local context and, only when explicitly requested, training adapter weights:
/train— it practices real tasks, runs its own solutions to check them, and keeps the lessons from what works.- Endless practice — run
endless-train.cmdon Windows to continuously generate, compile, execute, repair, and record passing multi-language campaign work until Ctrl+C or a no-progress round. Tune it withSONDER_ENDLESS_TOTAL,SONDER_ENDLESS_LANGUAGES,SONDER_ENDLESS_TIER,SONDER_ENDLESS_WORKERS,SONDER_ENDLESS_TIMEOUT, andSONDER_ENDLESS_REPAIRS. - Use it on your actual work — the more real, grounded outcomes it sees, the more its lessons reflect your code and conventions (not textbook generalities).
- Fine-tune (optional) —
/hardwareand/training plan --dry-runmake separate inference/training decisions from live VRAM and RAM. Explicit attended QLoRA trains integrity-bound adapter weights;/training deployseals a reviewed llama.cpp converter tree, compares the digest-pinned base and candidate on confined, nonce-varied SQL and instruction-following probes, allows no canary regression, requires measurable lift whenever the base is imperfect, verifies the published alias, and only then keeps it active./training rollbackverifies and restores an exact observedsonder:latestidentity without deleting models or checkpoints (TRAINING.md). - Safe source self-improvement (optional) —
/selfmoduses isolated Git worktrees or snapshot workspaces, immutable per-file backups, deterministic host-run tests, protected paths, explicit approval, atomic deployment, health checks, and exact rollback. It never pushes or rewrites user history (SELFMOD.md).
Keep your grounded, personal data private (it stays gitignored). The distilled, non-sensitive lessons can be exported to lessons.jsonl.
The Ollama model files, adapter weights, and raw interactions stay local. Only small, distilled lesson text is prepared for sharing, and only if you opt in:
contribute.pyexports lessons that pass a conservative privacy scrub (no paths, secrets, or emails; short generic sentences only) tocontrib/lessons_contrib.jsonl. Nothing is sent anywhere yet — review the file yourself.- Send it home base — open a PR adding your file under
contrib/, or copy it to your own file server. - CI aggregates —
.github/workflows/aggregate-lessons.ymldedupes everyone'scontrib/*.jsonlintocommunity_lessons.jsonlat the repo root. Scheduled runs are preview-only so they do not surprise-push over local GUI work; run the workflow manually when you want it to commit the updated file. pull_community.pymergescommunity_lessons.jsonl(fetched viagit pullor your file server) back into your localmemory.db, taggedsource_interaction='community'.
Local maintenance uses the same conservative privacy rules as contribution
export. /privacy shows only redacted previews and stable lesson IDs;
/privacyfix <ids> is a dry run, while /privacyfix apply <ids> can delete only
the explicitly selected lessons that are still flagged. /embeddings [N]
previews missing, legacy, or model-incompatible vectors; /embeddings apply [N]
probes the configured local model and refreshes a bounded batch with stored
model/revision/dimension provenance. Neither maintenance path uses a cloud model.
Privacy is opt-in and scrubbed at every step — nothing auto-uploads, and no PR or upload happens without you reviewing it first.
Shipped
-
✅ One-click engine setup — bundled installs can bootstrap the local engine, detect available memory, pick a practical default model size, and start the local server without terminal setup.
-
✅ Sealed offline engine bundles — optional per-platform payloads carry portable Python/Ollama runtimes and complete model-store subsets behind a fail-closed SHA-256 manifest; launchers and the Flutter System panel prefer them without removing lightweight host-runtime fallback.
-
✅ Richer passive learning — accepts explicit accept/use/copy/edit signals from the CLI, server, and GUI in addition to natural follow-up phrasing.
-
✅ Local-first hosted opt-in — cloud/hosted tiers are disabled unless
SONDER_ALLOW_CLOUD=1or the app setting is explicitly enabled. -
✅ General artifact grounding —
ground_artifactvalidates in-memory content, whileartifact_groundand/artifactcheckvalidate guarded files and bundles with format-specific writing, editable Office, data, UI, image, audio, model, and manifest recipes. Generated packs must pass these contracts before success is reported. -
✅ Editable Office deliverables — deterministic stdlib-only DOCX reports, XLSX workbooks, and PPTX decks are inferred from natural-language requests, open in installed Microsoft Office, and fail closed on unsafe ZIP paths, malformed XML, missing relationships, active content, external dependencies, or unmet content requirements.
-
✅ Editable media and timelines — deterministic animated GIFs, MIDI scores, SRT/WebVTT captions, and EDL edit timelines are inferred from media requests, independently parseable, and grounded for real frames, notes, timing, cue text, and non-overlapping edits.
-
✅ Self-contained video containers — deterministic RIFF/AVI previews combine real 24-bit frames with synchronized PCM audio, carry a complete seek index, open in the native Windows video stack, and serve as the local source media for generated EDL timelines.
-
✅ Passive learning — infers outcomes from natural follow-up ("that worked" / "no, still errors") so it learns without manual scoring.
-
✅ Personas —
/persona coder|explainer|reviewer|teacherso non-coders get value too. -
✅ Federated contribution — share scrubbed lessons back without hosting the model (see above).
-
✅ Mobile & desktop app (GUI) — a Flutter client with a shared chat and System UI (Android APK + Windows/Linux/macOS), CI-built with download links. Client-only apps can start, stop, and restart a configured host through authenticated, persistent launcher operations that survive client disconnects.
-
✅ Grounded animated humanoid 3D models — deterministic binary glTF 2.0 characters carry 384 vertices and 192 triangles, unit normals, orthogonal tangent frames, UVs, three embedded PBR maps, a canonical 17-joint humanoid hierarchy with affine inverse-bind matrices and normalized per-vertex weights, two nonzero position/normal/tangent morph frames, six named skeletal/blend-shape clips, and two validated clip sequences in one dependency-free GLB. The output passes Khronos glTF Validator with zero findings and independently imports through glTF Transform with every mesh, skin, morph frame, texture, clip, and sequence intact.
Next gaps — publish preassembled signed engine payloads for each desktop platform (the local assembler/package/runtime contract is shipped), add importer-specific runtime smoke profiles beyond format-level Khronos validation, and expand the deterministic humanoid baseline with configurable topology and retargetable motion libraries.
Flat, mostly-stdlib Python modules (plus mcp):
| module | role |
|---|---|
memory_store.py |
SQLite + FTS5 store (interactions, outcomes, lessons, visible tasks/todos) |
embeddings.py |
local Ollama embeddings + cosine (soft-fail) |
ollama_endpoint.py |
canonical Ollama origin, loopback/remote consent, proxy-free no-redirect transport |
retriever.py |
hybrid lexical+semantic retrieval with relevance threshold |
reward.py / reflection.py |
outcome → score; distill deduped lessons |
orchestrator.py |
the retrieve → augment → generate → capture flow |
master_orchestrator.py / fleet_store.py |
RAM/CPU-bounded fleet execution plus a process-shared restart/recovery ledger |
autopilot_controller.py / autopilot_store.py |
Persistent local goal planning, guarded execution/review, evidence gates, budgets, and explicit lifecycle control |
runtime_policy.py |
OS-locked, revision-checked per-user local-model aliases and execution-lane routing shared across live surfaces |
adaptive_training.py / promotion_eval.py / eval_models.py |
Attended QLoRA lifecycle, crash-recoverable alias/policy transactions, and digest-bound nonce-varied SQL/instruction promotion evaluation |
reloadable_mcp.py |
Fail-closed live server-source execution, atomic tool-manager swaps, schema-cache invalidation, and MCP tool-list notifications |
learning_health.py |
Outcome coverage, reward distribution, lesson provenance, distillation yield, and memory-hygiene reporting |
artifact_grounding.py |
Guarded format contracts for writing, data, UI, images, audio, models, and complete artifact bundles |
model_assets.py |
Deterministic stdlib-only binary glTF humanoids, embedded PBR textures, canonical skinning, full morph frames, affine inverse-bind matrices, and named animation clips/sequences |
creative_router.py |
conservative natural-language routing from concrete master build requests into grounded artifact, game, or game-campaign workflows |
server.py / workbench.py / activity_tracker.py / code_runner.py / web_tools.py / workflow_store.py / self_heal.py |
MCP workbench/agent tools, guarded discovery and execution, persistent checklists, exact action/end reports, bounded code/project runners, web tools, workflows, and self-healing |
server.py |
MCP server: offload / sonder / parallel_run_code / parallel_generate_run / parallel_generate_run_languages / campaign_generate_compile_execute_record / learn_tiers / record_outcome / sonder_stats / sonder_sessions / sonder_remember_fact |
assetgen.py / game_forge.py |
stdlib-only general artifact generation, manifest verification, portable cross-language game projects, model campaigns, and verified 4-language x 3-dimension fallbacks |
recall.py |
project-scoped, provenance-aware semantic recall of past good-outcome solutions |
summarizer.py |
rolling conversation summaries + session auto-titles (fast tier) |
sonder_repl.py / sonder_client.py |
local REPL / thin remote client |
sonder_serve.py |
OpenAI-compatible proxy (for chat UIs) |
intents.py, grounding.py, training_tasks.py, self_curriculum.py, eval_retrieval.py, game_ladder.py |
NL control, sandboxed execution, practice tasks, self-generated curriculum, retrieval eval, capability gauntlet |
training_data.py, qlora_train.py, export_training_data.py, cloud_train.sh |
strict shared dataset contract and fine-tuning pipeline |
Long-running sonder_serve.py and sonder_repl.py processes check for source edits before each request/turn. Edits to server.py and helper modules such as personas, retrieval, summarization, feedback, and code execution are picked up on the next call without hard restarting the proxy or REPL. Set SONDER_LIVE_RELOAD=0 to disable this.
The MCP server now stages the complete updated server.py tool registry in an
isolated namespace at the next list/tool request. A clean load atomically swaps
implementations and schemas, clears the protocol schema cache, and emits
notifications/tools/list_changed; a syntax/import/runtime failure discards the
stage and keeps every last known-good tool active. This covers changed, added,
and removed MCP tools without disconnecting the process. The first upgrade from
an older startup-bound build still needs one reconnect so this reloadable kernel
itself is loaded. Inspect convergence with /mcp, mcp_runtime_status(), or
live_reload_status().
Multiple installs can run the same system code, but they should not each own a
separate memory database. Runtime state defaults to one per-user home directory:
%LOCALAPPDATA%\sonder on Windows, $XDG_DATA_HOME/sonder or
~/.local/share/sonder on Linux, and the matching app data home on macOS.
Set SONDER_HOME to force a specific shared state folder, or SONDER_DB
to point directly at a database file. If an older install has memory.db beside
the code and the shared DB does not exist yet, sonder copies it into the
shared home on first run.
The same home contains runtime_policy.json, the single source of truth for
local model aliases and automatic execution lanes across MCP, the HTTP server,
REPL, workbench, Autopilot, fleet workers, and review. Every request boundary
reloads it, so an atomic update from one running surface is visible to the others
without a hard restart. Inspect it with /runtime or
runtime_policy_status(). Developer/admin-authorized edits use, for example,
/runtime set general=qwen2.5:7b-instruct review=general; /runtime reset
restores safe defaults. Updates reject cloud-looking or uninstalled model names.
The policy cannot enable cloud tiers, broaden permissions/roots, or store
credentials. The Flutter System page renders the same revision, aliases, lanes,
path, and any missing-model warning alongside MCP source/tool convergence.
system_profile.md is an editable Markdown profile injected into every sonder / OpenAI-proxy answer. Edit the file directly, or use system_profile_text() and update_system_profile(mode="append"|"replace"|"clear") through MCP. Because the profile is read at request time, changes apply on the next call.
emotion_vectors.json holds live tone-steering dimensions from -1.0 to +1.0 such as warmth, calm, curiosity, confidence, playfulness, urgency, skepticism, and brevity. These are behavioral controls, not claims about internal feelings. Edit the JSON directly, or use emotion_vector_status() and update_emotion_vectors(mode="merge"|"replace"|"clear"); changes apply on the next call.
workflows.json stores reusable loop action lists. Use workflow_save() to keep a routine, workflow_run() to execute it, and workflow_list() / workflow_delete() to manage it. The built-in status_sweep workflow checks diagnostics, profile, emotion vectors, and Ollama state.
The MCP surface also includes memory_search(), memory_export(), and session_export() so the model can inspect local lessons, facts, sessions, and transcripts without raw SQLite access. memory_embedding_backfill() and memory_interaction_embedding_backfill() preview or repair bounded local-only vector batches; the interaction tool reports IDs and counts without printing raw task text. tool_manifest() prints a compact map of the available tools.
learn_from_example() lets you teach from a known-good task/solution pair, while apply_learned() shows which lessons would be applied to a new task. Lesson usage is tracked: when a retrieved lesson participates in an answer and you later call record_outcome(), the lesson gets credited or debited so future retrieval can prefer lessons that actually helped.
workbench_agent(prompt) runs a bounded local tool-use loop with four enforced
phases: inspect, implement/analyze, validate, report. The host rejects mutation
before inspection and does not accept an equivalent in-memory snippet as proof
that an edited disk file works; scripts must be run from their persistent path
or covered by a real workspace test/build. agent() exposes the same tools with
optional checklist behavior. Both can inspect trees/files/programs/scripts/images,
mutate guarded files, generate arbitrary asset packs or games, execute bounded
checks, use memory/workflows/web, and return exact observable evidence.
web_search() and web_fetch() use stdlib HTTP only. Search defaults to
DuckDuckGo HTML, or set SONDER_SEARCH_URL to an endpoint containing
{query}. weather_lookup() resolves a supplied city/postal code and gets
sourced current conditions plus a short forecast from Open-Meteo. Ordinary chat
now routes explicit weather/current-web requests through these tools instead of
letting the base model falsely claim that internet access is unavailable.
Approximate location remains opt-in. The Flutter Settings switch contacts
ipwho.is only for a location-dependent prompt, minimizes the response to
city/region/country/timezone, discards coordinates, and never sends the raw IP
to Sonder.
The chat response identifies the resolved place as an approximate public-IP
estimate because VPN and ISP routing can make it wrong. Loopback clients can use
the same consented server-side fallback through approximate_location_lookup();
remote hosted clients must provide the client-side hint so the server's data
center location is not mistaken for the user's. Set SONDER_WEB_TOOLS=0 to
disable all web and location access.
self_heal_check() looks for common local breakage: invalid JSON config files, live-reload errors, broken venv pointers, and lesson-store integrity issues. self_heal_repair(apply=True) only applies conservative local fixes: rebuild missing lesson FTS rows, remove orphan FTS rows, clear corrupt lesson embeddings, and restore default JSON config files after making backups. Python/venv problems and syntax errors are reported for manual repair.
- Research/hobby project, built with heavy AI assistance; not a polished product.
- A local 7B trails frontier hosted models on raw capability — by design; the trade is privacy + ownership.
- Lesson-retrieval's measured benefit is real only when relevant lessons exist; on easy tasks it's do-no-harm, not a boost. Real gains come from your accumulated data and/or fine-tuning.
- Tests run in CI on every push. Local-first throughout; your private data stays yours.
python scripts/ci_watch.pyshows the latest GitHub Actions runs through the GitHub CLI, which makes failed build/debug loops faster from a local checkout.