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.
@@ -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
+ }