mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-03 08:46:15 -04:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 30e10127f2 | |||
| 5e66fc2318 | |||
| c1c99c7e0f | |||
| 04e3e83db3 | |||
| 4273714a62 | |||
| a21e237706 | |||
| aa9105649d | |||
| 53be288040 | |||
| 13dbf912ca | |||
| 69966c73f8 | |||
| a00de2df08 |
@@ -48,6 +48,7 @@
|
||||
"hono-openapi": "0.4.8",
|
||||
"isomorphic-git": "1.32.1",
|
||||
"jsonc-parser": "3.3.1",
|
||||
"minimatch": "10.0.3",
|
||||
"open": "10.1.2",
|
||||
"remeda": "catalog:",
|
||||
"tree-sitter": "0.22.4",
|
||||
@@ -355,6 +356,10 @@
|
||||
|
||||
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="],
|
||||
|
||||
"@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="],
|
||||
|
||||
"@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="],
|
||||
|
||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg=="],
|
||||
|
||||
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
||||
@@ -1271,6 +1276,8 @@
|
||||
|
||||
"miniflare": ["miniflare@4.20250730.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "^7.10.0", "workerd": "1.20250730.0", "ws": "8.18.0", "youch": "4.1.0-beta.10", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-avGXBStHQSqcJr8ra1mJ3/OQvnLZ49B1uAILQapAha1DHNZZvXWLIgUVre/WGY6ZOlNGFPh5CJ+dXLm4yuV3Jw=="],
|
||||
|
||||
"minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="],
|
||||
|
||||
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||
|
||||
"minimisted": ["minimisted@2.0.1", "", { "dependencies": { "minimist": "^1.2.5" } }, "sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA=="],
|
||||
|
||||
+6
-4
@@ -19,6 +19,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"formatter": {
|
||||
"test": {
|
||||
"extensions": [".json"],
|
||||
"command": ["sed", "-i", "s/name/poop/g", "$FILE"]
|
||||
}
|
||||
},
|
||||
"mcp": {
|
||||
"context7": {
|
||||
"type": "remote",
|
||||
@@ -28,9 +34,5 @@
|
||||
"type": "local",
|
||||
"command": ["opencode", "x", "@h1deya/mcp-server-weather"]
|
||||
}
|
||||
},
|
||||
"permission": {
|
||||
"edit": "ask",
|
||||
"bash": "ask"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,11 +46,12 @@
|
||||
"hono-openapi": "0.4.8",
|
||||
"isomorphic-git": "1.32.1",
|
||||
"jsonc-parser": "3.3.1",
|
||||
"minimatch": "10.0.3",
|
||||
"open": "10.1.2",
|
||||
"remeda": "catalog:",
|
||||
"turndown": "7.2.0",
|
||||
"tree-sitter": "0.22.4",
|
||||
"tree-sitter-bash": "0.23.3",
|
||||
"turndown": "7.2.0",
|
||||
"vscode-jsonrpc": "8.2.1",
|
||||
"xdg-basedir": "5.1.0",
|
||||
"yargs": "18.0.0",
|
||||
|
||||
@@ -278,6 +278,17 @@ export namespace Config {
|
||||
.optional()
|
||||
.describe("Custom provider configurations and model overrides"),
|
||||
mcp: z.record(z.string(), Mcp).optional().describe("MCP (Model Context Protocol) server configurations"),
|
||||
formatter: z
|
||||
.record(
|
||||
z.string(),
|
||||
z.object({
|
||||
disabled: z.boolean().optional(),
|
||||
command: z.array(z.string()).optional(),
|
||||
environment: z.record(z.string(), z.string()).optional(),
|
||||
extensions: z.array(z.string()).optional(),
|
||||
}),
|
||||
)
|
||||
.optional(),
|
||||
instructions: z.array(z.string()).optional().describe("Additional instruction files or patterns to include"),
|
||||
layout: Layout.optional().describe("@deprecated Always uses stretch layout."),
|
||||
permission: z
|
||||
|
||||
@@ -129,7 +129,9 @@ export const clang: Info = {
|
||||
command: ["clang-format", "-i", "$FILE"],
|
||||
extensions: [".c", ".cc", ".cpp", ".cxx", ".c++", ".h", ".hh", ".hpp", ".hxx", ".h++", ".ino", ".C", ".H"],
|
||||
async enabled() {
|
||||
return Bun.which("clang-format") !== null
|
||||
const app = App.info()
|
||||
const items = await Filesystem.findUp(".clang-format", app.path.cwd, app.path.root)
|
||||
return items.length > 0
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -5,20 +5,40 @@ import { Log } from "../util/log"
|
||||
import path from "path"
|
||||
|
||||
import * as Formatter from "./formatter"
|
||||
import { Config } from "../config/config"
|
||||
import { mergeDeep } from "remeda"
|
||||
|
||||
export namespace Format {
|
||||
const log = Log.create({ service: "format" })
|
||||
|
||||
const state = App.state("format", () => {
|
||||
const state = App.state("format", async () => {
|
||||
const enabled: Record<string, boolean> = {}
|
||||
const cfg = await Config.get()
|
||||
|
||||
const formatters = { ...Formatter } as Record<string, Formatter.Info>
|
||||
for (const [name, item] of Object.entries(cfg.formatter ?? {})) {
|
||||
if (item.disabled) {
|
||||
delete formatters[name]
|
||||
continue
|
||||
}
|
||||
const result: Formatter.Info = mergeDeep(formatters[name] ?? {}, {
|
||||
command: [],
|
||||
extensions: [],
|
||||
...item,
|
||||
})
|
||||
result.enabled = async () => true
|
||||
result.name = name
|
||||
formatters[name] = result
|
||||
}
|
||||
|
||||
return {
|
||||
enabled,
|
||||
formatters,
|
||||
}
|
||||
})
|
||||
|
||||
async function isEnabled(item: Formatter.Info) {
|
||||
const s = state()
|
||||
const s = await state()
|
||||
let status = s.enabled[item.name]
|
||||
if (status === undefined) {
|
||||
status = await item.enabled()
|
||||
@@ -28,8 +48,10 @@ export namespace Format {
|
||||
}
|
||||
|
||||
async function getFormatter(ext: string) {
|
||||
const formatters = await state().then((x) => x.formatters)
|
||||
const result = []
|
||||
for (const item of Object.values(Formatter)) {
|
||||
for (const item of Object.values(formatters)) {
|
||||
log.info("checking", { name: item.name, ext })
|
||||
if (!item.extensions.includes(ext)) continue
|
||||
if (!(await isEnabled(item))) continue
|
||||
result.push(item)
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Config } from "../config/config"
|
||||
import { Filesystem } from "../util/filesystem"
|
||||
import path from "path"
|
||||
import { lazy } from "../util/lazy"
|
||||
import { minimatch } from "minimatch"
|
||||
|
||||
const MAX_OUTPUT_LENGTH = 30000
|
||||
const DEFAULT_TIMEOUT = 1 * 60 * 1000
|
||||
@@ -84,7 +85,7 @@ export const BashTool = Tool.define("bash", {
|
||||
if (!needsAsk && command[0] !== "cd") {
|
||||
const ask = (() => {
|
||||
for (const [pattern, value] of Object.entries(permissions)) {
|
||||
if (new Bun.Glob(pattern).match(node.text)) {
|
||||
if (minimatch(node.text, pattern)) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ export const EditTool = Tool.define("edit", {
|
||||
file: filePath,
|
||||
})
|
||||
contentNew = await file.text()
|
||||
diff = trimDiff(createTwoFilesPatch(filePath, filePath, contentOld, contentNew))
|
||||
})()
|
||||
|
||||
FileTime.read(ctx.sessionID, filePath)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "0.0.0-202507312003",
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./dist/index.js"
|
||||
|
||||
@@ -17,6 +17,8 @@ export type Event = ({
|
||||
} & EventStorageWrite) | ({
|
||||
type: 'permission.updated';
|
||||
} & EventPermissionUpdated) | ({
|
||||
type: 'permission.replied';
|
||||
} & EventPermissionReplied) | ({
|
||||
type: 'file.edited';
|
||||
} & EventFileEdited) | ({
|
||||
type: 'session.updated';
|
||||
@@ -374,6 +376,15 @@ export type Permission = {
|
||||
};
|
||||
};
|
||||
|
||||
export type EventPermissionReplied = {
|
||||
type: string;
|
||||
properties: {
|
||||
sessionID: string;
|
||||
permissionID: string;
|
||||
response: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type EventFileEdited = {
|
||||
type: string;
|
||||
properties: {
|
||||
@@ -579,6 +590,11 @@ export type Config = {
|
||||
type: 'remote';
|
||||
} & McpRemoteConfig);
|
||||
};
|
||||
formatter?: {
|
||||
[key: string]: {
|
||||
disabled?: boolean;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Additional instruction files or patterns to include
|
||||
*/
|
||||
|
||||
@@ -69,12 +69,7 @@ export default defineConfig({
|
||||
|
||||
{
|
||||
label: "Usage",
|
||||
items: [
|
||||
"docs/cli",
|
||||
"docs/ide",
|
||||
"docs/share",
|
||||
"docs/github",
|
||||
]
|
||||
items: ["docs/cli", "docs/ide", "docs/share", "docs/github"],
|
||||
},
|
||||
|
||||
{
|
||||
@@ -86,9 +81,10 @@ export default defineConfig({
|
||||
"docs/models",
|
||||
"docs/themes",
|
||||
"docs/keybinds",
|
||||
"docs/permissions",
|
||||
"docs/mcp-servers",
|
||||
]
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
components: {
|
||||
Hero: "./src/components/Hero.astro",
|
||||
|
||||
@@ -1,144 +1,74 @@
|
||||
---
|
||||
title: Permissions
|
||||
description: Control what AI agents can do in your codebase.
|
||||
description: Control what agents can do in your codebase.
|
||||
---
|
||||
|
||||
The opencode permissions system provides granular control over what actions AI agents can perform in your codebase. It allows you to configure explicit approval requirements for sensitive operations like file editing, bash commands, and more.
|
||||
By default, opencode **allows all operations** without requiring explicit approval.
|
||||
|
||||
## How it works
|
||||
The permissions system provides granular control to restrict what actions AI agents can perform in your codebase, allowing you to configure explicit approval requirements for sensitive operations like file editing, bash commands, and more.
|
||||
|
||||
The permissions system works by intercepting tool calls and checking if user approval is required before executing potentially sensitive operations. When a tool requests permission, it creates a permission request that must be approved by the user.
|
||||
---
|
||||
|
||||
```typescript
|
||||
// Example of how a tool requests permission
|
||||
await Permission.ask({
|
||||
type: "edit",
|
||||
sessionID: ctx.sessionID,
|
||||
messageID: ctx.messageID,
|
||||
callID: ctx.callID,
|
||||
title: "Edit this file: " + filePath,
|
||||
metadata: {
|
||||
filePath,
|
||||
diff,
|
||||
},
|
||||
})
|
||||
```
|
||||
## Configure
|
||||
|
||||
When a permission is requested, the system checks the configuration to determine if approval is needed. If approval is required, the user is prompted to allow or deny the action.
|
||||
Permissions are configured in your `opencode.json` file under the `permission` key. Here are the available options.
|
||||
|
||||
## Configuration
|
||||
---
|
||||
|
||||
Permissions are configured in your `opencode.json` file under the `permission` key. Here are the available options:
|
||||
### edit
|
||||
|
||||
### permission.edit
|
||||
Use the `permission.edit` key to control whether file editing operations require user approval.
|
||||
|
||||
Controls whether file editing operations require user approval.
|
||||
- `"ask"` - Prompt for approval before editing files
|
||||
- `"allow"` - Allow all file editing operations without approval
|
||||
|
||||
```json title="opencode.json"
|
||||
```json title="opencode.json" {4}
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"permission": {
|
||||
"edit": "ask"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `"ask"` - Prompt user for approval before editing files
|
||||
- `"allow"` - Allow all file editing operations without approval
|
||||
---
|
||||
|
||||
### permission.bash
|
||||
### bash
|
||||
|
||||
Controls whether bash commands require user approval. This can be configured globally or with specific patterns.
|
||||
Controls whether bash commands require user approval.
|
||||
|
||||
```json title="opencode.json"
|
||||
{
|
||||
"permission": {
|
||||
"bash": "ask"
|
||||
}
|
||||
}
|
||||
```
|
||||
:::tip
|
||||
You can specify which commands you want to have run without approval.
|
||||
:::
|
||||
|
||||
Or with specific patterns:
|
||||
This can be configured globally or with specific patterns. Setting this to `"ask"` is the strictest mode, requiring approval for all bash commands.
|
||||
|
||||
```json title="opencode.json"
|
||||
{
|
||||
"permission": {
|
||||
"bash": {
|
||||
"git *": "allow",
|
||||
"npm install": "ask",
|
||||
"*": "ask"
|
||||
For example.
|
||||
|
||||
- **Ask for approval for all commands**
|
||||
|
||||
```json title="opencode.json"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"permission": {
|
||||
"bash": "ask"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
## Configuration examples
|
||||
- **Approve specific commands**
|
||||
|
||||
### Basic permission configuration
|
||||
|
||||
```json title="opencode.json"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"permission": {
|
||||
"edit": "ask",
|
||||
"bash": "ask"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Advanced bash permission configuration
|
||||
|
||||
```json title="opencode.json"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"permission": {
|
||||
"edit": "ask",
|
||||
"bash": {
|
||||
"git status": "allow",
|
||||
"git diff": "allow",
|
||||
"git add *": "ask",
|
||||
"git commit*": "ask",
|
||||
"npm install": "ask",
|
||||
"npm run build": "allow",
|
||||
"ls": "allow",
|
||||
"pwd": "allow",
|
||||
"*": "ask"
|
||||
```json title="opencode.json"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"permission": {
|
||||
"bash": {
|
||||
"git status": "allow",
|
||||
"git diff": "allow",
|
||||
"npm run build": "allow",
|
||||
"ls": "allow",
|
||||
"pwd": "allow"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Permissive configuration (development only)
|
||||
|
||||
```json title="opencode.json"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"permission": {
|
||||
"edit": "allow",
|
||||
"bash": "allow"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Strict configuration
|
||||
|
||||
```json title="opencode.json"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"permission": {
|
||||
"edit": "ask",
|
||||
"bash": {
|
||||
"*": "ask"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best practices
|
||||
|
||||
1. **Start with "ask"**: Begin with asking for permissions and adjust based on your workflow
|
||||
2. **Use patterns wisely**: Create specific patterns for commands you trust
|
||||
3. **Review regularly**: Periodically review your permission settings
|
||||
4. **Be specific**: Use specific patterns rather than broad wildcards when possible
|
||||
5. **Document exceptions**: Comment your configuration to explain why certain permissions are set
|
||||
|
||||
This permissions system ensures that you maintain control over what AI agents can do in your codebase while providing flexibility for trusted operations.
|
||||
```
|
||||
|
||||
@@ -45,6 +45,126 @@ You can customize the base URL for any provider by setting the `baseURL` option.
|
||||
|
||||
---
|
||||
|
||||
## 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).
|
||||
|
||||
---
|
||||
|
||||
## Directory
|
||||
|
||||
Let's look at some of the providers in detail. If you'd like to add a provider to the
|
||||
@@ -117,8 +237,30 @@ $ opencode auth login
|
||||
└
|
||||
```
|
||||
|
||||
This will ask you login with your Anthropic account in your browser. Now all the
|
||||
the Anthropic models should be available when you use the `/models` command.
|
||||
Here you can select the **Claude Pro/Max** option and it'll open your browser
|
||||
and ask you to authenticate.
|
||||
|
||||
```bash
|
||||
$ opencode auth login
|
||||
┌ Add credential
|
||||
│
|
||||
◇ Select provider
|
||||
│ Anthropic
|
||||
│
|
||||
◆ Login method
|
||||
│ ● Claude Pro/Max
|
||||
│ ○ Create API Key
|
||||
│ ○ Manually enter API Key
|
||||
└
|
||||
```
|
||||
|
||||
Now all the the Anthropic models should be available when you use the `/models` command.
|
||||
|
||||
##### Using API keys
|
||||
|
||||
You can also select **Create API Key** if you don't have a Pro/Max subscription. It'll also open your browser and ask you to login to Anthropic and give you a code you can paste in your terminal.
|
||||
|
||||
Or if you already have an API key, you can select **Manually enter API Key** and paste it in your terminal.
|
||||
|
||||
---
|
||||
|
||||
@@ -185,6 +327,78 @@ the Anthropic models should be available when you use the `/models` command.
|
||||
|
||||
---
|
||||
|
||||
### DeepSeek
|
||||
|
||||
1. Head over to the [DeepSeek console](https://platform.deepseek.com/), create an account, and click **Create new API key**.
|
||||
|
||||
2. Run `opencode auth login` and select **DeepSeek**.
|
||||
|
||||
```bash
|
||||
$ opencode auth login
|
||||
|
||||
┌ Add credential
|
||||
│
|
||||
◆ Select provider
|
||||
│ ● DeepSeek
|
||||
│ ...
|
||||
└
|
||||
```
|
||||
|
||||
3. Enter your DeepSeek API key.
|
||||
|
||||
```bash
|
||||
$ opencode auth login
|
||||
|
||||
┌ Add credential
|
||||
│
|
||||
◇ Select provider
|
||||
│ DeepSeek
|
||||
│
|
||||
◇ Enter your API key
|
||||
│ _
|
||||
└
|
||||
```
|
||||
|
||||
4. Run the `/models` command to select a DeepSeek model like _DeepSeek Reasoner_.
|
||||
|
||||
---
|
||||
|
||||
### Fireworks AI
|
||||
|
||||
1. Head over to the [Fireworks AI console](https://app.fireworks.ai/), create an account, and click **Create API Key**.
|
||||
|
||||
2. Run `opencode auth login` and select **Fireworks AI**.
|
||||
|
||||
```bash
|
||||
$ opencode auth login
|
||||
|
||||
┌ Add credential
|
||||
│
|
||||
◆ Select provider
|
||||
│ ● Fireworks AI
|
||||
│ ...
|
||||
└
|
||||
```
|
||||
|
||||
3. Enter your Fireworks AI API key.
|
||||
|
||||
```bash
|
||||
$ opencode auth login
|
||||
|
||||
┌ Add credential
|
||||
│
|
||||
◇ Select provider
|
||||
│ Fireworks AI
|
||||
│
|
||||
◇ Enter your API key
|
||||
│ _
|
||||
└
|
||||
```
|
||||
|
||||
4. Run the `/models` command to select a model like _Kimi K2 Instruct_.
|
||||
|
||||
---
|
||||
|
||||
### GitHub Copilot
|
||||
|
||||
To use your GitHub Copilot subscription with opencode:
|
||||
@@ -290,6 +504,78 @@ In this example:
|
||||
|
||||
---
|
||||
|
||||
### Moonshot AI
|
||||
|
||||
To use Kimi K2 from Moonshot AI:
|
||||
|
||||
1. Head over to the [Moonshot AI console](https://platform.moonshot.ai/console), create an account, and click **Create API key**.
|
||||
|
||||
2. Run `opencode auth login` and select **Other**.
|
||||
|
||||
```bash
|
||||
$ opencode auth login
|
||||
|
||||
┌ Add credential
|
||||
│
|
||||
◆ Select provider
|
||||
│ ...
|
||||
│ ● Other
|
||||
└
|
||||
```
|
||||
|
||||
3. Enter `moonshot` as the provider ID.
|
||||
|
||||
```bash
|
||||
$ opencode auth login
|
||||
|
||||
┌ Add credential
|
||||
│
|
||||
◇ Select provider
|
||||
│ Other
|
||||
│
|
||||
◇ Enter provider id
|
||||
│ moonshot
|
||||
└
|
||||
```
|
||||
|
||||
4. Enter your Moonshot API key.
|
||||
|
||||
```bash
|
||||
$ opencode auth login
|
||||
|
||||
┌ Add credential
|
||||
│
|
||||
◇ Enter your API key
|
||||
│ sk-...
|
||||
└
|
||||
```
|
||||
|
||||
5. Configure Moonshot in your opencode config.
|
||||
|
||||
```json title="opencode.json" "\"moonshot\"" {5-15}
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"provider": {
|
||||
"moonshot": {
|
||||
"npm": "@ai-sdk/openai-compatible",
|
||||
"name": "Moonshot AI",
|
||||
"options": {
|
||||
"baseURL": "https://api.moonshot.ai/v1"
|
||||
},
|
||||
"models": {
|
||||
"kimi-k2-0711-preview": {
|
||||
"name": "Kimi K2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
6. Run the `/models` command to select _Kimi K2_.
|
||||
|
||||
---
|
||||
|
||||
### Ollama
|
||||
|
||||
You can configure opencode to use local models through Ollama.
|
||||
@@ -435,8 +721,12 @@ https://platform.openai.com/api-keys
|
||||
}
|
||||
```
|
||||
|
||||
{ /*
|
||||
---
|
||||
|
||||
TODO: Test a model that actually works, currently getting errors form the API
|
||||
for Qwen non-thinking models.
|
||||
|
||||
### Cerebras
|
||||
|
||||
Cerebras offers fast inference with generous free tiers and competitive pricing.
|
||||
@@ -510,15 +800,15 @@ Cerebras offers fast inference with generous free tiers and competitive pricing.
|
||||
|
||||
6. Run the `/models` command to select a Cerebras model.
|
||||
|
||||
*/ }
|
||||
|
||||
---
|
||||
|
||||
### DeepSeek
|
||||
### Together AI
|
||||
|
||||
DeepSeek offers powerful reasoning models at competitive prices.
|
||||
1. Head over to the [Together AI console](https://api.together.ai), create an account, and click **Add Key**.
|
||||
|
||||
1. Head over to the [DeepSeek console](https://platform.deepseek.com/), create an account, and generate an API key.
|
||||
|
||||
2. Run `opencode auth login` and select **Other**.
|
||||
2. Run `opencode auth login` and select **Together AI**.
|
||||
|
||||
```bash
|
||||
$ opencode auth login
|
||||
@@ -526,12 +816,12 @@ DeepSeek offers powerful reasoning models at competitive prices.
|
||||
┌ Add credential
|
||||
│
|
||||
◆ Select provider
|
||||
│ ● Together AI
|
||||
│ ...
|
||||
│ ● Other
|
||||
└
|
||||
```
|
||||
|
||||
3. Enter `deepseek` as the provider ID.
|
||||
3. Enter your Together AI API key.
|
||||
|
||||
```bash
|
||||
$ opencode auth login
|
||||
@@ -539,286 +829,14 @@ DeepSeek offers powerful reasoning models at competitive prices.
|
||||
┌ Add credential
|
||||
│
|
||||
◇ Select provider
|
||||
│ Other
|
||||
│
|
||||
◇ Enter provider id
|
||||
│ deepseek
|
||||
└
|
||||
```
|
||||
|
||||
4. Enter your DeepSeek API key.
|
||||
|
||||
```bash
|
||||
$ opencode auth login
|
||||
|
||||
┌ Add credential
|
||||
│ Together AI
|
||||
│
|
||||
◇ Enter your API key
|
||||
│ sk-...
|
||||
│ _
|
||||
└
|
||||
```
|
||||
|
||||
5. Configure DeepSeek in your opencode config.
|
||||
|
||||
```json title="opencode.json" "deepseek" {5-17}
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"provider": {
|
||||
"deepseek": {
|
||||
"npm": "@ai-sdk/openai-compatible",
|
||||
"name": "DeepSeek",
|
||||
"options": {
|
||||
"baseURL": "https://api.deepseek.com/v1"
|
||||
},
|
||||
"models": {
|
||||
"deepseek-reasoner": {
|
||||
"name": "DeepSeek Reasoner"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
6. Run the `/models` command to select a DeepSeek model.
|
||||
|
||||
---
|
||||
|
||||
### Moonshot AI (Kimi)
|
||||
|
||||
Moonshot AI offers the Kimi models with long context capabilities.
|
||||
|
||||
1. Head over to the [Moonshot AI console](https://platform.moonshot.cn/), create an account, and generate an API key.
|
||||
|
||||
2. Run `opencode auth login` and select **Other**.
|
||||
|
||||
```bash
|
||||
$ opencode auth login
|
||||
|
||||
┌ Add credential
|
||||
│
|
||||
◆ Select provider
|
||||
│ ...
|
||||
│ ● Other
|
||||
└
|
||||
```
|
||||
|
||||
3. Enter `moonshot` as the provider ID.
|
||||
|
||||
```bash
|
||||
$ opencode auth login
|
||||
|
||||
┌ Add credential
|
||||
│
|
||||
◇ Select provider
|
||||
│ Other
|
||||
│
|
||||
◇ Enter provider id
|
||||
│ moonshot
|
||||
└
|
||||
```
|
||||
|
||||
4. Enter your Moonshot API key.
|
||||
|
||||
```bash
|
||||
$ opencode auth login
|
||||
|
||||
┌ Add credential
|
||||
│
|
||||
◇ Enter your API key
|
||||
│ sk-...
|
||||
└
|
||||
```
|
||||
|
||||
5. Configure Moonshot in your opencode config.
|
||||
|
||||
```json title="opencode.json" "moonshot" {5-17}
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"provider": {
|
||||
"moonshot": {
|
||||
"npm": "@ai-sdk/openai-compatible",
|
||||
"name": "Moonshot AI",
|
||||
"options": {
|
||||
"baseURL": "https://api.moonshot.cn/v1"
|
||||
},
|
||||
"models": {
|
||||
"kimi-k2-0711-preview": {
|
||||
"name": "Kimi K2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
6. Run the `/models` command to select a Kimi model.
|
||||
|
||||
---
|
||||
|
||||
### Custom
|
||||
|
||||
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).
|
||||
|
||||
#### Common Examples
|
||||
|
||||
**Together AI:**
|
||||
|
||||
```json title="opencode.json"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"provider": {
|
||||
"together": {
|
||||
"npm": "@ai-sdk/openai-compatible",
|
||||
"name": "Together AI",
|
||||
"options": {
|
||||
"baseURL": "https://api.together.xyz/v1"
|
||||
},
|
||||
"models": {
|
||||
"meta-llama/Llama-3.2-11B-Vision-Instruct-Turbo": {
|
||||
"name": "Llama 3.2 11B Vision"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Fireworks AI:**
|
||||
|
||||
```json title="opencode.json"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"provider": {
|
||||
"fireworks": {
|
||||
"npm": "@ai-sdk/openai-compatible",
|
||||
"name": "Fireworks AI",
|
||||
"options": {
|
||||
"baseURL": "https://api.fireworks.ai/inference/v1"
|
||||
},
|
||||
"models": {
|
||||
"accounts/fireworks/models/llama-v3p1-70b-instruct": {
|
||||
"name": "Llama 3.1 70B"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
4. Run the `/models` command to select a model like _Kimi K2 Instruct_.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
})
|
||||
|
||||
terminal.show()
|
||||
terminal.sendText(`OPENCODE_THEME=system OPENCODE_CALLER=vscode opencode --port ${port}`)
|
||||
terminal.sendText(`OPENCODE_CALLER=vscode opencode --port ${port}`)
|
||||
|
||||
const fileRef = getActiveFile()
|
||||
if (!fileRef) return
|
||||
|
||||
Reference in New Issue
Block a user