Skip to content

feat(assistants): per-workspace flag to default to OpenCode with a free model (Claude-less trial mode) #395

Description

@umi-appcoder

Goal

Add a per-workspace configuration flag (Helm value / env var) that makes a workspace default to OpenCode with a free model instead of Claude Code, so a new user can experience the full workspace (Hypervisor chat, Builds, sub-agents) without logging into or paying for Claude.

Explicitly not a change to the global default — vanilla deployments stay Claude-first. This is an opt-in knob set when provisioning a trial/demo workspace for a user.

Current state (audited 2026-07-21, main @ c512083)

A partial knob already exists, but it's not enough:

  • hypervisor.defaultAssistant (charts/workspace/values.yaml:292-298) → HYPERVISOR_DEFAULT_ASSISTANT (templates/deployment.yaml:196-200, server.py:135) — but it only governs Hypervisor chat. The task-create / New Build path has no equivalent: handle_claude_create_task() (server.py:5508) → create_task() (server.py:1421) defaults to claude.
  • available_assistants() hardcodes claude first with default=True (server.py:1148) — the SPA (NewTaskForm.tsx:30-34) and mobile (NewTaskScreen.tsx:46) both pick whichever entry carries default:true, so fixing the server list fixes both pickers.
  • The trap: resolve_assistant() (server.py:1272-1280) silently falls back to claude when the requested assistant isn't in the enabled set — and opencode-openrouter/opencode-deepseek are only enabled when OPENROUTER_API_KEY/DEEPSEEK_API_KEY are set (server.py:1174-1183). Setting defaultAssistant: opencode-openrouter with no key today just silently reverts to claude.
  • No zero-credential assistant exists. The only no-key path is assistant.fallback/kc-harness, which needs a self-hosted Ollama endpoint (KC_FALLBACK_BASE_URL).

Proposed scope

1. One workspace-wide default-assistant knob

  • New value, e.g. assistant.default (env KC_DEFAULT_ASSISTANT), governing both Hypervisor chat and task-create defaults. Keep hypervisor.defaultAssistant as a back-compat override.
  • available_assistants() flags the configured assistant default: true and orders it first; resolve_assistant() falls back to the configured default (final fallback claude), and logs loudly when the configured default isn't enabled instead of silently reverting.
  • GET /api/hypervisor/config + /api/claude/assistants then propagate it to SPA and mobile with no client logic changes for the pickers.

2. A genuinely free OpenCode path

The "free model" needs a provider that works without billing. Two options, not mutually exclusive:

Option A — OpenCode Zen (preferred): new assistant variant opencode-zen backed by OpenCode's hosted Zen gateway: free coding models (e.g. minimax-m2.5-free, Big Pickle, DeepSeek V4 Flash), ~100 req/day, no credit card — but it does require a one-time free signup key (details). Wire like the existing variants: gate on OPENCODE_API_KEY, support a shared key via the same mechanism as assistant.openrouter.sharedSecretName (values.yaml:312-316) so an operator can provision trial workspaces with one platform-owned free key. Extend start.sh:221-292 (opencode.json rendering) and assistant_command() (server.py:1311-1377).

  • ⚠️ Disclose in UI: Zen free models may use collected data for training — a trial-mode banner/note should say so.

Option B — shared OpenRouter key + :free model: the plumbing already exists (sharedSecretName + KC_OPENROUTER_MODEL, and the builtin model list already includes deepseek/deepseek-chat-v3-0324:free at server.py:1234-1240). Zero new assistant code; operator supplies a free-tier OpenRouter key. Cheapest path to ship; rate limits are the operator's problem.

3. Frontend copy + onboarding conditionalization

  • SPA: NewTaskForm.tsx:134,146 hardcodes "claude (default)"; use the fetched default instead.
  • SPA onboarding (Onboarding.tsx:97,107,132,169) says "This workspace runs Claude Code…", "Send Claude a starter prompt…" — make assistant-aware, and skip the Claude-login step when the default isn't claude (values.yaml:278-282 documents that login step today).
  • Mobile hardcoded fallbacks: client.ts:300,671,674,929, NewTaskScreen.tsx:24,36, HypervisorScreen.tsx:422.
  • Settings → Provider keys already lets a trial user add their own Anthropic/OpenRouter key later (ProviderKeysSection.tsx) — mention this in the trial onboarding as the upgrade path.

4. Keep the second registry in sync

mcp_agent_orchestrator.py duplicates the assistant list and hardcodes claude fallbacks (:242, :287-346, :375-382, :556, :592, :762) — new variant + configured default must land there too, or sub-agent spawning breaks the parity.

Acceptance criteria

  • Deploy chart with assistant.default: opencode-zen (or Option B equivalent) + shared free key → fresh workspace: Hypervisor chat and New Build both default to OpenCode on the free model; the assistant picker shows it as default; no Claude login prompt anywhere in onboarding.
  • Claude remains installed and selectable; adding an Anthropic key/OAuth later works unchanged.
  • Vanilla deployments (no flag) behave exactly as today — claude default everywhere.
  • Misconfigured default (assistant not enabled) logs a clear warning and falls back, rather than failing silently.
  • Sub-agent spawning (spawn_agent) honours the workspace default when no assistant is specified.

Suggested phasing

  1. Knob + server default propagation + SPA (core value)
  2. Free-path provider (A or B decision first — A is better long-term, B ships fastest)
  3. Onboarding conditionalization
  4. Mobile parity + orchestrator sync

Sourced from a code audit (Explore sweep of chart/server/SPA/mobile) + OpenCode Zen docs, 2026-07-21.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions