gemiterm 2.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.
Files changed (184) hide show
  1. package/.env +2 -0
  2. package/.github/workflows/manual-release.yml +34 -0
  3. package/.github/workflows/release.yml +198 -0
  4. package/.github/workflows/test.yml +29 -0
  5. package/.opencode/commands/opsx-apply.md +152 -0
  6. package/.opencode/commands/opsx-archive.md +157 -0
  7. package/.opencode/commands/opsx-explore.md +169 -0
  8. package/.opencode/commands/opsx-propose.md +104 -0
  9. package/.opencode/commands/opsx-sync.md +140 -0
  10. package/.opencode/commands/search-intelligently.md +9 -0
  11. package/.opencode/opencode.json +20 -0
  12. package/.opencode/skills/intellisearch/.version +1 -0
  13. package/.opencode/skills/intellisearch/SKILL.md +84 -0
  14. package/.opencode/skills/intellisearch/references/brave-search.md +67 -0
  15. package/.opencode/skills/intellisearch/references/ddg-search.md +79 -0
  16. package/.opencode/skills/intellisearch/references/deepwiki-tools.md +246 -0
  17. package/.opencode/skills/intellisearch/references/examples.md +97 -0
  18. package/.opencode/skills/intellisearch/references/gh-cli.md +143 -0
  19. package/.opencode/skills/intellisearch/references/google-search.md +40 -0
  20. package/.opencode/skills/intellisearch/references/search-workflow.md +143 -0
  21. package/.opencode/skills/intellisearch/references/workflow.md +115 -0
  22. package/.opencode/skills/openspec-apply-change/SKILL.md +159 -0
  23. package/.opencode/skills/openspec-archive-change/SKILL.md +117 -0
  24. package/.opencode/skills/openspec-explore/SKILL.md +287 -0
  25. package/.opencode/skills/openspec-propose/SKILL.md +111 -0
  26. package/.opencode/skills/openspec-sync-specs/SKILL.md +147 -0
  27. package/.serena/project.yml +133 -0
  28. package/AGENTS.md +136 -0
  29. package/CHANGELOG.md +3 -0
  30. package/README.md +245 -0
  31. package/bun.lock +105 -0
  32. package/docs/INSTALL.md +185 -0
  33. package/docs/PLAYWRIGHT_CLI_API.md +306 -0
  34. package/docs/python-release-for-reference.md +175 -0
  35. package/examples/sample_json_export.json +32 -0
  36. package/examples/sample_markdown_export.md +221 -0
  37. package/examples/usage_examples.sh +222 -0
  38. package/install.ps1 +264 -0
  39. package/install.sh +275 -0
  40. package/openspec/MAESTRO_MIGRATION.md +180 -0
  41. package/openspec/changes/archive/2026-06-08-command-spec-conformance/.openspec.yaml +2 -0
  42. package/openspec/changes/archive/2026-06-08-command-spec-conformance/design.md +194 -0
  43. package/openspec/changes/archive/2026-06-08-command-spec-conformance/proposal.md +52 -0
  44. package/openspec/changes/archive/2026-06-08-command-spec-conformance/specs/multi-profile-conversations/spec.md +133 -0
  45. package/openspec/changes/archive/2026-06-08-command-spec-conformance/tasks.md +95 -0
  46. package/openspec/changes/archive/2026-06-09-refactor-interactive-prompt-loop/.openspec.yaml +2 -0
  47. package/openspec/changes/archive/2026-06-09-refactor-interactive-prompt-loop/design.md +28 -0
  48. package/openspec/changes/archive/2026-06-09-refactor-interactive-prompt-loop/proposal.md +22 -0
  49. package/openspec/changes/archive/2026-06-09-refactor-interactive-prompt-loop/specs/interactive-prompt-loop/spec.md +35 -0
  50. package/openspec/changes/archive/2026-06-09-refactor-interactive-prompt-loop/tasks.md +28 -0
  51. package/openspec/changes/archive/2026-06-09-replace-gemini-api-placeholder-with-gemini-reverse/.openspec.yaml +2 -0
  52. package/openspec/changes/archive/2026-06-09-replace-gemini-api-placeholder-with-gemini-reverse/design.md +323 -0
  53. package/openspec/changes/archive/2026-06-09-replace-gemini-api-placeholder-with-gemini-reverse/proposal.md +122 -0
  54. package/openspec/changes/archive/2026-06-09-replace-gemini-api-placeholder-with-gemini-reverse/specs/no-capability-changes/spec.md +29 -0
  55. package/openspec/changes/archive/2026-06-09-replace-gemini-api-placeholder-with-gemini-reverse/tasks.md +172 -0
  56. package/openspec/changes/archive/2026-06-09-v2-install-migration/.openspec.yaml +2 -0
  57. package/openspec/changes/archive/2026-06-09-v2-install-migration/design.md +241 -0
  58. package/openspec/changes/archive/2026-06-09-v2-install-migration/proposal.md +41 -0
  59. package/openspec/changes/archive/2026-06-09-v2-install-migration/specs/v2-installer/spec.md +205 -0
  60. package/openspec/changes/archive/2026-06-09-v2-install-migration/tasks.md +97 -0
  61. package/openspec/changes/commander-cli-parser/.openspec.yaml +2 -0
  62. package/openspec/changes/commander-cli-parser/design.md +107 -0
  63. package/openspec/changes/commander-cli-parser/proposal.md +31 -0
  64. package/openspec/changes/commander-cli-parser/specs/cli/spec.md +48 -0
  65. package/openspec/changes/commander-cli-parser/tasks.md +33 -0
  66. package/openspec/changes/cross-platform-build-and-ci/.openspec.yaml +2 -0
  67. package/openspec/changes/cross-platform-build-and-ci/design.md +213 -0
  68. package/openspec/changes/cross-platform-build-and-ci/proposal.md +50 -0
  69. package/openspec/changes/cross-platform-build-and-ci/specs/path-and-file-mediation/spec.md +335 -0
  70. package/openspec/changes/cross-platform-build-and-ci/specs/release-pipeline/spec.md +95 -0
  71. package/openspec/changes/cross-platform-build-and-ci/tasks.md +164 -0
  72. package/openspec/config.yaml +20 -0
  73. package/openspec/specs/auth/spec.md +394 -0
  74. package/openspec/specs/cli/spec.md +108 -0
  75. package/openspec/specs/commands/spec.md +409 -0
  76. package/openspec/specs/configuration/spec.md +130 -0
  77. package/openspec/specs/conversations/spec.md +139 -0
  78. package/openspec/specs/domain-model/spec.md +128 -0
  79. package/openspec/specs/formatters/spec.md +158 -0
  80. package/openspec/specs/install-browser/spec.md +146 -0
  81. package/openspec/specs/interactive-prompt-loop/spec.md +41 -0
  82. package/openspec/specs/logger/spec.md +71 -0
  83. package/openspec/specs/mediator/spec.md +72 -0
  84. package/openspec/specs/multi-profile-conversations/spec.md +145 -0
  85. package/openspec/specs/path-utils/spec.md +101 -0
  86. package/openspec/specs/profiles/spec.md +94 -0
  87. package/openspec/specs/storage/spec.md +198 -0
  88. package/openspec/specs/testing/spec.md +237 -0
  89. package/openspec/specs/v2-installer/spec.md +205 -0
  90. package/openspec/specs/validators/spec.md +65 -0
  91. package/package.json +45 -0
  92. package/scripts/build.ts +88 -0
  93. package/scripts/clean-build.ps1 +4 -0
  94. package/scripts/clean-build.sh +5 -0
  95. package/scripts/install-browser.ps1 +5 -0
  96. package/scripts/install-browser.sh +6 -0
  97. package/scripts/lint-path-mediation.ps1 +65 -0
  98. package/scripts/lint-path-mediation.sh +40 -0
  99. package/src/cli/.gitkeep +0 -0
  100. package/src/cli/command-registry.ts +62 -0
  101. package/src/cli/commands/auth-command.ts +179 -0
  102. package/src/cli/commands/continue-command.ts +158 -0
  103. package/src/cli/commands/delete-command.ts +163 -0
  104. package/src/cli/commands/export-all-command.ts +243 -0
  105. package/src/cli/commands/export-command.ts +156 -0
  106. package/src/cli/commands/fetch-command.ts +176 -0
  107. package/src/cli/commands/help.ts +45 -0
  108. package/src/cli/commands/install-browser-command.ts +33 -0
  109. package/src/cli/commands/list-command.ts +226 -0
  110. package/src/cli/commands/new-command.ts +147 -0
  111. package/src/cli/commands/profile-command.ts +226 -0
  112. package/src/cli/commands/status-command.ts +59 -0
  113. package/src/cli/index.ts +213 -0
  114. package/src/cli/utils/interactive-prompt.ts +64 -0
  115. package/src/core/.gitkeep +0 -0
  116. package/src/core/command-handlers.ts +240 -0
  117. package/src/core/errors.ts +41 -0
  118. package/src/core/mediator.ts +58 -0
  119. package/src/core/query-handlers.ts +163 -0
  120. package/src/core/types.ts +43 -0
  121. package/src/infrastructure/.gitkeep +0 -0
  122. package/src/infrastructure/cli-table.ts +45 -0
  123. package/src/infrastructure/config.ts +52 -0
  124. package/src/infrastructure/formatters.ts +130 -0
  125. package/src/infrastructure/io.ts +161 -0
  126. package/src/infrastructure/logger.ts +41 -0
  127. package/src/infrastructure/path-utils.ts +157 -0
  128. package/src/infrastructure/storage.ts +209 -0
  129. package/src/infrastructure/validators.ts +28 -0
  130. package/src/services/.gitkeep +0 -0
  131. package/src/services/auth-service.ts +135 -0
  132. package/src/services/cookie-monitor.ts +159 -0
  133. package/src/services/cookie-storage-service.ts +74 -0
  134. package/src/services/gemini-client-wrapper.ts +239 -0
  135. package/src/services/install-browser-service.ts +205 -0
  136. package/src/services/playwright-cli-driver.ts +269 -0
  137. package/src/services/profile-auth-manager.ts +65 -0
  138. package/src/services/profile-service.ts +121 -0
  139. package/tests/cli/auth-command.test.ts +220 -0
  140. package/tests/cli/command-registry.test.ts +67 -0
  141. package/tests/cli/continue-command.test.ts +100 -0
  142. package/tests/cli/delete-command.test.ts +128 -0
  143. package/tests/cli/export-all-command.test.ts +375 -0
  144. package/tests/cli/install-browser-command.test.ts +48 -0
  145. package/tests/cli/list-command.test.ts +179 -0
  146. package/tests/cli/new-command.test.ts +139 -0
  147. package/tests/cli/status-command.test.ts +106 -0
  148. package/tests/core/query-handlers.test.ts +187 -0
  149. package/tests/fixtures/auth-fixtures.ts +98 -0
  150. package/tests/fixtures/chat-fixtures.ts +87 -0
  151. package/tests/infrastructure/cli-table.test.ts +107 -0
  152. package/tests/infrastructure/formatters.test.ts +202 -0
  153. package/tests/infrastructure/io.test.ts +197 -0
  154. package/tests/infrastructure/logger.test.ts +74 -0
  155. package/tests/infrastructure/storage.test.ts +335 -0
  156. package/tests/infrastructure/validators.test.ts +67 -0
  157. package/tests/integration/commands/auth.test.ts +186 -0
  158. package/tests/integration/commands/continue.test.ts +130 -0
  159. package/tests/integration/commands/delete.test.ts +140 -0
  160. package/tests/integration/commands/export.test.ts +266 -0
  161. package/tests/integration/commands/fetch.test.ts +238 -0
  162. package/tests/integration/commands/list.test.ts +281 -0
  163. package/tests/integration/commands/profile.test.ts +258 -0
  164. package/tests/integration/commands/status.test.ts +223 -0
  165. package/tests/integration/installer-script-shape.test.ts +67 -0
  166. package/tests/parity/compare-outputs.ts +359 -0
  167. package/tests/parity/test-commands-parity.ps1 +82 -0
  168. package/tests/parity/test-commands-parity.sh +61 -0
  169. package/tests/services/auth-service.test.ts +315 -0
  170. package/tests/services/cookie-monitor.test.ts +229 -0
  171. package/tests/services/cookie-storage-service.test.ts +230 -0
  172. package/tests/services/gemini-client-wrapper.test.ts +688 -0
  173. package/tests/services/install-browser-service.test.ts +83 -0
  174. package/tests/services/playwright-cli-driver.test.ts +468 -0
  175. package/tests/services/profile-auth-manager.test.ts +334 -0
  176. package/tests/services/profile-service.test.ts +224 -0
  177. package/tests/setup.ts +95 -0
  178. package/tests/smoke/smoke.test.ts +52 -0
  179. package/tests/unit/config.test.ts +159 -0
  180. package/tests/unit/errors.test.ts +119 -0
  181. package/tests/unit/formatters.test.ts +316 -0
  182. package/tests/unit/mediator.test.ts +152 -0
  183. package/tests/unit/path-utils.test.ts +289 -0
  184. package/tsconfig.json +16 -0
@@ -0,0 +1,306 @@
1
+ # playwright-cli API Reference
2
+
3
+ > Source: [microsoft/playwright-cli](https://github.com/microsoft/playwright-cli)
4
+ > Verified against: `@playwright/cli` (installed via `bunx --bun @playwright/cli --help`)
5
+
6
+ ## Architecture
7
+
8
+ - **Daemon-based**: `open` returns immediately; the browser runs as a background process.
9
+ - **Session-based**: Every command targets a browser session via `-s=<name>`. Without `-s`, commands hit the unnamed **default session**.
10
+ - **Session resolution priority**: `-s=<name>` flag → `PLAYWRIGHT_CLI_SESSION` env var → default session.
11
+
12
+ ## Session Management
13
+
14
+ ```bash
15
+ playwright-cli list # list all active sessions
16
+ playwright-cli -s=myprofile list # list details for one session
17
+ playwright-cli close # close the default session
18
+ playwright-cli close-all # close all sessions gracefully
19
+ playwright-cli kill-all # force-kill all sessions
20
+ playwright-cli delete-data # wipe persistent profile data for a session
21
+ ```
22
+
23
+ ## Core Commands
24
+
25
+ ### `open [url]`
26
+
27
+ Opens a headed browser and navigates to the URL. **Returns immediately** (daemon-style).
28
+
29
+ ```bash
30
+ playwright-cli open https://example.com
31
+ playwright-cli -s=myprofile open --browser=chromium --headed --persistent --profile=/path/to/dir https://example.com
32
+ ```
33
+
34
+ | Flag | Description | Values |
35
+ |---|---|---|
36
+ | `--browser` | Browser engine | `chromium`, `firefox`, `webkit`, `msedge` |
37
+ | `--headed` | Show the browser UI (default: headless) | flag |
38
+ | `--persistent` | Persist profile to disk on close | flag |
39
+ | `--profile=<path>` | Custom user-data directory path | absolute path |
40
+ | `--config=<file>` | Path to config file | default: `.playwright/cli.config.json` |
41
+ | `--extension` | Connect via browser extension | flag |
42
+
43
+ ### `goto <url>`
44
+
45
+ Navigate the current session to a URL (must target an open session):
46
+
47
+ ```bash
48
+ playwright-cli -s=myprofile goto https://other.example.com
49
+ ```
50
+
51
+ ### `close` / `detach` / `attach`
52
+
53
+ ```bash
54
+ playwright-cli -s=myprofile close # graceful close
55
+ playwright-cli -s=myprofile detach # detach CLI but keep browser running
56
+ playwright-cli attach myprofile # re-attach to a running session
57
+ ```
58
+
59
+ ## Input Commands
60
+
61
+ All input commands target an active session and operate on element references obtained from `snapshot`.
62
+
63
+ ```bash
64
+ playwright-cli -s=myprofile click <ref> [button]
65
+ playwright-cli -s=myprofile type <text>
66
+ playwright-cli -s=myprofile fill <ref> <text>
67
+ playwright-cli -s=myprofile press <key> # e.g. Enter, Tab, Escape
68
+ playwright-cli -s=myprofile hover <ref>
69
+ playwright-cli -s=myprofile select <ref> <val>
70
+ playwright-cli -s=myprofile upload <file>
71
+ playwright-cli -s=myprofile check <ref> / uncheck <ref>
72
+ playwright-cli -s=myprofile drag <startRef> <endRef>
73
+ playwright-cli -s=myprofile drop <ref>
74
+ playwright-cli -s=myprofile dialog-accept [prompt]
75
+ playwright-cli -s=myprofile dialog-dismiss
76
+ ```
77
+
78
+ ## Storage & State Commands
79
+
80
+ ### `state-save [filename]`
81
+
82
+ Exports the current session's cookies + localStorage to a JSON file. **Writes directly to disk.**
83
+
84
+ ```bash
85
+ playwright-cli -s=myprofile state-save auth.json
86
+ playwright-cli -s=myprofile state-save # auto-name: storage-state-{timestamp}.json
87
+ ```
88
+
89
+ The output JSON matches Playwright's `StorageState` format:
90
+
91
+ ```jsonc
92
+ {
93
+ "cookies": [{ "name": "...", "value": "...", "domain": "...", "path": "/", "expires": -1, "httpOnly": true, "secure": true, "sameSite": "Lax" }],
94
+ "origins": [{ "origin": "https://example.com", "localStorage": [{ "name": "...", "value": "..." }] }]
95
+ }
96
+ ```
97
+
98
+ ### `state-load <filename>`
99
+
100
+ Imports cookies and localStorage from a JSON file into the current session. **Must be called after the browser is open.**
101
+
102
+ ```bash
103
+ playwright-cli -s=myprofile state-load auth.json
104
+ ```
105
+
106
+ ### `cookie-list` / `cookie-get` / `cookie-set` / `cookie-delete` / `cookie-clear`
107
+
108
+ ```bash
109
+ playwright-cli -s=myprofile cookie-list # text table output
110
+ playwright-cli -s=myprofile cookie-list --json # JSON output
111
+ playwright-cli -s=myprofile cookie-list --domain=google.com # filter by domain
112
+ playwright-cli -s=myprofile cookie-get "__Secure-1PSID"
113
+ playwright-cli -s=myprofile cookie-set "name" "value" --domain=.example.com --secure --httpOnly
114
+ playwright-cli -s=myprofile cookie-delete "name"
115
+ playwright-cli -s=myprofile cookie-clear
116
+ ```
117
+
118
+ **Important**: `cookie-list` outputs a human-readable text table by default. The `--json` flag (undocumented in `--help`, silently supported) wraps that text in a JSON object: `{"result": "<text>"}` — it does **not** emit a JSON array of cookie objects. See [Cookie-list output format](#cookie-list-output-format) below for the real shapes.
119
+
120
+ ### Cookie-list output format
121
+
122
+ `cookie-list` is one of the most-misused commands because `--json` does not return what its name suggests.
123
+
124
+ **Default output (no flag)** — one cookie per line, no header:
125
+ ```
126
+ __Secure-1PSID=abc123 (domain: .google.com, path: /)
127
+ __Secure-1PSIDTS=xyz789 (domain: .google.com, path: /)
128
+ ```
129
+
130
+ **With `--json`** — single-line wrapper whose `result` field is the same text as above:
131
+ ```json
132
+ {"result": "__Secure-1PSID=abc123 (domain: .google.com, path: /)\n__Secure-1PSIDTS=xyz789 (domain: .google.com, path: /)\n"}
133
+ ```
134
+
135
+ **Empty state** — the literal line `No cookies found` (and with `--json`, `{"result": "No cookies found\n"}`).
136
+
137
+ **What's missing from the text format:** `expires`, `httpOnly`, `secure`, `sameSite`. If you need those, use `run-code` with `page.context().cookies()` or call `state-save` and parse the resulting file.
138
+
139
+ **Note:** `--json` is not listed in `cookie-list --help` but is silently supported. Verified in `@playwright/cli` v0.1.13.
140
+
141
+ ## Evaluation & Snapshots
142
+
143
+ ### `eval <func> [ref]`
144
+
145
+ Run JavaScript on the page and print the result.
146
+
147
+ ```bash
148
+ playwright-cli -s=myprofile eval "document.title"
149
+ playwright-cli -s=myprofile eval "document.querySelector('textarea') !== null"
150
+ playwright-cli -s=myprofile eval "window.location.href"
151
+ ```
152
+
153
+ ### `snapshot [target]`
154
+
155
+ Captures a page snapshot for obtaining element references. **Returns YAML/HTML, NOT JSON.**
156
+
157
+ ```bash
158
+ playwright-cli -s=myprofile snapshot # full page → stdout/YAML
159
+ playwright-cli -s=myprofile snapshot --filename=snap.yaml # save to file
160
+ playwright-cli -s=myprofile snapshot "div.main" # target a specific element
161
+ ```
162
+
163
+ > ⚠️ `snapshot` does **not** return an accessibility (AX) tree. Use `eval` with DOM queries for conditional logic like login detection.
164
+
165
+ ### `run-code [code]`
166
+
167
+ Run a Playwright code snippet with access to the `page` object.
168
+
169
+ ```bash
170
+ playwright-cli -s=myprofile run-code "async page => {
171
+ const title = await page.title();
172
+ return title;
173
+ }"
174
+ ```
175
+
176
+ ## Navigation Commands
177
+
178
+ ```bash
179
+ playwright-cli -s=myprofile go-back
180
+ playwright-cli -s=myprofile go-forward
181
+ playwright-cli -s=myprofile reload
182
+ ```
183
+
184
+ ## Tab Management
185
+
186
+ ```bash
187
+ playwright-cli -s=myprofile tab-list
188
+ playwright-cli -s=myprofile tab-new [url]
189
+ playwright-cli -s=myprofile tab-close [index]
190
+ playwright-cli -s=myprofile tab-select <index>
191
+ ```
192
+
193
+ ## Global Flags
194
+
195
+ | Flag | Description |
196
+ |---|---|
197
+ | `-s=<name>` | Target a named session |
198
+ | `--json` | Output as JSON (applies to most read commands) |
199
+ | `--raw` | Output only the value, no status wrapper |
200
+ | `--config=<file>` | Use a specific config file |
201
+ | `--help [command]` | Show help |
202
+ | `--version` | Print version |
203
+
204
+ ## Configuration File
205
+
206
+ Located at `.playwright/cli.config.json` by default:
207
+
208
+ ```jsonc
209
+ {
210
+ "browser": {
211
+ "browserName": "chromium", // chromium | firefox | webkit
212
+ "isolated": false, // true = in-memory only (no persistence)
213
+ "userDataDir": "/path/to/dir", // persistent profile directory
214
+ "launchOptions": {
215
+ "headless": false,
216
+ "channel": "chrome", // use system Chrome instead of bundled Chromium
217
+ "executablePath": "/path/to/browser"
218
+ },
219
+ "contextOptions": {
220
+ "viewport": { "width": 1280, "height": 720 }
221
+ }
222
+ },
223
+ "outputDir": "./output",
224
+ "outputMode": "stdout", // stdout | file
225
+ "console": { "level": "info" },
226
+ "testIdAttribute": "data-testid"
227
+ }
228
+ ```
229
+
230
+ ## Output Format Reference
231
+
232
+ | Command | Default Output | With `--json` |
233
+ |---|---|---|
234
+ | `cookie-list` | Text table (name, value, domain, flags) | JSON wrapper `{"result": "<text>"}` (not an array) |
235
+ | `snapshot` | YAML/HTML (not AX tree) | JSON status wrapper |
236
+ | `state-save` | Writes file to disk, confirmation on stdout | N/A |
237
+ | `eval` | Raw JS return value | JSON status wrapper |
238
+ | `list` | Text session info | JSON session objects |
239
+
240
+ ## Persistence Behavior
241
+
242
+ - `--persistent` / `--profile=<dir>`: Profile data is **automatically saved** when the browser closes. Reopening with the same profile preserves cookies, localStorage, etc.
243
+ - `state-save`: **Explicit export** to a portable JSON file. Needed when you want to share state across different profile directories or import into non-CLI Playwright contexts.
244
+ - For cookie scraping: use `state-save` to export to `.auth/<profile>.json`. The persistent profile is only for the browser's own session continuity.
245
+
246
+ ## Common Patterns
247
+
248
+ ### Login Detection (eval)
249
+
250
+ ```bash
251
+ # Check for Gemini prompt textarea
252
+ playwright-cli -s=gemini eval "document.querySelector('textarea[aria-label*=\"prompt\" i]') !== null"
253
+
254
+ # Check URL
255
+ playwright-cli -s=gemini eval "window.location.href"
256
+ ```
257
+
258
+ > Tip: cookie-based detection (poll `cookie-list` for `__Secure-1PSID`) is more reliable than DOM probes because cookies are observable even when the page is still mid-render. See [Cookie-list output format](#cookie-list-output-format) for how to parse the response.
259
+
260
+ ### Cookie Scraping Pipeline
261
+
262
+ ```bash
263
+ # 1. Open headed browser with persistent profile
264
+ playwright-cli -s=mysess open --headed --persistent --profile=./.auth/profiles/gemini https://gemini.google.com/app
265
+
266
+ # 2. User logs in manually...
267
+
268
+ # 3. Export state to portable JSON
269
+ playwright-cli -s=mysess state-save .auth/gemini.json
270
+
271
+ # 4. Close the session
272
+ playwright-cli -s=mysess close
273
+ ```
274
+
275
+ ### Re-verify a Saved Login
276
+
277
+ ```bash
278
+ # 1. Open browser (can use same persistent profile or fresh)
279
+ playwright-cli -s=mysess open --headed https://gemini.google.com/app
280
+
281
+ # 2. Inject saved state
282
+ playwright-cli -s=mysess state-load .auth/gemini.json
283
+
284
+ # 3. Reload page to apply cookies
285
+ playwright-cli -s=mysess reload
286
+
287
+ ## Common Pitfalls
288
+
289
+ Things that look right but will silently break your code. Verified against `@playwright/cli` v0.1.13.
290
+
291
+ ### `cookie-list --json` is not a JSON array
292
+
293
+ It's a wrapper `{"result": "<text>"}` around the same human-readable text. Calling `JSON.parse` and treating the result as an array will always yield zero cookies, and your login detection will time out without any visible error. See [Cookie-list output format](#cookie-list-output-format).
294
+
295
+ ### `eval` results are wrapped unless you pass `--raw`
296
+
297
+ `playwright-cli -s=X eval "..."` returns a JSON status envelope, e.g. `{"status":"success","result":"..."}`. To get the raw return value, append `--raw`. Required whenever you compare an eval result to a literal string (e.g. `=== "true"`).
298
+
299
+ ### `open` is fire-and-forget (daemon-style)
300
+
301
+ `playwright-cli open <url>` returns as soon as the browser process has been launched, not when the page is loaded. If you start polling the session immediately after, your first `eval` / `cookie-list` may race the still-spawning daemon and throw. Either delay the first poll or use the `state-save` round-trip to wait for the page to be ready.
302
+
303
+ ### `--profile` requires an absolute path
304
+
305
+ Relative paths are accepted by the CLI but the resulting profile directory is not portable across working directories and may not be picked up by subsequent runs.
306
+ ```
@@ -0,0 +1,175 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+ workflow_dispatch:
8
+ inputs:
9
+ skip_publish:
10
+ description: 'Skip PyPI publish (for testing)'
11
+ type: boolean
12
+ default: false
13
+ skip_release:
14
+ description: 'Skip GitHub release (for testing)'
15
+ type: boolean
16
+ default: true
17
+ tag:
18
+ description: 'Tag for release (e.g. v1.0.8) - only needed for workflow_dispatch'
19
+ type: string
20
+ default: ''
21
+
22
+ jobs:
23
+ test:
24
+ name: Test
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: actions/setup-python@v5
29
+ with:
30
+ python-version: '3.12'
31
+ - name: Install deps
32
+ run: |
33
+ pip install -e ".[dev]"
34
+ - name: Run tests
35
+ run: pytest -v
36
+
37
+ build-linux:
38
+ name: Build (Linux)
39
+ needs: test
40
+ runs-on: ubuntu-latest
41
+
42
+ steps:
43
+ - uses: actions/checkout@v4
44
+ - uses: actions/setup-python@v5
45
+ with:
46
+ python-version: '3.12'
47
+
48
+ - name: Build package
49
+ run: pip install build && python -m build
50
+
51
+ - name: Install dependencies
52
+ run: pip install rich click playwright gemini-webapi pyinstaller
53
+
54
+ - name: Build executable
55
+ run: |
56
+ pythonPath=$(python -c "import site; print(site.getsitepackages()[0])")
57
+ pyinstaller --onefile --name GemiTerm --add-data "src/gemiterm:gemiterm" --paths "$pythonPath" --hidden-import=rich --hidden-import=rich.console --hidden-import=rich.progress --hidden-import=rich.table --hidden-import=rich.panel --hidden-import=rich.markdown --hidden-import=rich.syntax --hidden-import=click --hidden-import=playwright --hidden-import=gemini_webapi --hidden-import=gemini_webapi_async src/gemiterm/__main__.py
58
+
59
+ - name: Verify build
60
+ run: |
61
+ exeSize=$(stat -c%s dist/GemiTerm)
62
+ exeSizeMB=$((exeSize / 1024 / 1024))
63
+ echo "GemiTerm size: $exeSizeMB MB"
64
+ if [ "$exeSizeMB" -lt 20 ]; then
65
+ echo "ERROR: Exe is too small ($exeSizeMB MB). Dependencies may not be bundled."
66
+ exit 1
67
+ fi
68
+ echo "Build verification passed"
69
+
70
+ - name: Upload artifact
71
+ uses: actions/upload-artifact@v4
72
+ with:
73
+ name: GemiTerm
74
+ path: dist/GemiTerm
75
+
76
+ build-windows:
77
+ name: Build (Windows)
78
+ needs: test
79
+ runs-on: windows-latest
80
+
81
+ steps:
82
+ - uses: actions/checkout@v4
83
+ - uses: actions/setup-python@v5
84
+ with:
85
+ python-version: '3.12'
86
+
87
+ - name: Build package
88
+ run: pip install build && python -m build
89
+
90
+ - name: Install dependencies
91
+ run: pip install rich click playwright gemini-webapi pyinstaller
92
+
93
+ - name: Build executable
94
+ run: |
95
+ $pythonPath = python -c "import site; print(site.getsitepackages()[0])"
96
+ pyinstaller --onefile --name GemiTerm --add-data "src/gemiterm;gemiterm" --paths "$pythonPath" --hidden-import=rich --hidden-import=rich.console --hidden-import=rich.progress --hidden-import=rich.table --hidden-import=rich.panel --hidden-import=rich.markdown --hidden-import=rich.syntax --hidden-import=click --hidden-import=playwright --hidden-import=gemini_webapi --hidden-import=gemini_webapi_async src/gemiterm/__main__.py
97
+
98
+ - name: Verify build
99
+ run: |
100
+ $exeSize = (Get-Item dist/GemiTerm.exe).Length / 1MB
101
+ Write-Host "GemiTerm.exe size: $exeSize MB"
102
+ if ($exeSize -lt 20) {
103
+ Write-Host "ERROR: Exe is too small ($exeSize MB). Dependencies may not be bundled."
104
+ exit 1
105
+ }
106
+ Write-Host "Build verification passed"
107
+
108
+ - name: Upload artifact
109
+ uses: actions/upload-artifact@v4
110
+ with:
111
+ name: GemiTerm.exe
112
+ path: dist/GemiTerm.exe
113
+
114
+ publish:
115
+ name: Publish to PyPI
116
+ needs: [build-linux, build-windows]
117
+ runs-on: ubuntu-latest
118
+ if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.skip_publish) }}
119
+ permissions:
120
+ id-token: write
121
+ contents: read
122
+
123
+ steps:
124
+ - uses: actions/checkout@v4
125
+
126
+ - uses: actions/setup-python@v5
127
+ with:
128
+ python-version: '3.12'
129
+
130
+ - name: Build package
131
+ run: pip install build && python -m build
132
+
133
+ - name: Publish to PyPI
134
+ uses: pypa/gh-action-pypi-publish@release/v1
135
+ with:
136
+ password: ${{ secrets.OIDC_PYPI_TOKEN }}
137
+
138
+ release:
139
+ name: Create Release
140
+ needs: [build-linux, build-windows]
141
+ runs-on: ubuntu-latest
142
+ if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.skip_release) }}
143
+ permissions:
144
+ contents: write
145
+
146
+ steps:
147
+ - uses: actions/checkout@v4
148
+
149
+ - name: Download Linux binary
150
+ uses: actions/download-artifact@v4
151
+ with:
152
+ name: GemiTerm
153
+ path: dist
154
+
155
+ - name: Download Windows binary
156
+ uses: actions/download-artifact@v4
157
+ with:
158
+ name: GemiTerm.exe
159
+ path: dist
160
+
161
+ - name: Determine tag
162
+ id: tag
163
+ run: |
164
+ if [ "${{ github.event_name }}" == "workflow_dispatch" ] && [ "${{ inputs.tag }}" != "" ]; then
165
+ echo "tag=${{ inputs.tag }}" >> $GITHUB_OUTPUT
166
+ else
167
+ echo "tag=${{ github.ref_name }}" >> $GITHUB_OUTPUT
168
+ fi
169
+
170
+ - name: Create Release
171
+ uses: softprops/action-gh-release@v2
172
+ with:
173
+ tag_name: ${{ steps.tag.outputs.tag }}
174
+ files: dist/*
175
+ generate_release_notes: true
@@ -0,0 +1,32 @@
1
+ {
2
+ "conversation_id": "sample_conversation_456",
3
+ "title": "API Design Discussion",
4
+ "export_date": "2026-03-21T15:00:00",
5
+ "metadata": {
6
+ "message_count": 4,
7
+ "first_message": "2026-03-21T14:45:00",
8
+ "last_message": "2026-03-21T15:00:00"
9
+ },
10
+ "messages": [
11
+ {
12
+ "role": "user",
13
+ "content": "What are the best practices for designing a REST API?",
14
+ "timestamp": "2026-03-21T14:45:00"
15
+ },
16
+ {
17
+ "role": "model",
18
+ "content": "Here are the key REST API best practices:\n\n## 1. Use Proper HTTP Methods\n\n| Method | Usage |\n|--------|-------|\n| GET | Retrieve resources |\n| POST | Create new resources |\n| PUT | Update entire resources |\n| PATCH | Partial updates |\n| DELETE | Remove resources |\n\n## 2. Use Nouns for Endpoints\n\n```\n# Good\nGET /users\nGET /users/123\n\n# Avoid\nGET /getUsers\nGET /user/123\n```\n\n## 3. Use Proper Status Codes\n\n- 200 OK - Success\n- 201 Created - Resource created\n- 400 Bad Request - Invalid input\n- 401 Unauthorized - Not authenticated\n- 404 Not Found - Resource doesn't exist\n- 500 Internal Server Error - Server issue",
19
+ "timestamp": "2026-03-21T14:46:30"
20
+ },
21
+ {
22
+ "role": "user",
23
+ "content": "How should we handle pagination?",
24
+ "timestamp": "2026-03-21T14:50:00"
25
+ },
26
+ {
27
+ "role": "model",
28
+ "content": "For pagination, I recommend cursor-based pagination for large datasets:\n\n```json\n{\n \"data\": [...],\n \"pagination\": {\n \"next_cursor\": \"eyJpZCI6MTIzfQ==\",\n \"has_more\": true,\n \"total_count\": 1042\n }\n}\n```\n\n## Comparison\n\n| Type | Pros | Cons |\n|------|------|------|\n| Offset | Simple, random access | Performance issues at scale |\n| Cursor | Efficient, consistent | No random access |\n| Page | Familiar to users | Inflexible |\n\nUse cursor-based pagination when:\n- Dealing with large datasets (millions of rows)\n- Real-time data where offset skips items\n- Infinite scroll interfaces\n\nUse offset pagination when:\n- Small datasets\n- User needs to jump to specific pages\n- Analytics or reporting use cases",
29
+ "timestamp": "2026-03-21T15:00:00"
30
+ }
31
+ ]
32
+ }