# Provider Setup

> Reports which delegation CLIs are installed and authenticated, installs missing ones, and stores the result. Use before delegating or when a provider errors.

- Skill: `athola/provider-setup` (Agent Skill)
- Install (CLI): `npx skillmds@latest add athola/provider-setup`
- Raw SKILL.md: https://api.skillmd.com/api/skills/athola/provider-setup/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: athola (https://skillmd.com/u/athola)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/athola/provider-setup

---


# Provider Setup

## Intent

An operator should be able to ask what this machine can delegate to,
get a truthful answer, install what is missing, and have that answer
remembered. Before this skill existed, an unconfigured provider
surfaced only as a failed delegation, and every call re-derived the
same facts by spawning up to sixteen subprocesses.

## When To Use

- Before the first delegation on a new machine
- When a provider errors out and it is unclear whether the cause is
  the binary, the credential, or the model
- When deciding which provider to name in a delegation request

## When NOT To Use

- Choosing between two providers that are both ready
  (`Skill(conjure:delegation-core)` routes)
- Debugging a provider's output rather than its availability

## What it reports

`scripts/delegation_setup.py` probes each registered service and
prints a table: binary, version, installed, authenticated, and the
fix for each unhealthy row.

```bash
python3 scripts/delegation_setup.py --status
python3 scripts/delegation_setup.py --doctor
python3 scripts/delegation_setup.py --available
```

`--available` is the short answer: the providers confirmed ready to
take work right now.

## Installing

Installs come from the provenance map in `delegation_executor`, which
is the only source of install commands. A binary with no recorded
provenance raises instead of falling back to a guess, because #655
shipped a service naming a binary that an unaffiliated package
publishes.

```bash
python3 scripts/delegation_setup.py --install gemini
python3 scripts/delegation_setup.py --all
```

Every install asks first. Declining is a recorded outcome, not a
failure, so `--all` on a machine where two of eight CLIs are wanted
still exits 0.

## What is remembered, and what is not

`plugins/conjure/scripts/provider_ledger.py` writes
`~/.claude/hooks/delegation/provider-state.json`. What it stores is
asymmetric on purpose:

| Fact | Cached | Why |
|------|--------|-----|
| Installed, version | Yes, under a 6-hour TTL | Cheap to re-derive, stable between runs |
| Confirmed credential | As a timestamp, never a boolean | A token expires without touching the binary |
| A recorded failure | Clears the confirmation immediately | A stale success must not outlive the credential |

A provider whose credentials live inside its CLI reports
`auth_checked: false`, and that never becomes a confirmation. "We did
not look" and "it works" are different claims, and the table keeps
them apart.

The file is a cache. A truncated or unreadable ledger loads as empty
and costs one round of probes.

## What this does not change

Routing still probes live. `Delegator.verify_service` spawns the
version and auth probes on the delegation path as it always did, and
the ledger does not short-circuit it.

That is a deliberate boundary, not an unfinished edge. Reading a cached
success into the router would send work to a provider whose token
expired since the probe, and reading a cached failure into the router
would disable a provider for the rest of the TTL after one transient
error. The ledger answers an operator's question, "what is set up on
this machine", where a six-hour-old answer is useful and a wrong one
costs a re-run. The router answers "can this call succeed now", where a
wrong answer costs the call.

Wiring the ledger into `verify_service` needs a failure taxonomy that
separates a transient refusal from a revoked credential. That does not
exist yet.

## Exit Criteria

- [ ] `python3 scripts/delegation_setup.py --status` prints one row
      per registered service with its installed and authenticated
      state
- [ ] `--available` names only providers that are installed, carry a
      confirmed credential, are inside the TTL, and have no recorded
      failure
- [ ] `~/.claude/hooks/delegation/provider-state.json` exists after a
      probe and parses as JSON with `"version": 1`
- [ ] An install request for a binary with no provenance entry raises
      `UnverifiedBinaryError` instead of running a guessed command
- [ ] A recorded failure clears any standing `auth_confirmed_at`, so a
      provider that starts refusing work leaves `--available`
- [ ] A corrupt ledger file loads as empty rather than raising

## Related Skills

- `Skill(conjure:delegation-core)`: the routing this setup feeds
- `Skill(leyline:service-registry)`: health checks for external
  services generally

