opencode-gemiterm-skills 0.5.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/AGENTS.md +66 -0
- package/CHANGELOG.md +36 -0
- package/LICENSE +21 -0
- package/README.md +217 -0
- package/assets/skills/debate-with-gemini/REFERENCE.md +119 -0
- package/assets/skills/debate-with-gemini/SKILL.md +96 -0
- package/assets/skills/gemiterm/REFERENCE.md +392 -0
- package/assets/skills/gemiterm/SKILL.md +87 -0
- package/index.ts +1 -0
- package/package.json +60 -0
- package/plugin.ts +33 -0
- package/src/cli.ts +88 -0
- package/src/commands/install.ts +21 -0
- package/src/commands/status.ts +15 -0
- package/src/commands/uninstall.ts +21 -0
- package/src/installer.ts +231 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
# GemiTerm CLI Reference
|
|
2
|
+
|
|
3
|
+
Complete command reference for GemiTerm CLI. Loaded on demand by [SKILL.md](SKILL.md).
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- [Commands](#commands)
|
|
8
|
+
- [`gemiterm auth`](#gemiterm-auth)
|
|
9
|
+
- [`gemiterm list`](#gemiterm-list)
|
|
10
|
+
- [`gemiterm fetch <chat_id>`](#gemiterm-fetch-chat_id)
|
|
11
|
+
- [`gemiterm export <chat_id>`](#gemiterm-export-chat_id)
|
|
12
|
+
- [`gemiterm export-all`](#gemiterm-export-all)
|
|
13
|
+
- [`gemiterm delete <chat_id>`](#gemiterm-delete-chat_id)
|
|
14
|
+
- [`gemiterm status`](#gemiterm-status)
|
|
15
|
+
- [`gemiterm profile`](#gemiterm-profile)
|
|
16
|
+
- [`gemiterm continue <chat_id>`](#gemiterm-continue-chat_id)
|
|
17
|
+
- [`gemiterm install-browser`](#gemiterm-install-browser)
|
|
18
|
+
- [Global Flags](#global-flags)
|
|
19
|
+
- [Exit Codes](#exit-codes)
|
|
20
|
+
- [Environment Variables](#environment-variables)
|
|
21
|
+
- [Config File](#config-file)
|
|
22
|
+
- [Rate Limits](#rate-limits)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Commands
|
|
27
|
+
|
|
28
|
+
### `gemiterm auth`
|
|
29
|
+
|
|
30
|
+
Authenticate with Google Gemini API.
|
|
31
|
+
|
|
32
|
+
**Usage:**
|
|
33
|
+
```bash
|
|
34
|
+
gemiterm auth
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Notes:**
|
|
38
|
+
- Interactive command requiring browser
|
|
39
|
+
- Opens OAuth flow in default browser
|
|
40
|
+
- Must be run once per profile
|
|
41
|
+
- Not automation-friendly
|
|
42
|
+
|
|
43
|
+
**Flags:** None
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
### `gemiterm list`
|
|
48
|
+
|
|
49
|
+
List all chats.
|
|
50
|
+
|
|
51
|
+
**Usage:**
|
|
52
|
+
```bash
|
|
53
|
+
gemiterm list [options]
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Flags:**
|
|
57
|
+
- `--format json|text` - Output format (default: text)
|
|
58
|
+
- `--limit N` - Maximum number of chats to return
|
|
59
|
+
- `--reverse` - Reverse sort order
|
|
60
|
+
- `--all-profiles` - List chats across all configured profiles
|
|
61
|
+
- `--sort recent|oldest|alpha` - Sort order (default: recent)
|
|
62
|
+
|
|
63
|
+
**Examples:**
|
|
64
|
+
```bash
|
|
65
|
+
gemiterm list
|
|
66
|
+
gemiterm list --format json
|
|
67
|
+
gemiterm list --format json --limit 10
|
|
68
|
+
gemiterm list --format json --limit 5 --reverse
|
|
69
|
+
gemiterm list --all-profiles --limit 10 --format json
|
|
70
|
+
gemiterm list --sort oldest --format json
|
|
71
|
+
gemiterm list --all-profiles --sort alpha --format json
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Output (JSON):**
|
|
75
|
+
```json
|
|
76
|
+
[
|
|
77
|
+
{
|
|
78
|
+
"id": "abc123def456",
|
|
79
|
+
"title": "Python debugging help",
|
|
80
|
+
"created_at": "2025-05-15T10:30:00Z",
|
|
81
|
+
"updated_at": "2025-05-15T11:45:00Z",
|
|
82
|
+
"message_count": 42
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
### `gemiterm fetch <chat_id>`
|
|
90
|
+
|
|
91
|
+
Fetch transcript for a specific chat.
|
|
92
|
+
|
|
93
|
+
**Usage:**
|
|
94
|
+
```bash
|
|
95
|
+
gemiterm fetch <chat_id> [options]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Arguments:**
|
|
99
|
+
- `chat_id` - The Gemini chat_id (required)
|
|
100
|
+
|
|
101
|
+
**Flags:**
|
|
102
|
+
- `--format json|text` - Output format (default: text)
|
|
103
|
+
|
|
104
|
+
**Examples:**
|
|
105
|
+
```bash
|
|
106
|
+
gemiterm fetch abc123def456
|
|
107
|
+
gemiterm fetch abc123def456 --format json
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Output (JSON):**
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"id": "abc123def456",
|
|
114
|
+
"title": "Python debugging help",
|
|
115
|
+
"created_at": "2025-05-15T10:30:00Z",
|
|
116
|
+
"updated_at": "2025-05-15T11:45:00Z",
|
|
117
|
+
"messages": [
|
|
118
|
+
{
|
|
119
|
+
"role": "user",
|
|
120
|
+
"content": "How do I debug this?",
|
|
121
|
+
"timestamp": "2025-05-15T10:30:00Z"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"role": "model",
|
|
125
|
+
"content": "Let me help you...",
|
|
126
|
+
"timestamp": "2025-05-15T10:30:05Z"
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
### `gemiterm export <chat_id>`
|
|
135
|
+
|
|
136
|
+
Export a chat to a file.
|
|
137
|
+
|
|
138
|
+
**Usage:**
|
|
139
|
+
```bash
|
|
140
|
+
gemiterm export <chat_id> --output <path>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Arguments:**
|
|
144
|
+
- `chat_id` - The Gemini chat_id (required)
|
|
145
|
+
|
|
146
|
+
**Flags:**
|
|
147
|
+
- `--output <path>` - Output file path (required)
|
|
148
|
+
- `--format md|txt` - Export format (default: md)
|
|
149
|
+
|
|
150
|
+
**Examples:**
|
|
151
|
+
```bash
|
|
152
|
+
gemiterm export abc123def456 --output /tmp/chat.md
|
|
153
|
+
gemiterm export abc123def456 --output /tmp/chat.txt --format txt
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Output Format (Markdown):**
|
|
157
|
+
```markdown
|
|
158
|
+
# Python debugging help
|
|
159
|
+
|
|
160
|
+
## User (2025-05-15 10:30)
|
|
161
|
+
How do I debug this?
|
|
162
|
+
|
|
163
|
+
## Model (2025-05-15 10:30)
|
|
164
|
+
Let me help you...
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
### `gemiterm export-all`
|
|
170
|
+
|
|
171
|
+
Export all chats to a directory.
|
|
172
|
+
|
|
173
|
+
**Usage:**
|
|
174
|
+
```bash
|
|
175
|
+
gemiterm export-all --output <directory>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Flags:**
|
|
179
|
+
- `--output <directory>` - Output directory path (required)
|
|
180
|
+
- `--format md|txt` - Export format (default: md)
|
|
181
|
+
- `--parallel N` - Number of parallel exports (default: 4)
|
|
182
|
+
|
|
183
|
+
**Examples:**
|
|
184
|
+
```bash
|
|
185
|
+
gemiterm export-all --output /tmp/gemini/
|
|
186
|
+
gemiterm export-all --output /tmp/chats/ --format txt
|
|
187
|
+
gemiterm export-all --output /tmp/backup/ --parallel 2
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Output Structure:**
|
|
191
|
+
```
|
|
192
|
+
/tmp/gemini/
|
|
193
|
+
├── chat_abc123.md
|
|
194
|
+
├── chat_def456.md
|
|
195
|
+
└── chat_ghi789.md
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
### `gemiterm delete <chat_id>`
|
|
201
|
+
|
|
202
|
+
Delete a chat.
|
|
203
|
+
|
|
204
|
+
**Usage:**
|
|
205
|
+
```bash
|
|
206
|
+
gemiterm delete <chat_id>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Arguments:**
|
|
210
|
+
- `chat_id` - The Gemini chat_id (required)
|
|
211
|
+
|
|
212
|
+
**Flags:**
|
|
213
|
+
- `--confirm` - Skip confirmation prompt
|
|
214
|
+
|
|
215
|
+
**Examples:**
|
|
216
|
+
```bash
|
|
217
|
+
gemiterm delete abc123def456
|
|
218
|
+
gemiterm delete abc123def456 --confirm
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Warning:** This operation is irreversible.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### `gemiterm status`
|
|
226
|
+
|
|
227
|
+
Check authentication status and profile information.
|
|
228
|
+
|
|
229
|
+
**Usage:**
|
|
230
|
+
```bash
|
|
231
|
+
gemiterm status
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**Flags:**
|
|
235
|
+
- `--format json|text` - Output format (default: text)
|
|
236
|
+
|
|
237
|
+
**Examples:**
|
|
238
|
+
```bash
|
|
239
|
+
gemiterm status
|
|
240
|
+
gemiterm status --format json
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**Output (Text):**
|
|
244
|
+
```
|
|
245
|
+
Authenticated: Yes
|
|
246
|
+
Profile: default
|
|
247
|
+
Email: user@gmail.com
|
|
248
|
+
Token expires: 2025-06-15T10:30:00Z
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Output (JSON):**
|
|
252
|
+
```json
|
|
253
|
+
{
|
|
254
|
+
"authenticated": true,
|
|
255
|
+
"profile": "default",
|
|
256
|
+
"email": "user@gmail.com",
|
|
257
|
+
"token_expires": "2025-06-15T10:30:00Z"
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
### `gemiterm profile`
|
|
264
|
+
|
|
265
|
+
Manage Gemini profiles.
|
|
266
|
+
|
|
267
|
+
**Usage:**
|
|
268
|
+
```bash
|
|
269
|
+
gemiterm profile [options]
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
**Flags:**
|
|
273
|
+
- `--set <name>` - Switch to profile
|
|
274
|
+
- `--list` - List all profiles
|
|
275
|
+
- `--create <name>` - Create new profile
|
|
276
|
+
- `--delete <name>` - Delete profile
|
|
277
|
+
|
|
278
|
+
**Examples:**
|
|
279
|
+
```bash
|
|
280
|
+
gemiterm profile --list
|
|
281
|
+
gemiterm profile --set work
|
|
282
|
+
gemiterm profile --create personal
|
|
283
|
+
gemiterm profile --delete old-profile
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
### `gemiterm continue <chat_id>`
|
|
289
|
+
|
|
290
|
+
Continue a chat (interactive mode).
|
|
291
|
+
|
|
292
|
+
**Usage:**
|
|
293
|
+
```bash
|
|
294
|
+
gemiterm continue <chat_id>
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**Arguments:**
|
|
298
|
+
- `chat_id` - The Gemini chat_id (required)
|
|
299
|
+
|
|
300
|
+
**Notes:**
|
|
301
|
+
- Interactive command not suitable for automation
|
|
302
|
+
- Opens REPL for continued chat
|
|
303
|
+
- Requires manual input
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
### `gemiterm install-browser`
|
|
308
|
+
|
|
309
|
+
Install browser for authentication.
|
|
310
|
+
|
|
311
|
+
**Usage:**
|
|
312
|
+
```bash
|
|
313
|
+
gemiterm install-browser
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**Flags:**
|
|
317
|
+
- `--browser chrome|firefox|edge` - Browser to install (default: chrome)
|
|
318
|
+
|
|
319
|
+
**Notes:**
|
|
320
|
+
- Run once during setup
|
|
321
|
+
- Installs Playwright browser
|
|
322
|
+
- Required for `gemiterm auth`
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## Global Flags
|
|
327
|
+
|
|
328
|
+
These flags work with all commands:
|
|
329
|
+
|
|
330
|
+
- `--config <path>` - Custom config file path
|
|
331
|
+
- `--profile <name>` - Use specific profile
|
|
332
|
+
- `--verbose` - Enable verbose output
|
|
333
|
+
- `--quiet` - Suppress non-error output
|
|
334
|
+
- `--help` - Show help message
|
|
335
|
+
- `--version` - Show version info
|
|
336
|
+
|
|
337
|
+
## Exit Codes
|
|
338
|
+
|
|
339
|
+
| Code | Meaning |
|
|
340
|
+
|------|---------|
|
|
341
|
+
| 0 | Success |
|
|
342
|
+
| 1 | General error |
|
|
343
|
+
| 2 | Authentication required |
|
|
344
|
+
| 3 | Chat not found |
|
|
345
|
+
| 4 | Invalid arguments |
|
|
346
|
+
| 5 | Rate limit exceeded |
|
|
347
|
+
| 6 | Network error |
|
|
348
|
+
|
|
349
|
+
## Environment Variables
|
|
350
|
+
|
|
351
|
+
| Variable | Description | Default |
|
|
352
|
+
|----------|-------------|---------|
|
|
353
|
+
| `GEMITERM_CONFIG` | Config file path | `~/.config/gemiterm/config.json` |
|
|
354
|
+
| `GEMITERM_DATA_DIR` | Data directory | `~/.local/share/gemiterm/` |
|
|
355
|
+
| `GEMITERM_CACHE_DIR` | Cache directory | `~/.cache/gemiterm/` |
|
|
356
|
+
| `GEMITERM_LOG_LEVEL` | Logging level | `INFO` |
|
|
357
|
+
| `BROWSER` | Browser for auth | System default |
|
|
358
|
+
|
|
359
|
+
## Config File
|
|
360
|
+
|
|
361
|
+
Location: `~/.config/gemiterm/config.json`
|
|
362
|
+
|
|
363
|
+
```json
|
|
364
|
+
{
|
|
365
|
+
"profiles": {
|
|
366
|
+
"default": {
|
|
367
|
+
"email": "user@gmail.com",
|
|
368
|
+
"access_token": "...",
|
|
369
|
+
"refresh_token": "...",
|
|
370
|
+
"token_expires": "2025-06-15T10:30:00Z"
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
"current_profile": "default",
|
|
374
|
+
"api_key": "...",
|
|
375
|
+
"timeout": 60,
|
|
376
|
+
"max_retries": 3
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Rate Limits
|
|
381
|
+
|
|
382
|
+
Google Gemini API enforces rate limits on the free tier:
|
|
383
|
+
|
|
384
|
+
| Limit | Default |
|
|
385
|
+
|-------|---------|
|
|
386
|
+
| Requests per minute | 60 |
|
|
387
|
+
| Requests per day | 1500 |
|
|
388
|
+
| Tokens per request | 2,000,000 |
|
|
389
|
+
|
|
390
|
+
> Reflects Gemini free-tier defaults at time of writing; verify with the latest Google AI docs.
|
|
391
|
+
|
|
392
|
+
GemiTerm implements automatic retry with exponential backoff.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gemiterm
|
|
3
|
+
description: Google Gemini Terminal CLI wrapper for listing chats, fetching transcripts, exporting conversations, and managing profiles via the gemiterm Python CLI. Use when the user asks to read, list, export, or interact with Gemini chat history from a terminal, or invokes "gemiterm" commands.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: opencode
|
|
6
|
+
metadata:
|
|
7
|
+
tool: gemiterm
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# GemiTerm — Google Gemini Terminal CLI
|
|
11
|
+
|
|
12
|
+
GemiTerm provides terminal access to Google Gemini chat history: list, fetch, export, delete, and manage profiles. Commands that emit `--format json` are automation-friendly; `auth` and `continue` require interactive flows.
|
|
13
|
+
|
|
14
|
+
## Install check
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
gemiterm --version
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
If missing:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pipx install gemiterm
|
|
24
|
+
gemiterm install-browser
|
|
25
|
+
gemiterm auth
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Commands
|
|
29
|
+
|
|
30
|
+
| Command | Purpose |
|
|
31
|
+
|---------|---------|
|
|
32
|
+
| `gemiterm list [--all-profiles] [--limit N] [--sort recent\|oldest\|alpha] [--format json]` | List chats with metadata |
|
|
33
|
+
| `gemiterm fetch <chat_id> [--format json]` | Fetch full transcript for one chat |
|
|
34
|
+
| `gemiterm export <chat_id> --output <path> [--format md\|txt]` | Export one chat to a file |
|
|
35
|
+
| `gemiterm export-all --output <dir> [--format md\|txt] [--parallel N]` | Bulk export all chats to a directory |
|
|
36
|
+
| `gemiterm delete <chat_id> [--confirm]` | Delete one chat (irreversible) |
|
|
37
|
+
| `gemiterm status [--format json]` | Show auth status and active profile |
|
|
38
|
+
| `gemiterm profile list\|default <name>\|add <name>\|delete <name>\|rename <name> <new_name>` | Manage Gemini profiles |
|
|
39
|
+
| `gemiterm continue <chat_id>` | Resume chat interactively (not automation-friendly) |
|
|
40
|
+
| `gemiterm auth` | Run OAuth flow (interactive, not automation-friendly) |
|
|
41
|
+
| `gemiterm install-browser [--browser chrome\|firefox\|edge]` | Install Playwright browser for auth |
|
|
42
|
+
|
|
43
|
+
**Interactive commands** (`auth`, `continue`) open a browser or REPL — run manually, never from a script.
|
|
44
|
+
|
|
45
|
+
## Output formats
|
|
46
|
+
|
|
47
|
+
| Flag | Effect |
|
|
48
|
+
|------|--------|
|
|
49
|
+
| `--format json` | Machine-readable JSON for automation |
|
|
50
|
+
| `--format text` | Human-readable text (default for most commands) |
|
|
51
|
+
| `--output <path>` | Write export to file (Markdown by default) |
|
|
52
|
+
| `--format md\|txt` | Export format for `export` and `export-all` (default: `md`) |
|
|
53
|
+
|
|
54
|
+
## Common patterns
|
|
55
|
+
|
|
56
|
+
**Find a chat by keyword:**
|
|
57
|
+
```bash
|
|
58
|
+
gemiterm list --format json | jq '.[] | select(.title | test("keyword"))'
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Export one chat:**
|
|
62
|
+
```bash
|
|
63
|
+
gemiterm fetch <chat_id> --format json > /tmp/chat.json
|
|
64
|
+
gemiterm export <chat_id> --output /tmp/chat.md
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Bulk analyze:**
|
|
68
|
+
```bash
|
|
69
|
+
gemiterm list --format json | jq -r '.[].id' | xargs -I {} gemiterm fetch {} --format json
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**List recent chats across all profiles:**
|
|
73
|
+
```bash
|
|
74
|
+
gemiterm list --all-profiles --limit 10 --format json
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Troubleshooting
|
|
78
|
+
|
|
79
|
+
- **Auth errors:** run `gemiterm auth` manually to complete the OAuth flow.
|
|
80
|
+
- **Expired tokens:** GemiTerm refreshes automatically; re-run `auth` if it fails.
|
|
81
|
+
- **Rate limits:** space out bulk operations; see [REFERENCE.md](REFERENCE.md) for limits and retry behaviour.
|
|
82
|
+
- **UNAUTHENTICATED warnings:** Profile cookies may need refresh — run `gemiterm auth` to re-authenticate the affected profile.
|
|
83
|
+
|
|
84
|
+
## References
|
|
85
|
+
|
|
86
|
+
- [REFERENCE.md](REFERENCE.md) — flags, JSON schemas, env vars, exit codes, rate limits
|
|
87
|
+
- Project: https://github.com/expert-vision-software/gemiterm
|
package/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./plugin.ts";
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "opencode-gemiterm-skills",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"module": "index.ts",
|
|
6
|
+
"description": "OpenCode plugin bundling the gemiterm and debate-with-gemini skills.",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"publisher": "Expert Vision Software",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"opencode",
|
|
11
|
+
"opencode-plugin",
|
|
12
|
+
"opencode-skills",
|
|
13
|
+
"gemiterm",
|
|
14
|
+
"gemini",
|
|
15
|
+
"debate"
|
|
16
|
+
],
|
|
17
|
+
"bin": {
|
|
18
|
+
"opencode-gemiterm-skills": "./src/cli.ts"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"bun": ">=1.0.0"
|
|
22
|
+
},
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"files": [
|
|
25
|
+
"index.ts",
|
|
26
|
+
"plugin.ts",
|
|
27
|
+
"src",
|
|
28
|
+
"assets",
|
|
29
|
+
"README.md",
|
|
30
|
+
"AGENTS.md",
|
|
31
|
+
"CHANGELOG.md",
|
|
32
|
+
"LICENSE"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"check": "tsc --noEmit",
|
|
36
|
+
"test": "bun test",
|
|
37
|
+
"prepublishOnly": "bun run check && bun test"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@opencode-ai/plugin": "^1.16.2"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/bun": "latest",
|
|
44
|
+
"@types/node": "latest",
|
|
45
|
+
"typescript": "^5.7.0"
|
|
46
|
+
},
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "https://github.com/Expert-Vision-Software/opencode-gemiterm-skills.git"
|
|
50
|
+
},
|
|
51
|
+
"homepage": "https://github.com/Expert-Vision-Software/opencode-gemiterm-skills#readme",
|
|
52
|
+
"bugs": {
|
|
53
|
+
"url": "https://github.com/Expert-Vision-Software/opencode-gemiterm-skills/issues",
|
|
54
|
+
"email": "support@expertvisionsoftware.com"
|
|
55
|
+
},
|
|
56
|
+
"author": "Expert Vision Software",
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"access": "public"
|
|
59
|
+
}
|
|
60
|
+
}
|
package/plugin.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Plugin } from "@opencode-ai/plugin";
|
|
2
|
+
import { install, getPackageVersion, getGlobalConfigPath } from "./src/installer.ts";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
|
|
5
|
+
const plugin: Plugin = async ({ directory }) => ({
|
|
6
|
+
config: async () => {
|
|
7
|
+
const version = await getPackageVersion();
|
|
8
|
+
const globalConfigPath = getGlobalConfigPath();
|
|
9
|
+
|
|
10
|
+
const isGlobal =
|
|
11
|
+
directory === globalConfigPath || directory.startsWith(globalConfigPath + "/") ||
|
|
12
|
+
directory.startsWith(globalConfigPath + "\\");
|
|
13
|
+
|
|
14
|
+
const scope = isGlobal ? "global" : "local";
|
|
15
|
+
const versionMarker = join(
|
|
16
|
+
isGlobal ? globalConfigPath : directory,
|
|
17
|
+
"skills",
|
|
18
|
+
"gemiterm",
|
|
19
|
+
".version",
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const installed = (await Bun.file(versionMarker).text()).trim();
|
|
24
|
+
if (installed === version) return;
|
|
25
|
+
} catch {
|
|
26
|
+
// Not installed, proceed
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
await install(scope, directory);
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export default plugin;
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { parseArgs } from "node:util";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { installCommand } from "./commands/install.ts";
|
|
6
|
+
import { uninstallCommand } from "./commands/uninstall.ts";
|
|
7
|
+
import { statusCommand } from "./commands/status.ts";
|
|
8
|
+
import type { Scope } from "./installer.ts";
|
|
9
|
+
|
|
10
|
+
const VERSION = JSON.parse(
|
|
11
|
+
await Bun.file(join(fileURLToPath(new URL("../", import.meta.url)), "package.json")).text(),
|
|
12
|
+
).version;
|
|
13
|
+
|
|
14
|
+
function printHelp(): void {
|
|
15
|
+
console.log(`
|
|
16
|
+
opencode-gemiterm-skills v${VERSION}
|
|
17
|
+
|
|
18
|
+
Commands:
|
|
19
|
+
install Copy skills to .opencode/skills/ and register in opencode.json
|
|
20
|
+
uninstall Remove installed skills from .opencode/skills/
|
|
21
|
+
status Check installation status
|
|
22
|
+
|
|
23
|
+
Options:
|
|
24
|
+
-s, --scope <scope> Installation scope: "local" (default) or "global"
|
|
25
|
+
-h, --help Show this help message
|
|
26
|
+
-v, --version Show version
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
bunx opencode-gemiterm-skills install
|
|
30
|
+
bunx opencode-gemiterm-skills install --scope global
|
|
31
|
+
bunx opencode-gemiterm-skills uninstall --scope local
|
|
32
|
+
bunx opencode-gemiterm-skills status
|
|
33
|
+
`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function main(): Promise<void> {
|
|
37
|
+
const { positionals, values } = parseArgs({
|
|
38
|
+
options: {
|
|
39
|
+
scope: { type: "string", short: "s" },
|
|
40
|
+
help: { type: "boolean", short: "h", default: false },
|
|
41
|
+
version: { type: "boolean", short: "v", default: false },
|
|
42
|
+
},
|
|
43
|
+
allowPositionals: true,
|
|
44
|
+
strict: true,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
if (values.version) {
|
|
48
|
+
console.log(`opencode-gemiterm-skills v${VERSION}`);
|
|
49
|
+
process.exit(0);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (values.help || positionals.length === 0) {
|
|
53
|
+
printHelp();
|
|
54
|
+
process.exit(0);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const command = positionals[0];
|
|
58
|
+
const scope: Scope | undefined = values.scope as Scope | undefined;
|
|
59
|
+
|
|
60
|
+
if (scope && scope !== "local" && scope !== "global") {
|
|
61
|
+
console.error(`Invalid scope: ${scope}. Must be "local" or "global".`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
switch (command) {
|
|
67
|
+
case "install":
|
|
68
|
+
await installCommand({ scope });
|
|
69
|
+
break;
|
|
70
|
+
case "uninstall":
|
|
71
|
+
await uninstallCommand({ scope });
|
|
72
|
+
break;
|
|
73
|
+
case "status":
|
|
74
|
+
await statusCommand();
|
|
75
|
+
break;
|
|
76
|
+
default:
|
|
77
|
+
console.error(`Unknown command: ${command}`);
|
|
78
|
+
printHelp();
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
} catch (error) {
|
|
82
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
83
|
+
console.error(`Error: ${message}`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
main();
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { install, type Scope } from "../installer.ts";
|
|
2
|
+
|
|
3
|
+
interface InstallOptions {
|
|
4
|
+
scope?: Scope;
|
|
5
|
+
force?: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export async function installCommand(options: InstallOptions = {}): Promise<void> {
|
|
9
|
+
const scope = options.scope ?? "local";
|
|
10
|
+
const result = await install(scope);
|
|
11
|
+
|
|
12
|
+
console.log(
|
|
13
|
+
`opencode-gemiterm-skills installed ${scope === "global" ? "globally" : "locally"}:`,
|
|
14
|
+
);
|
|
15
|
+
for (const p of result.skillPaths) {
|
|
16
|
+
console.log(` ${p}`);
|
|
17
|
+
}
|
|
18
|
+
if (result.migrated) {
|
|
19
|
+
console.log(" Migrated: opencode.json → .opencode/opencode.json");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { status } from "../installer.ts";
|
|
2
|
+
|
|
3
|
+
export async function statusCommand(): Promise<void> {
|
|
4
|
+
const result = await status();
|
|
5
|
+
|
|
6
|
+
if (!result.installed) {
|
|
7
|
+
console.log("opencode-gemiterm-skills is not installed.");
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
console.log(`opencode-gemiterm-skills [${result.scope}]`);
|
|
12
|
+
console.log(` Installed: yes`);
|
|
13
|
+
if (result.version) console.log(` Version: ${result.version}`);
|
|
14
|
+
console.log(` Plugin in config: ${result.pluginInConfig ? "yes" : "no"}`);
|
|
15
|
+
}
|