OpenCode Part 1: A Terminal AI Agent You Actually Control
June 25, 2026·5 min read
This is Part 1 of a two-part series. Part 2 covers running a local model on your laptop and pointing OpenCode at it.
GitHub Copilot's pricing has gotten complicated. What used to be a straightforward $10/month individual subscription has expanded into a tiered structure — Pro, Pro+, Max — ranging from $10 to $100/month, all moving toward a credit-based consumption model where heavy usage costs more on top of the base plan. New self-serve signups for Copilot Business were even temporarily paused in April 2026. On the enterprise side, if no user-level budget is configured, individual developers have no visibility into what they're personally consuming — only org and enterprise admins can see aggregate usage through the billing dashboard. You can be burning credits on long agent sessions with no idea what it's costing until the invoice lands.
OpenCode is an open source AI coding agent that runs in your terminal — and it's a reasonable answer to that problem. You bring your own model, and it tracks token usage and cost against every session locally. For custom or self-hosted providers you define your own per-token pricing. GitHub officially added Copilot subscription support for it earlier this year, so if you already have a paid Copilot plan you can authenticate into OpenCode with those credentials and use it without any additional setup.
Here's how I have it configured.
The Config
OpenCode lives at ~/.config/opencode/opencode.jsonc. Everything — providers, models, plugins, permissions, MCP servers — is in one file.
{
"$schema": "https://opencode.ai/config.json",
// Cross-repo references — use @alias in any session to bring in context
"reference": {
"api": { "path": "~/dev/my-api" },
"infra": { "path": "~/dev/my-infra" },
"shared-libs": { "path": "~/dev/shared-libs" }
},
"lsp": true,
"formatter": true,
"share": "disabled",
"snapshot": true,
"provider": {
"friends-gateway": {
"npm": "@ai-sdk/openai-compatible",
"name": "AI Gateway",
"options": {
"baseURL": "https://llm.azure_fakeness.app/v1",
"apiKey": "<api-key>"
},
"models": {
"claude-sonnet-4-5": {
"name": "Claude Sonnet (gateway)",
"cost": {
"input": 3.00,
"output": 15.00,
"cache_read": 0.30,
"cache_write": 3.75
},
"limit": { "context": 200000, "output": 16000 }
}
}
},
"local": {
"npm": "@ai-sdk/openai-compatible",
"name": "Ollama (local)",
"options": {
"baseURL": "http://127.0.0.1:11434/v1",
"apiKey": "ollama"
},
"models": {
"qwen3.6:27b-mlx": {
"name": "Qwen3.6 27B MLX (local)",
"limit": { "context": 128000, "output": 8192 }
}
}
}
},
"model": "friends-gateway/claude-sonnet-4-5",
"plugin": ["opencode-vibeguard", "@tarquinen/opencode-dcp"],
"permission": {
"bash": "ask",
"edit": "ask",
"webfetch": "ask",
"read": "allow",
"glob": "allow",
"grep": "allow"
},
"mcp": {
"github": {
"type": "remote",
"url": "https://api.githubcopilot.com/mcp/"
},
"your-observability-tool": {
"type": "remote",
"url": "https://mcp.yourtool.com/mcp",
"headers": {
"Authorization": "Bearer <token>"
}
}
}
}Cross-Repo References
The reference block lets you give repos an alias and pull them in by name during any session:
how does @infra handle network rules between environments?compare how @api and @shared-libs both handle auth middlewareOpenCode treats the referenced repo as additional context for that session. You can ask questions that span multiple codebases without switching directories or opening separate sessions. For any project where work is spread across repos, this alone is worth the setup.
Providers — Including a Friend's Gateway
OpenCode uses the AI SDK under the hood, so any OpenAI-compatible endpoint works as a provider. That includes hosted APIs from Anthropic, OpenAI, and Google — but also any custom gateway someone is running.
If you have a generous friend hosting a model AI gateway on a Blackwell 6000 they have laying around, you can point OpenCode at it the same way you'd point it at any API:
"friends-gateway": {
"npm": "@ai-sdk/openai-compatible",
"name": "Friend's Gateway",
"options": {
"baseURL": "https://llm.feverdreams.app/v1",
"apiKey": "<their-key>"
},
"models": {
"claude-sonnet-4-5": {
"name": "Claude Sonnet (gateway)",
"cost": { "input": 3.00, "output": 15.00 },
"limit": { "context": 200000, "output": 16000 }
}
}
}The cost values are whatever you've agreed to pay — or zero if they're sharing access. OpenCode doesn't validate pricing against any external source, it just multiplies tokens by whatever you define. Which is the whole point.
The local Ollama provider works the same way — same config pattern, just pointed at localhost. Part 2 covers what's worth running locally on Apple Silicon.
Switching providers mid-session is a keybind. No restart needed.
Plugins
Two plugins worth knowing about:
opencode-vibeguard — scans outgoing prompts for secrets, JWTs, API keys, and credentials before they leave. Any match gets replaced with a placeholder before the request goes out. Useful if you work in a codebase where sensitive values end up in config files.
@tarquinen/opencode-dcp — dynamic context pruning. Compresses and prunes context as sessions grow so you don't hit the limit mid-conversation on a long debugging session. The cache read numbers in the usage table below are large partly because of this plugin keeping context alive across turns efficiently.
MCP Servers
MCP (Model Context Protocol) servers let OpenCode call external tools mid-session — querying your observability platform, pulling issue data, reading a service catalog, checking deployment status. Most major platforms have MCP servers now: GitHub, Linear, Jira, Datadog, PagerDuty, Grafana, Notion, Slack. If it has an API, there's probably an MCP server for it.
Cost Tracking
Every session's token usage and cost gets written to a local SQLite database at ~/.local/share/opencode/opencode.db. For custom providers, the cost field reflects whatever per-token pricing you defined in the config — OpenCode multiplies tokens by your rates, no external validation.
For GitHub Copilot specifically: token counts are real, pulled from the API response. The dollar figure is OpenCode's own estimate using Anthropic's public per-token pricing via the AI SDK — it is not GitHub's AIC (AI Credits). If you want to know your actual AIC consumption, that's still in the GitHub billing dashboard. What OpenCode gives you is a relative measure — how many tokens a session consumed and roughly what that would cost at list price. Good enough for spotting runaway sessions.
If GitHub's AIC is coming out higher than OpenCode's estimate, that's the signal. OpenCode is calculating against Anthropic's public list price — if Copilot costs more than that for the same tokens, you're paying a premium for the subscription wrapper. A direct gateway gives you both numbers to compare.
I wrote a small Python script that reads that database and outputs a markdown summary. It runs via a custom /usage command:
---
description: Show token and cost usage stats
---
!`python3 ~/bin/opencode-usage-md`Type /usage in any session:
| Period | Sessions | Cost | In Tokens | Out Tokens | Cache Read | Cache Write |
|---|---|---|---|---|---|---|
| Today | 1 | $0.17 | 24 | 2,074 | 103,049 | 28,093 |
| This Week | 12 | $10.96 | 966 | 120,717 | 16,109,350 | 1,150,924 |
| This Month | 35 | $24.47 | 362,404 | 278,251 | 27,766,983 | 3,320,768 |
| All Time | 64 | $28.79 | 364,598 | 568,755 | 86,375,370 | 8,588,282 |
And the most recent sessions:
| Time | Cost | Out | Cache Read | Session |
|---|---|---|---|---|
| 06-24 17:26 | $0.20 | 5,724 | 115,965 | Explore React router changes |
| 06-24 15:53 | $3.68 | 37,506 | 6,403,169 | Security Scan and fix. |
| 06-24 15:34 | $1.81 | 24,614 | 2,606,697 | Incident write-up |
The script is straightforward — a few SQL queries against the local database:
#!/usr/bin/env python3
import sqlite3
from datetime import datetime
from pathlib import Path
DB = Path.home() / ".local/share/opencode/opencode.db"
conn = sqlite3.connect(DB)
cur = conn.cursor()
def agg(since_ms):
r = cur.execute(
"SELECT COUNT(*) n, SUM(cost) cost, SUM(tokens_input) ti, SUM(tokens_output) to_, "
"SUM(tokens_cache_read) cr, SUM(tokens_cache_write) cw FROM session WHERE time_updated >= ?",
(since_ms,)
).fetchone()
return r[0] or 0, r[1] or 0.0, r[2] or 0, r[3] or 0, r[4] or 0, r[5] or 0The session table has everything. Cost by project, week-over-week trends, alerting when a session goes over a threshold — it's all queryable.
Getting Started
brew install opencodeIf you have a Copilot subscription and want to try it first:
/connectSelect GitHub Copilot, complete the device login, done. If you want to use your own provider, add it to ~/.config/opencode/opencode.jsonc and switch models with Ctrl+M.
Part 2 covers running Ollama locally, which models are worth running on Apple Silicon, and how the local provider hooks into the same /usage tracking — except the cost column reads $0.00.
Enjoyed this post? Give it a clap!
Comments