Skip to content

Providers

A provider is an AI agent CLI tool that Magia orchestrates. Magia does not call the model APIs directly — instead, it spawns and manages the CLI processes that those tools provide, intercepts their output streams, and routes events into the UI.

ProviderCLI binaryStatusProcess model
Claude CodeclaudeFully supportedPersistent stdin-streaming
Gemini CLIgeminiSupportedTurn-based (spawn per message)
Codex CLIcodexSupportedTurn-based (spawn per message)

Persistent providers (Claude Code) start one long-running process per session. Messages are written to the process’s stdin; events stream back on stdout. The process lives until the session is stopped or the app exits.

Turn-based providers (Gemini CLI, Codex CLI) run once per prompt and exit after responding. When you send a message, Magia spawns a new process with --resume flags to continue the conversation. Process creation is deferred — for turn-based providers Magia does not spawn anything at session creation time; the first spawn happens when you send the first message.

On startup (and whenever the providers list is refreshed), Magia calls the detect_installed_providers Tauri command. The Rust backend resolves each CLI binary using a multi-strategy search:

  1. In-memory cache — instant on repeat calls within the same app process.
  2. Settings override — a previously saved path from providerBinaryPaths in settings.json.
  3. which crate — cross-platform PATH lookup.
  4. Platform fixed locations — e.g. ~/.local/bin, /opt/homebrew/bin, /usr/local/bin on macOS.
  5. nvm paths — scans ~/.nvm/versions/node/*/bin/ for Node-based CLIs.
  6. Login-shell fallback — runs zsh -lc "which <binary>" then bash -lc "which <binary>" to pick up shell-managed installations that are not on the GUI app’s PATH.

When a binary is found via steps 3–6 the resolved path is automatically persisted to providerBinaryPaths in settings so the next lookup is instant.

Each detected provider returns a ProviderStatus object that includes:

  • installed — whether the binary was found
  • binary_path — absolute path on disk
  • auth_status"ready", "not_authenticated", or "not_installed"
  • models — list of available model IDs
  • capabilities — feature flags (see Provider capabilities)

Detection alone does not enable a provider. A provider must be activated before Magia will use it for new sessions. Activation:

  1. Confirms the CLI binary is present and the user is authenticated (fails with an actionable error message if not).
  2. Marks the provider as active in AppSettings.active_providers.
  3. Syncs the flag into the runtime discovery system so new session discovery includes that provider’s session directories.

Deactivation reverses this: the provider is removed from active_providers and the discovery cache is invalidated.

Magia intercepts session events from Claude Code through a hooks injection system. When a Claude Code session is started, Magia injects an MCP server configuration and sets --permission-prompt-tool to route permission requests back through Magia’s permission handler.

For session lifecycle events (tool calls, notifications, session start/stop, etc.), Magia registers itself as a hooks listener via Claude Code’s hooks system. Hook events arrive as JSON payloads over a Unix socket. The Rust backend listens on this socket, parses the hook event type and payload, normalizes it into an AgentEvent struct, and emits a agent-event Tauri event that the frontend React store consumes.

The hook socket path is $TMPDIR/magia-{uid}/hooks.sock. The permission socket is $TMPDIR/magia-{uid}/permissions.sock.

Hook events that Magia processes include:

Hook eventWhat Magia does
PreToolUseEmits to frontend for live tool-call display
PostToolUseEmits tool result and updates diff views
NotificationTriggers desktop notifications if enabled
StopMarks session as idle, captures final metrics
SessionStartRecords PID → session mapping in the live-sessions index
SessionEndClears live-session entry, finalizes status
UserPromptSubmitUsed for eager title extraction (titleSource: "prompt")

Gemini CLI and Codex CLI use a simpler stdout-parsing approach for event extraction rather than the hooks system.

Each provider exposes a capabilities object. Key flags:

CapabilityClaudeGeminiCodex
headless_streamingyesyesyes
mcpyesyesyes
hooksyesyesno
permissionsyesnono
session_resumeyesyesyes
cost_trackingyesnono
sandboxnoyesyes
image_inputyesnono
project_instructionsCLAUDE.mdGEMINI.mdAGENTS.md

The UI uses these flags to conditionally show or hide features. For example, the cost display is only rendered for providers where cost_tracking is true.

Each provider supports multiple named accounts. An account is an isolated configuration identity — it has its own configDir and optional environment variable overrides. This lets you switch between, for example, a personal and a work Claude subscription without logging in and out.

Accounts are managed under Settings → Providers. Per-workspace account overrides let different workspaces automatically use different accounts (see Workspaces).

The check_provider_auth_status command reads the auth state from the provider’s config directory and reports loggedIn, authMethod, and apiProvider so Magia can surface which account is active without re-running authentication.

Provider session transcripts live under each provider’s own directory:

ProviderDefault session directory
Claude Code~/.claude/projects/
Gemini CLI~/.gemini/tmp/
Codex CLI~/.codex/sessions/

Magia’s discovery system scans these directories to import sessions started outside of Magia (e.g. from the terminal). Discovery is enabled per-provider and respects the active-providers setting.