gemiterm 2.1.1 → 2.2.0-beta.1

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/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 GemiTerm contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,268 +1,337 @@
1
+ <div align="center">
2
+
1
3
  # GemiTerm
2
4
 
3
- Access and manage your Gemini web chats from the command line. GemiTerm bridges Playwright-based Google authentication to let you list, fetch, export, continue, and delete conversations trapped in the Gemini web interface — without a standard API. Built with [Bun](https://bun.sh) and TypeScript.
5
+ ### Google Gemini in your terminal list, search, export, continue, and debate from the command line.
4
6
 
5
- ## Prerequisites
7
+ [![npm version](https://img.shields.io/npm/v/gemiterm?color=cb3837&label=npm)](https://www.npmjs.com/package/gemiterm)
8
+ [![Bun](https://img.shields.io/badge/Runtime-Bun-f9f1e1?logo=bun&logoColor=black)](https://bun.sh)
9
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Strict-3178c6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-22c55e)](LICENSE.md)
11
+ [![Platforms](https://img.shields.io/badge/Platforms-Windows%20%7C%20Linux%20%7C%20macOS-6366f1)](#installation)
6
12
 
7
- - **[Bun](https://bun.sh)** runtime 1.0.0
8
- - **Chromium Browser** — GemiTerm uses your system Chrome/Edge if available, otherwise installs Playwright's Chromium automatically
9
- - **Google Account** with access to [Gemini](https://gemini.google.com)
13
+ **List · Search · Export · Continue · Debate · Automate**
10
14
 
11
- ## Quick Start (no install)
15
+ [Quick Start](#quick-start) · [Features](#features) · [Cross-Agent Debates](#cross-agent-debates-with-gemini) · [Commands](#commands) · [Configuration](#configuration) · [Contributing](#contributing) · [Acknowledgements](#acknowledgments)
12
16
 
13
- Use `bunx` to run GemiTerm directly — no install step needed:
17
+ </div>
14
18
 
15
- ```bash
16
- bunx gemiterm auth # authenticate with Google
17
- bunx gemiterm list # list your chats
18
- ```
19
+ ---
19
20
 
20
- ## Installation
21
+ ## What is GemiTerm?
21
22
 
22
- ### Global install (recommended for daily use)
23
+ [Gemini](https://gemini.google.com) is one of the most capable AI assistants available — and almost all of your best conversations with it live **trapped inside the web UI**, with no public API to reach them. GemiTerm is the bridge.
23
24
 
24
- ```bash
25
- bun install gemiterm -g
26
- ```
25
+ It's a fast, scriptable command-line client for the **Google Gemini web app**. Authenticate once, then list, search, fetch, export, continue, and delete chats from your shell. Pipe JSON into other tools. Wire it into CI. Or hand it to your AI coding agent and let it argue trade-offs with Gemini in real time.
27
26
 
28
- Then use from anywhere:
27
+ GemiTerm is built with **[Bun](https://bun.sh)** and TypeScript, ships as a single native binary, and authenticates via Playwright — no Google API key, no rate limits, no quota.
29
28
 
30
- ```bash
31
- gemiterm auth
32
- gemiterm list
33
- ```
29
+ > **TL;DR:** If you've ever wanted to `grep` your Gemini history, bulk-export months of chats, or have your coding agent debate Gemini about architecture before you commit — GemiTerm is for you.
34
30
 
35
- ### Install scripts (binary drop)
31
+ ## Why GemiTerm?
36
32
 
37
- For systems without Bun the script auto-bootstraps Bun if needed.
33
+ - **No public API? No problem.** GemiTerm drives the real Gemini web app via a headless browser. It sees exactly what you see, including your entire history.
34
+ - **Cross-agent debates built-in.** Spin up a `debate-with-gemini` skill and your coding agent (Claude Code, OpenCode, GitHub Copilot, …) will argue both sides of a technical decision with real Gemini responses, for N rounds. Catch design flaws before they ship.
35
+ - **Scriptable & pipeable.** First-class `text` and `json` output. Works in cron jobs, Makefiles, shell loops, and CI.
36
+ - **Searchable archive.** Bulk-export to Markdown or JSON and run `grep`, `rg`, or your favorite search tool over months of AI conversations.
37
+ - **Multi-profile, multi-account.** Keep work, personal, and side-project identities separate. One CLI, many Gemini accounts.
38
+ - **Single binary, every OS.** Native builds for Windows, Linux, and macOS. No Node, no Python, no runtime to install.
39
+ - **Local-first, private.** Cookies never leave your machine. 7-day freshness window. You own your data.
38
40
 
39
- **Windows** (PowerShell 7+):
41
+ ## Features
40
42
 
41
- ```powershell
42
- irm https://github.com/expert-vision-software/GemiTerm/releases/latest/download/install.ps1 | iex
43
- ```
43
+ - 🔍 **List & search** — find any Gemini chat by title, date, or content (`--sort`, `--after`, `--before`, `--search`, `--all`, `--all-profiles`)
44
+ - 📥 **Bulk export** — Markdown or JSON, indexed `index.md`, ready for grep and archival
45
+ - 💬 **Continue or start** — interactive REPL or one-shot, with `--prompt-file` for long prompts
46
+ - 🗑️ **Delete with confirmation** — clean up old chats safely (`--force` to skip)
47
+ - 👤 **Multi-profile** — separate identities for work / personal / side-projects, one-click switching
48
+ - 🤖 **AI-agent skills** — plug into OpenCode, Claude Code, GitHub Copilot, and any agent that reads skills
49
+ - 🗣️ **Cross-agent debates** — your agent argues both sides with Gemini, surfaces real agreements and disagreements
50
+ - 📦 **Single binary** — Bun-compiled, no runtime required; works on Windows, Linux, macOS
51
+ - 🔐 **Local cookies** — never uploaded; 7-day freshness window
44
52
 
45
- **Linux / WSL**:
53
+ ## Cross-Agent Debates with Gemini
46
54
 
47
- ```bash
48
- curl -fsSL https://github.com/expert-vision-software/GemiTerm/releases/latest/download/install.sh | bash
49
- ```
55
+ The killer feature isn't just CLI access — it's what your **AI coding agent** can do with it.
50
56
 
51
- See [docs/INSTALL.md](docs/INSTALL.md) for the full guide, uninstall instructions, troubleshooting, and build-from-source steps.
57
+ GemiTerm ships with a companion **skills package** (`opencode-gemiterm-skills`) that teaches any LLM-powered terminal how to use GemiTerm on demand. Two skills are included:
52
58
 
53
- > **Upgrading from v1.4.1?** Your profiles, cookies, and default profile marker are preserved. See the "Upgrade from v1.4.1" section in [docs/INSTALL.md](docs/INSTALL.md) for details.
59
+ | Skill | What it does |
60
+ | --- | --- |
61
+ | **`gemiterm`** | Search, list, export, and manage your Gemini chats from inside an agent session. |
62
+ | **`debate-with-gemini`** | Run structured multi-turn technical debates with Gemini — perfect for stress-testing architecture decisions, trade-offs, and design choices. |
54
63
 
55
- ## Development
64
+ Install in one command:
56
65
 
57
66
  ```bash
58
- bun install
59
- bun run dev # run the CLI
60
- bun test # run tests (Bun test runner)
61
- bun run typecheck # TypeScript type checking
62
- bun run build # compile to standalone Bun binary
63
- bun run build:linux # cross-compile for Linux x64
64
- bun run build:windows # cross-compile for Windows x64
67
+ gemiterm install-skills
68
+ # or, for any agent that supports the skills CLI
69
+ bunx opencode-gemiterm-skills install
65
70
  ```
66
71
 
67
- For installing Chromium, use the platform-specific wrapper scripts:
68
- ```bash
69
- bash scripts/install-browser.sh # Linux/macOS
70
- pwsh scripts/install-browser.ps1 # Windows
71
- ```
72
+ Then in your agent session, just ask:
72
73
 
73
- ## Building from source
74
+ > **You:** "Debate Gemini for/against using SQLite as the primary database for a SaaS app. Context: docs/arch.md. 5 turns."
74
75
 
75
- GemiTerm is built with [Bun](https://bun.sh) 1.3.13 or later.
76
+ The agent reads your context, seeds a fresh Gemini chat with the opposing view, and runs a 5-round autonomous back-and-forth:
76
77
 
77
- ```bash
78
- bun run build # native binary (dist/gemiterm or dist/gemiterm.exe)
79
- bun run build:linux # Linux x64 binary (dist/gemiterm)
80
- bun run build:windows # Windows x64 binary (dist/gemiterm.exe)
81
- bun run build:release # minified release binary (dist/gemiterm)
78
+ ```
79
+ Debate complete (5 turns). Gemini argued FOR SQLite (simplicity, zero-config).
80
+ I argued AGAINST (concurrency limits, no network access, scaling ceiling).
81
+ Key agreements: fine for prototyping, migrate to Postgres before 100+ concurrent users.
82
82
  ```
83
83
 
84
- Output paths:
85
- - **Linux/macOS**: `dist/gemiterm`
86
- - **Windows**: `dist/gemiterm.exe`
84
+ Other use cases for `debate-with-gemini`:
87
85
 
88
- ## Release artifacts
86
+ - **Validate API design** — "Have Gemini argue against this REST contract. 3 turns."
87
+ - **Review a refactor** — "Stress-test the migration to event-sourcing with Gemini. 4 turns."
88
+ - **Compare libraries** — "Argue both sides of `Zod` vs. `valibot` for this schema. 3 turns."
89
+ - **Continue a previous debate** — "Resume chat `c_abc123` for 3 more turns."
89
90
 
90
- The v2.0.0 release ships the following GitHub Release assets:
91
- - `GemiTerm` — Linux x64 binary
92
- - `GemiTerm.exe` — Windows x64 binary
93
- - `install.sh` — POSIX installer script
94
- - `install.ps1` — Windows PowerShell installer script
91
+ The full skill bundle lives at [`opencode-gemiterm-skills`](https://www.npmjs.com/package/opencode-gemiterm-skills).
95
92
 
96
- ## Usage
93
+ ## Quick Start
97
94
 
98
- ### Authentication
95
+ ### Try without installing
99
96
 
100
97
  ```bash
101
- gemiterm auth
98
+ bunx gemiterm auth # sign in to Google
99
+ bunx gemiterm list # show your recent chats
102
100
  ```
103
101
 
104
- Opens a browser window to log in with your Google account. Cookies are saved for future use.
105
-
106
- ### Check Status
102
+ ### Install globally (recommended for daily use)
107
103
 
108
104
  ```bash
109
- gemiterm status
105
+ bun install -g gemiterm
106
+
107
+ gemiterm auth
108
+ gemiterm list
110
109
  ```
111
110
 
112
- Shows the config directory and a table of all profiles with their authentication state.
111
+ ### Install scripts (no Bun required bootstraps it for you)
113
112
 
114
- ### List Chats
113
+ **Windows (PowerShell 7+):**
115
114
 
116
- ```bash
117
- gemiterm list
115
+ ```powershell
116
+ irm https://github.com/expert-vision-software/GemiTerm/releases/latest/download/install.ps1 | iex
118
117
  ```
119
118
 
120
- Options:
121
- - `-n, --limit N`: Maximum number of chats (default: 10)
122
- - `--offset N`: Skip first N chats (default: 0)
123
- - `--sort <recent|oldest|alpha>`: Sort order
124
- - `-s, --search <query>`: Filter by title
125
- - `--after <date>`: Only chats after this date
126
- - `--before <date>`: Only chats before this date
127
- - `--all`: Show all chats (no limit)
128
- - `--all-profiles`: Merge chats from all profiles
129
- - `-f, --format <text|json>`: Output format
130
- - `-p, --path <path>`: Save output to file
131
-
132
- ### Fetch Chat History
119
+ **Linux / macOS:**
133
120
 
134
121
  ```bash
135
- gemiterm fetch <conversation_id>
122
+ curl -fsSL https://github.com/expert-vision-software/GemiTerm/releases/latest/download/install.sh | bash
136
123
  ```
137
124
 
138
- Options:
139
- - `-f, --format <text|json>`: Output format
140
- - `-p, --path <path>`: Save output to file
125
+ > **Upgrading from v1.4.1?** Your profiles, cookies, and default profile marker are preserved. See [docs/INSTALL.md](docs/INSTALL.md) for details.
126
+
127
+ See [docs/INSTALL.md](docs/INSTALL.md) for the full guide, uninstall instructions, troubleshooting, and build-from-source steps.
128
+
129
+ ## Prerequisites
130
+
131
+ - **[Bun](https://bun.sh)** runtime ≥ 1.0.0 (only required for `bunx` / `bun install` use — not needed for install scripts)
132
+ - **Chromium browser** — GemiTerm prefers your system Chrome / Edge; otherwise it installs Playwright's Chromium automatically (`gemiterm install-browser`)
133
+ - **Google Account** with access to [Gemini](https://gemini.google.com)
141
134
 
142
- ### Continue a Chat
135
+ ## Commands
136
+
137
+ | Command | Alias | Purpose |
138
+ | --- | --- | --- |
139
+ | `gemiterm auth` | `gemiterm login` | Sign in to Google and save cookies |
140
+ | `gemiterm status` | — | Show config dir and profile table |
141
+ | `gemiterm list` | — | List chats (filter, sort, search) |
142
+ | `gemiterm fetch <id>` | — | Fetch a chat's full history |
143
+ | `gemiterm new [message]` | — | Start a new chat (one-shot or REPL) |
144
+ | `gemiterm continue <id> [msg]` | — | Continue an existing chat |
145
+ | `gemiterm export <id>` | — | Export one chat to Markdown / JSON |
146
+ | `gemiterm export-all` | — | Bulk-export all chats with `index.md` |
147
+ | `gemiterm delete <id>` | — | Delete a chat (with confirmation) |
148
+ | `gemiterm profile <sub>` | — | Manage profiles (list / add / delete / rename / default) |
149
+ | `gemiterm install-browser` | — | Install Playwright Chromium |
150
+ | `gemiterm install-skills` | — | Install the cross-agent skills bundle |
151
+ | `gemiterm -v <cmd>` | — | Verbose logging for any command |
152
+
153
+ ### `gemiterm list`
154
+
155
+ List, filter, and search your Gemini chats.
143
156
 
144
157
  ```bash
145
- gemiterm continue <conversation_id> [message]
158
+ gemiterm list
159
+ gemiterm list -n 50 --sort alpha
160
+ gemiterm list --search "react server components"
161
+ gemiterm list --after 2026-01-01 --before 2026-06-01
162
+ gemiterm list --all --all-profiles -f json -p chats.json
146
163
  ```
147
164
 
148
- Without a message, enters an interactive REPL session. Without a conversation ID, falls back to `list`.
165
+ | Flag | Description |
166
+ | --- | --- |
167
+ | `-n, --limit N` | Max chats to show (default: 10) |
168
+ | `--offset N` | Skip the first N chats |
169
+ | `--sort <recent\|oldest\|alpha>` | Sort order |
170
+ | `-s, --search <query>` | Filter by title |
171
+ | `--after <date>` | Only chats after this date |
172
+ | `--before <date>` | Only chats before this date |
173
+ | `--all` | Show all chats (no limit) |
174
+ | `--all-profiles` | Merge chats from all profiles |
175
+ | `-f, --format <text\|json>` | Output format |
176
+ | `-o, --out <path>` | Save output to file |
149
177
 
150
- ### Start a New Chat
178
+ ### `gemiterm fetch <conversation_id>`
179
+
180
+ Fetch a single conversation's full history.
151
181
 
152
182
  ```bash
153
- gemiterm new [message]
183
+ gemiterm fetch c_abc123
184
+ gemiterm fetch c_abc123 -f json -o chat.json
154
185
  ```
155
186
 
156
- Options:
157
- - `-p, --profile <name>`: Use a specific profile
187
+ | Flag | Description |
188
+ | --- | --- |
189
+ | `-f, --format <text\|json>` | Output format |
190
+ | `-o, --out <path>` | Save output to file |
158
191
 
159
- Without a message, enters an interactive REPL session.
192
+ ### `gemiterm new [message]`
160
193
 
161
- ### Export Chat
194
+ Start a new chat. One-shot if you pass a message; otherwise drops into an interactive REPL.
162
195
 
163
196
  ```bash
164
- gemiterm export <conversation_id>
197
+ gemiterm new "Explain the CAP theorem like I'm 12"
198
+ gemiterm new --profile work "Draft a status update"
199
+ gemiterm new --prompt-file ./long-prompt.md
165
200
  ```
166
201
 
167
- Options:
168
- - `-o, --output <path>`: Custom output file path
169
- - `-f, --format <markdown|json>`: Export format (default: markdown)
170
- - `--include-metadata`: Include full metadata in export
202
+ | Flag | Description |
203
+ | --- | --- |
204
+ | `-p, --profile <name>` | Use a specific profile |
205
+ | `-f, --prompt-file <path>` | Read the message from a file (bypasses shell arg-length limits) |
206
+ | `-h, --help` | Show help |
207
+
208
+ ### `gemiterm continue <conversation_id> [message]`
171
209
 
172
- ### Export All Chats
210
+ Continue an existing chat. With no message, enters an interactive REPL. With no conversation ID, falls back to `list`.
173
211
 
174
212
  ```bash
175
- gemiterm export-all
213
+ gemiterm continue c_abc123
214
+ gemiterm continue c_abc123 "And what about edge cases?"
215
+ gemiterm continue c_abc123 --prompt-file ./refactor-context.md
176
216
  ```
177
217
 
178
- Options:
179
- - `-o, --output-dir <dir>`: Output directory (default: `./exports`)
180
- - `--since <date>`: Only chats newer than this date
181
- - `--include-metadata`: Include full metadata
182
- - `-a, --all-profiles`: Export from all profiles
218
+ | Flag | Description |
219
+ | --- | --- |
220
+ | `-f, --prompt-file <path>` | Read the message from a file (bypasses shell arg-length limits) |
221
+ | `-h, --help` | Show help |
183
222
 
184
- Creates an `index.md` with links to all exported files.
223
+ > **Long prompts?** On Windows the shell argument limit is roughly 2 048 UTF-16 code units. GemiTerm detects oversized messages and **spills them to a temp file automatically** — or you can use `--prompt-file` explicitly to read from a file you control.
185
224
 
186
- ### Delete a Chat
225
+ ### `gemiterm export <conversation_id>`
226
+
227
+ Export a single chat to a file.
187
228
 
188
229
  ```bash
189
- gemiterm delete <conversation_id>
230
+ gemiterm export c_abc123
231
+ gemiterm export c_abc123 -o ./chat.md -f json --include-metadata
190
232
  ```
191
233
 
192
- Options:
193
- - `-f, --force`: Skip confirmation prompt
234
+ | Flag | Description |
235
+ | --- | --- |
236
+ | `-o, --out <path>` | Custom output file path |
237
+ | `-f, --format <markdown\|json>` | Export format (default: `markdown`) |
238
+ | `--include-metadata` | Include full metadata in the export |
239
+
240
+ ### `gemiterm export-all`
194
241
 
195
- ### Manage Profiles
242
+ Bulk-export every chat (or every chat since a date) with an auto-generated `index.md`.
196
243
 
197
244
  ```bash
198
- gemiterm profile list # list all profiles
199
- gemiterm profile add <name> # add a new profile
200
- gemiterm profile delete <name> # delete a profile
201
- gemiterm profile rename <name> <newName> # rename a profile
202
- gemiterm profile default <name> # set default profile
245
+ gemiterm export-all
246
+ gemiterm export-all --since 2026-01-01 --include-metadata
247
+ gemiterm export-all -o ./exports -a
203
248
  ```
204
249
 
205
- ### Install Browser
250
+ | Flag | Description |
251
+ | --- | --- |
252
+ | `-o, --out-dir <dir>` | Output directory (default: `./exports`) |
253
+ | `--since <date>` | Only chats newer than this date |
254
+ | `--include-metadata` | Include full metadata |
255
+ | `-a, --all-profiles` | Export from all profiles |
256
+
257
+ ### `gemiterm delete <conversation_id>`
258
+
259
+ Delete a chat from your Gemini account. Confirms by default.
206
260
 
207
261
  ```bash
208
- gemiterm install-browser
262
+ gemiterm delete c_abc123
263
+ gemiterm delete c_abc123 --force
209
264
  ```
210
265
 
211
- Checks for system Chrome/Edge first, falls back to installing Playwright's Chromium.
266
+ | Flag | Description |
267
+ | --- | --- |
268
+ | `-f, --force` | Skip the confirmation prompt |
269
+
270
+ ### `gemiterm profile <subcommand>`
212
271
 
213
- ### Verbose Logging
272
+ Manage multiple Gemini profiles (separate Google accounts or isolated cookie stores).
214
273
 
215
274
  ```bash
216
- gemiterm -v <command>
275
+ gemiterm profile list
276
+ gemiterm profile add work
277
+ gemiterm profile delete work
278
+ gemiterm profile rename work jobs
279
+ gemiterm profile default work
217
280
  ```
218
281
 
219
- ## Skills
282
+ ### `gemiterm install-browser`
283
+
284
+ Checks for a system Chrome / Edge first; falls back to Playwright's Chromium. Usually only needed once after install.
285
+
286
+ ### `gemiterm install-skills`
220
287
 
221
- GemiTerm has an associated skills repository for AI coding agents (Copilot, Claude, etc.) that provides domain-specific instructions for working with **gemiterm** and automating common workflows. There's also a fun `debate-with-gemini` skill that created an interactive turn-based conversation between your agent and gemini. See [opencode-gemiterm-skills](https://www.npmjs.com/package/opencode-gemiterm-skills).
288
+ Installs the [`opencode-gemiterm-skills`](https://www.npmjs.com/package/opencode-gemiterm-skills) bundle so your AI agent can use GemiTerm (and the `debate-with-gemini` skill) automatically.
222
289
 
223
290
  ## Configuration
224
291
 
225
- ### Configuration Directory
292
+ ### Configuration directory
226
293
 
227
- Default locations:
228
- - **Binary**: `$env:LOCALAPPDATA\GemiTerm\` (Windows), `~/.local/bin/gemiterm` (Linux/macOS)
229
- - **Config**: `%APPDATA%\gemiterm\` (Windows), `~/gemiterm/` (Linux/macOS)
294
+ | Platform | Config dir | Binary location (install script) |
295
+ | --- | --- | --- |
296
+ | Windows | `%APPDATA%\gemiterm\` | `%LOCALAPPDATA%\GemiTerm\` |
297
+ | Linux / macOS | `~/gemiterm/` | `~/.local/bin/gemiterm` |
230
298
 
231
299
  Override with:
300
+
232
301
  ```bash
233
302
  export GEMITERM_CONFIG_DIR=/custom/path
234
303
  ```
235
304
 
236
- ### Profile Storage
305
+ ### Profile storage
237
306
 
238
307
  ```
239
308
  gemiterm/
240
309
  profiles/
241
- .default # text file with default profile name
310
+ .default # text file with the default profile name
242
311
  <profile-name>/
243
- storage_state.json # authentication cookies
312
+ storage_state.json # authenticated cookies
244
313
  ```
245
314
 
246
- ### Environment Variables
315
+ Upgrading from v1.4.1 keeps these paths and files unchanged.
316
+
317
+ ### Environment variables
247
318
 
248
319
  | Variable | Description | Default |
249
- |----------|-------------|---------|
250
- | `GEMITERM_CONFIG_DIR` | Configuration directory | Platform default |
320
+ | --- | --- | --- |
321
+ | `GEMITERM_CONFIG_DIR` | Override the configuration directory | Platform default |
251
322
 
252
- ## Architecture
323
+ ## Contributing
253
324
 
254
- ```
255
- src/
256
- cli/ # CLI commands, argument parsing, output formatting
257
- core/ # Mediator pattern (CQRS), typed commands/queries, handlers, domain types
258
- services/ # Business logic: auth flow, cookie management, Gemini API client
259
- infrastructure/ # Config, file I/O, logging, validation, formatters
260
- tests/
261
- cli/ # CLI command tests
262
- core/ # Query handler tests
263
- services/ # Service layer tests
264
- infrastructure/ # Infrastructure tests
265
- fixtures/ # Shared test fixtures
266
- ```
325
+ Architecture, development workflow, build instructions, and contribution guidelines live in **[CONTRIBUTING.md](CONTRIBUTING.md)**. The agent guide — including the path-mediation rules, the sensitive auth files, and the OpenSpec workflow — lives in **[AGENTS.md](AGENTS.md)**.
326
+
327
+ ## Acknowledgments
328
+
329
+ - [Google Gemini](https://gemini.google.com) the model and web app this CLI wraps
330
+ - [Bun](https://bun.sh) runtime, bundler, and the path to single-binary distribution
331
+ - [`@playwright/cli`](https://www.npmjs.com/package/@playwright/cli) — the headless browser that powers authentication
332
+ - [OpenCode](https://opencode.ai) and the broader AI-agent ecosystem — for the `debate-with-gemini` use case that inspired the skills bundle
333
+ - [`opencode-gemiterm-skills`](https://www.npmjs.com/package/opencode-gemiterm-skills) the agent-skills companion package
334
+
335
+ ## License
267
336
 
268
- Core uses a **Mediator pattern** with typed Command/Query messages dispatching to registered handlers, decoupling CLI commands from business logic.
337
+ [MIT](LICENSE.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gemiterm",
3
- "version": "2.1.1",
3
+ "version": "2.2.0-beta.1",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "repository": {
@@ -42,10 +42,12 @@
42
42
  "build:release": "bun run scripts/build.ts release"
43
43
  },
44
44
  "devDependencies": {
45
+ "@inquirer/testing": "^2.1.0",
45
46
  "@types/bun": "^1.3.14",
46
47
  "typescript": "^6.0.3"
47
48
  },
48
49
  "dependencies": {
50
+ "@inquirer/prompts": "^8.5.2",
49
51
  "chalk": "^5.6.2",
50
52
  "cli-table3": "^0.6.5",
51
53
  "commander": "^15.0.0",
@@ -1,5 +1,4 @@
1
1
  import chalk from "chalk";
2
- import { createInterface } from "node:readline";
3
2
  import type { CliCommand, CliCommandContext } from "../command-registry.ts";
4
3
  import { Logger } from "../../infrastructure/logger.ts";
5
4
  import { CookieStorage, ProfileManager } from "../../infrastructure/storage.ts";
@@ -10,6 +9,7 @@ import { getDefaultProfileName, listProfiles, setDefaultProfileName } from "../.
10
9
  import { GemitermError } from "../../core/errors.ts";
11
10
  import { validateProfileName } from "../../infrastructure/validators.ts";
12
11
  import { formatProfileTable } from "../../infrastructure/formatters.ts";
12
+ import { text } from "../utils/prompts.ts";
13
13
 
14
14
  export class AuthCommand implements CliCommand {
15
15
  readonly name = "auth";
@@ -90,7 +90,9 @@ export class AuthCommand implements CliCommand {
90
90
 
91
91
  switch (choice) {
92
92
  case "A": {
93
- const name = await this.promptInput("Enter profile name");
93
+ const name = await this.promptInput("Enter profile name", {
94
+ validate: (v) => /^[a-zA-Z0-9_-]+$/.test(v) || "Invalid profile name",
95
+ });
94
96
  validateProfileName(name.trim());
95
97
  if (listProfiles().includes(name.trim())) {
96
98
  throw new GemitermError(`Profile '${name.trim()}' already exists.`);
@@ -131,7 +133,9 @@ export class AuthCommand implements CliCommand {
131
133
  if (!profiles.includes(oldTrimmed)) {
132
134
  throw new GemitermError(`Profile '${oldTrimmed}' does not exist.`);
133
135
  }
134
- const newName = await this.promptInput("Enter new profile name");
136
+ const newName = await this.promptInput("Enter new profile name", {
137
+ validate: (v) => /^[a-zA-Z0-9_-]+$/.test(v) || "Invalid profile name",
138
+ });
135
139
  const newTrimmed = newName.trim();
136
140
  validateProfileName(newTrimmed);
137
141
  profileManager.rename(oldTrimmed, newTrimmed);
@@ -167,13 +171,10 @@ export class AuthCommand implements CliCommand {
167
171
  console.log(" -h, --help Show this help message");
168
172
  }
169
173
 
170
- private promptInput(prompt: string): Promise<string> {
171
- return new Promise<string>((resolve) => {
172
- const rl = createInterface({ input: process.stdin, output: process.stdout });
173
- rl.question(`${chalk.cyan(prompt + ": ")} `, (answer) => {
174
- rl.close();
175
- resolve(answer);
176
- });
177
- });
174
+ private promptInput(
175
+ prompt: string,
176
+ opts?: { validate?: (value: string) => boolean | string },
177
+ ): Promise<string> {
178
+ return text({ message: prompt, validate: opts?.validate });
178
179
  }
179
180
  }
@@ -1,5 +1,5 @@
1
1
  import chalk from "chalk";
2
- import { createInterface } from "node:readline";
2
+ import { confirm } from "../utils/prompts.ts";
3
3
  import type { CliCommand, CliCommandContext } from "../command-registry.ts";
4
4
  import type { Mediator, Command } from "../../core/mediator.ts";
5
5
  import { Logger } from "../../infrastructure/logger.ts";
@@ -126,17 +126,8 @@ export class DeleteCommand implements CliCommand {
126
126
  return options;
127
127
  }
128
128
 
129
- private promptConfirmation(conversationId: string): Promise<boolean> {
130
- return new Promise<boolean>((resolve) => {
131
- const rl = createInterface({ input: process.stdin, output: process.stdout });
132
- rl.question(
133
- `${chalk.cyan(`Delete conversation '${conversationId}'?`)} (yes/no): `,
134
- (answer) => {
135
- rl.close();
136
- resolve(answer.toLowerCase().startsWith("y"));
137
- },
138
- );
139
- });
129
+ private promptConfirmation(question: string): Promise<boolean> {
130
+ return confirm({ message: question, default: false });
140
131
  }
141
132
 
142
133
  private showUsage(): void {