opencode-switch-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +376 -0
- package/dist/bin.d.mts +2 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +1183 -0
- package/dist/bin.js.map +1 -0
- package/dist/bin.mjs +1171 -0
- package/dist/bin.mjs.map +1 -0
- package/dist/index.d.mts +175 -0
- package/dist/index.d.ts +175 -0
- package/dist/index.js +1192 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1161 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# opencode-switch
|
|
2
|
+
|
|
3
|
+
CLI and programmatic utilities for managing OpenCode providers, model mappings, and API key aliases.
|
|
4
|
+
|
|
5
|
+
`opencode-switch` keeps your real OpenCode provider configuration in sync while storing its own management metadata separately. It is useful when you want to:
|
|
6
|
+
|
|
7
|
+
- register multiple OpenCode-compatible vendors
|
|
8
|
+
- map stable model types such as `gpt-5.4` and `gemini` to real upstream model IDs
|
|
9
|
+
- maintain multiple API keys per vendor/model pair
|
|
10
|
+
- switch the active vendor or active key without editing JSON files by hand
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- interactive shortcuts for common workflows
|
|
15
|
+
- explicit `vendor`, `model`, and `key` subcommands for scripting
|
|
16
|
+
- deterministic updates to OpenCode `model` and `small_model` pointers
|
|
17
|
+
- separate metadata storage for active vendor, managed models, and key aliases
|
|
18
|
+
- programmatic API exports for embedding the workflow in your own tools
|
|
19
|
+
|
|
20
|
+
## Requirements
|
|
21
|
+
|
|
22
|
+
- Node.js `>= 18.18.0`
|
|
23
|
+
- An existing OpenCode setup, or permission to create files under `~/.config/opencode`
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
Install globally:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install -g opencode-switch-cli
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or run without installing:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx opencode-switch-cli vendor list
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Files managed by the CLI
|
|
40
|
+
|
|
41
|
+
`opencode-switch` manages two files under `~/.config/opencode`:
|
|
42
|
+
|
|
43
|
+
### `opencode.json`
|
|
44
|
+
|
|
45
|
+
This is the real OpenCode config file. Providers are written under:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"provider": {
|
|
50
|
+
"duck": {
|
|
51
|
+
"name": "duck",
|
|
52
|
+
"npm": "@ai-sdk/openai-compatible",
|
|
53
|
+
"options": {
|
|
54
|
+
"baseURL": "https://duck.example.com/v1",
|
|
55
|
+
"apiKey": "duck-key"
|
|
56
|
+
},
|
|
57
|
+
"models": {
|
|
58
|
+
"gpt-5.4": {
|
|
59
|
+
"name": "duck/gpt-5.4"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"model": "duck/gpt-5.4",
|
|
65
|
+
"small_model": "duck/gemini"
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### `opencode-switch.json`
|
|
70
|
+
|
|
71
|
+
This file stores switch-specific metadata such as:
|
|
72
|
+
|
|
73
|
+
- active vendor
|
|
74
|
+
- managed providers
|
|
75
|
+
- managed model registry
|
|
76
|
+
- active key alias per model
|
|
77
|
+
- stored key aliases and credentials
|
|
78
|
+
|
|
79
|
+
## Quick start
|
|
80
|
+
|
|
81
|
+
### 1. Add a vendor
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
opencode-switch vendor add duck \
|
|
85
|
+
--npm @ai-sdk/openai-compatible \
|
|
86
|
+
--base-url https://duck.example.com/v1 \
|
|
87
|
+
--api-key duck-key
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 2. Add models for that vendor
|
|
91
|
+
|
|
92
|
+
Supported model types are currently:
|
|
93
|
+
|
|
94
|
+
- `gpt-5.4`
|
|
95
|
+
- `gemini`
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
opencode-switch model add duck gpt-5.4 --model duck/gpt-5.4
|
|
99
|
+
opencode-switch model add duck gemini --model google/gemini-2.5-flash
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 3. Add one or more key aliases
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
opencode-switch key add duck gpt-5.4 project-a --api-key duck-project-a-key
|
|
106
|
+
opencode-switch key add duck gpt-5.4 project-b --api-key duck-project-b-key
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The first key added for a `vendor + modelType` becomes the active key by default.
|
|
110
|
+
|
|
111
|
+
### 4. Switch the active vendor
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
opencode-switch vendor use duck
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
This updates OpenCode pointers deterministically:
|
|
118
|
+
|
|
119
|
+
- `model` prefers `vendor/gpt-5.4` when available
|
|
120
|
+
- `small_model` prefers `vendor/gemini` when available
|
|
121
|
+
- if the active primary model has an active key alias, the provider `apiKey` is updated too
|
|
122
|
+
|
|
123
|
+
## Interactive shortcuts
|
|
124
|
+
|
|
125
|
+
These commands are useful for manual day-to-day operations:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
opencode-switch ls
|
|
129
|
+
opencode-switch add duck https://duck.example.com/v1
|
|
130
|
+
opencode-switch rm
|
|
131
|
+
opencode-switch addk
|
|
132
|
+
opencode-switch switch
|
|
133
|
+
opencode-switch rmk
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Shortcut behavior
|
|
137
|
+
|
|
138
|
+
- `ls` shows vendors in a dashboard-style list.
|
|
139
|
+
- `add <name> <url>` adds a vendor using the default npm package `@ai-sdk/openai`.
|
|
140
|
+
- `rm` opens an interactive vendor picker and confirmation step.
|
|
141
|
+
- `addk` walks through vendor -> model -> new key creation, and can create a missing model first.
|
|
142
|
+
- `switch` walks through vendor -> model -> existing key selection and activates the chosen key.
|
|
143
|
+
- `rmk` walks through vendor -> model -> key selection before deletion.
|
|
144
|
+
|
|
145
|
+
## Command reference
|
|
146
|
+
|
|
147
|
+
### Vendor commands
|
|
148
|
+
|
|
149
|
+
Add a vendor:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
opencode-switch vendor add <vendorName> \
|
|
153
|
+
--npm <npmPackage> \
|
|
154
|
+
[--base-url <baseUrl>] \
|
|
155
|
+
[--api-key <apiKey>]
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Example:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
opencode-switch vendor add duck \
|
|
162
|
+
--npm @ai-sdk/openai-compatible \
|
|
163
|
+
--base-url https://duck.example.com/v1 \
|
|
164
|
+
--api-key duck-key
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
List vendors:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
opencode-switch vendor list
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Switch the active vendor:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
opencode-switch vendor use duck
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Remove a vendor:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
opencode-switch vendor remove duck
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Model commands
|
|
186
|
+
|
|
187
|
+
Add a model mapping:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
opencode-switch model add <vendorName> <modelType> --model <realModel>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Examples:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
opencode-switch model add duck gpt-5.4 --model duck/gpt-5.4
|
|
197
|
+
opencode-switch model add duck gemini --model google/gemini-2.5-flash
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
List models for a vendor:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
opencode-switch model list duck
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Remove a model mapping:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
opencode-switch model remove duck gpt-5.4
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Key commands
|
|
213
|
+
|
|
214
|
+
Add a key alias:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
opencode-switch key add <vendorName> <modelType> <keyAlias> --api-key <apiKey> [--base-url <baseUrl>]
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Example:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
opencode-switch key add duck gpt-5.4 project-a --api-key duck-project-a-key
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
List keys for a vendor/model pair:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
opencode-switch key list duck gpt-5.4
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Switch the active key alias:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
opencode-switch key use duck gpt-5.4 project-a
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Remove a key alias:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
opencode-switch key remove duck gpt-5.4 project-a
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Behavior notes
|
|
245
|
+
|
|
246
|
+
- Unsupported model types are rejected. Right now only `gpt-5.4` and `gemini` are valid.
|
|
247
|
+
- `model list <vendorName>` includes the active key alias when one is set.
|
|
248
|
+
- `key use` changes the active key only for the selected `vendor + modelType` pair.
|
|
249
|
+
- `vendor use` updates OpenCode's default pointers based on available managed models.
|
|
250
|
+
- Removing a vendor also removes its switch metadata and clears OpenCode pointers that referenced it.
|
|
251
|
+
- Existing provider options and model template metadata are preserved where possible.
|
|
252
|
+
|
|
253
|
+
## Programmatic API
|
|
254
|
+
|
|
255
|
+
The package also exports reusable functions from `dist/index.js` / `dist/index.mjs`.
|
|
256
|
+
|
|
257
|
+
### Exported functions
|
|
258
|
+
|
|
259
|
+
```ts
|
|
260
|
+
import {
|
|
261
|
+
createJsonFileStore,
|
|
262
|
+
createModelService,
|
|
263
|
+
createOpencodeRepository,
|
|
264
|
+
createSwitchRepository,
|
|
265
|
+
createVendorService,
|
|
266
|
+
executeCli,
|
|
267
|
+
SUPPORTED_MODEL_TYPES,
|
|
268
|
+
} from 'opencode-switch-cli';
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Example: create repositories and services
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
import os from 'node:os';
|
|
275
|
+
import path from 'node:path';
|
|
276
|
+
|
|
277
|
+
import {
|
|
278
|
+
createJsonFileStore,
|
|
279
|
+
createModelService,
|
|
280
|
+
createOpencodeRepository,
|
|
281
|
+
createSwitchRepository,
|
|
282
|
+
createVendorService,
|
|
283
|
+
} from 'opencode-switch-cli';
|
|
284
|
+
|
|
285
|
+
const homeDir = os.homedir();
|
|
286
|
+
const configDir = path.join(homeDir, '.config', 'opencode');
|
|
287
|
+
const jsonStore = createJsonFileStore();
|
|
288
|
+
|
|
289
|
+
const opencodeRepository = createOpencodeRepository({
|
|
290
|
+
filePath: path.join(configDir, 'opencode.json'),
|
|
291
|
+
jsonStore,
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
const switchRepository = createSwitchRepository({
|
|
295
|
+
filePath: path.join(configDir, 'opencode-switch.json'),
|
|
296
|
+
jsonStore,
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
const vendorService = createVendorService({
|
|
300
|
+
opencodeRepository,
|
|
301
|
+
switchRepository,
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
const modelService = createModelService({
|
|
305
|
+
opencodeRepository,
|
|
306
|
+
switchRepository,
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
await vendorService.addVendor({
|
|
310
|
+
vendorName: 'duck',
|
|
311
|
+
npm: '@ai-sdk/openai-compatible',
|
|
312
|
+
baseURL: 'https://duck.example.com/v1',
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
await modelService.addModel({
|
|
316
|
+
vendorName: 'duck',
|
|
317
|
+
modelType: 'gpt-5.4',
|
|
318
|
+
realModel: 'duck/gpt-5.4',
|
|
319
|
+
});
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Example: execute the CLI programmatically
|
|
323
|
+
|
|
324
|
+
```ts
|
|
325
|
+
import { executeCli } from 'opencode-switch-cli';
|
|
326
|
+
|
|
327
|
+
const result = await executeCli(['vendor', 'list']);
|
|
328
|
+
|
|
329
|
+
console.log(result.exitCode);
|
|
330
|
+
console.log(result.stdout);
|
|
331
|
+
console.error(result.stderr);
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## Local development
|
|
335
|
+
|
|
336
|
+
Install dependencies:
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
npm install
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Run the CLI in development mode:
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
npm run dev -- vendor list
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Run verification:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
npm test
|
|
352
|
+
npm run typecheck
|
|
353
|
+
npm run build
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
## Publishing to npm
|
|
357
|
+
|
|
358
|
+
The package is already configured with a `prepublishOnly` script:
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
npm run test && npm run typecheck && npm run build
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
When you are ready to release:
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
npm login
|
|
368
|
+
npm version patch
|
|
369
|
+
npm publish
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
If this is the first release for the package name, make sure the package name is available and that you are logged into the correct npm account before publishing.
|
|
373
|
+
|
|
374
|
+
## License
|
|
375
|
+
|
|
376
|
+
MIT
|
package/dist/bin.d.mts
ADDED
package/dist/bin.d.ts
ADDED