Skip to content

Integrate Ollama as a fully-swappable LLM provider (standalone amux) #45

Description

@esteininger

Goal

Make amux completely standalone — runnable with no cloud LLM dependency — by adding Ollama (local models) as a first-class, fully-swappable provider alongside Claude Code, Codex, and Gemini. When a user selects Ollama, every amux feature must work identically to the cloud providers, driven by a locally-hosted model.

Definition of done: a user with only Ollama installed (no ANTHROPIC_API_KEY, no Gemini/OpenAI keys, no network) can create sessions, run the full agentic loop, and use every dashboard feature end-to-end. Validated against GLM‑5.2 and Qwen3.5 as the reference local models.


Two integration surfaces

Ollama is a local model server (http://localhost:11434, OpenAI‑compatible at /v1), not an interactive agentic coding CLI like claude/codex/gemini. So "integrate Ollama" spans two distinct surfaces, both required for standalone:

A. Session-driving agent (the terminal a peek renders)

amux drives an interactive agent CLI inside tmux. Ollama has no agentic CLI of its own (ollama run is a bare REPL — no tool use / file edits). Design decision needed (see Open Questions): wrap an open agentic CLI that speaks to an OpenAI‑compatible endpoint and point it at Ollama. Candidates: Codex CLI configured with a custom provider base‑url, aider --model ollama/<m>, opencode, crush. Whatever we pick becomes the "ollama" provider's launch command.

B. amux's own internal LLM calls (features that call an LLM directly)

Several features call Anthropic directly and must become provider-routable (or fall back to the local model):

  • Browser "Computer Use" agent — _run_browser_agent() uses anthropic.Anthropic() + client.beta.messages.create(model="claude-sonnet-4-5") (~line 1024–1144). Ollama has no Computer‑Use API — needs an OpenAI‑compatible tool-calling loop or a documented degradation.
  • YOLO auto-answers / feedback-survey auto-answers, any summarization/title generation, /api/agent.
  • Anywhere ANTHROPIC_API_KEY / api.anthropic.com is assumed.

Current provider abstraction (what already exists to build on)

CC_PROVIDER per-session env var; _SESSION_PROVIDERS = ("claude", "codex", "gemini", "iterm2"). Touch points:

  • _default_model_for_provider() (~9609), _provider_label() (~9617), _provider_yolo_flag() (~9626), _strip_provider_yolo_flags() (~9634), _is_yolo_enabled() (~9664)
  • Launch: start_session() (~9944) — per-provider command build (codex ~10053, gemini ~10104)
  • Restart: _stop_session_for_restart(name, provider) (~9771)
  • Status detection: _detect_claude_status() — codex patterns (~4120–4160), gemini (~4154). Peek parity parsers _pending_input(), _agent_panel(), _live_limit_region() (contract in docs/peek-parity.md + tests/test_peek_parity.py)
  • Session payload provider fields (~8710–8784); model extraction _extract_model_from_flags() for providers without Claude JSONL
  • Codex trust helper _auto_trust_codex_dir() (~5690)

Adding a provider = implementing this whole surface for "ollama", not just a launch string.


Task checklist

Provider plumbing

  • Add "ollama" to _SESSION_PROVIDERS
  • _default_model_for_provider("ollama") → default local model (e.g. qwen3.5)
  • _provider_label, _provider_yolo_flag, _strip_provider_yolo_flags, _is_yolo_enabled for ollama's autonomy flag
  • Config: Ollama base URL / model list (env, e.g. OLLAMA_HOST), preflight check that Ollama is reachable + model pulled

Launch & lifecycle

  • start_session() ollama branch — build the agentic-CLI command pointed at Ollama; fresh + resume paths
  • Session-id/resume persistence (mirror codex_session_id/gemini_session_id) if the chosen CLI supports it
  • _stop_session_for_restart() ollama handling; auto-trust/noninteractive equivalent

Status detection & peek parity (docs/peek-parity.md is the contract)

  • _detect_claude_status() patterns for the ollama CLI: active spinner, idle prompt, waiting/approval, limit/error states
  • _pending_input() + _agent_panel() parse the ollama CLI's prompt/agent UI (P5/P6)
  • Add ollama fixtures to tests/test_peek_parity.py; steering exactly-once + settle behavior verified

Internal LLM features → provider-routable

  • Abstraction for internal calls (e.g. _llm_complete(...)) that targets Ollama's OpenAI‑compatible /v1 when standalone
  • Browser agent: tool-calling loop over Ollama, or documented graceful degradation when Computer Use isn't available
  • Auto-answers / any summarization routed through the abstraction; never hard-require ANTHROPIC_API_KEY

Config / UI

  • New-session provider picker shows Ollama + model dropdown (pulled models)
  • Provider-switch flow (PATCH session provider) handles ollama (see ~47556–47710)
  • Usage/limits panel: hide or adapt Anthropic-subscription-only UI for local models (no quota)

Docs & cloud

  • README/onboarding: "Run amux fully local with Ollama"; single-file rule preserved (no if IS_CLOUD branches)
  • Confirm nothing calls api.anthropic.com when provider=ollama and no keys are set (network-off test)

Feature-parity test matrix

Every feature must pass with provider = ollama (model = GLM‑5.2, then Qwen3.5), matching Claude/Codex/Gemini behavior:

Area Feature claude codex gemini ollama
Session create / start / stop / restart / resume
Session rename (queue+history follow), archive, delete
Peek content parity, scrollback, freshness (P1–P3)
Peek status honesty: active/idle/waiting (P4)
Send exactly-once + settle delay + subagent hold (P5)
Steering queue, settle delivery, sent-history, standing instructions
Auto auto-continue, auto-restart, YOLO auto-answers
Context auto-compact / context tracking (or documented N/A)
Board/CRM/Notes/Calendar/Scheduler run against a local-model session
Browser agent /api/browser/agent drives a task
Standalone no api.anthropic.com calls; works network-off

Success criteria

  • A session on GLM‑5.2 (via Ollama) passes the entire matrix end-to-end.
  • A session on Qwen3.5 (via Ollama) passes the entire matrix end-to-end.
  • With ANTHROPIC_API_KEY/Gemini/OpenAI keys unset and networking to cloud LLM APIs blocked, amux still: creates sessions, runs the agentic loop, and serves every dashboard feature (internal LLM features either work via Ollama or degrade with a clear message — never crash).
  • Providers are hot-swappable per session: the same session can be switched claude ↔ codex ↔ gemini ↔ ollama and each still peeks/steers/statuses correctly.
  • tests/test_peek_parity.py includes ollama fixtures and passes.

Open questions / decisions

  1. Which agentic CLI backs the ollama provider? Reuse Codex CLI with a custom OpenAI‑compatible provider (base_url=http://localhost:11434/v1), or adopt aider/opencode/crush? Trade-off: parity of tool-use/agentic quality on local models vs. new status-detection surface to write.
  2. Browser Computer‑Use agent has no Ollama equivalent — implement an OpenAI‑tool‑calling agent loop, or mark it unsupported when standalone?
  3. Model naming — track the Ollama model tag (glm-5.2, qwen3.5) in CC_FLAGS/meta the way codex/gemini models are surfaced.
  4. Compaction/context semantics differ per CLI — define expected behavior (native compaction vs. N/A) for the ollama path.

Note: keep the single-file rule — no env-branched cloud/OSS code paths; provider behavior is driven by CC_PROVIDER + config, not build flags.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions