You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have asked Claude for a concept on how that could be done and I think the result is worth sharing.
Maybe lead developers of multica want to pick up on this.
Actually I think it is better to share the concept of the idea than opening a pull request against a fast evolving codebase.
So here we go:
Prompt used with Claude (Sonnet 4.6 High (thinking)
You are a software developer and we want to write an extenstion to the multica project on github. Momentarily so called runtimes (the tools like codex, gemini or claude) are automatically detect once multica is running. I want it to be also able to use vibe from antropic or ma local LMstudio with gemma4. So basically we need custom runtimes, which can be configured. Please look trough the multica code and investigate how this is currently handled and how we could potentially build that extension to the code.
Context: Right now the daemon auto-detects a fixed list of CLIs on PATH. This proposal adds two new providers — Anthropic's Vibe CLI and a local LMStudio server — and, more generally, establishes the pattern for adding any further custom runtime going forward.
How the current system works
After reading the codebase (around commit 4d110236), the runtime pipeline has five distinct layers:
LoadConfig() ← probes PATH for known CLIs
↓
agent.New(type, cfg) ← factory dispatches to the right backend struct
↓
Backend.Execute(...) ← spawns subprocess or makes HTTP call, returns Session
↓
execenv.InjectRuntimeConfig ← writes CLAUDE.md / AGENTS.md into the task dir
execenv.context.go ← maps provider → skills discovery path
↓
provider-logo.tsx ← renders brand icon in the UI
Every existing provider (claude, codex, hermes, gemini, …) touches all five layers. A new provider must be wired into each one.
Two new providers
Vibe (Anthropic Vibe CLI)
Follows the existing CLI pattern exactly. Detection via exec.LookPath, output assumed to be the same Claude SDK NDJSON stream format (--output-format stream-json). If Vibe's wire format turns out to differ from Claude Code's, only the message-parsing block needs adjusting — the rest of the plumbing is identical.
LMStudio (local OpenAI-compatible HTTP server)
A genuinely new pattern: no subprocess, pure HTTP SSE client. LMStudio exposes an OpenAI-compatible REST API at http://localhost:1234/v1. Because the Backend interface only requires returning a *Session (two channels), the implementation sits cleanly inside the existing abstraction without changing any calling code. Activation is controlled by a single env var (MULTICA_LMSTUDIO_URL) rather than exec.LookPath.
Layer 1 — server/internal/daemon/config.go
Add two stanzas after the kiro block (~line 152):
// ── VIBE ──────────────────────────────────────────────────────────────────vibePath:=envOrDefault("MULTICA_VIBE_PATH", "vibe")
if_, err:=exec.LookPath(vibePath); err==nil {
agents["vibe"] =AgentEntry{
Path: vibePath,
Model: strings.TrimSpace(os.Getenv("MULTICA_VIBE_MODEL")),
}
}
// ── LMSTUDIO ──────────────────────────────────────────────────────────────// No CLI to probe — activated by setting MULTICA_LMSTUDIO_URL.// The Path field carries the base URL (e.g. "http://localhost:1234").iflmURL:=strings.TrimSpace(os.Getenv("MULTICA_LMSTUDIO_URL")); lmURL!="" {
agents["lmstudio"] =AgentEntry{
Path: lmURL,
Model: strings.TrimSpace(os.Getenv("MULTICA_LMSTUDIO_MODEL")),
}
}
Update the len(agents) == 0 error message:
returnConfig{}, fmt.Errorf(
"no agent found: install claude, codex, copilot, opencode, openclaw, hermes, "+"gemini, pi, cursor-agent, kimi, kiro-cli, or vibe (PATH), "+"or set MULTICA_LMSTUDIO_URL for a local LMStudio server")
Optionally parse MULTICA_VIBE_ARGS alongside the existing claudeArgs/codexArgs block:
case"vibe":
// Vibe is Anthropic-native; reuse CLAUDE.md like Claude Code.returnwriteMD(dir, "CLAUDE.md", content)
case"lmstudio":
// LMStudio reads no native instruction file; write a generic AGENTS.md// so the task context is present if the model is prompted to check it.returnwriteMD(dir, "AGENTS.md", content)
Base URL of the LMStudio server — setting this activates the runtime
MULTICA_LMSTUDIO_MODEL
local-model
Model name sent in the request body
MULTICA_LMSTUDIO_API_KEY
(empty)
Bearer token for OpenAI-compatible servers that require auth
Open questions for maintainers
1. Vibe wire format. The implementation above assumes Vibe emits the same Claude SDK NDJSON protocol (type: assistant | result | system | user). If Vibe uses a different envelope, only vibeSDKMessage and the switch msg.Type block in stream() need updating — everything else is unchanged.
2. LMStudio version detection. The existing daemon calls DetectVersion (runs <binary> --version) for all CLI agents. LMStudio has no binary to probe, so it skips this automatically. If surfacing the currently loaded model name in the Runtimes UI is desirable, a lightweight GET /v1/models call could be added inside LoadConfig to populate a version string.
3. Scope of "custom runtimes" more generally. The LMStudio pattern (env-var activation, HTTP backend) is a reusable template for any locally-hosted OpenAI-compatible server — Ollama, vLLM, llama.cpp with an HTTP frontend, etc. It may be worth establishing a first-class custom provider type that reads its base URL and model entirely from env vars, rather than shipping one named backend per local server variant.
Files changed summary
File
Change
server/internal/daemon/config.go
+~15 lines: two new detection stanzas, updated error message
server/pkg/agent/agent.go
+4 lines: two switch cases, two launchHeaders entries
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
I have asked Claude for a concept on how that could be done and I think the result is worth sharing.
Maybe lead developers of multica want to pick up on this.
Actually I think it is better to share the concept of the idea than opening a pull request against a fast evolving codebase.
So here we go:
Prompt used with Claude (Sonnet 4.6 High (thinking)
You are a software developer and we want to write an extenstion to the multica project on github. Momentarily so called runtimes (the tools like codex, gemini or claude) are automatically detect once multica is running. I want it to be also able to use vibe from antropic or ma local LMstudio with gemma4. So basically we need custom runtimes, which can be configured. Please look trough the multica code and investigate how this is currently handled and how we could potentially build that extension to the code.
This is the result:
Feature proposal: custom / configurable runtimes (Vibe + LMStudio)
How the current system works
After reading the codebase (around commit
4d110236), the runtime pipeline has five distinct layers:Every existing provider (claude, codex, hermes, gemini, …) touches all five layers. A new provider must be wired into each one.
Two new providers
Vibe (Anthropic Vibe CLI)
Follows the existing CLI pattern exactly. Detection via
exec.LookPath, output assumed to be the same Claude SDK NDJSON stream format (--output-format stream-json). If Vibe's wire format turns out to differ from Claude Code's, only the message-parsing block needs adjusting — the rest of the plumbing is identical.LMStudio (local OpenAI-compatible HTTP server)
A genuinely new pattern: no subprocess, pure HTTP SSE client. LMStudio exposes an OpenAI-compatible REST API at
http://localhost:1234/v1. Because theBackendinterface only requires returning a*Session(two channels), the implementation sits cleanly inside the existing abstraction without changing any calling code. Activation is controlled by a single env var (MULTICA_LMSTUDIO_URL) rather thanexec.LookPath.Layer 1 —
server/internal/daemon/config.goAdd two stanzas after the
kiroblock (~line 152):Update the
len(agents) == 0error message:Optionally parse
MULTICA_VIBE_ARGSalongside the existingclaudeArgs/codexArgsblock:Layer 2 —
server/pkg/agent/agent.goExtend the
New()switch (after thekirocase):Add to
launchHeaders:Layer 3a —
server/pkg/agent/vibe.go(new file)Layer 3b —
server/pkg/agent/lmstudio.go(new file)Layer 4 —
server/internal/daemon/execenv/runtime_config.goInside the existing
switch providerblock:Layer 4 —
server/internal/daemon/execenv/context.goInside the existing
switch providerblock for skills discovery:Layer 5 —
packages/views/runtimes/components/provider-logo.tsxAdd two entries to the existing
providerTypeswitch (placeholder icons until brand assets are available):New environment variables
MULTICA_VIBE_PATHvibevibebinaryMULTICA_VIBE_MODELMULTICA_VIBE_ARGSMULTICA_LMSTUDIO_URLMULTICA_LMSTUDIO_MODELlocal-modelMULTICA_LMSTUDIO_API_KEYOpen questions for maintainers
1. Vibe wire format. The implementation above assumes Vibe emits the same Claude SDK NDJSON protocol (
type: assistant | result | system | user). If Vibe uses a different envelope, onlyvibeSDKMessageand theswitch msg.Typeblock instream()need updating — everything else is unchanged.2. LMStudio version detection. The existing daemon calls
DetectVersion(runs<binary> --version) for all CLI agents. LMStudio has no binary to probe, so it skips this automatically. If surfacing the currently loaded model name in the Runtimes UI is desirable, a lightweightGET /v1/modelscall could be added insideLoadConfigto populate a version string.3. Scope of "custom runtimes" more generally. The LMStudio pattern (env-var activation, HTTP backend) is a reusable template for any locally-hosted OpenAI-compatible server — Ollama, vLLM, llama.cpp with an HTTP frontend, etc. It may be worth establishing a first-class
customprovider type that reads its base URL and model entirely from env vars, rather than shipping one named backend per local server variant.Files changed summary
server/internal/daemon/config.goserver/pkg/agent/agent.goserver/pkg/agent/vibe.goserver/pkg/agent/lmstudio.goserver/internal/daemon/execenv/runtime_config.goserver/internal/daemon/execenv/context.gopackages/views/runtimes/components/provider-logo.tsxAll reactions