Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ on a readline for the next.
| `mcp-intellij` | MCP | replace | Add the JetBrains IDE MCP server (loopback HTTP, default port 64342) |
| `mcp-playwright` | MCP | replace | Add the Playwright MCP server (`@playwright/mcp`, local stdio via npx) |
| `mcp-vscode` | MCP | replace | Add the VS Code MCP server via the `JuehangQin.vscode-mcp-server` extension (loopback HTTP, default port 3000) |
| `plugin-litellm` | Plugin | append | Add `opencode-plugin-litellm` — discovers a LiteLLM proxy's models at runtime and adds them to the picker (localhost auto-detected; key from `$LITELLM_API_KEY`) |
| `provider-litellm` | Provider | replace | Point the `litellm` provider at a custom/remote proxy URL for `plugin-litellm` (prompts for base URL; key via `$LITELLM_API_KEY`, no models list) |
| `plugin-superpowers` | Plugin | append | Add the Superpowers OpenCode plugin from `obra/superpowers` (brainstorming, plans, TDD, review workflows) |
| `permissions-git-safe` | Permissions | merge | Read-only git commands (status, diff, log, branch --list, fetch, etc.) |
| `permissions-webfetch-ask` | Permissions | merge | Requires approval before opencode uses the webfetch tool |
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "opencode-presets",
"version": "0.8.8",
"version": "0.9.0",
"description": "Interactive CLI that patches OpenCode config files with curated presets — LSP, MCP, permissions, TUI.",
"type": "module",
"bin": {
Expand Down
17 changes: 17 additions & 0 deletions presets/plugin-litellm.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// @name: plugin-litellm
// @description: Adds the opencode-plugin-litellm plugin (npm
// opencode-plugin-litellm, repo yuseferi/opencode-litellm). At opencode
// startup it queries a LiteLLM proxy's /v1/models and injects every model
// into the picker at runtime — no hand-maintained models list. For a proxy
// on localhost:4000/8000/8080 with the key in $LITELLM_API_KEY (or
// $LITELLM_MASTER_KEY), this preset alone is enough: the plugin auto-detects
// the URL and creates the litellm provider itself. For a custom/remote URL,
// also install provider-litellm to set provider.litellm.options.baseURL.
// Pinned to an exact version; bump it here to update. After installing a
// plugin preset, quit and restart opencode.
// @author: Jan <jan@trick77.com>
// @version: 0.1.0
// @path: plugin
// @mode: append

["opencode-plugin-litellm@0.5.0"]
22 changes: 22 additions & 0 deletions presets/provider-litellm.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// @name: provider-litellm
// @description: Points opencode's litellm provider at a custom/remote LiteLLM
// proxy URL for use with the plugin-litellm preset (opencode-plugin-litellm),
// which discovers the model list at runtime. Sets provider.litellm with
// @ai-sdk/openai-compatible, the proxy baseURL, and apiKey read from the
// $LITELLM_API_KEY environment variable — export it in your shell before
// starting opencode (the plugin reads $LITELLM_API_KEY / $LITELLM_MASTER_KEY
// directly for model discovery). Deliberately declares NO models: the plugin
// fills them in. Skip this preset if your proxy is on localhost with the key
// in env — plugin-litellm auto-detects that on its own.
// @author: Jan <jan@trick77.com>
// @version: 0.2.0
// @path: provider.litellm
// @prompt: baseURL | text | LiteLLM proxy base URL (OpenAI-compatible /v1 endpoint) | http://localhost:4000/v1
{
"npm": "@ai-sdk/openai-compatible",
"name": "LiteLLM (proxy)",
"options": {
"baseURL": "{{prompt:baseURL}}",
"apiKey": "{env:LITELLM_API_KEY}"
}
}
38 changes: 38 additions & 0 deletions test/builtin-presets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,41 @@ test('ships a runaway guard preset with step limits for built-in agents', async
},
});
});

test('ships a litellm plugin preset that appends the runtime-discovery plugin', async () => {
const preset = resolve(process.cwd(), 'presets/plugin-litellm.conf');

const { meta, body } = await parseConf(preset);

assert.equal(meta.name, 'plugin-litellm');
assert.equal(meta.path, 'plugin');
assert.equal(meta.mode, 'append');
assert.deepEqual(body, ['opencode-plugin-litellm@0.5.0']);
});

test('ships a litellm provider preset that points at a proxy URL, no models', async () => {
const preset = resolve(process.cwd(), 'presets/provider-litellm.conf');

const { meta, body } = await parseConf(preset);

assert.equal(meta.name, 'provider-litellm');
assert.equal(meta.path, 'provider.litellm');
assert.equal(meta.mode, 'replace');

// Only the base URL is prompted; the key comes from $LITELLM_API_KEY.
assert.deepEqual(
meta.prompts.map((p) => ({ name: p.name, type: p.type })),
[{ name: 'baseURL', type: 'text' }],
);

// No `models` block — the plugin discovers models at runtime.
// Body keeps the {{prompt:...}} placeholder until install-time expansion.
assert.deepEqual(body, {
npm: '@ai-sdk/openai-compatible',
name: 'LiteLLM (proxy)',
options: {
baseURL: '{{prompt:baseURL}}',
apiKey: '{env:LITELLM_API_KEY}',
},
});
});
Loading