| description | OpenCode's free-tier models inside DeepSeek Harness, served by a local OpenCode process. |
|---|---|
| kind | group |
English | 中文
Use OpenCode's free-tier models inside DeepSeek Harness. The harness
already reads the opencode and opencode-go providers from the shared
models.dev catalogue, and those work — but only with an OpenCode API key. Their
free models fail, because the gateway refuses them for any client that is not
OpenCode:
OpenCode's free tier can only be used from within OpenCode
This plugin adds a separate provider route, opencode-free, that reaches those
same free models. It starts a real opencode serve process and asks that
process to run each turn, so the request genuinely originates from OpenCode and
the free models resolve. No API key is involved. This is the same arrangement
OpenChamber uses.
Requires the OpenCode CLI on your PATH (opencode --version).
From the npm registry, once published:
dsh plugin add dsh-deep-opencodeFrom GitHub:
dsh plugin add https://github.com/temidayoxyz/deep-opencodeThe built entry point is committed, so a GitHub install needs no build step —
pnpm refuses to run a git dependency's install scripts, and the package has no
prepare script to run.
To work on it locally instead, clone and install from the path:
git clone https://github.com/temidayoxyz/deep-opencode.git
cd deep-opencode && npm install && npm run build
dsh plugin add D:/path/to/deep-opencodeOr add it to a profile's cordis.patch.yml:
- name: dsh-deep-opencodePick provider opencode-free in the model selector. The models listed are
whatever your installed OpenCode version currently serves for free — read from
the running server, not pinned in this plugin, so a newly added free model shows
up on its own and a retired one disappears on its own.
As of OpenCode v2.0.18 that is: Big Pickle, Ling 3.0 Flash Fin Free, LongCat 2.5 Preview Free, MiMo-V2.6-Flash Free, Muse Spark 1.3 Free, Nemotron 3.5 Lightning Free, Nemotron 3 Ultra Free, and Space Bunny Free.
Every deployment-varying value is a cordis.yml field:
| Field | Default | Meaning |
|---|---|---|
opencodeCommand |
opencode |
Executable name or path, resolved through PATH. |
cwd |
harness working directory | Project directory for a session that has none, and where the model catalogue is read. A session with a project always uses its own. |
host |
127.0.0.1 |
Loopback host the managed server binds. |
port |
0 |
Port for the managed server; 0 lets the OS choose a free one. |
startupTimeoutMs |
120000 |
Deadline for the server to report its listening URL. |
turnTimeoutMs |
900000 |
Bound on one delegated turn; 0 disables it. |
reuseSessions |
true |
Keep one OpenCode session per Harness session so turns recall each other. false restores one provider session per request. |
maxSessionMappings |
32 |
Maximum Harness sessions mapped to a provider session at once; the least recently used is evicted. |
sessionIdleTtlMs |
1800000 |
Idle lifetime of a mapping; 0 disables idle reclamation. |
sessionTurnGraceMs |
600000 |
Reclaim grace window protecting a turn in flight. |
logDiagnostics |
true |
Report the managed server's version and discovered models on load. |
- name: dsh-deep-opencode
config:
opencodeCommand: opencode
turnTimeoutMs: 1200000The first turn of a conversation sends the system prompt, the capability list,
and the whole exchange labelled User: / Assistant:. Later turns send only the
messages that are new, because OpenCode already holds the rest. The model sees
its own prior turns through OpenCode's session rather than through text this
plugin resends.
This plugin adds no input tokens of its own. The label prefixes and the
capability line are part of the delegated instruction, and the provider's own
counting is reported unchanged in usage.
Independent per turn, and better than a fresh request: the delegated turn runs inside one OpenCode session, so the provider's own prefix cache survives across turns. A follow-up sends only the new message, so it re-reads a stable prefix rather than a rebuilt transcript. A rewritten past message replays the whole conversation, which invalidates that reuse.
- Continuity is held by the provider, not the log. A turn sends only what is new, because OpenCode keeps the conversation itself. If Harness rewrites a past message — a compaction, a fork — the cursor loses its anchor and the whole conversation is replayed into a fresh provider session. Continuity then resets to what was replayed.
- A fork starts a new provider session. An inherited prefix is not replayed into the child, so a forked session's provider memory begins at the fork point.
- Token accounting counts the whole conversation each turn. The provider holds the history, so per-turn input tokens reflect everything it re-reads, while the Harness log only records what was sent.
- OpenCode owns the turn, not the harness. The delegated run uses OpenCode's own agent and its own tools, so a dsh tool is not what runs on a turn driven by this route. The harness still owns the session log, the transcript, and the turn lifecycle.
- One managed server per project directory. OpenCode fixes a session's project
when its process starts, and ignores a per-request directory, so each session's
own directory gets its own
opencode serve. Work in several projects at once therefore costs one OpenCode process per project. - A session with no project directory falls back to the
cwdconfig field, or the harness's own working directory when that is unset. - Conversation history is flattened per turn. Prior turns are sent as labelled text rather than replayed as structured history, because OpenCode runs a fresh session per request and never saw the earlier exchanges.
- Only the free models are offered. A paid OpenCode model is reachable
through the harness's own
opencode/opencode-goproviders with a key; this route deliberately lists only zero-cost models, because a paid model reached through a free route would be a real charge. - A model the installed OpenCode does not serve cannot be used here, even if a catalogue lists it as free. Availability is whatever the running server reports, which is why the list is discovered rather than hard-coded.
- The transcript reports tools as removed. A turn driven by this route returns text and never a tool call, while the request declared the harness's tools, so the transcript shows the tool set being emptied once per turn. That is the delegation boundary showing through: OpenCode's own tools ran instead, and the harness did not observe them.
- No reasoning-effort selection. OpenCode chooses its own reasoning settings; this route does not expose the provider's effort levels.
- Image inputs are not forwarded. Only text reaches the delegated turn, so a model that accepts images is still driven with text here.
- A missing or broken OpenCode install fails at request time, not at mount: the route stays registered so a repaired install works without reloading the profile. Load-time discovery failure is logged as a warning.
- One managed server per Host. Reloading the plugin terminates and relaunches it, which drops in-flight delegated turns.
MIT