Skip to main content
These examples use the direct API host, https://api.nano-gpt.com. It has no IPv6 address, so clients with only IPv6 should use https://nano-gpt.com with the same paths. See API Hosts.

OpenCode Integration

Use NanoGPT with OpenCode, the open source AI coding agent for your terminal. This guide covers OpenCode 1 and OpenCode 2. They store API keys in different places, so run opencode --version to check which one you have.
Tested setup. Last verified November 6, 2026 with OpenCode 1.19.5 on macOS, using the manual config below with nano-gpt/deepseek/deepseek-v4.1-flash-1017 and its :thinking version. OpenCode read a file, edited it with its tools and finished the task. Requests went to https://nano-gpt.com/api/v1 through a local test proxy that capped output at 8,000 tokens.

Requirements

  • OpenCode installed. OpenCode 1: curl -fsSL https://opencode.ai/install | bash. OpenCode 2: curl -fsSL https://opencode.ai/v2/install | bash.
  • A NanoGPT account with API access

One-Click Setup (Mac/Linux)

Run this command in your terminal:
This will:
  1. Open your browser to authenticate with NanoGPT (or let you paste an API key)
  2. Save the key where your OpenCode reads it: auth.json for OpenCode 1, and OpenCode 2’s credential store when opencode or opencode2 is OpenCode 2
  3. Configure OpenCode to use NanoGPT as your AI provider
  4. Add starter model definitions while preserving existing model selections, filters, and connection options
OpenCode also includes NanoGPT models from its built-in Models.dev catalogue. You do not need to define each of those models manually. The installer adds starter model definitions; these do not restrict the model list. Python 3 is required to merge existing OpenCode files. The installer stops if an existing JSON file cannot be read, rather than replacing it. It updates opencode.json; if you use opencode.jsonc, follow the manual setup below and merge the settings into your existing file. Setup replaces NanoGPT authentication with your chosen login or pasted key. It removes provider-level options.apiKey and Authorization overrides in provider and model headers from opencode.json so the new credentials take effect, while preserving unrelated headers and custom model settings. In OpenCode 2, it adds a credential named NanoGPT installer with the date and time, and makes it the active NanoGPT credential. Earlier credentials remain listed in opencode auth list. If you install OpenCode 2 after running setup, run setup again or follow Add your API key.

Manual Setup

If you prefer to configure manually:

1. Add your API key

Run this command and paste your NanoGPT API key when prompted:
OpenCode 2 keeps API keys in its own credential store. It reads auth.json only once, when it first opens a database that OpenCode 1 created, and ignores later changes to the file. On a new OpenCode 2 installation, it never reads auth.json. Run opencode auth list to see your saved NanoGPT credentials.
Both versions also read NANO_GPT_API_KEY from the environment of the terminal that starts OpenCode. A saved key takes precedence over that variable: the auth.json entry in OpenCode 1, or the active credential in OpenCode 2.

2. Create the config file

Create ~/.config/opencode/opencode.json, or merge these settings into your existing config:
This uses OpenCode’s built-in NanoGPT catalogue. A models block is optional for models already in that catalogue. Use it to add a missing model or override model settings, as described in Adding More Models. OpenCode also supports opencode.jsonc for configs with comments. The examples here use strict JSON.

Usage

After setup, start OpenCode:

Switching Models

Use the /models command inside OpenCode to switch between models, or edit the model field in your opencode.json:

Available Models

Examples of NanoGPT models are listed below. OpenCode’s built-in catalogue and your custom definitions determine which models appear in /models; the list is not limited to entries in your models block.

Adding More Models

The models block adds model definitions or overrides settings for existing models. It does not hide models that you have not listed. If a model already appears in OpenCode and you do not need custom settings, you can omit its entry. Keep entries for missing models or custom names, options, variants, and context/output limits. To add or override a model, merge its definition into provider.nano-gpt.models:
List NanoGPT API models with GET https://api.nano-gpt.com/api/v1/models. OpenCode’s catalogue can lag behind the API, so a model missing from OpenCode may need a manual definition. A model appearing in the API list does not necessarily support the tool calls needed by OpenCode.

If a Task Stops Partway

When a provider fails during a reply, NanoGPT sends an error in the stream. OpenCode retries the same turn on its own: in our test it tried six times over about 100 seconds, then stopped with the error.
  • Each retry is a new request, and output that reached OpenCode before a failure is normally charged. Repeated failures on a long conversation add up.
  • If OpenCode stops with an error, run the task again. Your session and the files it changed are kept.
  • Don’t pick one provider for a long agent run unless you need to. It leaves NanoGPT fewer routes to fall back to.

Running OpenCode from a Script

opencode run waits for standard input when it isn’t attached to a terminal. In a script or CI job, close it, or the command can hang with no output:

Limiting the Model List

To show only selected NanoGPT models, add whitelist under provider.nano-gpt. Merge this example into your existing config, keeping your connection settings and any model overrides:
Use model IDs without the nano-gpt/ prefix inside whitelist, blacklist, and models. The top-level model field uses the full nano-gpt/model-id format. Alternatively, blacklist hides specific models while keeping the rest. If both filters are set, a model must be in whitelist and must not be in blacklist. Keep the selected default model inside your allowed list, then restart OpenCode after saving.

Claude Prompt Caching

OpenCode 1 adds explicit cache_control markers to Claude requests automatically. Its markers omit the TTL and use the five-minute default unless you request a different TTL. You do not need a promptCaching block or an anthropic-beta header just to use OpenCode 1’s default Claude caching. OpenCode 2 does not add these markers (checked with OpenCode 2.1.4), so its Claude requests are not cached by default. To enable caching, add promptCaching to the model’s options as shown in One-Hour Caching, with "ttl": "5m" for five-minute caching or "ttl": "1h" for one hour. A cache marker requests caching; it does not guarantee a cache hit. The prompt must meet the selected model’s minimum cacheable size, and later requests must reuse the same prefix before the cache expires.
On NanoGPT’s Chat Completions endpoint, supported explicit cache controls use pay-as-you-go billing, including the markers OpenCode 1 adds automatically and the promptCaching helper. They bypass subscription coverage for that request. See subscription billing for prompt caching.

One-Hour Caching

To request one-hour caching for Opus 5.5, merge this configuration into your existing opencode.json. Keep your API key where you saved it in Add your API key, not in this file:
OpenCode forwards the model’s options.promptCaching as the top-level promptCaching field in the API request. NanoGPT applies the requested TTL to the cache boundaries, including the markers OpenCode 1 adds. With OpenCode 2, which adds no markers, NanoGPT places the cache boundaries itself. No additional anthropic-beta header is required. One-hour caching has a higher cache-write price than five-minute caching on standard Claude cache pricing. Choose it when you expect to reuse a large prefix after pauses longer than five minutes. See cache pricing. The example leaves stickyProvider at its default, false, so NanoGPT can fail over when a service is unavailable. Adding "stickyProvider": true inside promptCaching disables failover and can return a 503 instead. It is optional and does not enable caching by itself.

Which Model Settings Should I Keep?

Removing the entire options block also removes your caching and request-level privacy settings. Removing variants only removes your custom effort choices.

Opus 5.5 Reasoning Effort

Opus 5.5 uses adaptive thinking automatically. You do not need reasoning: true or custom variants to enable its thinking. Supported effort values are low, medium, high, xhigh, and max; none cannot disable this model’s thinking. If your OpenCode version does not offer the choices you want, merge these variants into provider.nano-gpt.models["anthropic/claude-opus-5.5"], alongside the existing options:
OpenCode maps the selected variant’s reasoningEffort to NanoGPT’s reasoning_effort request field. See reasoning controls for the distinction between generating thinking and displaying it. The snippet includes reasoning: true so OpenCode can expose reasoning choices even with missing or stale catalogue metadata. You can omit it when the catalogue already describes the model correctly.

Checking Cache Hits

Look for cache_creation_input_tokens on an eligible write and cache_read_input_tokens > 0 on a subsequent request that reuses the prefix. A successful answer alone does not establish a cache hit or the requested TTL. Raw API responses can also include x_nanogpt_pricing.cacheTTL for the billing TTL. If your OpenCode version does not display these fields, use the API cache verification examples. A short prompt can return zero cached tokens even with a correct configuration. The request format above was checked with OpenCode 1.14.48, 1.19.4 and 2.1.4 using @ai-sdk/openai-compatible. All of them forward promptCaching and the selected variant’s reasoningEffort; only OpenCode 1 adds cache markers. Other SDKs or older client versions can map options differently.

Troubleshooting

OpenCode not finding the config? Use opencode.json or opencode.jsonc, without a leading dot:
  • Global config: ~/.config/opencode/opencode.json, or $XDG_CONFIG_HOME/opencode/opencode.json when XDG_CONFIG_HOME is set.
  • Project config: opencode.json in your project.
OpenCode merges config sources. Project settings can override global settings, and a custom config set with OPENCODE_CONFIG can add another source. See OpenCode’s config documentation for the full precedence rules. More models appear than expected? Check that whitelist is inside provider.nano-gpt, not inside models. Defining a models block does not filter the catalogue. Also check project configs and opencode.jsonc for settings that override your global filters. The installer cannot merge your config? Install Python 3 when updating existing OpenCode files. The installer reads strict JSON only; if your config contains comments, use manual setup in opencode.jsonc. The installer stops before authentication or file updates if existing auth or JSON config files cannot be read or parsed. “Invalid Authentication” or another authentication error? “Invalid Authentication” means OpenCode sent the request without an API key. Run opencode --version:
  • OpenCode 2: run opencode auth login nano-gpt and paste your key, or run the one-click setup again. OpenCode 2 ignores keys added to auth.json. Run opencode auth list to see your saved NanoGPT credentials, and opencode auth switch nano-gpt to choose the active one. The active credential is used instead of NANO_GPT_API_KEY and any apiKey in opencode.json.
  • OpenCode 1: check that ~/.local/share/opencode/auth.json has a nano-gpt entry with type and key. Remove any apiKey under provider.nano-gpt.options in opencode.json: it replaces the auth.json key, and an {env:...} value whose variable is unset sends no key at all.
“Invalid session” means OpenCode sent a key that NanoGPT does not accept. Copy an active key from nano-gpt.com/api and save it again. Claude caching is not being used? OpenCode 2 caches Claude requests only when you configure promptCaching; see Claude Prompt Caching. If you configured promptCaching, check that it is inside the selected model’s options, that enabled is true, and that the TTL is exactly "5m" or "1h". Keep reusable instructions and tool definitions at the beginning of the prompt. Changes to that prefix, insufficient prompt length, expiration, or failover can prevent a cache hit. A request returns “temporarily unavailable”? If you set promptCaching.stickyProvider: true, a 503 can mean failover was prevented to preserve the cache. Privacy and provider restrictions can also reduce the available routes. Keep intentional privacy requirements; a service error alone does not establish that those requirements caused the failure. Retry, and send support the new request ID, model ID, and approximate time if the error continues.