Choosing and configuring a provider¶
A provider is what cloop uses when it needs a model: a local CLI, a hosted API, or a server on your own machine. The plan, the tasks and the executors work the same whichever provider you pick, and you can switch to another one later with a single command.
- The backends
- Setting one up
- Checking what is configured
- How a provider is chosen
- How a model is chosen
- Reasoning effort
- GitHub Copilot
- Environment variables
- Named profiles
- Role-based routing
The backends¶
| Name | Talks to | Credential | Default model |
|---|---|---|---|
claudecode |
the claude CLI as a subprocess |
whatever the CLI is already signed in with | none (the CLI decides) |
copilot |
the GitHub Copilot CLI (copilot) as a subprocess |
whatever the CLI is already signed in with | none (the CLI decides) |
anthropic |
https://api.anthropic.com/v1 |
ANTHROPIC_API_KEY |
claude-opus-4-6 |
openai |
https://api.openai.com/v1 (Chat Completions) |
OPENAI_API_KEY |
gpt-4o |
ollama |
http://localhost:11434 |
none | llama3.2 |
claudecode is the default. Like copilot, it holds no credential of its
own. It runs the claude binary once per call and uses the sign-in that CLI
already has, so you pay through a Claude Code subscription instead of metered
API billing. cloop looks for claude on PATH first, then at
~/.local/bin/claude, ~/.npm-global/bin/claude and /usr/local/bin/claude,
so it also works when the dashboard is started by a service manager with a
minimal environment. claudecode has no default model. cloop passes --model
only when one is set, and otherwise the CLI chooses. On a single-user install
the sign-in is the machine's. On a hub with SSO it is the sign-in of the user
who made the request, because each identity has its own Claude login (see
per-user Claude Code logins).
copilot works the same way with GitHub Copilot. It runs the
GitHub Copilot CLI once per call, as an agent with its own
tools in the project directory, using the sign-in that CLI already has. You pay
through a Copilot seat instead of per token.
anthropic gives you the same family of models as claudecode over the
HTTP API, billed per token. Pick it when you want to use an API key instead of a
subscription. openai uses the Chat Completions API. Set openai.base_url
to use any other server that implements the same endpoint, such as Azure
OpenAI, a llama.cpp server or a gateway. This is the supported way to use
OpenAI-compatible backends. ollama needs no key and talks to a server on
your own machine, so nothing leaves it.
There is also a mock provider, accepted by cloop config set provider and
by cloop run --mock. It answers from .cloop/mock_responses.yaml (or
mock.responses_file) and by default returns TASK_DONE. It makes no calls and
costs nothing. Use it to test the shape of a plan or a CI pipeline, and for
nothing else.
Setting one up¶
Configuration lives in .cloop/config.yaml. cloop writes the file with mode
0600 because it may contain an API key. Use cloop config set to change it:
it checks each value before saving and rejects unknown keys.
cloop config set provider anthropic
cloop config set anthropic.api_key sk-ant-...
cloop config set anthropic.model claude-opus-4-6
These are all the provider keys that cloop config set accepts:
| Key | Notes |
|---|---|
provider |
one of anthropic, openai, ollama, claudecode, copilot, mock. Anything else is rejected |
anthropic.api_key / .model / .base_url |
|
openai.api_key / .model / .base_url |
base_url is how you reach an OpenAI-compatible server |
ollama.base_url / .model |
|
claudecode.model |
|
claudecode.effort |
low, medium, high, xhigh, max (see Reasoning effort) |
copilot.model |
auto lets Copilot pick per request |
copilot.effort |
the same values as claudecode.effort |
mock.responses_file / mock.default |
Some provider settings have no cloop config set key, so you edit them in
.cloop/config.yaml directly:
- the inference parameters:
temperature,top_p,max_tokens, andfrequency_penaltyfor OpenAI. Theanthropicprovider leaves outtemperatureandtop_pfor the Claude models that refuse them: every Fable model, Claude Opus 4.7 and later, Claude Sonnet 5 and later, and Claude Haiku 5.5. - the Claude Code subscription caps:
claudecode.max_weekly_pct,max_five_hour_pct,max_weekly_opus_pctandmax_weekly_sonnet_pct. You can also edit these in the dashboard. A run stopped by a cap resumes by itself when the window reopens (see Resuming a capped run). claudecode.background.*and the matchingcopilot.background.*
cloop config show prints the configuration in effect, with API keys masked.
Every save is also copied into .cloop/state.db. If the two drift apart,
cloop config diff compares them and cloop config sync reconciles them.
Checking what is configured¶
cloop providers # what is registered, what is configured, what is default
cloop providers --test # ...and does it actually answer
The listing marks the default with * and shows each backend's endpoint and
resolved model. "Configured" only means that a credential is present.
claudecode and ollama always show as configured because neither needs one,
and copilot shows as configured when its CLI is installed. To find out whether
a provider works, add --test. It creates each provider and asks it to reply
OK, with a 30-second timeout. A missing claude binary, a copilot that
isn't signed in or an unreachable Ollama shows up as FAIL with the underlying
error.
cloop providers reads the configuration through the same loader as every
other command, and that loader only applies the unprefixed environment
variables. A key exported as CLOOP_ANTHROPIC_API_KEY is used by cloop run
but doesn't show up here. See Environment variables.
How a provider is chosen¶
cloop run uses the first of these that is set:
--provideron the command line (--mockis shorthand for--provider mock).provider:in.cloop/config.yaml, afterCLOOP_PROVIDERand any--profileoverlay have been applied to it.- The provider saved in project state, set by
cloop init --provideror by the dashboard's Provider picker. - Auto-detection:
ANTHROPIC_API_KEYorCLOOP_ANTHROPIC_API_KEYselectsanthropic. OtherwiseOPENAI_API_KEYorCLOOP_OPENAI_API_KEYselectsopenai. If neither is set, cloop usesclaudecode.
In practice step 2 almost always decides. When .cloop/config.yaml doesn't
exist, the loader returns the built-in defaults, which already contain
provider: claudecode. Steps 3 and 4 are only reached when the file exists and
its provider: key is empty. If you want the provider saved in project state to
be used, leave that key blank.
At the start of the run cloop saves the chosen provider in project state, so the
next cloop run without flags uses the same one.
How a model is chosen¶
cloop chooses the model separately from the provider. It uses the first of these that is set:
| Source | |
|---|---|
| 1 | --model on the command line |
| 2 | CLOOP_MODEL in the environment |
| 3 | the per-provider key: anthropic.model, openai.model, ollama.model, claudecode.model, copilot.model |
| 4 | the model saved in project state (cloop init --model, or the dashboard's picker) |
| 5 | the provider's own default |
The provider's own default is claude-opus-4-6 for anthropic, gpt-4o for
openai and llama3.2 for ollama. claudecode and copilot have none. If
no model is set, cloop passes no --model to the CLI, and the CLI uses its own
default.
For claudecode and anthropic, the dashboard's model pickers and
cloop init --interactive offer every Claude model Anthropic serves: Claude
Fable 5.2, 5.1 and 5, Claude Opus 5.5, 5, 4.8, 4.7, 4.6 and 4.5, Claude Sonnet
5.5, 5, 4.6 and 4.5, and Claude Haiku 5.5 and 4.5. Their IDs follow one
pattern, for example claude-fable-5-2, claude-opus-5-5 and
claude-haiku-4-5. Any other model ID works too: pass it with --model or
cloop config set, or type it in the wizard. Claude Mythos is not offered
because Anthropic serves it only to organizations in its verification programs.
cloop only reads the per-provider key of the provider in use. Setting
openai.model changes nothing while the project runs on anthropic, so you can
keep all of them configured at once.
Reasoning effort¶
claudecode and copilot accept a reasoning-effort level and pass it to the
CLI unchanged: as --effort to claude, and as --reasoning-effort to
copilot. Valid values are low, medium, high, xhigh and max. If no
level is set, the CLI uses its default.
cloop run --effort high
cloop config set claudecode.effort high # the project-wide default
cloop init --effort high "…" # saved into project state
--effort takes precedence over claudecode.effort (or copilot.effort) in
the config, which takes precedence over the effort saved in project state. An
invalid --effort is an error. An invalid value in the file is reported on
stderr and ignored, so a bad value in the YAML can't make every CLI call fail.
The other backends ignore this setting. OpenAI's o-series models do get a
reasoning_effort, but cloop derives it from its extended-thinking budget, not
from --effort, and only for models whose name begins with o1, o3 or
o4-mini.
With --think, the anthropic provider asks Claude Opus 4.6, Claude Sonnet 4.6
and every later Claude model for adaptive thinking, where the model decides how
much to think. Only older models accept a fixed budget, so --think-budget is
sent to them alone. The Fable models and Claude Opus 5.5 think on every call,
with or without --think.
GitHub Copilot¶
The copilot provider runs the GitHub Copilot
CLI. Like claude, it is
an agent harness: it edits files, runs commands and searches the project
itself. Install it and sign in once, as the user that cloop runs as:
npm install -g @github/copilot # or: curl -fsSL https://gh.io/copilot-install | bash
copilot login # or export COPILOT_GITHUB_TOKEN=github_pat_…
cloop config set provider copilot
cloop providers --test # copilot … OK
cloop looks for copilot on PATH, then at ~/.local/bin/copilot (where the
install script puts it when run as a normal user), ~/.npm-global/bin/copilot,
/usr/local/bin/copilot and /opt/homebrew/bin/copilot.
Signing in. cloop keeps no Copilot credential of its own, and on a hub
without single sign-on it adds none to a run on its host. The CLI uses the first
of these it finds: COPILOT_GITHUB_TOKEN, GH_TOKEN, GITHUB_TOKEN, the
account stored by copilot login, and the GitHub CLI's account. On a hub with
single sign-on, each person's runs sign in with their own credential instead
(see below).
A token must act for a person with a Copilot seat. Use a fine-grained personal
access token with the Copilot Requests permission, or an OAuth token. Classic
ghp_ tokens are not accepted. If the environment may also contain a GitHub
token for something else, export COPILOT_GITHUB_TOKEN instead of GH_TOKEN,
because the CLI reads it first. With COPILOT_PROVIDER_BASE_URL set, the CLI
uses a model provider of your own and needs no GitHub sign-in. This is "bring
your own key", and it works with OpenAI-compatible, Azure or Anthropic
endpoints, including Ollama. See copilot help providers.
How cloop runs it. cloop starts the CLI once per call in prompt mode, with
the prompt on stdin and --silent, so it reads only the agent's answer,
including the TASK_DONE / TASK_FAILED / TASK_SKIPPED signal. Every tool is
allowed (--allow-all-tools --allow-all-paths --allow-all-urls), in the same
way that claudecode runs with bypassPermissions, because nobody is there to
approve tool use. --no-ask-user stops the agent from pausing to ask questions.
COPILOT_AUTO_UPDATE is false unless your environment sets it, so a run uses
the CLI version that was installed.
The model and effort are passed as --model and --reasoning-effort. Each
conversation gets an ID (--session-id), so when an agent ends its turn before
the task is finished, cloop hands the task back to it in the same conversation
(--resume), as with claudecode. Token usage comes from the CLI's own usage
report and is recorded like any other provider's, with the model auto
replaced by the model Copilot chose. The review gate's reviewer runs with only
the reading tools (view, grep, glob), no built-in MCP servers, and the
CLI's path and URL checks left on. Background work the agent leaves running is
waited for in the same way as for claudecode, under copilot.background (see
Background work left by an
agent).
Models. Which models you can use depends on your Copilot plan. To list them,
start copilot and type /model. The dashboard's picker suggests auto,
claude-sonnet-4.5, claude-opus-4.5, claude-haiku-4.5, gpt-5.4 and
gpt-5-mini, and it also keeps a model saved on the project that isn't in that
list. If your plan doesn't offer the model, the call fails with the CLI's own
error.
In a sandbox. A copilot project bound to an executor that isolates it from
the hub needs the CLI installed where the task runs, and a credential granted to
the project.
- In a container (a container executor, a device in container mode, or a
virtual executor), use
ghcr.io/blechschmidt/cloop-harness-copilot, the published harness image with the Copilot CLI added. It is a separate variant because the CLI nearly doubles the image size (+445 MB unpacked, +217 MB pulled; see the published images). The defaultcloop-harnessimage contains onlyclaude, and itsorg.cloop.harnesseslabel says so. If acopilotproject uses it, the hub refuses the run before it starts (409sandbox_image_lacks_harness) and the error names the variant. - On a device's own host, the device installs the CLI the first time a task
sent to it needs one, as it does for
claude. It uses GitHub's documented installer (https://gh.io/copilot-install) and installs into the agent user's~/.local/bin. Ifexecutors.auto_install_harnessis off, the task is refused instead, and the error lists the ways to fix it. An agent built before this release has no installer forcopilotand reports that. Upgrade the agent, or install the CLI on the device yourself. A device advertisescopilotwhen the CLI is on the agent'sPATH.
The credential is COPILOT_GITHUB_TOKEN, or COPILOT_PROVIDER_BASE_URL if the
project uses its own model provider. Without one, the hub refuses to start the
task. The Copilot credential card on the Overview grants one in a single step
(see the credential of a sandboxed
run). The CLI
keeps its token out of the environment of the commands the agent runs.
On a hub with single sign-on, each person uses their own credential. This
covers a copilot run on the hub's own host, the dashboard's model calls on a
copilot project (Split, Revise, the blocker analysis, the plan assistant, the
replays), and every resume or failover of a run. Each of these acts for a
person, and the hub signs the CLI in with a credential granted to the project
for that person. That is either their own token, pasted into the project's
Copilot credential card and stored as their personal secret, or one that an
administrator shared with the project. The CLI never uses the host's copilot
login, GH_TOKEN or GITHUB_TOKEN: the hub strips every COPILOT_*
variable, GH_TOKEN, GITHUB_TOKEN and GH_HOST from the environment the CLI
inherits, and gives each person their own Copilot home for its sessions and
logs. Someone without a credential is refused and shown the dialog that grants
one, and a run the hub would continue for them is paused instead. See
per-person Copilot credentials.
What does not apply. The Claude Code usage caps and the model relay only
apply to Claude. A copilot run is not paused by claudecode.max_*_pct, and
its model calls go directly to GitHub (or to your own provider). The hub's own
host doesn't keep people apart: a run there uses the hub's own user account, and
its agent can read anything that account can. To keep people's agents apart,
bind copilot projects to an isolating executor, where the same personal grant
signs the sandbox in.
Environment variables¶
There are two sets of variables, and they behave differently. The configuration loader applies the first set, so these affect every command:
| Variable | Overrides |
|---|---|
CLOOP_PROVIDER |
provider |
ANTHROPIC_API_KEY |
anthropic.api_key |
ANTHROPIC_BASE_URL |
anthropic.base_url |
OPENAI_API_KEY |
openai.api_key |
OPENAI_BASE_URL |
openai.base_url |
OLLAMA_BASE_URL |
ollama.base_url |
GITHUB_TOKEN |
github.token |
CLOOP_OIDC_CLIENT_SECRET |
ui.oidc.client_secret |
Only cloop run applies the second set, on top of the first:
| Variable | Overrides |
|---|---|
CLOOP_ANTHROPIC_API_KEY |
anthropic.api_key |
CLOOP_ANTHROPIC_BASE_URL |
anthropic.base_url |
CLOOP_OPENAI_API_KEY |
openai.api_key |
CLOOP_OPENAI_BASE_URL |
openai.base_url |
CLOOP_OLLAMA_BASE_URL |
ollama.base_url |
CLOOP_MODEL |
the model for this run (also read by cloop mcp) |
Both the loader and cloop run apply CLOOP_PROVIDER, which is why it works
everywhere. The other CLOOP_-prefixed variables don't: cloop providers,
cloop config show and the dashboard won't see a key exported that way. Use the
unprefixed names unless you need an override for a single cloop run.
Two more sources sit below the config layer. The anthropic and openai
providers read ANTHROPIC_API_KEY / OPENAI_API_KEY themselves when they are
created without a key, so those variables work even where no config file was
loaded. The claudecode provider fills in missing variables, including
CLAUDE_CODE_OAUTH_TOKEN, from ~/.openclaw/workspace/.env, ~/.env and
./.env. It never overwrites a variable that is already set.
On shared or hosted machines, keep credentials in the environment instead of in
.cloop/config.yaml. To have a hub broker credentials to sandboxes instead of
keeping them in a file, see the secrets guide.
Named profiles¶
A profile is a saved set of provider, model, base URL and API key. Profiles are
kept outside the project in ~/.cloop/profiles.yaml, and you manage them with
cloop profile create | use | list | show | delete. cloop applies a profile to
the loaded configuration before the command-line flags, so --provider and
--model still take precedence:
cloop profile create work --provider anthropic --model claude-opus-4-6
cloop profile use work # make it the active profile
cloop run --profile work # or override the active one for a single run
--api-key stores the key in that file as plain text.
Role-based routing¶
Every task the planner creates has a role: backend, frontend, testing,
security, devops, data, docs or review. The router assigns a provider
to a role, so the tasks of one plan can run on several backends:
cloop router set backend anthropic
cloop router set docs ollama
cloop router list # the full table, with unrouted roles showing the default
cloop router clear docs
cloop router clear --all
Routes are stored under router.routes in .cloop/config.yaml. Roles without
a route use the project's provider. set checks both arguments and accepts
anthropic, openai, ollama, claudecode and copilot, but not mock. If
a routed provider can't be created, the run fails at startup with an error that
names the role, so it doesn't fail partway through.
The model is chosen once for the whole project, and every routed provider is called with that same model name. So when you route across providers, leave the model unset and let each provider use its own default. Don't set a model that only one of them understands.
To fall back to other providers instead of splitting the work between them, use
cloop run --fallback anthropic,openai. It tries each named provider in turn
after the primary one fails.
Next: The web dashboard shows how to run cloop and its projects from a browser instead of a terminal. See also core concepts, your first project and the command reference.