node launcher.mjs ← chat mode (default)
node launcher.mjs --mode api ← API mode only (no REPL)
Access dashboard: http://localhost:3100/dashboard
Key env vars — set in config/api-keys.env:
DEEPSEEK_API_KEY— primary smart/code tierOPENAI_API_KEY— fallback smart tierOLLAMA_MODEL_FAST— fast tier local model (e.g.qwen3:1.5b)OLLAMA_MODEL_SMART— smart tier local model (e.g.qwen3:8b)MAX_AUTO_APPROVE—read|write|all(default:write)MAX_PORT— dashboard port (default: 3100)MAX_DAILY_BUDGET— hard API spend cap in USD (default:10.00)MAX_SECURITY_COUNCIL— adversarial code review before file writes (default:true; setfalseonly for emergency local debugging)
Deployment models:
- MAX standalone (default): MAX ships and runs independently. No SOMA needed.
SOMA_URLis commented out. This is the production product. - SOMA + MAX bundled: When SOMA ships, she includes MAX as her execution engine. Set
SOMA_URL=http://localhost:3001to connect. MAX will use SOMA's QuadBrain when available and fall back to its own brain otherwise.
MAX is a standalone autonomous engineering agent — a complete product in its own right. It also ships as SOMA's execution engine when SOMA is deployed, but has no dependency on SOMA and runs fully independently by default.
Brain (LLM tiers)
→ Memory (MaxMemory + KnowledgeBase)
→ Tools (ToolRegistry: file, shell, web, git, api, vision, etc.)
→ GoalEngine (goal economy — goals compete for execution)
→ AgentLoop (autonomous task execution, parallel wave dependency resolution)
→ ReflectionEngine (per-turn scoring, deep reflection every 10 turns)
→ Heartbeat (background tension/curiosity loop)
→ Scheduler (recurring jobs: diagnostics 1h, reflection 4h, briefing 24h)
→ SomaBridge (SOMA connection — uses SOMA's QuadBrain when available)
| Tier | Purpose | Backend priority |
|---|---|---|
| fast | Acknowledgments, queue acks, 40-token responses | Ollama fast model |
| smart | Main chat, reasoning | Ollama smart → DeepSeek → OpenAI |
| code | Code generation, file edits | DeepSeek → OpenAI → Ollama |
/status — tension, satisfaction, brain backend, memory count
/run <cmd> — direct shell execution (no LLM, streams live)
/ps — list background shell processes
/kill <name> — stop a named background process
/goals — list active goals
/goals add "x" — queue a goal for AgentLoop
/goals done <id> — mark goal complete
/goals clear — clear pending goals
/reflect — trigger deep reflection immediately
/reason <query> — multi-strategy reasoning (causal, simulation, security)
/expand [id] — expand an insight from the insight box
/pause — interrupt AgentLoop at next step boundary
/resume — resume interrupted AgentLoop
/swarm — next message uses parallel swarm
/persona <name> — switch persona (architect/grinder/paranoid/breaker/explainer)
/self edit <path> <instruction> — propose an edit to MAX's own source
/self commit <path> — apply staged edit (with backup)
/self rollback <path> — discard staged edit
/artifacts — list generated artifacts
/proposals — list SOMA self-modification proposals
/approve <id> — approve a SOMA proposal (runs full apply pipeline)
/deny <id> — deny a SOMA proposal
/quit — save session and exit
| File | What it does |
|---|---|
launcher.mjs |
Entry point, REPL, all slash commands |
core/MAX.js |
Main agent — think(), initialize(), _buildStateContext() |
core/Brain.js |
LLM tier router (fast/smart/code) + DeepSeek/OpenAI/Ollama backends |
core/AgentLoop.js |
Autonomous task execution — parallel wave dependency resolution |
core/GoalEngine.js |
Goal queue, priority scoring, auto-generation |
core/Heartbeat.js |
Background tension loop — triggers AgentLoop, curiosity, auto-goals |
core/ReflectionEngine.js |
Per-turn scoring + deep reflect every 10 turns + prompt patches |
core/SomaBridge.js |
SOMA connection — think(), injectGoal(), getSomaStatus() |
core/SomaController.js |
Mechanical SOMA control — stop/start/health/git checkpoint/apply proposal |
tools/ShellTool.js |
Live-streaming shell, background process management, persistent CWD |
tools/ToolRegistry.js |
Tool dispatch + LLM TOOL: call parser |
server/server.js |
Dashboard API + SSE + SOMA proposal queue (/api/soma/propose) |
server/ui.html |
Dashboard frontend |
- Execution requests ("fix X", "add Y to file Z") → MAX uses tools directly, reads file, makes change, verifies, reports done. Does NOT ask for confirmation mid-task.
- Investigation requests ("why isn't X working", "figure out Y") → MAX queues a goal via
TOOL:goals:add, AgentLoop investigates autonomously. - Shell requests ("run tests", "start server") →
TOOL:shell:runfor commands,TOOL:shell:startfor background processes. - Complex multi-step → MAX outputs a
PLAN:block first (numbered steps), then executes. Printed to terminal before tools run so Barry can interrupt.
TOOL:<name>:<action>:<json_params>
Examples:
TOOL:file:read:{"filePath": "core/MAX.js"}
TOOL:shell:run:{"command": "npm test", "timeoutMs": 60000}
TOOL:shell:start:{"command": "node launcher.mjs", "name": "max-dev"}
TOOL:goals:add:{"title": "Investigate memory leak", "priority": 0.9}
read— only file reads auto-approved, everything else gateswrite— reads + writes auto-approved; onlygit.commit,git.push,file.deleterequire approvalall— fully autonomous, nothing requires approval
Default is write. Set MAX_AUTO_APPROVE=all in config/api-keys.env for hands-off operation.
_executeStep(step, goal, stepResultMap) — the third argument carries outputs from prior steps for dependent steps to consume. Without this, dependent steps can't see what earlier steps produced. Always pass stepResultMap when calling _executeStep.
Goals planned by the LLM must include action_name and params fields for tool steps. Without params, file tool calls get filePath: undefined and fail silently. The planner prompt in GoalEngine.js documents this.
scheduler.addJob({ id, label, every, type, handler }) — NOT scheduler.add(). The every field uses '30m', '1h', '4h', '24h' format. The handler field is the function, not fn.
_promptCache is keyed by ${personaId}|${tensionDecile}|${contextLength}. This means the cache is invalidated on every new turn (context grows). The cache primarily protects against expensive tool manifest rebuilds during the same turn with tool loops.
When routing a chat turn through SOMA's bridge, always pass systemPrompt in the options object. Without it, SOMA has no tool manifest and can't generate TOOL: calls.
When MAX uses file:write or file:replace during a chat tool loop, a ✏️ write <path> line is printed to terminal before the operation. This is intentional — it's the only visible signal that MAX changed a file.
MAX is designed as SOMA's execution layer. When SOMA is running:
- Chat turns route through SOMA's QuadBrain (DeepSeek-backed) instead of MAX's local brain
- MAX can inject goals into SOMA's GoalEngine via
TOOL:goals:inject_soma - SOMA proposals (self-modifications) arrive at
POST /api/soma/proposeand are queued for Barry's review /approve <id>runs the fullSomaController.applyProposal()pipeline: syntax check → git checkpoint → atomic write → restart → health verify → auto-revert on failure
- AgentLoop approval UI — when
autoApproveLevel: 'read'and MAX needs approval for a write, the approval request is emitted asapprovalNeededand displayed as a box in the REPL. The user must type/approveor/deny. If using the IDE exclusively, they may miss the REPL prompt. Consider mirroring the approval request to the IDE via WebSocket.
- MAX SwarmCoordinator is the simple version —
swarm/SwarmCoordinator.jsis the basic parallel-subtask version. SOMA has the fullEngineeringSwarmArbiterwith research/plan/debate/synthesis cycles. Eventually MAX's/swarmshould route complex engineering tasks to SOMA's swarm and use its own simple version only for quick parallel queries. - SkillLibrary prune threshold — skills pruned if
age > 30 days && usedCount < 3. For a newly booted MAX that hasn't run many tasks, all skills are <3 uses and get pruned on first boot. Consider requiring both conditions:age > 30 days AND usedCount < 3 AND lastUsed > 7 days ago. - Curiosity pipeline goal quality —
CuriosityEngine.signalsGoal()uses keyword matching (should/must/critical/etc.) to decide if a curiosity result should become a goal. This generates noisy goals. Consider adding a priority floor (curiosity-sourced goals capped at 0.5 priority) so they don't crowd out user-sourced goals. - LSP server availability —
core/RealLSPBridge.jsprobes fortypescript-language-server,pylsp,gopls,rust-analyzerin PATH. If none found it falls back to AI pseudo-diagnostics. For full IDE capability install:npm i -g typescript-language-server typescript.
- Running processes lost after restart —
ShellTool._procsis module-level state. If MAX is restarted, allshell:startbackground processes are forgotten even if still running. On boot, consider scanning for processes with known names viaps aux | grep. - Context compression loses tool trace detail —
_compressContext()compresses old turns into a 2-3 sentence summary. If those turns contained tool results (file reads, shell output), the specific data is lost. Important facts should be inMaxMemorybefore compression happens._flushMemories()partially handles this but fires reactively (at 80% context).
- Live-streaming shell with background process management (ShellTool)
- Planning blocks (
PLAN:) printed before complex tool executions - File write/replace notifications in terminal
- Full REPL command set: /run, /ps, /kill, /goals, /reflect
- Project auto-detection (package.json + README injected into system prompt)
- Background processes in system context (MAX knows what's running)
- Task outcome reflection wired to Scheduler (every 4h)
- SOMA proposal queue + apply pipeline + dashboard UI
- SomaController (mechanical SOMA control with git checkpoint + auto-revert)
- Brain: Gemini replaced with DeepSeek (deepseek-reasoner as smart/code tier)
- Feedback loops closed — ReflectionEngine writes insights to KB after every deep reflection. AgentLoop writes goal outcomes (success + failure) to KB.
dream()auto-triggers every 3rd reflection + runs on 12h Scheduler.KnowledgeBase.remember()shortcut added for plain-text ingestion. - Streaming responses — Brain.js has
onTokencallback; launcher.mjs streams tokens live. Both Ollama and DeepSeek backends stream. Spinner stops on first token;MAX:prefix printed inline. - Interactive approval prompt —
approvalNeededevent renders a full UI box in REPL with goal/tool/params. User types/approveor/deny. AgentLoop has_pendingApproval+approve()/deny()methods wired. - Ghost buffer pipeline — Maxwell IDE sends
buffer_updateWebSocket messages →max._ghostBuffers→ ContextPagerArbiter injects unsaved content into system prompt. LSP diagnostics triggered on each update. - Real LSP integration —
core/RealLSPBridge.jsspawns real language servers (typescript-language-server, pylsp, gopls, rust-analyzer) via stdio JSON-RPC. Falls back to AI pseudo-diagnostics when servers are unavailable. - Monaco completions + hover + go-to-def — Maxwell IDE registers LSP-backed completion provider, hover provider, definition provider, and AI inline ghost-text provider (Cursor-style Tab completions).
- SkillMutator closed loop —
spawnVariant()→queueForTest()→runNextTest()(executes via_executeStep) →_scoreAndPromote(). High-scoring variants (≥8.0) auto-promoted to SkillLibrary. Scheduled every 12h (spawn) + 3h (test). - AgentLoop cycle queue — dropped cycles while busy now set
_pendingCycle = true; retried immediately infinallyblock viasetImmediate.
- Mirror approval requests to IDE — when AgentLoop emits
approvalNeeded, also broadcast to WebSocket clients so IDE users see the request without checking the REPL. - MAX → SOMA engineering dispatch — when MAX's
/swarmis called with a complex engineering request, check if SOMA is available and route toEngineeringSwarmArbiterinstead of MAX's simpleSwarmCoordinator. - Session state on dashboard — show current goals, active agent loop status, last 5 insights, and memory stats on the dashboard. Most data is already in
max.getStatus().
- Persistent shell processes across restarts — save
_procsregistry to.max/procs.jsonon shutdown, attempt to re-attach or report orphaned processes on boot. - Goal dependency UI — when
/goals listshows blocked goals, display the dependency chain so it's clear what needs to complete first. - Structured output for AgentLoop steps — currently steps return raw text. For code-writing steps, parse the result and extract file paths that were written. Feed these back to the system context automatically.
- Curiosity → KB — CuriosityEngine interesting results aren't written to KB yet. Wire
CuriosityEngineto callkb.remember()when it discovers something novel. This makes the KB grow organically from MAX's own exploration.
- MAX as SOMA arbiter — register MAX itself as an arbiter in SOMA's MessageBroker. SOMA can then dispatch execution signals directly to MAX rather than through HTTP. MAX becomes a first-class component of the COS.
- Multi-MAX swarm — spawn multiple MAX instances with different personas for parallel execution.
SwarmCoordinatorbecomes a true multi-agent system with each worker being a specialized MAX persona. - Continuous self-improvement —
ReflectionEngineidentifies behavioral patterns.SelfEditorproposes code changes.SomaControllerapplies them. Full closed loop: MAX observes its own behavior, reflects, proposes improvements to its own code, and applies them safely.
- Ternary computing —
\|/notation — dreamed up a balanced ternary system where\=-1 (false),|=0 (uncertain),/=+1 (true). Symbols represent geometric orientation, not just magnitude. Potential applications: (1) build a\|/ternary interpreter/arithmetic library, (2) wire ternary belief states into SOMA's cognition so she has genuine uncertainty rather than binary true/false, (3) write it up — the visual notation is novel and not in the literature. This is real math (balanced ternary, Soviet Setun 1958, Knuth) with a new representation layer on top.