Running opencode in Shikigami.
How to run opencode as an agent engine, and how to point it at a local model so the whole loop runs on your own machine.
Shikigami hosts opencode alongside Claude Code and Codex. Each agent gets its own PTY, its own git worktree, and its own tab. opencode runs as its real TUI inside it, not through a wrapper.
Setup
-
Install opencode. Shikigami finds it on your
PATH, or at~/.opencode/bin(the official installer’s default target). An install in some other location that neither of those resolves will only produce a generic “Agent failed” toast. -
Log in once, from your own terminal:
opencode providers loginDo this outside Shikigami. Shikigami strips credential-shaped environment variables (
ANTHROPIC_API_KEY,OPENAI_API_KEY, anything matching*_API_KEY,*SECRET*,*_TOKEN, and friends) before spawning any agent, so an API key exported in your shell profile won’t reach opencode, which will then look logged out. OAuth and file-based auth are untouched, which is whyproviders loginis the path that works. - New Agent → engine: opencode. That’s the whole setup. Shikigami passes the working directory, your prompt, and the resume id; everything else is opencode’s own.
Choosing the model
Shikigami doesn’t pick a model for opencode. There’s no model or effort selector for this engine, by design: opencode’s catalog depends on which providers you’re authenticated with and resolves at runtime, so it can’t be enumerated ahead of time. Pick your model inside opencode with /models, and it remembers the choice.
To pin a model per agent instead, create a preset (Settings → Presets), set the engine to opencode, and put this in Additional arguments:
--model=ollama/qwen2.5-coder:7b
Use the --flag=value form. The field takes exactly one argument and appends it verbatim, so a space-separated --model ollama/qwen2.5-coder:7b arrives as a single malformed token.
A few flags are rejected: -s / --session, --prompt and --auto are Shikigami’s to emit, and --port, --hostname, --mdns and --mdns-domain are blocked because they would bind opencode’s built-in HTTP server beyond loopback.
What’s different about opencode agents
A few things to know up front, so nothing looks broken:
- No activity indicator. opencode doesn’t report a working/waiting state, so a mid-turn agent looks the same as one sitting idle at the prompt. The activity glow never lights.
- No turn-finished notification. Neither an OS notification nor the in-app done pip.
- Session capture happens on exit only. opencode prints its resume id (
opencode -s ses_…) when it shuts down cleanly, and that’s what Shikigami reads to make the conversation resumable. Suspend an opencode agent to keep it; a crash, a hard Stop, or a force-quit leaves it unresumable. An agent that never received a prompt has no id either, because opencode creates the session lazily on the first message. - Permissions are all-or-nothing. opencode has no per-tool allow/deny list, so the granular tool-permission fields don’t apply; it’s
--autoor interactive approval. - Handoff is one-way. You can send another agent’s last exchange to an opencode agent, but not from one. Its conversation lives in its own store, which Shikigami doesn’t read yet.
Using a local model via Ollama
opencode talks to Ollama through Ollama’s OpenAI-compatible endpoint. Nothing in Shikigami needs changing. Configure opencode once, and every opencode agent picks it up.
1. Pull a model
ollama pull qwen2.5-coder:7b
The model must support tool calling, or it can chat but can’t act as an agent. Check with:
curl -s localhost:11434/api/tags | grep -o '"capabilities":\[[^]]*\]'
Look for tools in the list. That’s Ollama telling you the model supports tool calling; you’ll still have to tell opencode about it in step 2. Coding-tuned models such as qwen2.5-coder are strong at writing code; general models with a larger context window (qwen3, for instance) sometimes do better across a long agentic session, where file reads and tool output fill the window quickly. Try both.
2. Declare the provider
opencode doesn’t auto-detect a local Ollama, and opencode providers login won’t help, since that flow is for credentialed providers. Ollama isn’t in the model catalog opencode ships with, so you declare it, and its models, by hand.
Edit ~/.config/opencode/opencode.jsonc, creating it if it doesn’t exist:
{
"$schema": "https://opencode.ai/config.json",
// Default model when none is passed on the command line.
"model": "ollama/qwen2.5-coder:7b",
// Local Ollama, exposed through its OpenAI-compatible endpoint. Ollama is
// not in the models.dev catalog opencode ships with, so the provider and
// every model id have to be declared here by hand.
"provider": {
"ollama": {
"npm": "@ai-sdk/openai-compatible",
"name": "Ollama (local)",
"options": { "baseURL": "http://localhost:11434/v1" },
"models": {
"qwen2.5-coder:7b": { "name": "Qwen2.5 Coder 7B", "tool_call": true },
"qwen3:8b": { "name": "Qwen3 8B", "tool_call": true },
"qwen3-vl:8b": { "name": "Qwen3 VL 8B", "tool_call": true }
}
}
}
}
Every model you want needs an entry under models, keyed by its exact Ollama tag. The npm field pulls the adapter automatically the first time. The top-level model key sets the default; drop it if you’d rather choose per session with /models.
"tool_call": true is the one that’s easy to miss. opencode normally reads a model’s capabilities from the models.dev catalog it ships with, and a provider you declared by hand has no catalog entry, so without that flag opencode assumes the model can’t call tools and never offers it any. The agent then answers your prompt in prose and never touches a file, which reads like a broken agent rather than a missing line of config. Declaring the flag doesn’t grant the capability; the check in step 1 is what confirms the model has it.
3. Verify, before opening Shikigami
opencode models | grep ollama
You should see ollama/qwen2.5-coder:7b. Then check that it actually answers:
opencode run "Reply with exactly: PONG"
If the model list is empty, the provider block isn’t being read: confirm the file path and that the JSON parses. If the list is fine but the run hangs or errors, Ollama itself isn’t reachable at the baseURL; curl localhost:11434/api/tags should return your models. And if it answers happily but never reads or writes a file once you put it to work, that’s the missing "tool_call": true.
4. Use it
New Agent → engine opencode. It starts on your default model, and /models switches between the ones you declared. To pin a specific local model to a preset, use --model=ollama/qwen3:8b in the preset’s Additional arguments.
Remote or non-default Ollama
Point baseURL at the machine running it:
"options": { "baseURL": "http://192.168.1.50:11434/v1" }
OLLAMA_HOST also survives into the agent’s environment if you’d rather set it that way. It isn’t credential-shaped, so it doesn’t get stripped. No API key is involved at all, which sidesteps the credential-stripping problem entirely: a local model is the one provider that needs no secret.
Don’t have Shikigami yet?
signed .dmg · macOS & Linux · free