summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--cloud/app/src/routes/index.css81
-rw-r--r--cloud/app/src/routes/index.tsx34
-rw-r--r--cloud/app/src/routes/workspace/[id].tsx6
-rw-r--r--packages/web/astro.config.mjs10
-rw-r--r--packages/web/config.mjs4
-rw-r--r--packages/web/src/content/docs/docs/enterprise.mdx7
-rw-r--r--packages/web/src/content/docs/docs/providers.mdx281
-rw-r--r--packages/web/src/content/docs/docs/zen.mdx95
8 files changed, 347 insertions, 171 deletions
diff --git a/cloud/app/src/routes/index.css b/cloud/app/src/routes/index.css
index 0a903026c..c4b1fb726 100644
--- a/cloud/app/src/routes/index.css
+++ b/cloud/app/src/routes/index.css
@@ -78,22 +78,22 @@
[data-component="cta"] {
border-top: 2px solid var(--color-border);
- display: grid;
- grid-template-columns: auto 1fr auto;
- align-items: stretch;
+ display: flex;
& > div + div {
border-left: 2px solid var(--color-border);
}
- [data-slot="left"],
- [data-slot="right"] {
+ [data-slot="left"] {
+ flex: 0 0 auto;
text-align: center;
line-height: 1.4;
padding: var(--vertical-padding) 2rem;
text-transform: uppercase;
+ font-size: 1.125rem;
@media (max-width: 30rem) {
+ font-size: 1rem;
padding-bottom: calc(var(--vertical-padding) + 4px);
}
@@ -103,53 +103,18 @@
}
}
- [data-slot="center"] {
+ [data-slot="right"] {
+ flex: 1;
padding: var(--vertical-padding) 1rem;
}
- @media (max-width: 55rem) {
- display: grid;
- grid-template-columns: 1fr 1fr;
- grid-template-rows: auto auto;
-
- [data-slot="left"] {
- grid-column: 1;
- grid-row: 1;
- }
+ @media (max-width: 50rem) {
+ flex-direction: column;
[data-slot="right"] {
- grid-column: 2;
- grid-row: 1;
- }
-
- [data-slot="center"] {
- grid-column: 1 / -1;
- grid-row: 2;
border-left: none;
border-top: 2px solid var(--color-border);
}
-
- @media (max-width: 22rem) {
- grid-template-columns: 1fr;
- grid-template-rows: auto auto auto;
-
- [data-slot="left"] {
- grid-column: 1;
- grid-row: 1;
- }
-
- [data-slot="right"] {
- grid-column: 1;
- grid-row: 2;
- border-top: 2px solid var(--color-border);
- border-left: none;
- }
-
- [data-slot="center"] {
- grid-column: 1;
- grid-row: 3;
- }
- }
}
[data-slot="command"] {
@@ -168,7 +133,7 @@
@media (max-width: 24rem) {
font-size: 0.875rem;
}
- @media (max-width: 64rem) {
+ @media (max-width: 56rem) {
[data-slot="protocol"] {
display: none;
}
@@ -188,6 +153,32 @@
}
}
+ [data-component="zen"] {
+ border-top: 2px solid var(--color-border);
+ text-align: center;
+ font-size: 1.125rem;
+ padding: var(--vertical-padding) 2rem;
+
+ @media (max-width: 30rem) {
+ font-size: 1rem;
+ padding-left: 1rem;
+ padding-right: 1rem;
+ }
+
+ a[target="_self"] {
+ text-transform: uppercase;
+ }
+
+ [data-slot="description"] {
+ color: var(--color-text-secondary);
+ }
+
+ [data-slot="divider"] {
+ font-weight: bold;
+ color: var(--color-border);
+ }
+ }
+
[data-component="features"] {
border-top: 2px solid var(--color-border);
padding: var(--padding);
diff --git a/cloud/app/src/routes/index.tsx b/cloud/app/src/routes/index.tsx
index a3bc8285b..4f8e671da 100644
--- a/cloud/app/src/routes/index.tsx
+++ b/cloud/app/src/routes/index.tsx
@@ -11,6 +11,7 @@ import { createAsync, query, redirect } from "@solidjs/router"
import { getActor } from "~/context/auth"
import { withActor } from "~/context/auth.withActor"
import { Account } from "@opencode/cloud-core/account.js"
+import { Show } from "solid-js"
function CopyStatus() {
return (
@@ -26,13 +27,13 @@ const isLoggedIn = query(async () => {
const actor = await getActor()
if (actor.type === "account") {
const workspaces = await withActor(() => Account.workspaces())
- throw redirect(`/workspace/${workspaces[0].id}`)
+ return workspaces[0].id
+ // throw redirect(`/workspace/${workspaces[0].id}`)
}
- return false
}, "isLoggedIn")
export default function Home() {
- createAsync(() => isLoggedIn(), {
+ const workspaceId = createAsync(() => isLoggedIn(), {
deferStream: true,
})
onMount(() => {
@@ -69,7 +70,7 @@ export default function Home() {
<div data-slot="left">
<a href="/docs">Get Started</a>
</div>
- <div data-slot="center">
+ <div data-slot="right">
<button data-copy data-slot="command">
<span>
<span>curl -fsSL&nbsp;</span>
@@ -80,13 +81,28 @@ export default function Home() {
<CopyStatus />
</button>
</div>
- <div data-slot="right">
- <a href="/auth/authorize" target="_self">
- Login
- </a>
- </div>
</section>
+ <Show when={false}>
+ <section data-component="zen">
+ <a href="/docs/zen">opencode zen</a>
+ <span data-slot="description">
+ , a curated list of models provided by opencode
+ </span>
+ <span data-slot="divider">&nbsp;/&nbsp;</span>
+ <a
+ href={
+ workspaceId()
+ ? `/workspace/${workspaceId()}`
+ : "/auth/authorize"
+ }
+ target="_self"
+ >
+ Sign in
+ </a>
+ </section>
+ </Show>
+
<section data-component="features">
<ul data-slot="list">
<li>
diff --git a/cloud/app/src/routes/workspace/[id].tsx b/cloud/app/src/routes/workspace/[id].tsx
index 38e19612a..b10a87e81 100644
--- a/cloud/app/src/routes/workspace/[id].tsx
+++ b/cloud/app/src/routes/workspace/[id].tsx
@@ -63,7 +63,7 @@ const createPortalUrl = action(async (returnUrl: string) => {
return withActor(() => Billing.generatePortalUrl({ returnUrl }))
}, "portalUrl")
-export default function () {
+export default function() {
/////////////////
// Keys section
@@ -180,9 +180,9 @@ export default function () {
<div data-slot="root">
{/* Title */}
<section data-slot="title-section">
- <h1>Gateway</h1>
+ <h1>opencode zen</h1>
<p>
- Coding models optimized for use with opencode. <a href="/docs">Learn more</a>.
+ Curated list of models provided by opencode. <a href="/docs/zen">Learn more</a>.
</p>
</section>
diff --git a/packages/web/astro.config.mjs b/packages/web/astro.config.mjs
index 350d0b31b..c23b5a4e0 100644
--- a/packages/web/astro.config.mjs
+++ b/packages/web/astro.config.mjs
@@ -67,7 +67,15 @@ export default defineConfig({
{
label: "Usage",
- items: ["docs/tui", "docs/cli", "docs/ide", "docs/share", "docs/github", "docs/gitlab"],
+ items: [
+ "docs/tui",
+ "docs/cli",
+ "docs/ide",
+ // "docs/zen",
+ "docs/share",
+ "docs/github",
+ "docs/gitlab"
+ ],
},
{
diff --git a/packages/web/config.mjs b/packages/web/config.mjs
index bb1ec003b..c13ed125f 100644
--- a/packages/web/config.mjs
+++ b/packages/web/config.mjs
@@ -4,6 +4,10 @@ export default {
url: stage === "production"
? "https://opencode.ai"
: `https://${stage}.opencode.ai`,
+ console: stage === "production"
+ ? "https://console.opencode.ai"
+ : `https://console.${stage}.opencode.ai`,
+ email: "[email protected]",
socialCard: "https://social-cards.sst.dev",
github: "https://github.com/sst/opencode",
discord: "https://opencode.ai/discord",
diff --git a/packages/web/src/content/docs/docs/enterprise.mdx b/packages/web/src/content/docs/docs/enterprise.mdx
index 3783f5478..3e4b281e0 100644
--- a/packages/web/src/content/docs/docs/enterprise.mdx
+++ b/packages/web/src/content/docs/docs/enterprise.mdx
@@ -3,13 +3,16 @@ title: Enterprise
description: Using opencode in your organization.
---
+import config from "../../../../config.mjs"
+export const email = `mailto:${config.email}`
+
opencode does not store any of your code or context data. This makes it easy for
you to use opencode at your organization.
To get started, we recommend:
1. Do a trial internally with your team.
-2. [**Contact us**](mailto:[email protected]) to discuss pricing and implementation options.
+2. **<a href={email}>Contact us</a>** to discuss pricing and implementation options.
---
@@ -55,7 +58,7 @@ We recommend you disable this for your trial.
## Deployment
Once you have completed your trial and you are ready to self-host opencode at
-your organization, you can [**contact us**](mailto:[email protected]) to discuss
+your organization, you can **<a href={email}>contact us</a>** to discuss
pricing and implementation options.
---
diff --git a/packages/web/src/content/docs/docs/providers.mdx b/packages/web/src/content/docs/docs/providers.mdx
index de1cf8b39..2e8a3b5a3 100644
--- a/packages/web/src/content/docs/docs/providers.mdx
+++ b/packages/web/src/content/docs/docs/providers.mdx
@@ -3,6 +3,9 @@ title: Providers
description: Using any LLM provider in opencode.
---
+import config from "../../../../config.mjs"
+export const console = config.console
+
opencode uses the [AI SDK](https://ai-sdk.dev/) and [Models.dev](https://models.dev) to support for **75+ LLM providers** and it supports running local models.
To add a provider you need to:
@@ -45,123 +48,21 @@ You can customize the base URL for any provider by setting the `baseURL` option.
---
-## Custom provider
+## opencode zen
-To add any **OpenAI-compatible** provider that's not listed in `opencode auth login`:
+opencode zen is a list of models provided by the opencode team that have been
+tested and verified to work well with opencode. [Learn more](/docs/zen).
:::tip
-You can use any OpenAI-compatible provider with opencode. Most modern AI providers offer OpenAI-compatible APIs.
+If you are new, we recommend starting with opencode zen.
:::
-1. Run `opencode auth login` and scroll down to **Other**.
-
- ```bash
- $ opencode auth login
-
- ┌ Add credential
- │
- ◆ Select provider
- │ ...
- │ ● Other
- └
- ```
-
-2. Enter a unique ID for the provider.
-
- ```bash
- $ opencode auth login
-
- ┌ Add credential
- │
- ◇ Enter provider id
- │ myprovider
- └
- ```
-
- :::note
- Choose a memorable ID, you'll use this in your config file.
- :::
-
-3. Enter your API key for the provider.
-
- ```bash
- $ opencode auth login
-
- ┌ Add credential
- │
- ▲ This only stores a credential for myprovider - you will need configure it in opencode.json, check the docs for examples.
- │
- ◇ Enter your API key
- │ sk-...
- └
- ```
-
-4. Create or update your `opencode.json` file in your project directory:
-
- ```json title="opencode.json" ""myprovider"" {5-15}
- {
- "$schema": "https://opencode.ai/config.json",
- "provider": {
- "myprovider": {
- "npm": "@ai-sdk/openai-compatible",
- "name": "My AI ProviderDisplay Name",
- "options": {
- "baseURL": "https://api.myprovider.com/v1"
- },
- "models": {
- "my-model-name": {
- "name": "My Model Display Name"
- }
- }
- }
- }
- }
- ```
-
- Here are the configuration options:
-
- - **npm**: AI SDK package to use, `@ai-sdk/openai-compatible` for OpenAI-compatible providers
- - **name**: Display name in UI.
- - **models**: Available models.
- - **options.baseURL**: API endpoint URL.
- - **options.apiKey**: Optionally set the API key, if not using auth.
- - **options.headers**: Optionally set custom headers.
-
- More on the advanced options in the example below.
-
-5. Run the `/models` command and your custom provider and models will appear in the selection list.
-
----
-
-##### Example
-
-Here's an example setting the `apiKey` and `headers` options.
-
-```json title="opencode.json" {9,11}
-{
- "$schema": "https://opencode.ai/config.json",
- "provider": {
- "myprovider": {
- "npm": "@ai-sdk/openai-compatible",
- "name": "My AI ProviderDisplay Name",
- "options": {
- "baseURL": "https://api.myprovider.com/v1",
- "apiKey": "{env:ANTHROPIC_API_KEY}",
- "headers": {
- "Authorization": "Bearer custom-token"
- }
- },
- "models": {
- "my-model-name": {
- "name": "My Model Display Name"
- }
- }
- }
- }
-}
-```
+1. You sign in to **<a href={console}>opencode zen</a>** and get your API key.
+2. You run `opencode auth login` and select opencode zen and add your API key.
+3. Run `/models` in the TUI to see the list of models we recommend.
-We are setting the `apiKey` using the `env` variable syntax, [learn more](/docs/config#env-vars).
+It works like any other provider in opencode. And is completely optional to use
+it.
---
@@ -648,6 +549,44 @@ In this example:
---
+### opencode zen
+
+opencode zen is a list of tested and verified models provided by the opencode team. [Learn more](/docs/zen).
+
+1. Sign in to **<a href={console}>opencode zen</a>** and click **Create API Key**.
+
+2. Run `opencode auth login` and select **opencode zen**.
+
+ ```bash
+ $ opencode auth login
+
+ ┌ Add credential
+ │
+ ◆ Select provider
+ │ ● opencode zen
+ │ ...
+ └
+ ```
+
+3. Enter your opencode API key.
+
+ ```bash
+ $ opencode auth login
+
+ ┌ Add credential
+ │
+ ◇ Select provider
+ │ opencode zen
+ │
+ ◇ Enter your API key
+ │ _
+ └
+ ```
+
+4. Run the `/models` command to select a model like _Qwen 3 Coder 480B_.
+
+---
+
### OpenRouter
1. Head over to the [OpenRouter dashboard](https://openrouter.ai/settings/keys), click **Create API Key**, and copy the key.
@@ -812,6 +751,126 @@ monitor and improve Grok Code.
---
+## Custom provider
+
+To add any **OpenAI-compatible** provider that's not listed in `opencode auth login`:
+
+:::tip
+You can use any OpenAI-compatible provider with opencode. Most modern AI providers offer OpenAI-compatible APIs.
+:::
+
+1. Run `opencode auth login` and scroll down to **Other**.
+
+ ```bash
+ $ opencode auth login
+
+ ┌ Add credential
+ │
+ ◆ Select provider
+ │ ...
+ │ ● Other
+ └
+ ```
+
+2. Enter a unique ID for the provider.
+
+ ```bash
+ $ opencode auth login
+
+ ┌ Add credential
+ │
+ ◇ Enter provider id
+ │ myprovider
+ └
+ ```
+
+ :::note
+ Choose a memorable ID, you'll use this in your config file.
+ :::
+
+3. Enter your API key for the provider.
+
+ ```bash
+ $ opencode auth login
+
+ ┌ Add credential
+ │
+ ▲ This only stores a credential for myprovider - you will need configure it in opencode.json, check the docs for examples.
+ │
+ ◇ Enter your API key
+ │ sk-...
+ └
+ ```
+
+4. Create or update your `opencode.json` file in your project directory:
+
+ ```json title="opencode.json" ""myprovider"" {5-15}
+ {
+ "$schema": "https://opencode.ai/config.json",
+ "provider": {
+ "myprovider": {
+ "npm": "@ai-sdk/openai-compatible",
+ "name": "My AI ProviderDisplay Name",
+ "options": {
+ "baseURL": "https://api.myprovider.com/v1"
+ },
+ "models": {
+ "my-model-name": {
+ "name": "My Model Display Name"
+ }
+ }
+ }
+ }
+ }
+ ```
+
+ Here are the configuration options:
+
+ - **npm**: AI SDK package to use, `@ai-sdk/openai-compatible` for OpenAI-compatible providers
+ - **name**: Display name in UI.
+ - **models**: Available models.
+ - **options.baseURL**: API endpoint URL.
+ - **options.apiKey**: Optionally set the API key, if not using auth.
+ - **options.headers**: Optionally set custom headers.
+
+ More on the advanced options in the example below.
+
+5. Run the `/models` command and your custom provider and models will appear in the selection list.
+
+---
+
+##### Example
+
+Here's an example setting the `apiKey` and `headers` options.
+
+```json title="opencode.json" {9,11}
+{
+ "$schema": "https://opencode.ai/config.json",
+ "provider": {
+ "myprovider": {
+ "npm": "@ai-sdk/openai-compatible",
+ "name": "My AI ProviderDisplay Name",
+ "options": {
+ "baseURL": "https://api.myprovider.com/v1",
+ "apiKey": "{env:ANTHROPIC_API_KEY}",
+ "headers": {
+ "Authorization": "Bearer custom-token"
+ }
+ },
+ "models": {
+ "my-model-name": {
+ "name": "My Model Display Name"
+ }
+ }
+ }
+ }
+}
+```
+
+We are setting the `apiKey` using the `env` variable syntax, [learn more](/docs/config#env-vars).
+
+---
+
## Troubleshooting
If you are having trouble with configuring a provider, check the following:
diff --git a/packages/web/src/content/docs/docs/zen.mdx b/packages/web/src/content/docs/docs/zen.mdx
new file mode 100644
index 000000000..46d457932
--- /dev/null
+++ b/packages/web/src/content/docs/docs/zen.mdx
@@ -0,0 +1,95 @@
+---
+title: Zen
+description: Curated list of models provided by opencode.
+---
+
+import config from "../../../../config.mjs"
+export const console = config.console
+export const email = `mailto:${config.email}`
+
+opencode zen is a list of tested and verified models provided by the opencode team.
+
+:::note
+opencode zen is currently in beta.
+:::
+
+Zen works like any other provider in opencode. You login to opencode zen and get
+your API key. It's **completely optional** and you don't need to use it to use
+opencode.
+
+---
+
+## Background
+
+There are a large number of models out there but only a few of
+these models work well as coding agents. Additionally, most providers are
+configured very differently; so you get very different performance and quality.
+
+:::tip
+We tested a select group of models and providers that work well with opencode.
+:::
+
+So if you are using a model through something like OpenRouter, you can never be
+sure if you are getting the best version of the model you want.
+
+To fix this, we did a couple of things:
+
+1. We tested a select group of models and talked to their teams about how to
+ best run them.
+2. We then worked with a few providers to make sure these were being served
+ correctly.
+3. Finally, we benchmarked the combination of the model/provider and came up
+ with a list that we feel good recommending.
+
+opencode zen is an AI gateway that gives you access to these models.
+
+---
+
+## Motivation
+
+We created opencode zen to:
+
+1. **Benchmark** the best models/providers for coding agents.
+2. Access to **highest quality**; we don't downgrade performance or route to cheaper providers.
+3. **Sell at cost**; the only markup is to cover our processing fees and any price
+ drops will be passed along.
+4. **No lock-in**; you can use opencode zen with any other coding agent and you
+ can use any other provider with opencode.
+
+---
+
+## How it works
+
+opencode zen works like any other provider in opencode.
+
+1. You sign in to **<a href={console}>opencode zen</a>** and get your API key.
+2. You run `opencode auth login` and select opencode zen and add your API key.
+3. Run `/models` in the TUI to see the list of models we recommend.
+
+You are charged per request and you can add credits to your account.
+
+---
+
+## Pricing
+
+Below are the models that we currently support and their prices **per 1M
+tokens**.
+
+| Model | Input | Output |
+| ----- | ----- | ------ |
+| Qwen3 Coder 480B | $0.38 | $0.50 |
+| Grok Code Fast 1 | Free | Free |
+| Sonnet 4 | Soon | Soon |
+
+:::note
+We add a small markup to cover our costs.
+:::
+
+A couple of notes:
+
+- These are the raw prices based on the provider we are using internally. We
+charge a small markup on top of this to cover our processing fees.
+- Grok Code Fast 1 is currently free on opencode till Sep 10th. The xAI team is
+ using this time to collect feedback and improve Grok Code.
+
+<a href={email}>Contact us</a> if you have any questions.