TL;DR
Configure CometAPI once in OpenCode, then select Claude, GPT, or DeepSeek for your programming task. This guide expands the official CometAPI OpenCode integration guide into a complete project setup: one CometAPI API key, a configuration file with three model examples, model-switching commands, and a small JavaScript task with a repeatable check.
Key Takeaways
- OpenCode CometAPI setup requires a provider ID, API base URL, credential, and model ID.
- Use {env:COMETAPI_KEY} to keep the actual API key out of opencode.json.
- Register Claude, GPT, and DeepSeek examples in one opencode.json; all three entries use the same CometAPI key and gateway.
- Switch the selected provider/model in OpenCode without obtaining separate Anthropic, OpenAI, and DeepSeek keys.
- Watch for missing environment variables, mismatched API routes, and approval prompts that can look like stalled requests.
What Is OpenCode and Why Use It with CometAPI?
OpenCode is an open-source AI coding agent with a terminal interface, desktop app, and IDE extension. In a project, it can explain existing code, plan a change, edit files, and run commands under configured permissions. This tutorial uses the terminal workflow: give the agent a small programming task, review its proposed actions, and verify the resulting files with a local test. See the official OpenCode documentation for installation and usage.
CometAPI provides the model access layer. A multi-model workflow otherwise involves managing credentials, billing, and connection settings across suppliers. Routing supported models through one CometAPI account gives this project a shared key and base URL, while OpenCode retains the repository and task instructions. This is useful when comparing models on the same task or changing the selected model without reorganizing the project. An aggregation gateway is optional: direct supplier access may fit a single-provider workflow or specific contractual requirements. The benefit here is simpler multi-provider access; API formats, model behavior, and tool compatibility still need separate validation.
CometAPI supports OpenAI-compatible Chat Completions and also exposes other API formats. The official integration selects an adapter for each format. Here, Claude Sonnet 5 uses Messages, GPT-6.1 Sol uses Responses, and DeepSeek V4.1 Flash uses Chat Completions, following the examples linked below. All requests still go to CometAPI with the same key. A supplier name and an API format describe different things; a single model should not be assumed to accept every format.
| Configuration | Claude Sonnet 5 API in CometAPI | GPT-6.1 Sol API in CometAPI | DeepSeek V4.1 Flash API in CometAPI |
|---|---|---|---|
| Model supplier | Anthropic | OpenAI | DeepSeek |
| Model ID | claude-sonnet-5 | gpt-6.1-sol | deepseek-v4.1-flash |
| OpenCode provider ID | cometapi-messages | cometapi-responses | cometapi-chat |
| API format used here | Messages | Responses/ chat | Chat Completions |
| Adapter | @ai-sdk/anthropic | @ai-sdk/openai | @ai-sdk/openai-compatible |
What Do You Need Before Configuring CometAPI in OpenCode?
Use a terminal, Node.js with npm, a CometAPI account with API access and available balance, and a disposable project directory. Bash examples apply to macOS, Linux, or WSL; the labeled PowerShell examples use Windows syntax. Node.js must also be available in the same session for the JavaScript check later in this guide.
This walkthrough uses the OpenCode 1 configuration style. The official documentation distinguishes OpenCode 1 from OpenCode 2; both use the opencode command. Record opencode --version before starting and use the configuration documentation for that major version. The three-model workflow below is an integration walkthrough with expected outcomes, not a claim of a completed end-to-end test.
Record your CLI, Node.js, npm, operating system, and test date when running the examples. API usage is billed to your CometAPI account. The commands below are a hands-on walkthrough with expected outcomes; no model-generated output or successful three-model integration run is claimed.
node --versionnpm --versionopencode --version
How to Configure CometAPI in OpenCode Step by Step?
Step 1: Install OpenCode
Install the official npm package if OpenCode is not already available. The unpinned installation follows the current package release; record the installed version before using the configuration. If you need to reproduce the source guideโs environment, its stated CLI version is 1.18.16.
Install the OpenCode CLI and display its version.
npm install -g opencode-aiopencode --version
Open a new terminal if the executable is not found after installation. Continue inside a disposable project directory so the first agent task has a clear boundary.
Create and enter a project directory.
mkdir cometapi-opencode-democd cometapi-opencode-demo
Step 2: Create a CometAPI API Key
Generate an API key from your CometAPI account and set it in the same terminal used to start OpenCode. Replace the placeholder locally. Do not commit the key, paste it into prompts, or include it in shared logs.
The variable applies to the current shell and processes launched from it. Do not screenshot a real token. The following checks report whether the variable exists without printing its value.
Set the CometAPI key for the current Bash session.
export COMETAPI_KEY="YOUR_COMETAPI_KEY"
Set the CometAPI key for the current PowerShell session.
$env:COMETAPI_KEY = "YOUR_COMETAPI_KEY"test -n "$COMETAPI_KEY" && printf "COMETAPI_KEY is set\n" || printf "COMETAPI_KEY is missing\n"if ([string]::IsNullOrWhiteSpace($env:COMETAPI_KEY)) { ย "COMETAPI_KEY is missing"} else { ย "COMETAPI_KEY is set"}
Step 3: Create opencode.json
Create opencode.json in the project root, or use ~/.config/opencode/opencode.json to make the entries available across projects. The project file keeps this tutorial self-contained. Use a single provider object containing the three entries below; if a provider object already exists, merge its entries instead of creating a duplicate JSON key.
For conflicting fields, project configuration overrides global configuration; non-conflicting fields are retained. The custom OPENCODE_CONFIG file is loaded between global and project configuration. Check the documented precedence chain if managed or inline settings are also present.
Save the following complete configuration as opencode.json. Each provider reads COMETAPI_KEY from the environment. The default model is deliberately omitted so you can explicitly choose one of the three examples.
The Flash variant makes the requested DeepSeek V4.1 example explicit. Keep GPT on the Responses adapter for tool use; the CometAPI DeepSeek guide documents the Chat Completions route used here. Recheck model availability and permissions in your account before running the examples.
{ ย "$schema": "https://opencode.ai/config.json", ย "provider": { ย ย "cometapi-messages": { ย ย ย "npm": "@ai-sdk/anthropic", ย ย ย "name": "CometAPI Claude", ย ย ย "options": { ย ย ย ย "baseURL": "https://api.cometapi.com/v1", ย ย ย ย "apiKey": "{env:COMETAPI_KEY}" ย ย }, ย ย ย "models": { ย ย ย ย "claude-sonnet-5": { ย ย ย ย ย "name": "Claude Sonnet 5" ย ย ย } ย ย } ย }, ย ย "cometapi-responses": { ย ย ย "npm": "@ai-sdk/openai", ย ย ย "name": "CometAPI GPT", ย ย ย "options": { ย ย ย ย "baseURL": "https://api.cometapi.com/v1", ย ย ย ย "apiKey": "{env:COMETAPI_KEY}" ย ย }, ย ย ย "models": { ย ย ย ย "gpt-6.1-sol": { ย ย ย ย ย "name": "GPT-6.1 Sol" ย ย ย } ย ย } ย }, ย ย "cometapi-chat": { ย ย ย "npm": "@ai-sdk/openai-compatible", ย ย ย "name": "CometAPI DeepSeek", ย ย ย "options": { ย ย ย ย "baseURL": "https://api.cometapi.com/v1", ย ย ย ย "apiKey": "{env:COMETAPI_KEY}" ย ย }, ย ย ย "models": { ย ย ย ย "deepseek-v4.1-flash": { ย ย ย ย ย "name": "DeepSeek V4.1 Flash" ย ย ย } ย ย } ย } }, ย "permission": { ย ย "edit": "ask", ย ย "shell": "ask" }}
Correct baseURL: https://api.cometapi.com/v1. Incorrect baseURL: https://api.cometapi.com/v1/chat/completions. The adapter adds the endpoint path. Merge the example into an existing opencode.json without removing unrelated settings.
The edit and shell settings request approval for file changes and commands under the current OpenCode permission rules. Run the coding examples interactively and inspect those requests. OpenCode also inherits the operating-system access of its launching process; use a disposable directory for this exercise.
Step 4: Check the Gateway Connection
Optional Gemini setup and verification are provided after the three-model connection checks below.
The HTTP example below checks the DeepSeek Chat Completions entry directly. It is a useful way to isolate the gateway connection from OpenCode. Claude and GPT use their selected adapter routes in the next step; changing the model ID inside this HTTP request does not automatically change its protocol.
Send a minimal Chat Completions request from Bash.
curl --silent --show-error \ ย --output response.json \ ย --write-out "HTTP %{http_code}\n" \ https://api.cometapi.com/v1/chat/completions \ ย -H "Authorization: Bearer $COMETAPI_KEY" \ ย -H "Content-Type: application/json" \ ย -d '{"model":"deepseek-v4.1-flash","messages":[{"role":"user","content":"Reply with a short greeting."}]}'
This command uses curl write-out and output options to separate the HTTP status from response.json. A successful transfer can still contain an HTTP error, so inspect the printed status and the JSON body. This avoids depending on --fail-with-body, which requires curl 7.76.0 or later.
Send the same request from PowerShell without shell-specific JSON quoting.
$body = @{ ย model = "deepseek-v4.1-flash" ย messages = @(@{ role = "user"; content = "Reply with a short greeting." })} | ConvertTo-Json -Depth 4โ$response = Invoke-WebRequest -UseBasicParsing -Method Post ` ย -Uri "https://api.cometapi.com/v1/chat/completions" ` ย -Headers @{ Authorization = "Bearer $env:COMETAPI_KEY" } ` ย -ContentType "application/json" ` ย -Body $body$response.Content | Set-Content -Encoding UTF8 response.json"HTTP $($response.StatusCode)"
On an HTTP error, PowerShell may raise an exception before the last two lines run. Capture the status and redacted error details from that failure; do not record it as a successful response.
Expected result for the DeepSeek request: HTTP 200 and non-empty text in choices[0].message.content. Inspect the saved response.json rather than accepting HTTP 200 alone. The following additions show the response shape and how to check all three configured routes. Examples are illustrative; this revision does not claim live CometAPI test results. A text-only request does not validate streaming or tool calls.
Illustrative DeepSeek response shape: the greeting, usage values, and other fields depend on the actual request. The following JSON is a deliberately shortened example, not a captured API response.
{"choices":[{"message":{"role":"assistant","content":"Hello!"}}]}
After an actual successful HTTP request, the status line should read HTTP 200 and response.json should contain non-empty assistant text. Keep the actual status and body for your own run; do not copy the example as test evidence.
Step 5: Switch Between Claude, GPT, and DeepSeek
The commands in this step should return the requested assistant markers. Illustrative assistant text, with terminal banners, timing, and metadata omitted:
Claude: ย CLAUDE_READYGPT: ย ย GPT_READYDeepSeek: DEEPSEEK_READY
These lines show the expected content only. They are not a terminal transcript. Record the actual output and process exit status for each provider; a missing marker or failed request requires investigation.
Start in the directory containing opencode.json. List the models for each configured provider, then make a short text request to each entry. These commands change the selected model and adapter; the CometAPI key and base URL remain the same.
Use these commands to check that all three entries are visible and can return text.
opencode models cometapi-messagesopencode models cometapi-responsesopencode models cometapi-chatโopencode run --model cometapi-messages/claude-sonnet-5 "Reply exactly with: CLAUDE_READY"opencode run --model cometapi-responses/gpt-6.1-sol "Reply exactly with: GPT_READY"opencode run --model cometapi-chat/deepseek-v4.1-flash "Reply exactly with: DEEPSEEK_READY"
For interactive switching, start opencode, enter /models, and select CometAPI Claude, CometAPI GPT, or CometAPI DeepSeek. OpenCode uses that entryโs provider/model pair. You do not need three supplier accounts or three API keys. With this environment-backed configuration, do not use /connect to supply a second credential; a missing COMETAPI_KEY must be fixed in the launching shell.
Expected outcome: each short request returns its requested marker. Record the actual result for each model. A visible model entry confirms registration; a successful text response confirms that request path. Neither alone proves that file tools work.
Gemini uses a separate provider and protocol. Keep the Claude, GPT, and DeepSeek entries above; merge the following entry into the existing provider object. The base URL below follows the reviewer-supplied CometAPI configuration. Confirm its current route and model access in your CometAPI account before use.
The Google adapter supports a custom baseURL and sends apiKey using x-goog-api-key. See the official AI SDK Google provider reference. This confirms the adapter settings; it does not prove that a particular Gemini model is enabled on the CometAPI gateway.
{ ย "provider": { ย ย "cometapi-gemini": { ย ย ย "npm": "@ai-sdk/google", ย ย ย "name": "CometAPI Gemini", ย ย ย "options": { ย ย ย ย "baseURL": "https://api.cometapi.com/v1beta", ย ย ย ย "apiKey": "{env:COMETAPI_KEY}" ย ย }, ย ย ย "models": { ย ย ย ย "YOUR_GEMINI_MODEL_ID": { ย ย ย ย ย "name": "CometAPI Gemini (account-selected model)" ย ย ย } ย ย } ย } }}
Replace YOUR_GEMINI_MODEL_ID in both the JSON key and the command below with the exact Gemini model ID enabled for your CometAPI account. It is a placeholder, not a real model ID. Merge this provider entry without duplicating the top-level provider key, and start OpenCode from the same shell where COMETAPI_KEY is set.
opencode models cometapi-geminiopencode run --model cometapi-gemini/YOUR_GEMINI_MODEL_ID "Reply exactly with: GEMINI_READY"
Expected assistant text: GEMINI_READY. A listed model confirms local registration; receiving the marker confirms the text request. Save the actual response and exit status. To validate coding tools, launch opencode --model cometapi-gemini/YOUR_GEMINI_MODEL_ID in a fresh disposable directory and repeat the greet.cjs/check.cjs task below. Text success alone does not verify streaming, editing, or tool calls.
How Do You Run a Coding Task with Claude, GPT, and DeepSeek?
Use the same small task for each model: create a greeting function, add an assertion, and run it. Keep three fresh directories so the second model cannot simply reuse files created by the first. This checks the integration workflow without turning the article into a performance ranking.
Save prepare-runs.cjs beside opencode.json and run it once. It creates three new directories and copies only the shared configuration. It stops if any target directory already exists, so previous work is not overwritten.
const fs = require("node:fs");const path = require("node:path");const root = __dirname;const names = ["claude-demo", "gpt-demo", "deepseek-demo"];const config = path.join(root, "opencode.json");if (!fs.existsSync(config)) throw new Error("Missing opencode.json");for (const name of names) { ย if (fs.existsSync(path.join(root, name))) { ย ย throw new Error(`Directory already exists: ${name}`); }}for (const name of names) { ย const dir = path.join(root, name); ย fs.mkdirSync(dir); ย fs.copyFileSync(config, path.join(dir, "opencode.json"));}node prepare-runs.cjscd claude-demoopencode --model cometapi-messages/claude-sonnet-5# After exiting OpenCode:cd ..cd gpt-demoopencode --model cometapi-responses/gpt-6.1-sol# After exiting OpenCode:cd ..cd deepseek-demoopencode --model cometapi-chat/deepseek-v4.1-flash# After exiting OpenCode:cd ..
Run one of the following sessions at a time, starting from the parent project directory. Exit the session before moving to the next example. In each session, submit the same task below and review the proposed edits and commands. Node.js must be available to the process that launches OpenCode.
Ask the agent to create and verify a small JavaScript function.
Create greet.cjs in this directory.Export a function named greet(name) that returns "Hello, " + name + "!".Create check.cjs using node:assert/strict.Assert that greet("Ada") equals "Hello, Ada!".Run node check.cjs and report its actual exit status.Do not modify opencode.json or unrelated files.
Expected result: the agent requests the configured approvals, creates both files, and completes node check.cjs with exit status 0. Record what actually happened. Inspect the files and rerun the check yourself; a prose success claim is not sufficient. If a tool call is rejected or malformed, investigate route compatibility separately from a pending approval.
Reference Files and Local Verification
The following files are a reference implementation of the requested task. They were written directly for this guide; they are not presented as model-generated artifacts. Matching their observable behavior is the acceptance condition for your agent run.
function greet(name) { ย return "Hello, " + name + "!";}โmodule.exports = { greet };const assert = require("node:assert/strict");const { greet } = require("./greet.cjs");โassert.equal(greet("Ada"), "Hello, Ada!");node check.cjsprintf "exit=%s\n" "$?"node check.cjs"exit=$LASTEXITCODE"
Local reference check: Windows, Node.js v24.19.0, October 22, 2026; node check.cjs returned exit status 0 with no standard output. This checks only the two reference files. It does not verify OpenCode installation, CometAPI access, approval prompts, or model tool calls.
| Run | Selected model entry | What to record |
|---|---|---|
| Claude | cometapi-messages/claude-sonnet-5 | Response, generated files, approvals, test exit code |
| GPT | cometapi-responses/gpt-6.1-sol | Response, generated files, approvals, test exit code |
| DeepSeek | cometapi-chat/deepseek-v4.1-flash | Response, generated files, approvals, test exit code |
Keep one result record per model: selected provider/model, whether a response arrived, whether greet.cjs and check.cjs were created, whether approvals appeared, and the exit code of node check.cjs. Record failures as failures; do not infer a pass from the reference implementation.
Protect Credentials and Verify Reliability
Store COMETAPI_KEY in an environment variable rather than configuration files or shared logs. Keep file-editing and shell-command approvals enabled, and test new configurations in a disposable project.
Verify the direct API request, OpenCode response, and file-editing workflow separately. Record errors and test results, retry only transient failures, and inspect the workspace before repeating interrupted tasks.
CometAPI simplifies switching between models, but OpenCode does not automatically provide cross-model failover through this configuration. If a model becomes unavailable, manually select another verified model and repeat the acceptance check.
How much does it cost to use Opencode with CometAPI?
Prices for CometAPI, and how is billing structured
CometAPI offers pay-as-you-go pricing with no monthly subscription fees, charging only for actual API usage. Its official-model rates are generally 20% lower than providers' standard prices, with additional volume discounts available. Developers can access Claude, GPT, DeepSeek, and other models through one account, paying based on the selected model's token consumption. Check the CometAPI pricing page for current rates.
For requests without caching or additional fees:
Cost = (Input tokens ร Input rate + Output tokens ร Output rate) / 1,000,000
For example, at hypothetical rates of $1/M input tokens and $4/M output tokens, using 20,000 input and 2,000 output tokens costs $0.028. These are illustrative rates, not actual model prices.
Record token usage, total API charges, execution time, and test results for each task. To reduce costs, limit unnecessary context, use concise prompts, avoid repeated failed requests, and choose lower-cost models when they meet the same quality requirements.
OpenCode API Cost Optimization Strategies
To reduce OpenCode costs without compromising coding quality, focus on model selection, token efficiency, and unnecessary API requests.
- Choose the right model: Use lower-cost models such as DeepSeek for routine coding tasks, while reserving Claude or GPT for complex debugging, refactoring, and reasoning.
- Reduce token consumption: Keep prompts concise, provide only relevant project files, and avoid repeatedly sending large amounts of repository context.
- Use prompt caching: Take advantage of supported caching features for repeated context, such as project instructions and code references, to reduce input costs.
- Avoid unnecessary retries: Fix configuration and authentication errors before retrying requests, and review previous outputs to prevent duplicate work.
- Monitor actual spending: Track token usage, API charges, and successful task completion through CometAPI. Compare the cost per successful task rather than token prices alone.
Combined with CometAPI's discounted, pay-as-you-go pricing, these practices help developers control spending while maintaining reliable coding performance in OpenCode.
How Can You Extend the CometAPI Configuration?
To add another model, place its model ID under the provider whose API format it supports, or add a new provider entry with the required adapter. Then select that provider/model through /models. Keep credentials in COMETAPI_KEY and keep the existing entries so switching remains a selection operation.
The official guide covers four API formats, including Gemini. This article uses the three entries needed for Claude, GPT, and DeepSeek. If several selected models support Chat Completions, they can share one cometapi-chat models map. Do not move a Responses-only or Messages-only route into that map merely to reduce the number of entries.
Choose the adapter based on the route you intend to call, and the model based on the programming task. A change of supplier does not require a new CometAPI key; a change of API format requires the matching configured adapter.
How to Troubleshoot CometAPI in OpenCode?
Follow the first failing stage: HTTP request โ OpenCode provider โ file tools. If HTTP fails, inspect credentials, model access, and endpoint details. If HTTP works but OpenCode fails, inspect configuration and the launch environment. If both text checks work but file actions fail, inspect permissions and tool-call compatibility.
| Symptom | First check | Next action | Diagnostic command / evidence |
|---|---|---|---|
| 401 response | Key value and Authorization header | Set the key in the current terminal; check for accidental whitespace. | Check variable presence without printing the key; retain the HTTP status and redacted error. |
| 403 or account restriction | Error body and account permissions | Confirm model access and account status in CometAPI. | Save the redacted response error and confirm account access. |
| 404 response | Host, endpoint path, and model ID | Compare the request with the selected model API documentation. | Compare response.json with the requested model and endpoint. |
| Model missing in OpenCode | Project directory and provider configuration | Check valid JSON and matching provider/model names; restart after editing. | Run opencode models cometapi-chat, opencode models cometapi-messages, and opencode models cometapi-responses; record opencode --version. |
| Text works, tools fail | Tool-call response and adapter compatibility | Verify route support; distinguish a rejected tool call from an approval prompt. | Compare the short text request with the failed tool action; retain the error. |
| Command waits for approval | Interactive session and permission settings | Review and approve the intended action; do not treat a pending request as an API outage. | Use the interactive session; record the requested action and approval outcome. |
| 429 or transient server error | Error details and usage limits | Reduce request concurrency; follow any retry guidance instead of retrying continuously. | Retain the HTTP status and retry guidance; reduce concurrency. |
When sharing an issue, include the OpenCode version, operating system, model ID, endpoint path, and redacted error text. Exclude API keys and private repository content. Keep the smallest request that reproduces the failure so configuration and tool failures can be investigated separately.
FAQ
Why does OpenCode lose my CometAPI key in a new terminal?
The export and PowerShell commands above set an environment variable for the current session and its child processes. A separately opened terminal or already-running editor may not inherit it. Set the key in the environment that launches OpenCode and restart that process. For persistent setup, use your environmentโs credential management rather than embedding the secret in a repository file.
Does OpenCode load COMETAPI_KEY from a .env file automatically?
The {env:COMETAPI_KEY} expression reads the process environment. Merely creating a .env file does not establish that the variable has been loaded. Use your shell or an explicitly configured environment loader before starting OpenCode. Diagnose an empty value at the launching process instead of assuming the provider is unavailable.
Can a global OpenCode configuration change this project setup?
OpenCode merges configuration rather than replacing every earlier file. The project file overrides overlapping fields in the global file, while unrelated global settings remain. A custom OPENCODE_CONFIG file is loaded between them. If behavior differs across repositories, compare these sources and any managed or inline settings instead of assuming the local file is the only input.
Does refreshing the OpenCode model list enable CometAPI access?
No. The model refresh option updates the models.dev cache; it does not grant account access or prove an endpoint accepts a model ID. A manually configured entry can be visible before any successful request. Use an actual request to check the route and consult CometAPI account settings for access restrictions.
Why does curl work while OpenCode cannot call CometAPI?
The two processes may load different credentials, use different model IDs, or send different request shapes. First rerun the short text prompt from the same terminal as the successful HTTP request. Then compare the provider base URL, adapter, and selected model. If simple text works but an agent task fails, preserve the tool-related error separately; HTTP connectivity alone does not demonstrate tool compatibility.
Conclusion
You now have one opencode.json with Claude, GPT, and DeepSeek examples, a shared CometAPI credential, and commands for switching the active model. Use the short text requests to check access, then run the same file-creation task in separate directories to verify the coding workflow. Keep the observed results with your environment details before applying the setup to a larger repository.
