Editorial graphic titled 'Is OpenCode private by default?' with three fact cards — v1.18.28 as the tag we read, zero references left to the R2 bucket, and your first message sent twice — above a terracotta pill reading 'The Grok claim does not match the code shipping today.'

Is OpenCode private by default? Reading the source


Search for OpenCode privacy and you land on the same two claims, repeated by nearly everyone: that it ships your prompts to Grok’s free tier to name your sessions, and that authenticating through its cloud dumps every prompt and response into a Cloudflare bucket with no way out.

Every page ranking for those questions cites the same two sources: one Hacker News comment and one GitHub issue. None of them went and looked.

We did. This is a source read, not a hands-on test — we never installed or ran OpenCode. Everything below is from the published repository at tag v1.18.28, the release that was current on September 4, 2026, plus the docs that ship in the same tree.

Short version: OpenCode is not private by default in the one sense that matters, but neither of the two claims you’ll read about it is currently true. Nothing routes your prompts to Grok, and the code that stored prompts server-side is gone. What’s left is real, documented, and much less discussed: several free models on OpenCode’s own service may train on what you send them.

Key takeaways

  • The Grok claim is stale. In the current code, the model that titles your session is picked from the provider you’re already using. There is no path to xAI in it.
  • The prompt-storage code is gone. The request dumper that wrote to a Cloudflare R2 bucket doesn’t exist at this tag, and nothing references the bucket bindings any more.
  • The real answer is per-model, and it’s in the docs. Several free models on OpenCode’s own service may use your data to improve the model. The docs name them.
  • Your provider choice is the whole game. The x-opencode-* session headers are attached only when the provider ID starts with opencode. Bring your own key and they never fire.
  • One number everyone quotes isn’t OpenCode’s. The viral “68k tokens before your first message” figure comes from an issue describing a third-party agent stack, not stock OpenCode.

Does OpenCode send your prompts to Grok?

No — not in the code shipping today.

The claim comes from a comment by user heavyset_go on the Hacker News thread titled “OpenCode – Open source AI coding agent”, which reached 1,274 points on March 20, 2026. The comment went up at 04:07 UTC the next day: “By default OpenCode sends all of your prompts to Grok’s free tier to come up with chat summaries for the UI. To change that, you need to set a custom ‘small model’ in the settings.”

Here’s what the current source does instead. Session titling lives in packages/opencode/src/session/prompt.ts. It grabs the title agent, and if that agent has no model pinned it calls provider.getSmallModel(input.providerID) — passing in the provider of the session you’re already running.

That function, in packages/opencode/src/provider/provider.ts, resolves in this order:

  1. Your small_model config value, if you set one.
  2. Whatever an experimental.provider.small_model plugin returns.
  3. A small model from the same provider’s own catalog, matched by family.

Step three is the one that matters. It filters provider.models — the catalog of the provider whose ID was passed in — against a priority list, hardcoded as ["gemini-flash", "gpt-nano", "claude-haiku"], with two special cases: a provider ID starting with opencode looks for gpt-nano, and github-copilot tries gpt-mini first. Azure returns nothing on purpose, with a comment blaming unreliable deployment reporting.

If none of that matches, getSmallModel returns undefined and the caller falls back to the model you’re already using. The provider ID never changes hands. Point OpenCode at Anthropic and the title comes from a Claude model on your Anthropic key; point it at Ollama and, with no matching family, it uses whatever local model you’re running.

Diagram: two boxes inside a single bordered container, joined by an arrow that loops from one back into the other, and a separate terracotta box outside the container with nothing connecting to it

The docs match, which isn’t always a given: “The small_model option configures a separate model for lightweight tasks like title generation. By default, OpenCode tries to use a cheaper model if one is available from your provider, otherwise it falls back to your main model.” The Zen pricing page says the same thing from the billing side: “You may notice low-cost models, such as Haiku, Nano, or Flash, in your usage history. OpenCode uses these models to generate session titles.”

We can’t diff March’s code from here. We don’t have to, because a maintainer answered in that same Hacker News thread eight hours later: “this isn’t true — it will use whatever small model there is in your provider. we had a fallback where we provided free small models if your provider did not have one (gpt nano). some configs fell back to this unexpectedly which upset people so we removed it.” A second commenter dated the change to about a week before that.

So the fallback was real, and people really were surprised by it. The destination was a free small model OpenCode hosted itself, not Grok’s free tier, and it had already been pulled when the comment went up. The pages that copied the claim in May, June and August didn’t read that far down the thread.

What is still true, and nobody mentions: your first message gets sent twice. Once to your main model, and once more to the small model, prefixed with “Generate a title for this conversation:”. Nobody asks you first. It’s one extra request per session against your own provider, but if you assumed your prompt went to exactly one model, it doesn’t.

Does OpenCode store your prompts on its servers?

There was code that did exactly that. It isn’t in the repository any more.

The source of the claim is issue #14281, opened on February 19, 2026 by someone with no prior association with the project, under the title “Privacy concern: All user prompts and responses are stored server-side without disclosure or opt-out.” It’s an unusually careful report. It walks the path file by file: the CLI attaches x-opencode-session on requests to the Zen endpoint, the server handler builds a dataDumper from that session ID, the full request body and the full response both get handed to it, and the dumper writes two JSON files per request into the R2 bucket declared in infra/console.ts.

The reporter also does something the pages citing them since have not: they scope it themselves. Their own note says this applies only when using the opencode provider with an opencode.ai token, and that with your own key against api.anthropic.com the CLI bypasses the proxy entirely.

A maintainer answered in about ninety minutes: “this is only relevant for free models provided by opencode zen which is clearly documented in our docs — storeModel is only set for free models.”

That’s a flat contradiction of the report, which had traced the same guard and concluded the opposite: that standard models have storeModel configured, so every prompt gets stored in normal use. One of them is wrong about the scope of a switch in their own codebase, and the thread never settles which.

Instead it sat. A bot closed it on April 21 under a 60-days-without-activity rule — by timeout, not by resolution, which matters because a closed issue reads like a fixed one.

What we can verify is the state of the tree now:

  • packages/console/app/src/routes/zen/util/dataDumper.ts doesn’t exist at v1.18.28.
  • Grepping the whole repository for Resource.ZenData returns nothing. The ZenData and ZenDataNew buckets are still declared in infra/console.ts, and still typed in sst-env.d.ts, but no code at this tag reaches for them.
  • There is no .put( anywhere under the Zen routes.
  • The file’s commit history says it arrived on December 2, 2025 in a commit named “zen: data dumper” and was last touched on May 21, 2026. It was already gone by v1.15.12 on May 28 — the day before the page that ranks first today for “opencode review 2026” went up still describing the behavior as live.

Diagram: a row of five cards, four of them filled and outlined, with the middle one reduced to an empty dashed terracotta outline where a card used to be

What sits there instead is much narrower. A helper called requiresGoTrainingConsent returns true for exactly two model IDs — muse-spark-1.3-contributor and muse-spark-1.2-contributor, the internal constants for the Go tier, listed in the public docs with a -free suffix — and the request handler rejects those with a data-policy error unless the workspace has explicitly allowed training. That’s a consent gate on two models, not a dump of everything.

The limit on all of this: the console is server-side code. Reading the repository tells you what the project publishes, not what runs in production at opencode.ai. Nobody outside the company can close that gap by reading GitHub, and any article claiming otherwise — including a friendlier version of this one — is overreaching.

What rides along with a request to the model?

Which provider you point OpenCode at, and nothing else, decides that — the code makes the fork unusually explicit.

One scope note before the detail: this section is about inference requests, the ones carrying your prompt. It says nothing about the other things a coding agent talks to at startup — plugin fetching, the hourly model-catalog refresh, the update check, the share feature. Those need a packet capture, not a source read, and we didn’t do one.

In packages/opencode/src/session/llm/request.ts, the request headers branch on one condition: does the provider ID start with opencode? If yes, the request carries x-opencode-session, x-opencode-request, x-opencode-client and, when there is one, x-opencode-project. If no, it carries x-session-affinity, X-Session-Id and a user agent — an anonymous session ID for routing, going to the provider you chose.

That’s the fork. Everything in the storage discussion above hangs off the first branch.

One wrinkle if you never signed in: with no credentials for the opencode provider, the registration code walks its model list and deletes every model whose input cost isn’t zero. So a fresh install without an API key doesn’t get locked out of the built-in service — it gets the free models. Which are exactly the ones with conditions attached.

Those conditions are documented, per model, and they’re the part of this story that actually deserves the attention the other two claims got. Zen’s privacy section says its providers follow a zero-retention policy and don’t train on your data, then lists the exceptions by name: Big Pickle, MiMo-V2.5 Free and Ling 3.0 Flash Fin Free may use collected data to improve the model during their free period. NVIDIA’s free endpoints are labelled trial use only, with a flat instruction not to submit confidential data and a note that sessions are logged. Requests through OpenAI and Anthropic are retained 30 days under those vendors’ own policies. And the Muse Spark Contributor tiers are explicit about the trade: heavily discounted tokens in exchange for permission to train future Meta models on your prompts and completions.

The Go tier ships a table with two columns per model, model training and data retention. Most rows read “Not used / 0 days”. Grok 4.6 and GPT 5.6 Luna read 30 days. We track what each tier costs on our OpenCode pricing page.

That’s a better privacy disclosure than most closed tools manage, and it’s sitting behind a heading nobody links to. It’s also been quietly trimmed at least once: a Go subscriber has an open request from July 31 to restore per-model provider attribution that two undisclosed commits removed from the Go page and its public models endpoint, naming the commit and pasting the curl output that no longer says which upstream serves a model. Documentation that good is only worth what its edit history is worth.

Does OpenCode really burn 68,000 tokens before your first message?

Not stock OpenCode, no. And we helped move that number, so this one is ours to correct. When we measured Claude Code’s startup token overhead, we cited an OpenCode issue reporting roughly 68,000 tokens before the first user message, and said plainly that we hadn’t measured OpenCode ourselves. We still haven’t. But the issue deserved a closer read than we gave it.

Issue #26661 describes its setup in its first line: a Sisyphus agent, about 100 skills, 50-plus tools, with a “using-superpowers” skill injected at session start. Sisyphus isn’t part of OpenCode. It’s the orchestrator agent from oh-my-openagent, a third-party layer that installs on top, and the name appears nowhere in the OpenCode repository — not at v1.18.28, and not at v1.14.45, the version the reporter says they were running. So the 68k figure measures a heavily loaded third-party stack, in the same way the viral comparison it was answering measured a loaded Claude Code against a bare OpenCode. It’s a number about configuration, which was our conclusion the first time and is more true than we knew.

A maintainer closed it on June 12 as a duplicate.

What we’d check next

The thing this method can’t reach is the wire. A source read tells you what the code intends; it doesn’t tell you what a binary does when you run it, and it says nothing about server behavior at all. We did the wire version of this for what GitHub Copilot sends, and the interesting findings there were the ones no documentation mentioned.

Until someone points a proxy at a fresh OpenCode install, treat everything here as a claim about published source code — including the parts that make the tool look good.

If you’re weighing it against the alternatives, our Gemini CLI alternatives guide covers where OpenCode fits among terminal agents, and what AI coding tools do with your code covers the questions to ask of any of them. More teardowns like this one live in our guides.

  • opencode
  • privacy
  • ai-coding-assistants
  • open-source
  • terminal-agents

Frequently asked questions

Does OpenCode send your prompts to Grok?

Not in the current source. At tag v1.18.28 the model that writes your session title comes from getSmallModel(providerID), which only looks inside the provider you are already talking to — it filters that provider's own catalog for a small model family, and falls back to your main model if it finds none. There is no cross-provider hop to xAI anywhere in that path. The claim comes from a Hacker News comment posted on March 21, 2026, and a maintainer answered in that same thread eight hours later to say it was already wrong: there had been a fallback to a free small model OpenCode hosted itself, gpt-nano rather than Grok, and it had been removed. So the destination was never xAI, and the mechanism was gone before the claim started circulating.

Does OpenCode store your prompts on its own servers?

There was code that did, and it is gone at v1.18.28. A February 2026 issue traced a request dumper writing full requests and responses to a Cloudflare R2 bucket for traffic through OpenCode's Zen proxy. That file no longer exists in the repository, nothing references the R2 bucket bindings, and the Zen route writes nothing to a bucket. One caveat we can't clear: this is server-side code, so the repository tells you what is published, not what is deployed.

Is it safe to use OpenCode with proprietary code?

The variable is which provider you point it at, not the agent. With your own API key against Anthropic, OpenAI, or a local model, requests go to that provider and the opencode-specific session headers are never attached — the code gates them on the provider ID starting with 'opencode'. Through OpenCode's own Zen or Go service the terms are per-model, and the free models are the ones with strings attached.

Do the free models on OpenCode Zen train on your code?

Some do, and the docs say so model by model. Zen's privacy section states its providers follow a zero-retention policy with named exceptions: Big Pickle, MiMo-V2.5 Free and Ling 3.0 Flash Fin Free may use collected data to improve the model during their free period, NVIDIA's free endpoints log sessions and are labelled trial use only, and the Muse Spark Contributor tiers trade discounted pricing for permission to train future Meta models on your prompts and completions.