@steipete/summarize 0.8.2 → 0.10.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 (284) hide show
  1. package/CHANGELOG.md +114 -1
  2. package/LICENSE +1 -1
  3. package/README.md +309 -182
  4. package/dist/cli.js +1 -1
  5. package/dist/esm/cache.js +72 -4
  6. package/dist/esm/cache.js.map +1 -1
  7. package/dist/esm/config.js +197 -1
  8. package/dist/esm/config.js.map +1 -1
  9. package/dist/esm/content/asset.js +75 -2
  10. package/dist/esm/content/asset.js.map +1 -1
  11. package/dist/esm/daemon/agent.js +547 -0
  12. package/dist/esm/daemon/agent.js.map +1 -0
  13. package/dist/esm/daemon/chat.js +97 -0
  14. package/dist/esm/daemon/chat.js.map +1 -0
  15. package/dist/esm/daemon/cli.js +105 -10
  16. package/dist/esm/daemon/cli.js.map +1 -1
  17. package/dist/esm/daemon/env-snapshot.js +3 -0
  18. package/dist/esm/daemon/env-snapshot.js.map +1 -1
  19. package/dist/esm/daemon/flow-context.js +53 -28
  20. package/dist/esm/daemon/flow-context.js.map +1 -1
  21. package/dist/esm/daemon/launchd.js +27 -0
  22. package/dist/esm/daemon/launchd.js.map +1 -1
  23. package/dist/esm/daemon/process-registry.js +206 -0
  24. package/dist/esm/daemon/process-registry.js.map +1 -0
  25. package/dist/esm/daemon/schtasks.js +64 -0
  26. package/dist/esm/daemon/schtasks.js.map +1 -1
  27. package/dist/esm/daemon/server.js +1034 -52
  28. package/dist/esm/daemon/server.js.map +1 -1
  29. package/dist/esm/daemon/summarize.js +66 -18
  30. package/dist/esm/daemon/summarize.js.map +1 -1
  31. package/dist/esm/daemon/systemd.js +61 -0
  32. package/dist/esm/daemon/systemd.js.map +1 -1
  33. package/dist/esm/flags.js +24 -0
  34. package/dist/esm/flags.js.map +1 -1
  35. package/dist/esm/llm/attachments.js +2 -0
  36. package/dist/esm/llm/attachments.js.map +1 -0
  37. package/dist/esm/llm/errors.js +6 -0
  38. package/dist/esm/llm/errors.js.map +1 -0
  39. package/dist/esm/llm/generate-text.js +206 -356
  40. package/dist/esm/llm/generate-text.js.map +1 -1
  41. package/dist/esm/llm/html-to-markdown.js +1 -2
  42. package/dist/esm/llm/html-to-markdown.js.map +1 -1
  43. package/dist/esm/llm/prompt.js.map +1 -1
  44. package/dist/esm/llm/providers/anthropic.js +126 -0
  45. package/dist/esm/llm/providers/anthropic.js.map +1 -0
  46. package/dist/esm/llm/providers/google.js +78 -0
  47. package/dist/esm/llm/providers/google.js.map +1 -0
  48. package/dist/esm/llm/providers/models.js +111 -0
  49. package/dist/esm/llm/providers/models.js.map +1 -0
  50. package/dist/esm/llm/providers/openai.js +150 -0
  51. package/dist/esm/llm/providers/openai.js.map +1 -0
  52. package/dist/esm/llm/providers/shared.js +48 -0
  53. package/dist/esm/llm/providers/shared.js.map +1 -0
  54. package/dist/esm/llm/providers/types.js +2 -0
  55. package/dist/esm/llm/providers/types.js.map +1 -0
  56. package/dist/esm/llm/transcript-to-markdown.js +1 -2
  57. package/dist/esm/llm/transcript-to-markdown.js.map +1 -1
  58. package/dist/esm/llm/types.js +2 -0
  59. package/dist/esm/llm/types.js.map +1 -0
  60. package/dist/esm/llm/usage.js +69 -0
  61. package/dist/esm/llm/usage.js.map +1 -0
  62. package/dist/esm/logging/daemon.js +124 -0
  63. package/dist/esm/logging/daemon.js.map +1 -0
  64. package/dist/esm/logging/ring-file.js +66 -0
  65. package/dist/esm/logging/ring-file.js.map +1 -0
  66. package/dist/esm/media-cache.js +251 -0
  67. package/dist/esm/media-cache.js.map +1 -0
  68. package/dist/esm/model-auto.js +103 -5
  69. package/dist/esm/model-auto.js.map +1 -1
  70. package/dist/esm/processes.js +2 -0
  71. package/dist/esm/processes.js.map +1 -0
  72. package/dist/esm/refresh-free.js +3 -3
  73. package/dist/esm/refresh-free.js.map +1 -1
  74. package/dist/esm/run/attachments.js +8 -4
  75. package/dist/esm/run/attachments.js.map +1 -1
  76. package/dist/esm/run/bird.js +118 -5
  77. package/dist/esm/run/bird.js.map +1 -1
  78. package/dist/esm/run/cache-state.js +3 -2
  79. package/dist/esm/run/cache-state.js.map +1 -1
  80. package/dist/esm/run/cli-preflight.js +19 -1
  81. package/dist/esm/run/cli-preflight.js.map +1 -1
  82. package/dist/esm/run/constants.js +0 -7
  83. package/dist/esm/run/constants.js.map +1 -1
  84. package/dist/esm/run/finish-line.js +58 -11
  85. package/dist/esm/run/finish-line.js.map +1 -1
  86. package/dist/esm/run/flows/asset/extract.js +70 -0
  87. package/dist/esm/run/flows/asset/extract.js.map +1 -0
  88. package/dist/esm/run/flows/asset/input.js +209 -25
  89. package/dist/esm/run/flows/asset/input.js.map +1 -1
  90. package/dist/esm/run/flows/asset/media-policy.js +3 -0
  91. package/dist/esm/run/flows/asset/media-policy.js.map +1 -0
  92. package/dist/esm/run/flows/asset/media.js +224 -0
  93. package/dist/esm/run/flows/asset/media.js.map +1 -0
  94. package/dist/esm/run/flows/asset/output.js +98 -0
  95. package/dist/esm/run/flows/asset/output.js.map +1 -0
  96. package/dist/esm/run/flows/asset/preprocess.js +92 -16
  97. package/dist/esm/run/flows/asset/preprocess.js.map +1 -1
  98. package/dist/esm/run/flows/asset/summary.js +165 -11
  99. package/dist/esm/run/flows/asset/summary.js.map +1 -1
  100. package/dist/esm/run/flows/url/extract.js +6 -6
  101. package/dist/esm/run/flows/url/extract.js.map +1 -1
  102. package/dist/esm/run/flows/url/flow.js +338 -36
  103. package/dist/esm/run/flows/url/flow.js.map +1 -1
  104. package/dist/esm/run/flows/url/markdown.js +6 -1
  105. package/dist/esm/run/flows/url/markdown.js.map +1 -1
  106. package/dist/esm/run/flows/url/slides-output.js +485 -0
  107. package/dist/esm/run/flows/url/slides-output.js.map +1 -0
  108. package/dist/esm/run/flows/url/slides-text.js +628 -0
  109. package/dist/esm/run/flows/url/slides-text.js.map +1 -0
  110. package/dist/esm/run/flows/url/summary.js +358 -83
  111. package/dist/esm/run/flows/url/summary.js.map +1 -1
  112. package/dist/esm/run/help.js +94 -5
  113. package/dist/esm/run/help.js.map +1 -1
  114. package/dist/esm/run/logging.js +12 -4
  115. package/dist/esm/run/logging.js.map +1 -1
  116. package/dist/esm/run/media-cache-state.js +33 -0
  117. package/dist/esm/run/media-cache-state.js.map +1 -0
  118. package/dist/esm/run/progress.js +19 -1
  119. package/dist/esm/run/progress.js.map +1 -1
  120. package/dist/esm/run/run-context.js +19 -0
  121. package/dist/esm/run/run-context.js.map +1 -0
  122. package/dist/esm/run/run-output.js +1 -1
  123. package/dist/esm/run/run-output.js.map +1 -1
  124. package/dist/esm/run/run-settings.js +182 -0
  125. package/dist/esm/run/run-settings.js.map +1 -0
  126. package/dist/esm/run/runner.js +225 -32
  127. package/dist/esm/run/runner.js.map +1 -1
  128. package/dist/esm/run/slides-cli.js +225 -0
  129. package/dist/esm/run/slides-cli.js.map +1 -0
  130. package/dist/esm/run/slides-render.js +163 -0
  131. package/dist/esm/run/slides-render.js.map +1 -0
  132. package/dist/esm/run/stream-output.js +63 -0
  133. package/dist/esm/run/stream-output.js.map +1 -0
  134. package/dist/esm/run/streaming.js +16 -43
  135. package/dist/esm/run/streaming.js.map +1 -1
  136. package/dist/esm/run/summary-engine.js +59 -41
  137. package/dist/esm/run/summary-engine.js.map +1 -1
  138. package/dist/esm/run/transcriber-cli.js +148 -0
  139. package/dist/esm/run/transcriber-cli.js.map +1 -0
  140. package/dist/esm/shared/sse-events.js +26 -0
  141. package/dist/esm/shared/sse-events.js.map +1 -0
  142. package/dist/esm/shared/streaming-merge.js +44 -0
  143. package/dist/esm/shared/streaming-merge.js.map +1 -0
  144. package/dist/esm/slides/extract.js +1942 -0
  145. package/dist/esm/slides/extract.js.map +1 -0
  146. package/dist/esm/slides/index.js +4 -0
  147. package/dist/esm/slides/index.js.map +1 -0
  148. package/dist/esm/slides/settings.js +73 -0
  149. package/dist/esm/slides/settings.js.map +1 -0
  150. package/dist/esm/slides/store.js +111 -0
  151. package/dist/esm/slides/store.js.map +1 -0
  152. package/dist/esm/slides/types.js +2 -0
  153. package/dist/esm/slides/types.js.map +1 -0
  154. package/dist/esm/tty/osc-progress.js +21 -1
  155. package/dist/esm/tty/osc-progress.js.map +1 -1
  156. package/dist/esm/tty/progress/fetch-html.js +8 -4
  157. package/dist/esm/tty/progress/fetch-html.js.map +1 -1
  158. package/dist/esm/tty/progress/transcript.js +82 -31
  159. package/dist/esm/tty/progress/transcript.js.map +1 -1
  160. package/dist/esm/tty/spinner.js +2 -2
  161. package/dist/esm/tty/spinner.js.map +1 -1
  162. package/dist/esm/tty/theme.js +189 -0
  163. package/dist/esm/tty/theme.js.map +1 -0
  164. package/dist/esm/tty/website-progress.js +17 -13
  165. package/dist/esm/tty/website-progress.js.map +1 -1
  166. package/dist/esm/version.js +1 -1
  167. package/dist/esm/version.js.map +1 -1
  168. package/dist/types/cache.d.ts +14 -2
  169. package/dist/types/config.d.ts +34 -0
  170. package/dist/types/daemon/agent.d.ts +25 -0
  171. package/dist/types/daemon/chat.d.ts +27 -0
  172. package/dist/types/daemon/env-snapshot.d.ts +1 -1
  173. package/dist/types/daemon/flow-context.d.ts +24 -3
  174. package/dist/types/daemon/launchd.d.ts +4 -0
  175. package/dist/types/daemon/process-registry.d.ts +73 -0
  176. package/dist/types/daemon/schtasks.d.ts +4 -0
  177. package/dist/types/daemon/server.d.ts +7 -1
  178. package/dist/types/daemon/summarize.d.ts +47 -5
  179. package/dist/types/daemon/systemd.d.ts +4 -0
  180. package/dist/types/flags.d.ts +1 -0
  181. package/dist/types/llm/attachments.d.ts +6 -0
  182. package/dist/types/llm/errors.d.ts +1 -0
  183. package/dist/types/llm/generate-text.d.ts +29 -13
  184. package/dist/types/llm/prompt.d.ts +7 -2
  185. package/dist/types/llm/providers/anthropic.d.ts +30 -0
  186. package/dist/types/llm/providers/google.d.ts +29 -0
  187. package/dist/types/llm/providers/models.d.ts +27 -0
  188. package/dist/types/llm/providers/openai.d.ts +38 -0
  189. package/dist/types/llm/providers/shared.d.ts +14 -0
  190. package/dist/types/llm/providers/types.d.ts +6 -0
  191. package/dist/types/llm/types.d.ts +5 -0
  192. package/dist/types/llm/usage.d.ts +5 -0
  193. package/dist/types/logging/daemon.d.ts +26 -0
  194. package/dist/types/logging/ring-file.d.ts +10 -0
  195. package/dist/types/media-cache.d.ts +22 -0
  196. package/dist/types/model-auto.d.ts +1 -0
  197. package/dist/types/processes.d.ts +1 -0
  198. package/dist/types/run/attachments.d.ts +9 -6
  199. package/dist/types/run/bird.d.ts +7 -0
  200. package/dist/types/run/constants.d.ts +0 -2
  201. package/dist/types/run/finish-line.d.ts +59 -1
  202. package/dist/types/run/flows/asset/extract.d.ts +18 -0
  203. package/dist/types/run/flows/asset/input.d.ts +12 -2
  204. package/dist/types/run/flows/asset/media-policy.d.ts +2 -0
  205. package/dist/types/run/flows/asset/media.d.ts +21 -0
  206. package/dist/types/run/flows/asset/output.d.ts +42 -0
  207. package/dist/types/run/flows/asset/preprocess.d.ts +22 -2
  208. package/dist/types/run/flows/asset/summary.d.ts +6 -0
  209. package/dist/types/run/flows/url/extract.d.ts +2 -1
  210. package/dist/types/run/flows/url/slides-output.d.ts +66 -0
  211. package/dist/types/run/flows/url/slides-text.d.ts +87 -0
  212. package/dist/types/run/flows/url/summary.d.ts +11 -3
  213. package/dist/types/run/flows/url/types.d.ts +29 -2
  214. package/dist/types/run/help.d.ts +3 -0
  215. package/dist/types/run/logging.d.ts +3 -2
  216. package/dist/types/run/media-cache-state.d.ts +7 -0
  217. package/dist/types/run/progress.d.ts +2 -1
  218. package/dist/types/run/run-context.d.ts +44 -0
  219. package/dist/types/run/run-settings.d.ts +62 -0
  220. package/dist/types/run/slides-cli.d.ts +9 -0
  221. package/dist/types/run/slides-render.d.ts +30 -0
  222. package/dist/types/run/stream-output.d.ts +12 -0
  223. package/dist/types/run/streaming.d.ts +10 -4
  224. package/dist/types/run/summary-engine.d.ts +15 -3
  225. package/dist/types/run/summary-llm.d.ts +2 -2
  226. package/dist/types/run/transcriber-cli.d.ts +8 -0
  227. package/dist/types/shared/sse-events.d.ts +64 -0
  228. package/dist/types/shared/streaming-merge.d.ts +4 -0
  229. package/dist/types/slides/extract.d.ts +42 -0
  230. package/dist/types/slides/index.d.ts +5 -0
  231. package/dist/types/slides/settings.d.ts +20 -0
  232. package/dist/types/slides/store.d.ts +15 -0
  233. package/dist/types/slides/types.d.ts +40 -0
  234. package/dist/types/tty/osc-progress.d.ts +2 -2
  235. package/dist/types/tty/progress/fetch-html.d.ts +3 -1
  236. package/dist/types/tty/progress/transcript.d.ts +3 -1
  237. package/dist/types/tty/spinner.d.ts +3 -1
  238. package/dist/types/tty/theme.d.ts +44 -0
  239. package/dist/types/tty/website-progress.d.ts +3 -1
  240. package/dist/types/version.d.ts +1 -1
  241. package/docs/README.md +13 -8
  242. package/docs/_config.yml +26 -0
  243. package/docs/_layouts/default.html +60 -0
  244. package/docs/agent.md +333 -0
  245. package/docs/assets/site.css +748 -0
  246. package/docs/assets/site.js +72 -0
  247. package/docs/assets/summarize-cli.png +0 -0
  248. package/docs/assets/summarize-extension.png +0 -0
  249. package/docs/assets/youtube-slides.png +0 -0
  250. package/docs/cache.md +29 -3
  251. package/docs/chrome-extension.md +85 -7
  252. package/docs/config.md +74 -2
  253. package/docs/extract-only.md +10 -2
  254. package/docs/index.html +205 -0
  255. package/docs/index.md +25 -0
  256. package/docs/language.md +1 -1
  257. package/docs/llm.md +17 -1
  258. package/docs/manual-tests.md +2 -0
  259. package/docs/media.md +37 -0
  260. package/docs/model-auto.md +2 -1
  261. package/docs/nvidia-onnx-transcription.md +55 -0
  262. package/docs/openai.md +5 -0
  263. package/docs/releasing.md +26 -0
  264. package/docs/site/assets/site.css +399 -228
  265. package/docs/site/assets/summarize-cli.png +0 -0
  266. package/docs/site/assets/summarize-extension.png +0 -0
  267. package/docs/site/docs/chrome-extension.html +89 -0
  268. package/docs/site/docs/config.html +1 -0
  269. package/docs/site/docs/extract-only.html +1 -0
  270. package/docs/site/docs/firecrawl.html +1 -0
  271. package/docs/site/docs/index.html +5 -0
  272. package/docs/site/docs/llm.html +1 -0
  273. package/docs/site/docs/openai.html +1 -0
  274. package/docs/site/docs/website.html +1 -0
  275. package/docs/site/docs/youtube.html +1 -0
  276. package/docs/site/index.html +148 -84
  277. package/docs/slides.md +74 -0
  278. package/docs/timestamps.md +103 -0
  279. package/docs/website.md +13 -0
  280. package/docs/youtube.md +16 -0
  281. package/package.json +22 -18
  282. package/dist/esm/daemon/request-settings.js +0 -91
  283. package/dist/esm/daemon/request-settings.js.map +0 -1
  284. package/dist/types/daemon/request-settings.d.ts +0 -27
@@ -0,0 +1,89 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width,initial-scale=1" />
6
+ <meta name="color-scheme" content="dark light" />
7
+ <title>Chrome extension — summarize</title>
8
+ <link rel="canonical" href="https://summarize.sh/docs/chrome-extension" />
9
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
11
+ <link
12
+ href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap"
13
+ rel="stylesheet"
14
+ />
15
+ <link rel="stylesheet" href="../assets/site.css" />
16
+ </head>
17
+ <body>
18
+ <main class="shell">
19
+ <header class="top">
20
+ <a class="brand" href="../index.html" aria-label="summarize home">
21
+ <span class="brand__mark" aria-hidden="true">s</span>
22
+ <span class="brand__word">summarize</span>
23
+ </a>
24
+ <nav class="nav" aria-label="Primary">
25
+ <a data-nav="home" href="../index.html">Home</a>
26
+ <a data-nav="docs" href="./index.html">Docs</a>
27
+ <a href="https://github.com/steipete/summarize">GitHub</a>
28
+ </nav>
29
+ </header>
30
+
31
+ <section class="docShell">
32
+ <aside class="side" aria-label="Docs navigation">
33
+ <h2>Docs</h2>
34
+ <a href="./index.html">Overview</a>
35
+ <a href="./chrome-extension.html">Chrome extension</a>
36
+ <a href="./website.html">Website mode</a>
37
+ <a href="./youtube.html">YouTube mode</a>
38
+ <a href="./extract-only.html">Extract</a>
39
+ <a href="./llm.html">LLM</a>
40
+ <a href="./openai.html">OpenAI</a>
41
+ <a href="./firecrawl.html">Firecrawl</a>
42
+ <a href="./config.html">Config</a>
43
+ </aside>
44
+
45
+ <article class="doc reveal">
46
+ <p class="kicker">product</p>
47
+ <h1>Chrome extension</h1>
48
+ <p>
49
+ Summarize ships a Chrome Side Panel extension backed by a tiny local daemon. It streams Markdown summaries
50
+ for the active tab and supports auto-summarize on navigation.
51
+ </p>
52
+
53
+ <h2>Setup</h2>
54
+ <ul>
55
+ <li><code>npm i -g @steipete/summarize</code> or <code>brew install steipete/tap/summarize</code></li>
56
+ <li>Build extension: <code>pnpm -C apps/chrome-extension build</code></li>
57
+ <li>Load unpacked: <code>apps/chrome-extension/.output/chrome-mv3</code></li>
58
+ <li>Open side panel → copy token command → run <code>summarize daemon install --token &lt;TOKEN&gt;</code></li>
59
+ <li>Verify: <code>summarize daemon status</code></li>
60
+ </ul>
61
+
62
+ <h2>Dev</h2>
63
+ <ul>
64
+ <li>Install daemon for dev: <code>pnpm summarize daemon install --token &lt;TOKEN&gt; --dev</code></li>
65
+ <li>Dev server: <code>pnpm -C apps/chrome-extension dev</code></li>
66
+ </ul>
67
+
68
+ <h2>Troubleshooting</h2>
69
+ <ul>
70
+ <li>Daemon unreachable: <code>summarize daemon status</code></li>
71
+ <li>Logs: <code>~/.summarize/logs/daemon.err.log</code></li>
72
+ <li>Token mismatch: update token in side panel and Save</li>
73
+ </ul>
74
+
75
+ <div class="note">
76
+ The daemon listens on <code>127.0.0.1:8787</code> only and is token-protected.
77
+ </div>
78
+ </article>
79
+ </section>
80
+
81
+ <footer class="footer">
82
+ <span>summarize — Link → clean text → summary.</span>
83
+ <span><a href="./index.html">Docs</a> · <a href="https://github.com/steipete/summarize">Repo</a></span>
84
+ </footer>
85
+ </main>
86
+
87
+ <script type="module" src="../assets/site.js"></script>
88
+ </body>
89
+ </html>
@@ -29,6 +29,7 @@
29
29
  <aside class="side" aria-label="Docs navigation">
30
30
  <h2>Docs</h2>
31
31
  <a href="./index.html">Overview</a>
32
+ <a href="./chrome-extension.html">Chrome extension</a>
32
33
  <a href="./website.html">Website mode</a>
33
34
  <a href="./youtube.html">YouTube mode</a>
34
35
  <a href="./extract-only.html">Extract</a>
@@ -29,6 +29,7 @@
29
29
  <aside class="side" aria-label="Docs navigation">
30
30
  <h2>Docs</h2>
31
31
  <a href="./index.html">Overview</a>
32
+ <a href="./chrome-extension.html">Chrome extension</a>
32
33
  <a href="./website.html">Website mode</a>
33
34
  <a href="./youtube.html">YouTube mode</a>
34
35
  <a href="./extract-only.html">Extract</a>
@@ -29,6 +29,7 @@
29
29
  <aside class="side" aria-label="Docs navigation">
30
30
  <h2>Docs</h2>
31
31
  <a href="./index.html">Overview</a>
32
+ <a href="./chrome-extension.html">Chrome extension</a>
32
33
  <a href="./website.html">Website mode</a>
33
34
  <a href="./youtube.html">YouTube mode</a>
34
35
  <a href="./extract-only.html">Extract</a>
@@ -42,6 +42,11 @@
42
42
  </section>
43
43
 
44
44
  <section class="grid">
45
+ <a class="card reveal" href="./chrome-extension.html">
46
+ <h2>Chrome extension</h2>
47
+ <p>Side panel UI + local daemon pairing.</p>
48
+ <div class="small">docs/chrome-extension.md</div>
49
+ </a>
45
50
  <a class="card reveal" href="./website.html">
46
51
  <h2>Website mode</h2>
47
52
  <p>HTML extraction + normalization + Firecrawl fallback.</p>
@@ -29,6 +29,7 @@
29
29
  <aside class="side" aria-label="Docs navigation">
30
30
  <h2>Docs</h2>
31
31
  <a href="./index.html">Overview</a>
32
+ <a href="./chrome-extension.html">Chrome extension</a>
32
33
  <a href="./website.html">Website mode</a>
33
34
  <a href="./youtube.html">YouTube mode</a>
34
35
  <a href="./extract-only.html">Extract</a>
@@ -29,6 +29,7 @@
29
29
  <aside class="side" aria-label="Docs navigation">
30
30
  <h2>Docs</h2>
31
31
  <a href="./index.html">Overview</a>
32
+ <a href="./chrome-extension.html">Chrome extension</a>
32
33
  <a href="./website.html">Website mode</a>
33
34
  <a href="./youtube.html">YouTube mode</a>
34
35
  <a href="./extract-only.html">Extract</a>
@@ -29,6 +29,7 @@
29
29
  <aside class="side" aria-label="Docs navigation">
30
30
  <h2>Docs</h2>
31
31
  <a href="./index.html">Overview</a>
32
+ <a href="./chrome-extension.html">Chrome extension</a>
32
33
  <a href="./website.html">Website mode</a>
33
34
  <a href="./youtube.html">YouTube mode</a>
34
35
  <a href="./extract-only.html">Extract</a>
@@ -29,6 +29,7 @@
29
29
  <aside class="side" aria-label="Docs navigation">
30
30
  <h2>Docs</h2>
31
31
  <a href="./index.html">Overview</a>
32
+ <a href="./chrome-extension.html">Chrome extension</a>
32
33
  <a href="./website.html">Website mode</a>
33
34
  <a href="./youtube.html">YouTube mode</a>
34
35
  <a href="./extract-only.html">Extract</a>
@@ -4,18 +4,24 @@
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width,initial-scale=1" />
6
6
  <meta name="color-scheme" content="dark light" />
7
- <title>summarize — Link clean text summary.</title>
8
- <meta name="description" content="Link → clean text → summary. A CLI that turns URLs into clean text and fast summaries." />
7
+ <title>summarize — CLI + Chrome Side Panel for fast summaries</title>
8
+ <meta
9
+ name="description"
10
+ content="Summarize is a fast CLI and a Chrome Side Panel extension for clean extraction and sharp summaries."
11
+ />
9
12
  <link rel="canonical" href="https://summarize.sh/" />
10
13
  <meta property="og:title" content="summarize" />
11
- <meta property="og:description" content="Link clean text summary." />
14
+ <meta property="og:description" content="Fast summaries, in the CLI and the Chrome Side Panel." />
12
15
  <meta property="og:type" content="website" />
13
16
  <meta property="og:url" content="https://summarize.sh/" />
14
- <meta name="theme-color" content="#0b1018" />
17
+ <meta name="theme-color" content="#0b0f12" />
15
18
 
16
19
  <link rel="preconnect" href="https://fonts.googleapis.com" />
17
20
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
18
- <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet" />
21
+ <link
22
+ href="https://fonts.googleapis.com/css2?family=Fraunces:wght@600;700&family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans:wght@400;500;600&display=swap"
23
+ rel="stylesheet"
24
+ />
19
25
  <link rel="stylesheet" href="./assets/site.css" />
20
26
  </head>
21
27
  <body>
@@ -33,99 +39,157 @@
33
39
  </header>
34
40
 
35
41
  <section class="hero">
36
- <div class="hero__card reveal">
37
- <div class="hero__grid">
38
- <div class="hero__inner">
39
- <p class="kicker">CLI</p>
40
- <h1 class="title">Link → clean text → summary.</h1>
41
- <p class="lede">
42
- A pragmatic pipeline for the web: <strong>extract</strong> the good stuff, <strong>sanitize</strong> it,
43
- then <strong>summarize</strong> with your model of choice. Podcast episode pages included. Plus a Chrome
44
- side panel extension when you want it in-browser.
45
- </p>
46
-
47
- <div class="pillRow">
48
- <span class="pill"><span class="pill__dot" aria-hidden="true"></span> Website extraction</span>
49
- <span class="pill"><span class="pill__dot" aria-hidden="true" style="background: var(--accent2)"></span> YouTube transcripts</span>
50
- <span class="pill"><span class="pill__dot" aria-hidden="true" style="background: var(--accent3)"></span> Podcast compatibility</span>
51
- <span class="pill"><span class="pill__dot" aria-hidden="true" style="background: var(--accent3)"></span> JSON + metrics</span>
52
- <span class="pill"><span class="pill__dot" aria-hidden="true" style="background: var(--accent2)"></span> Chrome extension</span>
42
+ <div class="hero__frame reveal">
43
+ <div class="hero__copy">
44
+ <p class="kicker">CLI + Chrome Extension</p>
45
+ <h1 class="title">Summaries that live where you work.</h1>
46
+ <p class="lede">
47
+ Summarize turns links, files, and media into sharp summaries with a real extraction pipeline.
48
+ Use the <strong>CLI</strong> for automation or the <strong>Chrome Side Panel</strong> for one-click
49
+ summaries of the current tab. Supports <strong>local, paid, and free</strong> models.
50
+ </p>
51
+ <div class="ctaRow">
52
+ <a class="btn btn--primary" href="./docs/index.html">Docs</a>
53
+ <a class="btn" href="https://github.com/steipete/summarize">GitHub</a>
54
+ </div>
55
+ <div class="quickRow">
56
+ <div class="quickRow__label">Quickstart</div>
57
+ <div class="quickRow__code">
58
+ <code id="install">npm i -g @steipete/summarize</code>
59
+ <code id="run">summarize "https://example.com/article"</code>
53
60
  </div>
54
-
55
- <div class="ctaRow">
56
- <a class="btn btn--primary" href="./docs/index.html" aria-label="Read docs">
57
- <svg class="btn__icon" viewBox="0 0 24 24" fill="none" aria-hidden="true">
58
- <path d="M6 4h9l3 3v13a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2Z" stroke="currentColor" stroke-width="1.5"/>
59
- <path d="M15 4v4h4" stroke="currentColor" stroke-width="1.5"/>
60
- </svg>
61
- Docs
62
- </a>
63
- <a class="btn" href="https://github.com/steipete/summarize">
64
- <svg class="btn__icon" viewBox="0 0 24 24" fill="none" aria-hidden="true">
65
- <path d="M12 2a10 10 0 0 0-3.16 19.49c.5.09.68-.22.68-.48v-1.7c-2.77.6-3.35-1.18-3.35-1.18-.45-1.14-1.1-1.45-1.1-1.45-.9-.62.07-.6.07-.6 1 .07 1.52 1.02 1.52 1.02.9 1.52 2.36 1.08 2.94.82.09-.64.35-1.08.63-1.33-2.2-.25-4.52-1.1-4.52-4.88 0-1.08.39-1.96 1.02-2.65-.1-.25-.44-1.27.1-2.65 0 0 .84-.27 2.75 1.02a9.46 9.46 0 0 1 5 0c1.9-1.29 2.75-1.02 2.75-1.02.54 1.38.2 2.4.1 2.65.64.69 1.02 1.57 1.02 2.65 0 3.79-2.33 4.63-4.55 4.88.36.31.68.92.68 1.86v2.76c0 .26.18.58.69.48A10 10 0 0 0 12 2Z" fill="currentColor" opacity=".9"/>
66
- </svg>
67
- Repo
68
- </a>
61
+ <div class="quickRow__actions">
62
+ <button class="btn" data-copy="#install">Copy install</button>
63
+ <button class="btn" data-copy="#run">Copy run</button>
69
64
  </div>
70
65
  </div>
66
+ </div>
71
67
 
72
- <aside class="codeCard">
73
- <p class="kicker">Quickstart</p>
68
+ <div class="hero__visual">
69
+ <figure class="shot shot--cli">
70
+ <img src="./assets/summarize-cli.png" alt="Summarize CLI output" loading="lazy" />
71
+ <figcaption>CLI: streaming summaries in the terminal.</figcaption>
72
+ </figure>
73
+ <figure class="shot shot--ext">
74
+ <img src="./assets/summarize-extension.png" alt="Summarize Chrome extension side panel" loading="lazy" />
75
+ <figcaption>Extension: a live Side Panel for the active tab.</figcaption>
76
+ </figure>
77
+ </div>
78
+ </div>
79
+ </section>
74
80
 
75
- <div class="terminal">
76
- <div class="terminal__bar" aria-hidden="true">
77
- <span class="terminal__dot terminal__dot--a"></span>
78
- <span class="terminal__dot terminal__dot--b"></span>
79
- <span class="terminal__dot terminal__dot--c"></span>
80
- </div>
81
- <pre><code id="install">npm i -g @steipete/summarize</code>
82
- <code id="run">summarize "https://example.com/article"</code></pre>
83
- </div>
81
+ <section class="productGrid" aria-label="Products">
82
+ <article class="productCard reveal" id="cli">
83
+ <div class="productCard__head">
84
+ <span class="badge">CLI</span>
85
+ <h2>Fast summaries, scripted or interactive.</h2>
86
+ </div>
87
+ <p>
88
+ Built for automation: extract clean text, summarize with your model, and output JSON or Markdown.
89
+ Works with URLs, PDFs, images, audio/video, YouTube, and podcasts.
90
+ </p>
91
+ <ul class="list">
92
+ <li><strong>Extract + summarize</strong> with Firecrawl fallback.</li>
93
+ <li><strong>Media pipeline</strong> with transcript-first flow and Whisper fallback.</li>
94
+ <li><strong>Scriptable output</strong> via <code>--json</code>, <code>--extract</code>, <code>--metrics</code>.</li>
95
+ </ul>
96
+ <div class="cardCode">
97
+ <pre><code>summarize "https://example.com" --length long
98
+ summarize "https://youtu.be/..." --youtube auto
99
+ summarize "/path/report.pdf" --model google/gemini-3-flash-preview</code></pre>
100
+ </div>
101
+ <div class="ctaRow">
102
+ <a class="btn btn--ghost" href="./docs/cli.html">CLI docs</a>
103
+ <a class="btn" href="./docs/config.html">Config</a>
104
+ </div>
105
+ </article>
84
106
 
85
- <div class="copyRow">
86
- <span class="hint">Install, then summarize a URL.</span>
87
- <div class="ctaRow" style="margin-top:0">
88
- <button class="btn" data-copy="#install">Copy install</button>
89
- <button class="btn" data-copy="#run">Copy run</button>
90
- </div>
91
- </div>
92
- </aside>
107
+ <article class="productCard reveal" id="extension">
108
+ <div class="productCard__head">
109
+ <span class="badge badge--alt">Chrome Extension</span>
110
+ <h2>Summaries in the Side Panel, one click away.</h2>
93
111
  </div>
94
- </div>
112
+ <p>
113
+ A real Chrome Side Panel with a tiny local daemon. It streams Markdown summaries for the active tab,
114
+ with auto-summary on navigation.
115
+ </p>
116
+ <ol class="steps">
117
+ <li>Install the CLI + daemon.</li>
118
+ <li>Load the unpacked extension.</li>
119
+ <li>Open Side Panel and connect with the token.</li>
120
+ </ol>
121
+ <div class="callout">
122
+ <strong>Runs locally</strong> on your machine. The daemon is localhost-only and token-protected.
123
+ </div>
124
+ <div class="ctaRow">
125
+ <a class="btn btn--ghost" href="./docs/chrome-extension.html">Extension docs</a>
126
+ <a class="btn" href="https://github.com/steipete/summarize/releases/latest">Latest release</a>
127
+ </div>
128
+ </article>
95
129
  </section>
96
130
 
97
- <section class="grid" aria-label="Features">
98
- <div class="card reveal">
99
- <h2>Extraction that’s not naive</h2>
100
- <p>HTML normalized text, with fallbacks when a site fights back.</p>
101
- <div class="small">Cheerio + sanitization + optional Firecrawl</div>
131
+ <section class="capGrid" aria-label="Capabilities">
132
+ <div class="capCard reveal">
133
+ <span class="capCard__eyebrow">Extraction</span>
134
+ <h3>HTML -> clean text -> summary</h3>
135
+ <p>Readability, markitdown, and Firecrawl fallback when sites fight back.</p>
102
136
  </div>
103
- <div class="card reveal">
104
- <h2>Podcast-friendly</h2>
105
- <p>Apple/Spotify/RSS episode pages, plus embedded YouTube podcasts.</p>
106
- <div class="small">Prefers published transcripts; Whisper fallback</div>
137
+ <div class="capCard reveal">
138
+ <span class="capCard__eyebrow">Media</span>
139
+ <h3>Podcast + YouTube aware</h3>
140
+ <p>Prefers published transcripts, then Whisper when needed.</p>
107
141
  </div>
108
- <div class="card reveal">
109
- <h2>YouTube transcripts, without drama</h2>
110
- <p>Pull captions via multiple paths so “missing transcript” becomes rare.</p>
111
- <div class="small">Website vs YouTube modes</div>
142
+ <div class="capCard reveal">
143
+ <span class="capCard__eyebrow">Models</span>
144
+ <h3>Provider-agnostic</h3>
145
+ <p>Local OpenAI-compatible gateways, paid providers, and OpenRouter free models.</p>
112
146
  </div>
113
- <div class="card reveal">
114
- <h2>Built for pipelines</h2>
115
- <p><code>--extract</code>, <code>--json</code>, and <code>--metrics</code> make it scriptable.</p>
116
- <div class="small">Compose it with your own tools</div>
147
+ <div class="capCard reveal">
148
+ <span class="capCard__eyebrow">Outputs</span>
149
+ <h3>Readable + scriptable</h3>
150
+ <p>Streaming TTY output, ANSI Markdown, JSON diagnostics, and metrics.</p>
117
151
  </div>
118
- <div class="card reveal">
119
- <h2>Provider-agnostic LLMs</h2>
120
- <p>OpenAI, xAI, Gemini — use what you’ve got, pin what you need.</p>
121
- <div class="small">Control via <code>--model</code> + env vars</div>
152
+ </section>
153
+
154
+ <section class="flow">
155
+ <div class="flow__card reveal">
156
+ <h2>How it works</h2>
157
+ <div class="flow__steps">
158
+ <div class="flowStep">
159
+ <span class="flowStep__num">01</span>
160
+ <div>
161
+ <h4>Fetch + extract</h4>
162
+ <p>Pull the source, clean HTML, normalize, or convert to Markdown.</p>
163
+ </div>
164
+ </div>
165
+ <div class="flowStep">
166
+ <span class="flowStep__num">02</span>
167
+ <div>
168
+ <h4>Transcript when needed</h4>
169
+ <p>Use published transcripts, then Whisper fallback for media.</p>
170
+ </div>
171
+ </div>
172
+ <div class="flowStep">
173
+ <span class="flowStep__num">03</span>
174
+ <div>
175
+ <h4>Summarize + format</h4>
176
+ <p>LLM output, streaming in the CLI or Side Panel, with metrics.</p>
177
+ </div>
178
+ </div>
179
+ </div>
122
180
  </div>
123
- <div class="card reveal">
124
- <h2>Chrome side panel</h2>
125
- <p>Summarize the active tab without leaving your browser.</p>
126
- <div class="small">
127
- Companion extension for the CLI. Download from the
128
- <a href="https://github.com/steipete/summarize/releases/latest">latest GitHub release</a>.
181
+ </section>
182
+
183
+ <section class="more">
184
+ <div class="more__card reveal">
185
+ <h2>More</h2>
186
+ <div class="more__grid">
187
+ <a class="moreLink" href="./docs/website.html">Website extraction</a>
188
+ <a class="moreLink" href="./docs/youtube.html">YouTube transcripts</a>
189
+ <a class="moreLink" href="./docs/media.html">Media pipeline</a>
190
+ <a class="moreLink" href="./docs/model-auto.html">Auto model rules</a>
191
+ <a class="moreLink" href="./docs/llm.html">Model + key setup</a>
192
+ <a class="moreLink" href="./docs/config.html">Config schema</a>
129
193
  </div>
130
194
  </div>
131
195
  </section>
package/docs/slides.md ADDED
@@ -0,0 +1,74 @@
1
+ ---
2
+ summary: "Plan for slide-first UX without model usage."
3
+ read_when:
4
+ - "When changing slide summaries, slide UI, or slide/seek behavior in the side panel."
5
+ ---
6
+
7
+ # Slides plan (no model)
8
+
9
+ ## Goals
10
+ - Expanded slides view = full-width cards, top of summary.
11
+ - Click slide = seek video timestamp (no modal).
12
+ - Descriptions scale with length setting.
13
+ - Always show all slides (even if text missing).
14
+ - No model call for slide descriptions.
15
+
16
+ ## Data sources
17
+ - Primary: transcript timed text (already available with timestamps).
18
+ - Secondary: OCR text from slides (truncate, selectable).
19
+ - Tertiary: empty description (still render card).
20
+
21
+ ## Description generation (no model)
22
+ - For each slide timestamp `t`:
23
+ - Pull transcript segments within a time window around `t`.
24
+ - Concatenate into plain text (no bullets).
25
+ - If no transcript: use OCR text (trim).
26
+ - If neither: empty string.
27
+ - Always render all slide cards; missing text → show slide only.
28
+
29
+ ## Length scaling
30
+ - Map summary length to per-slide target chars.
31
+ - Use existing length presets (short/medium/long/xl/xxl + custom):
32
+ - `short`: ~120 chars/slide
33
+ - `medium`: ~200 chars/slide
34
+ - `long`: ~320 chars/slide
35
+ - `xl`: ~480 chars/slide
36
+ - `xxl`: ~700 chars/slide
37
+ - custom: derive from maxCharacters (e.g. `maxChars / min(slideCount, 10)`, clamp).
38
+ - Clamp per-slide text: `[80, 900]` chars.
39
+ - Window size should expand with length (e.g. 20s → 90s).
40
+
41
+ ## UI behavior
42
+ - Default summary stays unchanged (no slide text).
43
+ - Slide strip (compact) stays horizontal; no modal required.
44
+ - Expand toggle switches to vertical full-width list:
45
+ - cards: thumbnail, timestamp, text.
46
+ - cards appear above summary.
47
+ - Slide click: seek only (no modal).
48
+ - OCR toggle appears near summarize control only when OCR is significant
49
+ (enough slides + total OCR chars); otherwise hide it.
50
+
51
+ ## CLI
52
+ - `summarize <url> --slides` streams a short intro paragraph and then a continuous narrative with slide images inserted inline where `[slide:N]` markers appear.
53
+ - The model is responsible for inserting every slide marker in order; text length is still governed by `--length`.
54
+ - If inline images are unsupported, the CLI prints text-only output and notes how to export slides to disk.
55
+ - Timestamp links use OSC-8 when supported (YouTube/Vimeo/Loom/Dropbox).
56
+ - Progress line reports slide extraction steps (includes slide counts when available).
57
+ - `summarize <url> --slides --extract` prints the full timed transcript and inserts slide images inline at matching timestamps.
58
+ - `summarize slides <url>` extracts slides without summarizing (use `--render auto|kitty|iterm` for inline thumbnails).
59
+ - Defaults to writing images under `./slides/<sourceId>/` (override via `--slides-dir` / `--output`).
60
+
61
+ ## Implementation notes
62
+ - Build `slideDescriptions` map in panel:
63
+ - Use `summary.timedText` when available.
64
+ - Split transcript into segments with timestamps (already in payload).
65
+ - Store per-slide text on client (no daemon model calls).
66
+ - Ensure summary cache keys untouched; only client-only rendering.
67
+ - Slide extraction downloads the media once for detect+extract; set `SLIDES_EXTRACT_STREAM=1` to allow stream fallback (lower accuracy).
68
+
69
+ ## Steps
70
+ 1) Add slide-description builder in sidepanel using transcript timed text + OCR fallback.
71
+ 2) Add length-based per-slide char budget and window sizing.
72
+ 3) Render expanded card list with timestamps + text.
73
+ 4) Remove modal; click = seek only.
74
+ 5) Add tests for slide description + fallback.
@@ -0,0 +1,103 @@
1
+ ---
2
+ summary: "Transcript timestamps plan + clickable chat jumps."
3
+ read_when:
4
+ - "When planning transcript timestamps or click-to-seek UX."
5
+ ---
6
+
7
+ # Transcript Timestamps Plan
8
+
9
+ Short scope
10
+ - Add `--timestamps` flag to request timed transcripts.
11
+ - Preserve existing plain transcript text; add structured segments + timed text.
12
+ - Chat mode: include timed transcript + prompt for `[mm:ss]` references.
13
+ - Sidepanel: click timestamp → seek media (video or audio), keep play state.
14
+ - Coverage: YouTube, podcasts, embedded captions, generic media; whisper.cpp = no segments unless we add verbose output later.
15
+
16
+ ## 1) API / data model
17
+ - New option: `FetchLinkContentOptions.transcriptTimestamps?: boolean`.
18
+ - Thread through provider options (`ProviderFetchOptions`).
19
+ - New types:
20
+ - `TranscriptSegment`: `{ startMs: number; endMs?: number | null; text: string }`.
21
+ - `TranscriptResolution.segments?: TranscriptSegment[] | null`.
22
+ - `ExtractedLinkContent.transcriptSegments?: TranscriptSegment[] | null`.
23
+ - `ExtractedLinkContent.transcriptTimedText?: string | null` (helper).
24
+ - Keep `TranscriptResolution.text` unchanged (plain transcript).
25
+
26
+ Notes
27
+ - `--timestamps` should only alter output when requested; default output remains stable.
28
+ - For JSON output, include both `transcriptSegments` and `transcriptTimedText` when requested.
29
+
30
+ ## 2) Provider updates
31
+ YouTube (youtubei)
32
+ - Parse `startMs` (and duration if present) from `transcriptSegmentRenderer`.
33
+ - Build segments array; `text` still plain (join of text).
34
+
35
+ YouTube (captionTracks json3 / xml)
36
+ - json3 provides `events[].tStartMs` and `dDurationMs`; parse segments from `events.segs[].utf8`.
37
+ - XML captions include `start` + `dur`; parse segments when present.
38
+
39
+ Podcast RSS transcripts
40
+ - VTT parser should output segments (start/end + cue text).
41
+ - JSON transcript: support `segments` with `start`/`startMs` + `end`/`endMs` + `text`.
42
+ - Plain text transcripts: `segments = null`.
43
+
44
+ Generic embedded captions
45
+ - When track is VTT/JSON, parse into segments; otherwise `null`.
46
+
47
+ yt-dlp / whisper / whisper.cpp
48
+ - Keep `segments = null` (plain text only).
49
+ - Optional future: request verbose or SRT output from OpenAI/FAL when supported.
50
+
51
+ ## 3) Cache behavior
52
+ - Store `segments` in transcript metadata (or dedicated cache field).
53
+ - If `--timestamps` and cached transcript lacks segments, treat as miss and refetch.
54
+ - Keep cache keys stable; only bypass when timestamps requested.
55
+
56
+ ## 4) CLI / daemon
57
+ - Add `--timestamps` to CLI help + config.
58
+ - Map to `FetchLinkContentOptions.transcriptTimestamps`.
59
+ - `--extract --json`: include `transcriptSegments` + `transcriptTimedText`.
60
+ - Non-JSON extract: keep plain transcript unless `--timestamps`, then output timed text block.
61
+
62
+ ## 5) Chat prompt + content
63
+ - `buildChatPageContent`: when timestamps requested, include `Timed transcript:` block using `[mm:ss]`.
64
+ - `buildChatSystemPrompt`: add instruction:
65
+ - “When referencing moments, include `[mm:ss]` timestamps from the transcript.”
66
+
67
+ ## 6) Chrome extension UI
68
+ Render
69
+ - Linkify `[mm:ss]` and `[hh:mm:ss]` in assistant messages.
70
+ - Convert to `timestamp:<seconds>` hrefs (or data attribute).
71
+
72
+ Seek handler
73
+ - On click: prevent default, parse seconds, send `panel:seek` → background → content script.
74
+ - Content script:
75
+ - Find `<video>` or `<audio>`.
76
+ - Record `wasPaused = media.paused`.
77
+ - `media.currentTime = seconds`.
78
+ - If `!wasPaused`, call `media.play()`; else do nothing.
79
+ - YouTube fallback when no media element:
80
+ - If `window.ytplayer` / YT IFrame API available, `player.seekTo(seconds, true)`.
81
+
82
+ ## 7) Tests
83
+ Core
84
+ - youtubei transcript parsing yields segments + plain text.
85
+ - captionTracks json3 + xml yield segments.
86
+ - VTT parser yields segments.
87
+ - Cache: timestamps requested + cached without segments → refetch.
88
+
89
+ Daemon / CLI
90
+ - `--timestamps` propagates into fetch options.
91
+ - JSON extract includes `transcriptSegments` + `transcriptTimedText`.
92
+
93
+ Chrome extension
94
+ - Chat content includes timed transcript when requested.
95
+ - Sidepanel: timestamp link emits `panel:seek`.
96
+ - Content script seek: playing stays playing, paused stays paused; audio + video.
97
+
98
+ ## 8) Changelog
99
+ - Entry: `--timestamps` flag, timed transcripts in chat, clickable timestamps in extension, podcast support.
100
+
101
+ ## 9) Notes / open
102
+ - “VisPoR” = whisper.cpp: no timestamps unless we add verbose output path.
103
+ - Decide exact format of `transcriptTimedText` (recommend `[mm:ss] text` per line).