diff --git a/CHANGELOG.md b/CHANGELOG.md
index 466032ab8..a9ea82eff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,14 @@
All notable changes to the **OpenCode Go BYOK Provider** extension are documented here.
+## [Unreleased]
+
+### Fixed
+
+- **`[Models]` Free-tier Zen models are hidden from the picker, `opencodego.freeOnly` is deprecated, and every free-Zen claim is removed from the docs (Marketplace review, follow-up to #235/#240).** OpenCode has gated free-tier Zen models to its own app/CLI since Sep 17, 2026 (HTTP 403 for third-party clients — upstream anomalyco/opencode#49580), verified live against all 10 free models in the Zen catalog. With `freeOnly` defaulting to `true`, the Zen picker showed _only_ models that could never serve a request. Free-tier Zen models (`-free` suffix, plus `big-pickle`) are now always filtered out via a vendor-scoped `isZenFreeTierModel()` — the gate is Zen-only: Go's free models (`beam-free`, `minimax-m3.1-flash-free`, `longcat-2.5-preview-free`) are unlimited within a paid Go subscription, explicitly permitted for third-party clients, and remain selectable. `freeOnly` stays registered so existing settings don't error but no longer has any effect. README, extension description, and keywords no longer advertise free Zen models: the free-models table is replaced with a dated policy notice, and stale free claims (quick start, comparison table, FAQ, `free-models` keyword, "free Claude Opus" in the description) are corrected. Documented in `docs/issues/112-20261020-zen-free-tier-policy-followup.md`.
+
+- **`[Errors]` The free-tier / Router.Unavailable hint now renders in the chat, not only the toast (#258 follow-up).** `buildOpenCodeRequestError()` placed the actionable hint in `userMessage`, but VS Code's chat surface renders `error.message` — which carried the raw gateway JSON (`Error from provider (Console): OpenCode's free tier can only be used…`). The hint now replaces the raw detail in both messages; the upstream body is still preserved in the OpenCode output channel (`[http-error-body]`).
+
## [0.7.10] — unreleased
### Added
diff --git a/README.md b/README.md
index fe9d3635d..044f235b2 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
**Use 30+ frontier AI models** (DeepSeek V4, Kimi K3, GLM-5.3, GPT-5.6, Claude Opus 5, Gemini 3.6, Grok 4.6…) in GitHub Copilot Chat. **BYOK**
-**Bring Your Own Key (BYOK)** · OpenCode Zen (free + paid models) or Go ($10/mo subscription) · Works with native Copilot Agent Mode
+**Bring Your Own Key (BYOK)** · OpenCode Zen (pay-as-you-go) or Go ($10/mo subscription) · Works with native Copilot Agent Mode
[](https://github.com/ltmoerdani/opencode-copilot-chat/actions/workflows/ci.yml)
[](https://marketplace.visualstudio.com/items?itemName=ltmoerdani.opencode-copilot-chat)
@@ -37,7 +37,7 @@
| 🧠 **Thinking controls** | Per-model reasoning effort (DeepSeek `max`, Qwen `thinking_budget`, MiniMax `on/off`, Mimo `low/med/high`) |
| 🖼️ **Vision proxy** | Text-only models can "see" images via a configured vision model. Per-image descriptions are cached & reused across turns to save quota. Run **OpenCode Go: Configure Vision Proxy** to set it up. |
| 📊 **Live usage tracking** | Status bar shows Go subscription burn-rate across 5h / weekly / monthly tiers |
-| 🔌 **Dual providers** | OpenCode **Go** ($10/mo subscription) + OpenCode **Zen** (free + paid models). Run both at once, switch instantly |
+| 🔌 **Dual providers** | OpenCode **Go** ($10/mo subscription) + OpenCode **Zen** (pay-as-you-go). Run both at once, switch instantly |
| 🪫 **Provider on/off** | Remove or re-add **OpenCode Go** / **OpenCode Zen** from Language Models & every picker anytime; your API keys and BYOK groups are kept, so re-enabling restores everything |
| 🎯 **Smart routing** | Each model family auto-routes to its native transport (`/responses`, `/messages`, `streamGenerateContent`, `/chat/completions`) |
| 🖼️ **Vision + PDF + Audio** | Multimodal models pass through image, PDF, audio, and video inputs. Oversized images auto-resize to 2000×2000 / 5MB to match the gateway contract. |
@@ -53,7 +53,7 @@
2. Install this extension ──────────────────────────────────────── ✓
3. Get an OpenCode Zen API key → opencode.ai/auth ─────────────── ✓
4. Open Copilot Chat → click model → "Add Models" → OpenCode Zen ── ✓
-5. Paste API key → pick a free model → CHAT 🎉
+5. Paste API key → pick a model → CHAT 🎉
```
@@ -62,9 +62,8 @@
1. **Install or update [VS Code](https://code.visualstudio.com/)** to version 1.125 or newer. OpenCode BYOK chat works without a GitHub sign-in or Copilot plan.
2. **Install this extension** from the VS Code Marketplace (or press `F5` in this repo for dev mode).
3. **Get an API key:**
- - **Free models:** Sign up at [opencode.ai](https://opencode.ai) → grab an **OpenCode Zen** key. Several models are truly free (Big Pickle, DeepSeek V4 Flash Free, MiMo-V2.5 Free, and others rotate).
- - **Paid Zen models (optional):** Add a payment method to your Zen account to unlock Claude Opus, GPT-5.5, Gemini, and other paid models at pay-as-you-go rates. Adding $20+ balance also improves rate limits on free models.
- - **OpenCode Go (optional):** Subscribe to **OpenCode Go** ($10/mo, $5 first month promo) for curated open models like DeepSeek V4 Pro, Kimi K3, GLM-5.3, Qwen3.8 Max, MiMo V2.5 Pro.
+ - **OpenCode Zen (pay-as-you-go):** Sign up at [opencode.ai](https://opencode.ai), add billing, and grab an **OpenCode Zen** key for Claude, GPT-5.5, Gemini, and other models at pay-as-you-go rates.
+ - **OpenCode Go (optional):** Subscribe to **OpenCode Go** ($10/mo, $5 first month promo) for curated open models like DeepSeek V4 Pro, Kimi K3, GLM-5.3, Qwen3.8 Max, MiMo V2.5 Pro — including its free-tier models, unlimited while subscribed.
4. **Open Copilot Chat** (Cmd/Ctrl+Shift+I, or click the Copilot icon).
5. **Click the model picker** (current model name) → **Add Models…**
6. **Select** **OpenCode Go** or **OpenCode Zen**.
@@ -77,7 +76,7 @@
>
> - Go and Zen are **separate provider groups**: both can be active simultaneously. Switch anytime from the picker.
> - If a model shows in **Language Models** view but not the chat picker, hover its row and click the **eye icon (👁)** to enable it.
-> - Set `opencodego.freeOnly: false` to reveal **paid Zen models** in the picker.
+> - **Free-tier Zen models (names ending in `-free`, plus `big-pickle`) no longer work from VS Code:** since Sep 17, 2026 OpenCode restricts them to its own app/CLI (HTTP 403 for third-party clients). The extension hides them automatically — run them in the OpenCode app/CLI, or use paid Zen/Go models here.
@@ -128,24 +127,18 @@ Curated open coding models, refreshed live from the endpoint. Deprecated/legacy
| `hy4-preview` | **1,024,000** | 64,000 | 🧠 Preview | $30 |
| `hy3` | 256,000 | 128,000 | 🧠 Text-only | $60 |
-> **Usage:** most Go models include **$60/mo** of included usage; premium models include less (`glm-5.3`, `glm-5.3-flash`, `gpt-5.6-luna`, `grok-4.6`, `kimi-k3`, `qwen3.8-max`, `deepseek-v4-pro`, `deepseek-v4-flash-vision-exp`, `mimo-v2.5-pro` at $15/mo; `qwen3.8-flash`, `qwen3.7-max`, `deepseek-v4-flash`, `hy4-preview` at $30/mo), and `omen-alpha` includes a larger **$100/mo**. Cheaper per-token models stretch their allowance further, so request counts vary widely: the docs estimate ~226K requests/mo on Muse Spark 1.3 vs ~490 on Kimi K3. If you hit a limit, keep using the free Zen models (or enable the "Use balance" option in the Zen console).
+> **Usage:** most Go models include **$60/mo** of included usage; premium models include less (`glm-5.3`, `glm-5.3-flash`, `gpt-5.6-luna`, `grok-4.6`, `kimi-k3`, `qwen3.8-max`, `deepseek-v4-pro`, `deepseek-v4-flash-vision-exp`, `mimo-v2.5-pro` at $15/mo; `qwen3.8-flash`, `qwen3.7-max`, `deepseek-v4-flash`, `hy4-preview` at $30/mo), and `omen-alpha` includes a larger **$100/mo**. Cheaper per-token models stretch their allowance further, so request counts vary widely: the docs estimate ~226K requests/mo on Muse Spark 1.3 vs ~490 on Kimi K3. If you hit a limit, enable the "Use balance" option in the Zen console.
-### 🆓 OpenCode Zen free models (no payment needed)
+### ⚠️ Zen free models no longer work from VS Code (since Sep 17, 2026)
-OpenCode Zen offers **rotating free models**, no balance required. Currently free: **Big Pickle** (stealth model), DeepSeek V4 Flash Free, MiMo-V2.5 Free, Hy3 Free, Laguna S 2.1 Free, Ling-3.0-tiny Free, Nemotron 3 Ultra Free, and Nemotron 3.5 Lightning Free. Without a balance, rate limits are low. Adding $20+ to your Zen balance significantly improves rate limits on free models.
+OpenCode restricts free-tier Zen models — every model with a `-free` suffix, plus `big-pickle` — to its own app and CLI. Third-party clients like this extension get **HTTP 403** on every request to them. This is OpenCode's policy (effective **September 17, 2026**, see [anomalyco/opencode#49580](https://github.com/anomalyco/opencode/issues/49580)), not a bug in this extension. Questions or reports: [pinned announcement #265](https://github.com/ltmoerdani/opencode-copilot-chat/issues/265).
-> **Note:** Per the OpenCode docs, free models are all offered **for a limited time** and rotate periodically. The table shows current offerings; availability may change.
+What still works:
-| Model | Context | Max Output | Vendor |
-| ----------------------------- | --------: | ---------: | ---------- |
-| `big-pickle` | 200,000 | 32,000 | 🥒 Stealth |
-| `deepseek-v4-flash-free` | 200,000 | 128,000 | DeepSeek |
-| `mimo-v2.5-free` | 200,000 | 32,000 | Xiaomi |
-| `hy3-free` | 190,000 | 64,000 | OpenCode |
-| `laguna-s-2.1-free` | 256,000 | 32,000 | OpenCode |
-| `ling-3.0-tiny-free` | 262,144 | 32,768 | OpenCode |
-| `nemotron-3-ultra-free` | 1,000,000 | 128,000 | NVIDIA |
-| `nemotron-3.5-lightning-free` | 262,144 | 262,144 | NVIDIA |
+- **All paid Zen models** (pay-as-you-go with a Zen balance) — unaffected.
+- **Every OpenCode Go model, including Go's own free models** (`beam-free`, `minimax-m3.1-flash-free`, `longcat-2.5-preview-free`) — unlimited while subscribed, third-party clients explicitly permitted.
+
+The extension hides the gated models from the picker automatically. If you still see a free-tier error, update to the latest version. To keep using Zen free models, run them in the [OpenCode app or CLI](https://opencode.ai).
### 💰 OpenCode Zen paid models (requires balance)
@@ -177,7 +170,7 @@ Add a payment method to your Zen account to unlock these models at pay-as-you-go
| `minimax-m3` | 512,000 | 128,000 | $0.30 / $1.20 |
| `minimax-m2.7` | 204,800 | 131,072 | $0.30 / $1.20 |
-> Set `opencodego.freeOnly: false` to show paid Zen models in the picker (default shows only free models).
+> Free-tier Zen models are hidden from the picker — OpenCode restricts them to its own app/CLI since Sep 17, 2026. Paid Zen models and all Go models (including Go's free-tier models) remain available.
🔬 How model metadata is resolved (3-tier fallback)
@@ -212,23 +205,23 @@ All Qwen models use `/chat/completions` because they use OpenAI-native tool-call
GitHub Copilot has four tiers now: **Free**, **Pro ($10/mo)**, **Pro+ ($39/mo)**, and **Max ($100/mo)**. Here's how BYOK via OpenCode compares:
-| | **Copilot Free** | **Copilot Pro $10/mo** | **Copilot Pro+ $39/mo** | **OpenCode for Copilot Chat** |
-| -------------------------------- | ----------------------------------------- | -------------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------- |
-| 💰 **Cost** | $0 | $10/mo | $39/mo | **$0** with free Zen models · Go is **$10/mo** subscription |
-| 🤖 **Models** | GPT-5 mini, Haiku 4.5 (2,000 completions) | Pro catalog + Claude Code/Codex agents | Premium (Opus) | **30+ models**: DeepSeek V4, Kimi K3, GLM-5.3, Qwen3.8, MiMo V2.5, MiniMax M3, + rotating free models |
-| 🧠 **Reasoning controls** | ❌ | Per-model (GitHub decides) | Per-model (GitHub decides) | **Per-family thinking effort** you control (DeepSeek `max`, Qwen `thinking_budget`, etc.) |
-| 🖼️ **Multimodal** | Limited | Yes (limited) | Yes (limited) | **Vision + PDF + Audio + Video** (per-model) |
-| 🔧 **Agent Mode / tool-calling** | ❌ | ✅ | ✅ | ✅ **Full** (read, edit, terminal) |
-| 📊 **Usage transparency** | Opaque | Opaque | Audit logs | **Status bar burn-rate** + diagnostics report |
-| 🔌 **Provider** | GitHub only | GitHub only | GitHub only | **Bring any OpenCode key**: Go ($10/mo subscription) or Zen (free + paid), run both at once |
-| 🎁 **Free frontier models?** | ❌ | ❌ | ❌ (paid tier only) | ✅ **Rotating free models** via Zen (Big Pickle + 7 currently) |
-| 🚫 **Rate limit** | 2,000 completions/mo | Unlimited (rate-limited) | 4× Pro credits | Per OpenCode tier (Zen free has low limits without balance; Go has generous limits) |
+| | **Copilot Free** | **Copilot Pro $10/mo** | **Copilot Pro+ $39/mo** | **OpenCode for Copilot Chat** |
+| -------------------------------- | ----------------------------------------- | -------------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------- |
+| 💰 **Cost** | $0 | $10/mo | $39/mo | Zen is pay-as-you-go · Go is **$10/mo** subscription |
+| 🤖 **Models** | GPT-5 mini, Haiku 4.5 (2,000 completions) | Pro catalog + Claude Code/Codex agents | Premium (Opus) | **30+ models**: DeepSeek V4, Kimi K3, GLM-5.3, Qwen3.8, MiMo V2.5, MiniMax M3, + more |
+| 🧠 **Reasoning controls** | ❌ | Per-model (GitHub decides) | Per-model (GitHub decides) | **Per-family thinking effort** you control (DeepSeek `max`, Qwen `thinking_budget`, etc.) |
+| 🖼️ **Multimodal** | Limited | Yes (limited) | Yes (limited) | **Vision + PDF + Audio + Video** (per-model) |
+| 🔧 **Agent Mode / tool-calling** | ❌ | ✅ | ✅ | ✅ **Full** (read, edit, terminal) |
+| 📊 **Usage transparency** | Opaque | Opaque | Audit logs | **Status bar burn-rate** + diagnostics report |
+| 🔌 **Provider** | GitHub only | GitHub only | GitHub only | **Bring any OpenCode key**: Go ($10/mo subscription) or Zen (pay-as-you-go), run both at once |
+| 🎁 **Free frontier models?** | ❌ | ❌ | ❌ (paid tier only) | ✅ On **OpenCode Go** (free models included while subscribed) — not from VS Code on Zen since Sep 17, 2026 |
+| 🚫 **Rate limit** | 2,000 completions/mo | Unlimited (rate-limited) | 4× Pro credits | Per OpenCode tier (Zen pay-as-you-go scales with balance; Go has generous limits) |
-> **Model bridge, not completions replacement.** OpenCode BYOK models work in VS Code Chat without a Copilot plan or GitHub sign-in. Standard inline suggestions, next-edit suggestions, semantic search, and embedding-backed features still require GitHub/Copilot support. OpenCode requests bypass Copilot billing entirely: you pay OpenCode directly (or nothing, on Zen free).
+> **Model bridge, not completions replacement.** OpenCode BYOK models work in VS Code Chat without a Copilot plan or GitHub sign-in. Standard inline suggestions, next-edit suggestions, semantic search, and embedding-backed features still require GitHub/Copilot support. OpenCode requests bypass Copilot billing entirely: you pay OpenCode directly (Zen pay-as-you-go, or the Go subscription).
### 💡 When to use which?
-- **VS Code + OpenCode Zen** → **$0 total** for BYOK chat. Best for students, hobbyists, and trying frontier models.
+- **VS Code + OpenCode Zen** → pay-as-you-go BYOK chat with frontier models. Best for trying Claude, GPT, and Gemini without a subscription.
- **Copilot Pro + OpenCode Go** → $10/mo for Copilot's polish + $10/mo for DeepSeek Pro, Kimi K2.6, Qwen3.7 Max.
- **This extension alone** → Chat, agent tools, and configured utility tasks work without Copilot. Add Copilot only when you also need inline suggestions, semantic search, or embedding-backed features.
@@ -466,11 +459,11 @@ Inline suggestions, next-edit suggestions, semantic search, and embedding-backed
Is it really free? What's the catch?
-**OpenCode Zen** offers **rotating free models**, no balance required. Currently free: Big Pickle, DeepSeek V4 Flash Free, MiMo-V2.5 Free, Hy3 Free, Laguna S 2.1 Free, Ling-3.0-tiny Free, Nemotron 3 Ultra Free, Nemotron 3.5 Lightning Free (all limited-time, per the OpenCode docs). Without a balance, rate limits are low. Adding $20+ to your Zen balance significantly improves rate limits on free models. Paid Zen models (Claude Opus, GPT-5.6, Gemini, etc.) require adding a payment method; they're pay-as-you-go.
+**OpenCode Zen** is **pay-as-you-go**: add a payment method and a balance, then pay per token for Claude Opus, GPT-5.6, Gemini, and the rest at rates OpenCode passes through at cost. Its free-tier models (names ending in `-free`, plus `big-pickle`) **no longer work from VS Code** — since Sep 17, 2026 OpenCode restricts them to its own app/CLI (HTTP 403 for third-party clients). The extension hides them automatically; run them in the OpenCode app/CLI if you need them.
-**OpenCode Go** is a **subscription**: **$10/mo** ($5 first month promo) with generous usage limits (5h/$12, weekly/$30, monthly/$60). It unlocks curated open models like DeepSeek V4 Pro, Kimi K3, GLM-5.3, Qwen3.8 Max, MiMo V2.5 Pro. When you hit the limit, you can continue using the free Zen models.
+**OpenCode Go** is a **subscription**: **$10/mo** ($5 first month promo) with generous usage limits (5h/$12, weekly/$30, monthly/$60). It unlocks curated open models like DeepSeek V4 Pro, Kimi K3, GLM-5.3, Qwen3.8 Max, MiMo V2.5 Pro — and Go's own free models (`beam-free`, `minimax-m3.1-flash-free`, `longcat-2.5-preview-free`) are unlimited while subscribed.
-**This extension is free and open source**: you never pay us. You pay OpenCode directly (or nothing, on Zen free).
+**This extension is free and open source**: you never pay us. You pay OpenCode directly (Zen balance or Go subscription).
@@ -632,7 +625,7 @@ Press `F5` in VS Code to launch an **Extension Development Host**.
[](https://github.com/ltmoerdani/opencode-copilot-chat/discussions)
[](https://github.com/ltmoerdani/opencode-copilot-chat/issues)
-[](https://twitter.com/intent/tweet?text=Using%2030%2B%20AI%20models%20in%20GitHub%20Copilot%20Chat%20for%20free%20with%20BYOK!&url=https://github.com/ltmoerdani/opencode-copilot-chat&hashtags=vscode,copilot,ai,byok,opencode)
+[](https://twitter.com/intent/tweet?text=Using%2030%2B%20AI%20models%20in%20GitHub%20Copilot%20Chat%20with%20BYOK!&url=https://github.com/ltmoerdani/opencode-copilot-chat&hashtags=vscode,copilot,ai,byok,opencode)
[](https://www.reddit.com/submit?url=https://github.com/ltmoerdani/opencode-copilot-chat&title=OpenCode%20for%20Copilot%20Chat)
**If this saves you money or unlocks a model you needed, ⭐ star the repo and share it!**
diff --git a/docs/issues/106-20260923-issue235-240-free-tier-policy.md b/docs/issues/106-20260923-issue235-240-free-tier-policy.md
index e17aade05..a14f714e8 100644
--- a/docs/issues/106-20260923-issue235-240-free-tier-policy.md
+++ b/docs/issues/106-20260923-issue235-240-free-tier-policy.md
@@ -50,3 +50,9 @@ Paid models (OpenCode Go) are **not** affected. Any client that still serves fre
---
Detected 2026-09-16 (#235) and 2026-09-22 (#240) | Reported by @gp-slick-coder, @AIlaowong | Fixed 2026-09-23
+
+---
+
+## Follow-up (2026-10-20) — doc 112
+
+The 0.7.6 fix only replaced the error text in the toast; chat still showed the raw gateway JSON, and the Zen picker (default `freeOnly: true`) kept steering users into the gated models. A Marketplace review surfaced both gaps. Free-tier Zen models are now hidden from the picker entirely, `freeOnly` is deprecated, and the hint renders in chat. Verified the gate is Zen-only — Go free models stay selectable. See [`112-20261020-zen-free-tier-policy-followup.md`](112-20261020-zen-free-tier-policy-followup.md).
diff --git a/docs/issues/112-20261020-zen-free-tier-policy-followup.md b/docs/issues/112-20261020-zen-free-tier-policy-followup.md
new file mode 100644
index 000000000..3272f894e
--- /dev/null
+++ b/docs/issues/112-20261020-zen-free-tier-policy-followup.md
@@ -0,0 +1,53 @@
+# Hide Zen Free-Tier Models, Deprecate freeOnly, Surface the 403 Hint in Chat
+
+**Status:** ✅ Solved
+**Topic:** provider / policy / models / errors
+**Updated:** 2026-10-20
+**Tags:** #provider #zen #free-tier #policy #models #errors
+**Related:** doc [106 — issue235/240 free-tier policy](106-20260923-issue235-240-free-tier-policy.md), [110 — issue247 api-base-url](110-20261013-issue247-api-base-url-ignored.md), upstream [anomalyco/opencode#49580](https://github.com/anomalyco/opencode/issues/49580)
+
+---
+
+## Problem
+
+A Marketplace review reported the extension "suddenly stopped working" with `OpenCode's free tier can only be used from within OpenCode. Download it at https://opencode.ai and keep building`. This is the same upstream policy already handled in doc 106 (issues #235/#240), but with three extension-side defects on top:
+
+1. **`opencodego.freeOnly` defaults to `true`**, so the Zen picker listed _only_ free-tier models — every one of which upstream now 403s for third-party clients. A default install was a guaranteed dead end.
+2. **The actionable hint never reached the chat.** `buildOpenCodeRequestError()` put the hint in `userMessage` (toast only); VS Code renders `error.message`, which carried the raw gateway JSON (confirmed by the #258 screenshot).
+3. **The Zen `testModelId` was dead** (410 `ModelDeprecated`) — fixed separately in #263, which also confirmed issue #258/#261's "Test Connection" failures.
+
+## Evidence (verified live 2026-10-20)
+
+| Probe | Result |
+| --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
+| Zen `POST /chat/completions` on all 10 live free models (`big-pickle`, `deepseek-v4.1-flash-free`, `glm-5.3-flash-free`, …) | HTTP 403 `FreeTierError`, message identical to the review |
+| Zen paid model (`gpt-5.4`) | HTTP 401 `AuthError` — paid models are not gated |
+| Go endpoint (any model incl. `beam-free`) | HTTP 401 "Go requires a credential" — credential check runs first, no free-tier gate |
+| `GET /zen/v1/models` | 85 models, 10 free still advertised in the catalog |
+
+**Key design fact: the gate is Zen (Console) only.** Go's own free models (`beam-free`, `minimax-m3.1-flash-free`, `longcat-2.5-preview-free`) are unlimited within a paid Go subscription and Go explicitly supports third-party clients — so the filter must be vendor-scoped, never global. Upstream maintainer statements in #49580 confirm the restriction is deliberate anti-abuse ("Our free tier is only meant to be used in opencode") and covers only the free tier; client-identity spoofing was tried by third parties and rejected upstream (every header combination still returns `FreeTierError`), so bypassing remains off the table.
+
+## Changes
+
+| File | Change |
+| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `src/config.ts` | New `isZenFreeTierModel()` with a CONTRACT comment: vendor-scoped (Zen only), lists the Go free-tier exceptions, points at upstream #49580, marked removable if upstream reopens |
+| `src/provider/definitions.ts` | Zen `filterModel` now **excludes** free-tier models unconditionally (live, cached, and bundled paths all flow through it); `CONFIG_SECTION`/`SETTING_FREE_ONLY`/`FREE_ZEN_MODEL_IDS` imports dropped |
+| `src/errors.ts` | `describeFreeTierRestriction()` / `describeRouterUnavailable()` hint now replaces the raw detail in **both** `message` and `userMessage`; raw body still logged via `[http-error-body]` in the output channel |
+| `package.json` | `opencodego.freeOnly` marked deprecated (kept registered so existing user settings don't error); description explains the policy and that the setting is ignored |
+| `README.md` | Setup steps no longer point free-tier users at Zen; free-tier models called out as unavailable from VS Code with the why and the workaround |
+| `src/test/config.test.ts` | `isZenFreeTierModel` classification (suffix, `big-pickle`, Go suffix sharing, paid negatives) |
+| `src/test/errors.test.ts` | Hint asserted in `error.message` (chat surface) and raw gateway text asserted absent from user-facing messages |
+
+## Decisions
+
+- **Ignore `freeOnly` rather than flip it.** Auto-writing user configuration without permission is worse than a documented no-op; the setting description now says so.
+- **Go free models stay selectable.** Verified unlimited-for-subscribers and not behind the gate.
+- **Model list still fetched live** — if upstream reopens the free tier, removing the `isZenFreeTierModel` gate (one function) restores visibility everywhere.
+
+## Verification
+
+- `npm run lint` — all 7 checks pass (editorconfig, eslint, markdown, prettier, shellcheck, typecheck, unit tests).
+- Live probes above re-run after the change to confirm the gate classification still matches the catalog.
+
+Follow-up to doc 106 | Detected via Marketplace review, 2026-10-20
diff --git a/package.json b/package.json
index 81607fa66..5f9686b90 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "opencode-copilot-chat",
"displayName": "OpenCode for Copilot Chat: BYOK 30+ AI Models",
- "description": "Use 30+ frontier AI models (DeepSeek V4, Kimi K2.6, GLM-5.1, Qwen3.7, MiMo V2.5, MiniMax M2.7, free Claude Opus, GPT-5.5, Gemini 3.5, Grok) in GitHub Copilot Chat. Bring Your Own Key, no Copilot Pro needed.",
+ "description": "Use 30+ frontier AI models (DeepSeek V4, Kimi K2.6, GLM-5.1, Qwen3.7, MiMo V2.5, MiniMax M2.7, Claude Opus, GPT-5.5, Gemini 3.5, Grok) in GitHub Copilot Chat. Bring Your Own Key, no Copilot Pro needed.",
"version": "0.7.9",
"publisher": "ltmoerdani",
"license": "MIT",
@@ -34,8 +34,7 @@
"chat",
"agent",
"reasoning",
- "thinking",
- "free-models"
+ "thinking"
],
"repository": {
"type": "git",
@@ -261,7 +260,7 @@
"opencodego.freeOnly": {
"type": "boolean",
"default": true,
- "description": "When enabled, only free OpenCode Zen models are shown in the Copilot model selector. Disable to include paid Zen models as well."
+ "description": "Deprecated: OpenCode restricts free Zen models to its own app/CLI since Sep 17, 2026 (403 for third-party clients), so the extension now always hides them and lists paid Zen models. This setting no longer has any effect."
},
"opencodego.enabled": {
"type": "boolean",
@@ -431,7 +430,7 @@
"off"
],
"default": "off",
- "markdownDescription": "Thinking mode for Qwen models (`qwen3.5-plus`, `qwen3.6-plus`, `qwen3.6-plus-free`). Maps to `enable_thinking`. `auto` lets the model decide (omits the flag), `on`/`off` force-enable or disable hybrid thinking. Off is the recommended default to avoid empty Copilot replies."
+ "markdownDescription": "Thinking mode for Qwen models (`qwen3.5-plus`, `qwen3.6-plus`, `qwen3.7-plus`). Maps to `enable_thinking`. `auto` lets the model decide (omits the flag), `on`/`off` force-enable or disable hybrid thinking. Off is the recommended default to avoid empty Copilot replies."
},
"opencodego.thinking.qwenBudget": {
"type": "string",
@@ -455,7 +454,7 @@
"xhigh"
],
"default": "off",
- "markdownDescription": "Thinking mode for Muse Spark models (`muse-spark-1.2-contributor`, `muse-spark-1.2-contributor-free`). Maps to the Responses API `reasoning.effort` field. Higher effort increases reasoning depth and may increase latency and usage."
+ "markdownDescription": "Thinking mode for Muse Spark models (`muse-spark-1.2-contributor`, `muse-spark-1.3-contributor`). Maps to the Responses API `reasoning.effort` field. Higher effort increases reasoning depth and may increase latency and usage."
},
"opencodego.thinking.gemini": {
"type": "string",
diff --git a/src/config.ts b/src/config.ts
index 6e4b17c08..60cba8d13 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -399,6 +399,19 @@ export const TRANSIENT_FETCH_RETRY_JITTER_MS = 250;
/** Zen free-model IDs that do not end in `-free`. */
export const FREE_ZEN_MODEL_IDS = new Set(["big-pickle"]);
+
+/**
+ * CONTRACT: OpenCode gates Zen (Console) free-tier models to their own
+ * clients since 2026-09-17 (anomalyco/opencode#49580 — issues #235/#240), so
+ * third-party clients get HTTP 403 FreeTierError on every request. Applies to
+ * ZEN ONLY: Go free models (`beam-free`, `minimax-m3.1-flash-free`,
+ * `longcat-2.5-preview-free`) are unlimited within a paid Go subscription and
+ * Go explicitly permits third-party clients, so they must stay selectable.
+ * Remove this gate if upstream ever reopens the Zen free tier.
+ */
+export function isZenFreeTierModel(modelId: string): boolean {
+ return modelId.endsWith("-free") || FREE_ZEN_MODEL_IDS.has(modelId);
+}
/**
* Models removed upstream — always filtered from the picker.
* `deepseek-v4-flash-free` / `laguna-s-2.1-free`: gone from the Zen gateway
diff --git a/src/errors.ts b/src/errors.ts
index a0b1db0a9..f46aa1ec9 100644
--- a/src/errors.ts
+++ b/src/errors.ts
@@ -55,8 +55,14 @@ export function buildOpenCodeRequestError(
);
}
- const userMessage = `${providerDisplayName} API request failed (HTTP ${String(response.status)})${modelId ? ` for ${modelId}` : ""}: ${describeFreeTierRestriction(apiMessage) ?? describeRouterUnavailable(apiError, apiMessage)}${capacityHint}`;
- const requestMessage = `${providerDisplayName} API request failed (${String(response.status)})${modelHint}${sizeHint}${capacityHint}: ${apiMessage}`;
+ // The actionable hint replaces the raw gateway detail in BOTH messages: VS
+ // Code's chat surface renders `message` (issue #258 — users saw raw gateway
+ // JSON with no explanation), while `userMessage` feeds the toast. The raw
+ // upstream body is still preserved in the provider output channel
+ // (`[http-error-body]` in transports/engine.ts), so no diagnostic is lost.
+ const hint = describeFreeTierRestriction(apiMessage) ?? describeRouterUnavailable(apiError, apiMessage);
+ const userMessage = `${providerDisplayName} API request failed (HTTP ${String(response.status)})${modelId ? ` for ${modelId}` : ""}: ${hint}${capacityHint}`;
+ const requestMessage = `${providerDisplayName} API request failed (${String(response.status)})${modelHint}${sizeHint}${capacityHint}: ${hint}`;
return new OpenCodeRequestError(requestMessage, userMessage);
}
diff --git a/src/provider/definitions.ts b/src/provider/definitions.ts
index 8fdd64462..1b2f7872c 100644
--- a/src/provider/definitions.ts
+++ b/src/provider/definitions.ts
@@ -2,15 +2,13 @@ import * as vscode from "vscode";
import {
appendApiPath,
apiRoutesFromBaseUrl,
- CONFIG_SECTION,
DEFAULT_GO_API_BASE_URL,
DEFAULT_GO_GOOGLE_MODELS_URL,
DEFAULT_ZEN_API_BASE_URL,
FALLBACK_USER_AGENT,
- FREE_ZEN_MODEL_IDS,
+ isZenFreeTierModel,
normalizeApiBaseUrl,
SETTING_API_BASE_URL,
- SETTING_FREE_ONLY,
} from "../config";
import type { ModelEndpointKind } from "../core/registry";
import type { ApiMessage } from "../request/types";
@@ -236,10 +234,11 @@ export const PROVIDERS: Record
"qwen3.5-plus",
"big-pickle",
],
- filterModel: (modelId) =>
- vscode.workspace.getConfiguration(CONFIG_SECTION).get(SETTING_FREE_ONLY, true)
- ? modelId.endsWith("-free") || FREE_ZEN_MODEL_IDS.has(modelId)
- : true,
+ // Free-tier Zen models are always hidden: OpenCode gates them to its own
+ // clients since 2026-09-17 (403 FreeTierError, upstream #49580). The
+ // `freeOnly` setting is deprecated and deliberately ignored — honoring it
+ // would leave free-only users with a picker where every model 403s.
+ filterModel: (modelId) => !isZenFreeTierModel(modelId),
};
return {
[GO_VENDOR]: go,
diff --git a/src/test/config.test.ts b/src/test/config.test.ts
index 508c2ac9b..34ca73598 100644
--- a/src/test/config.test.ts
+++ b/src/test/config.test.ts
@@ -22,6 +22,7 @@ import {
EXTENSION_ID,
FALLBACK_USER_AGENT,
FREE_ZEN_MODEL_IDS,
+ isZenFreeTierModel,
GO_LIMITS,
GO_MAX_LOG_ENTRIES,
GO_MAX_SESSIONS,
@@ -176,6 +177,16 @@ describe("config — model classification sets", () => {
assert.ok(!FREE_ZEN_MODEL_IDS.has(id), `${id} is both unavailable and free`);
}
});
+
+ it("classifies Zen free-tier models by suffix and known id (upstream #49580)", () => {
+ assert.ok(isZenFreeTierModel("deepseek-v4.1-flash-free"));
+ assert.ok(isZenFreeTierModel("big-pickle"));
+ // Go free-tier models share the -free suffix — the Zen filter is only
+ // applied to the Zen provider's filterModel, never globally.
+ assert.ok(isZenFreeTierModel("beam-free"));
+ assert.ok(!isZenFreeTierModel("gpt-5.4"));
+ assert.ok(!isZenFreeTierModel("deepseek-v4.1-flash"));
+ });
});
describe("config — storage keys", () => {
diff --git a/src/test/errors.test.ts b/src/test/errors.test.ts
index 0d3bd2e3f..c69030426 100644
--- a/src/test/errors.test.ts
+++ b/src/test/errors.test.ts
@@ -30,7 +30,11 @@ describe("describeFreeTierRestriction (issues #235/#240)", () => {
);
assert.ok(error instanceof OpenCodeRequestError);
assert.match(error.userMessage, /restricts this free-tier model to their official app/);
+ // Chat renders `message` (issue #258): the hint must be there too, and the
+ // raw gateway text must not leak into the user-facing message.
+ assert.match(error.message, /restricts this free-tier model to their official app/);
assert.match(error.message, /muse-spark-1.2-contributor-free/);
+ assert.doesNotMatch(error.message, /can only be used from within OpenCode/);
});
});