Add a deus connect Connector

SkillAI & models

Onboard a `deus connect` connector — a way to route Claude Code sessions to non-Claude models (e.g. GPT via CLIProxyAPI) alongside normal Claude access. Generic orchestrator over whichever connector is selected.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Add a deus connect Connector skill

What this skill tells your AI

The instructions your AI receives, as published by sliamh11/deus in .claude/skills/add-connector/SKILL.md and read by ahel’s review.

deus connect launches the real, unmodified claude binary with which upstream model answers its requests redirected via ANTHROPIC_BASE_URL — identity, vault/memory context, preferences, and portable skills stay intact, exactly like a normal deus/deus home session. This is separate from Deus's own container-agent backend adapters (deus codex, DEUS_AGENT_BACKEND) — see docs/decisions/backend-neutral-agent-runtime.md's note near the Parity Matrix.

This skill is generic over any registered connector (ships with cliproxy-oauth and ollama) — adding another connector in the future changes connectors/providers/, not this skill.

Four distinct "ollama" surfaces exist in this repo — do not conflate them when guiding a user:

  1. deus connect ollama (this skill, this section) — routes a Claude Code session directly to a local Ollama instance via its native Anthropic-API mode. No proxy, no daemon management.
  2. deus provider ollama / deus fcc (deus-cmd.sh's fcc proxy system) — a different mechanism: routes through fcc-server's OpenAI-compat translation proxy. Also reaches a local Ollama install, but via proxy translation, not a direct native-mode redirect.
  3. deus backend set ollama — a persisted DEUS_AGENT_BACKEND value. Not yet wired to a working CLI agent; its stub error message points here (deus connect ollama) and to deus provider ollama/fcc.
  4. .claude/skills/add-ollama-tool — an unrelated feature: adds an Ollama MCP server so a container agent (not a deus connect session) can offload tasks to a local model.

Phase 1: Pre-flight

python3 scripts/connectors_cli.py list

Shows every registered connector and whether it's already configured. If the target connector shows configured (e.g. a repeat run, or a machine inherited from another user), still walk through Phase 2 (select) and Phase 3 (risk acknowledgment) — Phase 3 is required every time, regardless of configuration state, per its own rule; skipping it here would let an already-configured install proceed straight to a real connector launch without ever showing the risks. Only Phases 4-8 (install/authenticate/ write-config) are skippable on an already-configured connector — jump from Phase 3 straight to Phase 9 (Verify) unless the user explicitly wants to reconfigure.

cliproxy-oauth-specific one-time check, added for the model-picker- visibility follow-up — this is a deliberate, documented exception to this skill's normal connector-generic design, not a pattern to copy for a future connector. An already-configured cliproxy-oauth install predating this feature has no claude-gpt-* discovery aliases in its real config, and the normal skip straight to Phase 9 would never surface the migration step needed to add them. Before jumping to Phase 9 on an already-configured cliproxy-oauth, run:

if [ -f ~/.config/deus/connectors/cliproxy/config.local.yaml ]; then
  grep -c 'claude-gpt-' ~/.config/deus/connectors/cliproxy/config.local.yaml
else
  echo 0
fi

If the count is below 3 (a fresh install has 0; a partially-applied manual edit could have 1 or 2 — -c counts matches rather than a bare presence check specifically so a partial edit isn't mistaken for a complete one), walk through Phase 7's "Already configured? Add discovery aliases manually" subsection before continuing to Phase 9 — every other Phase 4-8 step still stays skipped.

Second cliproxy-oauth-specific one-time check, added for the per-model reasoning-effort feature — same reasoning as the check above, same deliberate exception. An already-configured install predating this feature has no payload.override block, and the normal skip straight to Phase 9 would never surface the migration step needed to add it:

if [ -f ~/.config/deus/connectors/cliproxy/config.local.yaml ]; then
  grep -c 'reasoning\.effort' ~/.config/deus/connectors/cliproxy/config.local.yaml
else
  echo 0
fi

If the count is below 3, walk through Phase 7's "Already configured? Add reasoning-effort overrides manually" subsection before continuing to Phase 9 (in addition to the discovery-alias check above, if that one also applies) — every other Phase 4-8 step still stays skipped.

Also for any already-configured cliproxy-oauth install (regardless of the check above): if it predates the credential-fallthrough fix, it may have gone through the old (now-deleted) Phase 8 flow, which left a plaintext copy of the connector's inbound key sitting in ~/.claude.json's customApiKeyResponses.approved array — orphaned and functionally dead once this connector authenticates via ANTHROPIC_AUTH_TOKEN, but still real credential material at rest. Cleanup for this is tracked as a separate follow-up (not yet built) — flag it to the user rather than hand-editing their ~/.claude.json yourself.

Phase 2: Which connector

AskUserQuestion: Which connector do you want to set up?

  • cliproxy-oauth — CLIProxyAPI, OAuth-login, reuses your ChatGPT/Codex subscription for GPT models alongside Claude.
  • ollama — routes to a locally-pulled Ollama model via its native Anthropic-API mode. No OAuth, no proxy daemon (Ollama runs its own service already).

Phase 3: Required risk acknowledgment

Not a footnote — block progression on explicit confirmation, every time, for every future user. Risks 2-5 below are structural to deus connect itself and apply to every connector; risk 1 is cliproxy-oauth-specific (OAuth-subscription reuse — Ollama has no OAuth token extraction, this risk class does not apply to it), risk 6 is cliproxy-oauth-specific, and risk 7 is ollama-specific. Show the set that matches the connector selected in Phase 2:

deus connect risk disclosure:

  1. (cliproxy-oauth only) OAuth-subscription reuse is a real, non-zero, documented account-ban risk class. This connector extracts an OAuth token from your ChatGPT/Codex subscription and reuses it for a separate HTTP client — see examples/multi-model-cliproxyapi/README.md's "Known open risks" for the full account, including real dated ban reports in CLIProxyAPI's own issue tracker for other providers. Unlike a config mistake, there is no rollback if this fires. This leg was dormant for every install predating the credential-fallthrough fix (a ~/.claude.json approval-check mismatch meant the connector's key was silently never used, so this OAuth leg was never actually exercised) — it becomes genuinely live for the first time once that fix lands, not something that "was already happening."
  2. Anthropic explicitly disclaims support for routing Claude Code to non-Claude models through any gateway (https://code.claude.com/docs/en/llm-gateway) — a support-scope statement independent of whether this is configured correctly.
  3. Connector sessions are discoverable via a bare claude's resume picker. --name tags the session (connect:<id> (non-Claude)) so it's identifiable, not invisible or inaccessible — native Claude Code session-resume is not isolated between a connector session and a bare one.
  4. A nested claude/deus claude launched from inside a connector session inherits that session's model redirection. Once ANTHROPIC_* env vars are set for the launched session, any subprocess it spawns (e.g. a Bash tool call running claude again) inherits them — a plain Unix process-inheritance property, no mechanism exists to prevent it. Narrow in practice (requires deliberately launching another interactive session mid-connector-session).
  5. A connector session gets the same no-prompt tool execution as a trusted Claude session, driven by a model outside Anthropic's support scope. deus connect launches through the same launch_claude every other session uses; if bypass_permissions is true in your Deus preferences (the default), a connector session runs with --dangerously-skip-permissions like any other Deus session — full, unprompted tool execution, just with a non-Claude, unsupported model driving it instead of Claude. Each connector's inline subagents are scoped to Read/Grep/Glob/Bash/WebSearch/WebFetch (not the session's full tool set), but the top-level connector session itself is not additionally restricted beyond your normal Deus bypass setting.
  6. (cliproxy-oauth only) /model surfaces GPT model names directly in Claude Code's native picker, labeled "From gateway", rather than only being reachable by typing an exact alias. Applies to every fresh setup (the tracked template always includes the picker-discovery aliases now — not an opt-in); an already-configured install only gains this once its real config is migrated per Phase 7's "Already configured" step. Not a new exposure either way — the same models were already reachable via ANTHROPIC_MODEL/typed /model — this just makes it easier to notice at a glance which model is actually selected, which is a mitigation of confusion, not a new risk in its own right. Discovery itself never fired at all before the credential-fallthrough fix (see risk 1) — this goes from a picker showing nothing extra to one showing exactly these 3 curated models, not from an unfiltered catalog down to 3.
  7. (ollama only) A small/weak local model can silently produce lower-quality or subtly wrong tool-use sequences — misread instructions, bad tool-call arguments, incomplete reasoning — while running under the exact same full bypass-permission trust as Claude (risk 5). This is a different risk profile than cliproxy-oauth's, not a lesser version of it: it's about the model's own capability silently degrading task correctness, not about where the model comes from, and it carries no distinct warning signal beyond noticing the output itself looks off.
  8. (cliproxy-oauth only) A background/--bg session launched from inside a connector session loses the model redirect. Claude Code strips ANTHROPIC_AUTH_TOKEN (this connector's credential mechanism) when starting a background session against a custom ANTHROPIC_BASE_URL — a background session spawned this way silently falls back to your normal Claude access instead of the connector's model, rather than erroring or redirecting. Disclosed as a known consequence, not something this connector tries to prevent.

AskUserQuestion: Confirm you understand and accept the risks above (risks 6 and 8 apply only to cliproxy-oauth; risk 7 applies only to ollama) before continuing?

  • Yes, continue
  • No, cancel setup

Stop here if the user declines.

Phase 4: Install the engine

cliproxy-oauth:

python3 scripts/connectors_cli.py install-check cliproxy-oauth

If not installed, tell the user:

The cli-proxy-api binary isn't on your PATH. Build or download it from https://github.com/router-for-me/CLIProxyAPI (see the upstream repo's releases/instructions).

After installation, verify: cli-proxy-api --version

Require explicit confirmation before proceeding once installed — never silently auto-fetch a binary that's about to hold real OAuth tokens.

Re-run the install-check after the user confirms installation is done.

ollama:

python3 scripts/connectors_cli.py install-check ollama

Checks only that the ollama binary is on PATH — deliberately does NOT probe whether the background service is actually running, since at this point Phase 5 hasn't collected the user's real host yet and a live check here could only ever reach the default localhost:11434 (silently wrong for a non-default-host setup, with no way to recover except repeating the same failing check). Service liveness — against the real configured host — is checked in Phase 9's verify-setup, after Phase 7 writes it. If not installed, tell the user to install Ollama (https://ollama.com/download); if it's installed but the service isn't running (menu-bar app on macOS / systemd unit on Linux), Phase 9 will catch that instead, with the real host. This connector never manages the Ollama service itself — no daemon to start on the user's behalf, unlike cliproxy-oauth's launchd plist.

ollama-only: context window prerequisite. Ollama defaults its context window by available VRAM — under 24 GiB VRAM defaults to 4k, well below what a real Deus session needs (Ollama's own Claude Code guidance recommends 64k+). Tell the user to raise OLLAMA_CONTEXT_LENGTH to at least 64000 before continuing:

  • macOS menu-bar app: Settings → context-length slider.
  • CLI/systemd-managed install: export OLLAMA_CONTEXT_LENGTH=65536 in the service's environment, then restart the service.

Phase 9's verify-setup checks this automatically (via /api/ps's context_length) and fails if it's still too small — but flag it now so the user isn't surprised by a failed verify later.

Phase 5: Collect config values

cliproxy-oauth:

  • Inbound key — generate one rather than asking the user to invent it: python3 -c "import secrets; print(secrets.token_urlsafe(24))". This is what Claude Code authenticates to the local proxy with.
  • Route Opus/Claude through the same proxy too? Optional. If yes, collect a real, official Anthropic API key (not OAuth) for the claude-api-key leg.
  • Confirm the real upstream Codex/GPT model id strings. The tracked placeholder (connectors/cliproxy/config.yaml) ships with illustrative names (gpt-5.6-sol/gpt-5.6-terra/gpt-5.6-luna) — not confirmed real IDs for the user's account/plan. These get hand-edited into oauth-model-alias.codex[].name in the written config (Phase 7) — the alias values (sol/terra/luna-max, and their claude-gpt-* picker- discovery twins) stay fixed; only the name values (real upstream ids) vary per account. Each claude-gpt-* entry's name must be set to the exact same value as its plain-alias twin (e.g. claude-gpt-sol's name = sol's name) — a mismatch wouldn't error, CLIProxyAPI would just silently treat them as two different upstream models.
  • Reasoning effort per model — CLIProxyAPI force-sets the outbound Codex reasoning.effort for each of the 3 GPT models via a config-side override (confirmed live: it overrides whatever Claude Code itself sends, regardless). Tracked-template defaults are sol=high, terra=high, luna=xhigh (Codex's ceiling — there's no max level on this protocol). Offer the user each default and let them change any of them. Accepted values: low/medium/high/xhigh.
  • Default model for the session itself when no /model switch has been made — recommend luna-max (max reasoning effort) unless the user prefers otherwise. This is separate from picker visibility: the plain aliases (not the claude-gpt-* twins) are what ANTHROPIC_MODEL uses.
  • Picker visibility for the 3 GPT models — included automatically, not a choice to make here. The tracked template (Phase 7) already bakes in a claude--prefixed alias + display-name per GPT model, and write-config always writes the full template verbatim — there's no partial-write mechanism to selectively drop these three entries, so don't present skipping them as an option. This is low-risk by design (see Phase 3 risk 6): purely additive, no real alias sacrificed, no new credential exposure. If a user genuinely wants /model to show nothing extra, they can remove the 3 claude-gpt-* entries from their real config.local.yaml by hand after setup — but that's a post-setup edit, not a Phase 5 choice.

ollama:

  • Which locally-pulled model backs deus-ollama-local? Run ollama list and show the user the real, currently-pulled models — never invent a plausible-looking tag the way cliproxy-oauth's placeholder does for GPT ids (that's necessary there because a remote account's real upstream id can't be locally enumerated; here it can, so there's no reason to guess). If nothing is pulled yet, help the user ollama pull <model> first.
  • Host — default http://localhost:11434, only ask if the user runs Ollama on a non-default host/port.
  • No inbound key, no OAuth leg, no launchd config — this connector doesn't need them.

Phase 6: Authenticate

cliproxy-oauth:

python3 scripts/connectors_cli.py authenticate cliproxy-oauth

Runs cli-proxy-api --codex-login --config <local config> — opens a browser for OAuth. Running headless/remote instead of a local desktop? The underlying engine supports --no-browser with a printed URL; if that's needed, tell the user to run the login step manually with that flag instead of through this script, then continue to Phase 7.

ollama:

python3 scripts/connectors_cli.py authenticate ollama

No-op — always returns success. No OAuth/login concept for locally-pulled models. (Ollama's optional hosted "cloud" model aliases require ollama signin, out of scope for this connector's current scope.)

Phase 7: Write config

cliproxy-oauth (+ launchd daemon):

echo '<json values>' | python3 scripts/connectors_cli.py write-config cliproxy-oauth

Where <json values> is a JSON object:

{
  "inbound_key": "<generated key from Phase 5>",
  "anthropic_api_key": "<optional, only if the user opted in>",
  "model_map": {"deus-gpt-sol": "sol", "deus-gpt-terra": "terra", "deus-gpt-luna": "luna-max"},
  "default_model_alias": "luna-max",
  "effort_map": {"deus-gpt-luna": "xhigh"},
  "binary_path": "<absolute path from: command -v cli-proxy-api>"
}

effort_map is optional — only include the subagents whose effort level the user changed from the tracked template's defaults (Phase 5). Omitting it, or omitting a specific subagent's key, leaves that subagent at its template default (sol=high, terra=high, luna=xhigh).

This writes the real config to ~/.config/deus/connectors/cliproxy/config.local.yamloutside any project root a container agent could ever have mounted (confirmed against src/project-registry.ts:155-174 + src/container-mounter.ts:76-102: the tracked placeholder at connectors/cliproxy/config.yaml stays in-repo and safe to commit; the real values never do) — and the launchd plist (~/Library/LaunchAgents/com.deus.connectors.cliproxy-oauth.plist, RunAtLoad+KeepAlive, macOS-only for now) with a fully home-expanded absolute --config path (launchd execs directly with literal argv strings, never shell-expanding ~).

If write-config errors with "A launchd job already exists at ... with different settings": something else — possibly the user's own, unrelated launchd job — already occupies that exact path. This is a refusal-to-overwrite safety check (_write_launchd_plist), not a bug. Show the user the error's own ProgramArguments detail and ask them to move or remove that file themselves before retrying — never delete or overwrite it on their behalf.

Then hand-edit the real upstream model id strings collected in Phase 5 into ~/.config/deus/connectors/cliproxy/config.local.yaml's oauth-model-alias.codex[].name fields and the matching payload.override[].models[].name field for each GPT model (the write-config call above does not touch either — only deus-model-map, api-keys, claude-api-key, default-model-alias, and — new for the reasoning-effort feature — payload.override[].params["reasoning.effort"] when effort_map was given). Keep each model's oauth-model-alias.name and payload.override[].models[].name identical, same requirement as the claude-gpt-* picker-discovery twin's name — a mismatch wouldn't error, the effort override would just silently stop matching any real request.

Load the daemon:

launchctl load ~/Library/LaunchAgents/com.deus.connectors.cliproxy-oauth.plist
launchctl kickstart -k gui/$(id -u)/com.deus.connectors.cliproxy-oauth

Already configured (cliproxy-oauth)? Add discovery aliases manually

For an existing config.local.yaml predating the model-picker- visibility feature (reached via Phase 1's check on an already-configured cliproxy-oauth) — do NOT re-run write-config above: it always rebuilds the file from the tracked template, which would discard the real upstream name values you already hand-edited in. Instead, hand-edit ~/.config/deus/connectors/cliproxy/config.local.yaml directly, adding 3 new entries under oauth-model-alias.codex[] — reuse the SAME real upstream name value already present for each existing plain alias (sol/terra/luna-max); only alias (add a claude- prefix) and display-name are new:

oauth-model-alias:
  codex:
    # ... existing sol/terra/luna-max entries -- do not remove or modify ...
    - name: "<same real name as the existing sol entry, verbatim>"
      alias: "claude-gpt-sol"
      display-name: "GPT Sol"
    - name: "<same real name as the existing terra entry, verbatim>"
      alias: "claude-gpt-terra"
      display-name: "GPT Terra"
    - name: "<same real name as the existing luna entry, verbatim>"
      alias: "claude-gpt-luna"
      display-name: "GPT Luna (max)"

No daemon restart needed — CLIProxyAPI watches its config file for changes and reloads automatically on write (confirmed: internal/watcher/events.go's fsnotify-based watcher), and Claude Code's own gateway discovery re-queries /v1/models on each new session start, so the very next deus connect cliproxy-oauth launch picks this up.

Already configured (cliproxy-oauth)? Add reasoning-effort overrides manually

For an existing config.local.yaml predating the per-model reasoning-effort feature (reached via Phase 1's second check on an already-configured cliproxy-oauth) — same rule as the discovery-alias subsection above: do NOT re-run write-config, for the same reason (it rebuilds the file from the tracked template, discarding the real upstream name values already hand-edited in). Instead, hand-edit ~/.config/deus/connectors/cliproxy/config.local.yaml directly, adding a top-level payload.override block — reuse the SAME real upstream name value already present for each existing plain alias (sol/terra/ luna-max), never the tracked template's placeholder names:

payload:
  override:
    - models:
        - name: "<same real name as the existing sol entry, verbatim>"
          protocol: "codex"
      params:
        "reasoning.effort": "high"
    - models:
        - name: "<same real name as the existing terra entry, verbatim>"
          protocol: "codex"
      params:
        "reasoning.effort": "high"
    - models:
        - name: "<same real name as the existing luna entry, verbatim>"
          protocol: "codex"
      params:
        "reasoning.effort": "xhigh"

Ask the user for each level the same way Phase 5 would for a fresh setup (defaults shown above; accepted values low/medium/high/ xhigh). No daemon restart needed — same fsnotify-based config watcher as the discovery-alias subsection above, since it's the same config file.

ollama (no daemon):

echo '<json values>' | python3 scripts/connectors_cli.py write-config ollama

Where <json values> is a JSON object:

{
  "host": "http://localhost:11434",
  "model_map": {"deus-ollama-local": "<real pulled model tag from Phase 5>"},
  "default_model_alias": "<same real pulled model tag>"
}

Writes only ~/.config/deus/connectors/ollama/config.local.yaml — no launchd plist, no daemon to load or kickstart. Ollama's own service is already running (confirmed in Phase 4) and this connector never manages it.

Phase 8: Validate subagent definitions

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
51
Forks
4
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
add-connector-sliamh11
Source
github.com/sliamh11/deus