Bring your own model
You installed OpenCode and met the TUI in the last lesson, and now you want to point it at feedmill and start working. But OpenCode won’t move yet, and the reason is the thing that makes it different from every other terminal agent you’ve tried. Claude Code assumes Anthropic. Codex assumes OpenAI. OpenCode assumes nothing — it is provider-agnostic by design, which means the very first decision it hands back to you is one those tools quietly made on your behalf: which provider’s model is going to run the loop?
That’s not a hurdle. It’s the whole pitch. You bring a key you already have — Anthropic, OpenAI, an OpenRouter account, a local Ollama, whatever’s in your drawer — and OpenCode drives feedmill with it. The same way feedmill itself doesn’t care whether a source speaks RSS, Atom, or JSON as long as it can parse the feed, OpenCode doesn’t care whose model is behind the prompt as long as it can run the loop. So the first move isn’t a task. It’s wiring up credentials.
Connect a provider
Section titled “Connect a provider”Open the TUI in your repo and run the connect command:
> /connect
Select a provider to authenticate ❯ Anthropic OpenAI OpenRouter Google (Gemini / Vertex AI) Groq Amazon Bedrock Azure OpenAI Ollama LM Studio … 75+ providers
Anthropic → paste API key: ******************************** ✓ Connected. Credentials saved.That list isn’t OpenCode trying to support a handful of vendors it had time for. It ships with 75+ providers preloaded from the Models.dev catalog — Anthropic, OpenAI, OpenRouter, Groq, Google, Amazon Bedrock, Azure OpenAI, Ollama, LM Studio, and a long tail beyond — so the provider you already pay for is almost certainly already in the picker. You’re not configuring an integration; you’re handing over a key.
Prefer to stay on the command line, or scripting your setup? The same thing happens outside the TUI:
$ opencode auth loginIt walks you through the identical provider picker and key prompt, and on success drops the credential into ~/.local/share/opencode/auth.json. opencode auth list shows what you’ve connected and opencode auth logout removes one — handy when you’re rotating a key or clearing a machine you don’t own.
Connect more than one if you have them. There’s no penalty, and the next lesson — and several chapters past it — get a lot more interesting once OpenCode can reach two or three providers at once. Parsing feedmill’s gnarly Atom edge cases is a different job from drafting its README, and being able to put a different model on each is exactly the leverage you’re buying here.
Pick the model that runs the loop
Section titled “Pick the model that runs the loop”Connecting a provider unlocks its catalog; it doesn’t choose for you. That’s /models:
> /models
anthropic/claude-sonnet-4-5 anthropic/claude-opus-4-5 anthropic/claude-haiku-4-5 openai/gpt-5.2 openrouter/… ❯ select a model for this sessionOpenCode references every model as provider/model — the provider you connected, a slash, the model id. anthropic/claude-sonnet-4-5, openai/gpt-5.2, ollama/llama3.1. The slash is load-bearing: it’s why OpenCode can hold credentials for several providers at once and never has to guess which one you mean. /models lists exactly what your connected providers offer — connect nothing and the list is empty; connect three and you’re choosing across all three in one menu. Pick one here and it drives the loop for this session.
Make it the default
Section titled “Make it the default”Choosing per session is fine while you’re trying providers out. Once you’ve settled, set a default so OpenCode never has to ask again. The top-level model field in opencode.json is the project-wide default:
{ "$schema": "https://opencode.ai/config.json", "model": "anthropic/claude-sonnet-4-5"}Drop that in feedmill’s opencode.json and every session in this repo starts on Sonnet without a prompt. Want to override it for a single run — say, to throw a cheaper model at a throwaway question — reach for the flag instead of editing config:
$ opencode run -m anthropic/claude-haiku-4-5 "what does the dedupe step key on?"--model (or -m) takes the same provider/model string and wins for that one invocation, leaving your committed default untouched. You’ll lean on both of these hard once you reach the models chapter, where putting the right model on the right job stops being a convenience and becomes the difference between a parser refactor that lands and one that flails. For now you just need a default that lets the loop run.
You’ve answered the question Claude Code and Codex never asked — a provider is connected, a model is chosen, and feedmill is ready for its first real turn. Next: understand one turn of the loop.