@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,72 @@
1
+ const canonicalHost = 'summarize.sh'
2
+ const redirectHostnames = new Set(['summarize.is', 'www.summarize.is'])
3
+
4
+ const maybeRedirect = () => {
5
+ try {
6
+ const { hostname, pathname, search, hash } = window.location
7
+ if (!redirectHostnames.has(hostname)) return
8
+ const target = `https://${canonicalHost}${pathname}${search}${hash}`
9
+ window.location.replace(target)
10
+ } catch {
11
+ // ignore
12
+ }
13
+ }
14
+
15
+ const highlightNav = () => {
16
+ const path = window.location.pathname
17
+ const isDocs = path.includes('/docs/')
18
+ const navDocs = document.querySelector('a[data-nav="docs"]')
19
+ const navHome = document.querySelector('a[data-nav="home"]')
20
+ if (navDocs && isDocs) navDocs.setAttribute('aria-current', 'page')
21
+ if (navHome && !isDocs) navHome.setAttribute('aria-current', 'page')
22
+
23
+ const sideLinks = document.querySelectorAll('.side a[href]')
24
+ for (const a of sideLinks) {
25
+ const href = a.getAttribute('href') ?? ''
26
+ if (!href) continue
27
+ const normalized = href.replace(/^\.\//, '')
28
+ if (path.endsWith(normalized)) a.setAttribute('aria-current', 'page')
29
+ }
30
+ }
31
+
32
+ const wireCopyButtons = () => {
33
+ const buttons = document.querySelectorAll('[data-copy]')
34
+ const handleCopyClick = async (button) => {
35
+ const selector = button.getAttribute('data-copy')
36
+ const target = selector ? document.querySelector(selector) : null
37
+ const text = target?.textContent?.trim() ?? ''
38
+ if (!text) return
39
+ try {
40
+ await navigator.clipboard.writeText(text)
41
+ const prev = button.textContent ?? ''
42
+ button.textContent = 'Copied'
43
+ button.setAttribute('data-copied', '1')
44
+ window.setTimeout(() => {
45
+ button.textContent = prev
46
+ button.removeAttribute('data-copied')
47
+ }, 900)
48
+ } catch {
49
+ // ignore
50
+ }
51
+ }
52
+ for (const button of buttons) {
53
+ button.addEventListener('click', () => {
54
+ void handleCopyClick(button)
55
+ })
56
+ }
57
+ }
58
+
59
+ const reveal = () => {
60
+ const items = document.querySelectorAll('.reveal')
61
+ let i = 0
62
+ for (const el of items) {
63
+ const delay = Math.min(380, i * 70)
64
+ window.setTimeout(() => el.classList.add('is-on'), delay)
65
+ i++
66
+ }
67
+ }
68
+
69
+ maybeRedirect()
70
+ highlightNav()
71
+ wireCopyButtons()
72
+ reveal()
Binary file
Binary file
package/docs/cache.md CHANGED
@@ -21,15 +21,28 @@ Lightweight, CLI-only SQLite cache. Single DB file.
21
21
  - Override: `cache.path` in config.
22
22
  - SQLite pragmas: WAL, NORMAL sync, busy timeout, incremental vacuum.
23
23
 
24
+ ## Media cache (downloads)
25
+
26
+ Separate file cache for downloaded media (yt-dlp, direct media URLs). This is **not** the SQLite DB.
27
+
28
+ - Default path: `~/.summarize/cache/media`
29
+ - TTL: 7 days
30
+ - Size cap: 2048 MB
31
+ - Config: `cache.media` (see below)
32
+ - CLI: `--no-media-cache` disables media caching only
33
+ - Note: `--no-cache` **does not** disable the media cache
34
+
24
35
  ## What we cache
25
36
 
26
37
  - **Transcripts**
27
- - key: `sha256({url, namespace, formatVersion})`
38
+ - key: `sha256({url, namespace, fileMtime?, formatVersion})` (local file paths include `fileMtime` for invalidation)
28
39
  - **Extracted content** (URL → text/markdown)
29
40
  - key: `sha256({url, extractSettings, formatVersion})`
30
41
  - **Summaries**
31
42
  - key: `sha256({contentHash, promptHash, model, length, language, formatVersion})`
32
43
  - cache hit even if URL differs (content hash wins).
44
+ - **Slides** (manifest + on-disk images in the slides output dir)
45
+ - key: `sha256({url, slideSettings, formatVersion})`
33
46
 
34
47
  ## Keys / hashes
35
48
 
@@ -46,7 +59,14 @@ Lightweight, CLI-only SQLite cache. Single DB file.
46
59
  "enabled": true,
47
60
  "maxMb": 512,
48
61
  "ttlDays": 30,
49
- "path": "~/.summarize/cache.sqlite"
62
+ "path": "~/.summarize/cache.sqlite",
63
+ "media": {
64
+ "enabled": true,
65
+ "maxMb": 2048,
66
+ "ttlDays": 7,
67
+ "path": "~/.summarize/cache/media",
68
+ "verify": "size"
69
+ }
50
70
  }
51
71
  }
52
72
  ```
@@ -55,7 +75,7 @@ Defaults: `enabled=true`, `maxMb=512`, `ttlDays=30`, `path` unset.
55
75
 
56
76
  ## CLI flags
57
77
 
58
- - `--no-cache`: bypass read + write.
78
+ - `--no-cache`: bypass summary cache reads + writes (LLM output). Extract/transcript caches still apply.
59
79
  - `--cache-stats`: print cache stats and exit.
60
80
  - `--clear-cache`: delete cache DB (and WAL/SHM); must be used alone.
61
81
 
@@ -65,6 +85,12 @@ Defaults: `enabled=true`, `maxMb=512`, `ttlDays=30`, `path` unset.
65
85
  - Size cap: if DB > `maxMb`, delete oldest entries by `last_accessed_at` until under cap.
66
86
  - Optional count cap if needed later.
67
87
 
88
+ Media cache eviction:
89
+
90
+ - TTL sweep on read/write.
91
+ - Size cap: evict least-recently-used files until under cap.
92
+ - `verify` controls integrity checks: `size` (default), `hash`, or `none`.
93
+
68
94
  ## Notes
69
95
 
70
96
  - No extension cache (daemon uses CLI cache).
@@ -4,7 +4,7 @@ read_when:
4
4
  - "When working on the extension, daemon, or side panel UX."
5
5
  ---
6
6
 
7
- # Chrome Side Panel (Chrome Extension + Daemon)
7
+ # Browser Side Panel (Chrome + Firefox Extension + Daemon)
8
8
 
9
9
  Goal: Chrome **Side Panel** (“real sidebar”) summarizes **what you see** on the current tab. Panel open → navigation → auto summarize (optional) → **streaming** Markdown rendered in-panel.
10
10
 
@@ -14,12 +14,18 @@ Quickstart:
14
14
  - `npm i -g @steipete/summarize`
15
15
  - `brew install steipete/tap/summarize` (macOS arm64)
16
16
  - Build/load extension: `apps/chrome-extension/README.md`
17
+ - Firefox sidebar build: `pnpm -C apps/chrome-extension build:firefox` (load via `about:debugging` → temporary add-on)
17
18
  - Open side panel → copy token install command → run:
18
19
  - `summarize daemon install --token <TOKEN>` (macOS: LaunchAgent, Linux: systemd user, Windows: Scheduled Task)
19
20
  - Verify:
20
21
  - `summarize daemon status`
21
22
  - Restart (if needed): `summarize daemon restart`
22
23
 
24
+ Firefox notes:
25
+ - Sidebar UX differs from Chrome’s side panel (persistent sidebar instead of slide-in panel).
26
+ - Firefox testing is limited in Playwright; see `apps/chrome-extension/tests/README-firefox.md`.
27
+ - Compatibility details: `apps/chrome-extension/docs/firefox.md`.
28
+
23
29
  Dev (repo checkout):
24
30
 
25
31
  - Use: `pnpm summarize daemon install --token <TOKEN> --dev` (autostart service runs `src/cli.ts` via `tsx`, no `dist/` build required).
@@ -32,12 +38,23 @@ Dev (repo checkout):
32
38
  - “Daemon not reachable”:
33
39
  - `summarize daemon status`
34
40
  - Logs: `~/.summarize/logs/daemon.err.log`
41
+ - “Need extension-side traces”:
42
+ - Options → Logs → `extension.log` (panel/background events).
43
+ - Enable “Extended logging” in Advanced settings for full pipeline traces.
44
+ - “Stream ended unexpectedly” / empty chat response:
45
+ - The daemon likely stopped mid-stream. Restart it, then click “Try again”.
46
+ - `summarize daemon restart`
35
47
  - Tweet video not transcribing / no progress:
36
48
  - Ensure `yt-dlp` is available on your PATH (or set `YT_DLP_PATH`) and you have a transcription provider (`whisper.cpp` installed or `OPENAI_API_KEY` / `FAL_KEY`).
37
49
  - Re-run `summarize daemon install --token <TOKEN>` to refresh the daemon env snapshot (launchd won’t inherit your shell PATH).
38
50
  - “Could not establish connection / Receiving end does not exist”:
39
51
  - The content script wasn’t injected (yet), or Chrome blocked site access.
40
52
  - Chrome → extension details → “Site access” → “On all sites” (or allow the domain), then reload the tab.
53
+ - “<site> wants to look for and connect to any device on your local network”:
54
+ - Trigger: content scripts (page context) hitting the daemon on `http://127.0.0.1:8787` (hover summaries) can cause Chrome to attribute the request to the current origin and prompt per-site.
55
+ - Fix: hover summaries must proxy daemon calls via the extension background service worker (reload the extension after updating).
56
+ - Verify daemon: `summarize daemon status` (or `curl http://127.0.0.1:8787/health`).
57
+ - Repro/dev: `pnpm -C apps/chrome-extension dev` then enable “Hover summaries” and hover a link.
41
58
 
42
59
  ## Architecture
43
60
 
@@ -73,6 +90,18 @@ The daemon decides the best pipeline:
73
90
  - Normal articles with extracted text → prefer **page** pipeline (“what you see”).
74
91
  - Fallback: if the preferred path fails before output starts, try the other input (when available).
75
92
 
93
+ ## Video Selection (Page vs Video)
94
+
95
+ When the page contains embedded audio/video, the Summarize button gains a dropdown caret. Click the caret to pick Page vs Video/Audio. Selecting Video/Audio forces URL mode with transcript-first extraction (captions → yt-dlp/Whisper fallback). Selection is per-run (not persisted).
96
+
97
+ See `docs/media.md` for detection and transcript rules.
98
+
99
+ ## Slides (Side Panel)
100
+
101
+ - The slides toggle lights up on media-friendly URLs (YouTube/watch|shorts, youtu.be, direct media) or when the page reports video/audio. Defaults to Video on those pages.
102
+ - Turning slides **on** refreshes the current summary and requests slide extraction (`yt-dlp`, `ffmpeg`). OCR text is opt-in (Advanced setting) and requires `tesseract`. Missing tools surface a footer notice with install instructions; restart the daemon after installing.
103
+ - Slides stay off elsewhere and the toggle is disabled on non-media pages.
104
+
76
105
  ## SPA Navigation
77
106
 
78
107
  - Background listens to `chrome.webNavigation.onHistoryStateUpdated` (SPA route changes) and `tabs.onUpdated` (page loads).
@@ -85,23 +114,36 @@ The daemon decides the best pipeline:
85
114
  - `linkify: true`.
86
115
  - Render links with `target=_blank` + `rel=noopener noreferrer`.
87
116
 
117
+ ## Timestamp Links (Chat)
118
+
119
+ - When timed transcripts are available, chat context includes `[mm:ss]` lines.
120
+ - Assistant is prompted to cite timestamps; clicking them seeks the current media (video/audio) while preserving play/pause state.
121
+
88
122
  ## Model Selection UX
89
123
 
90
124
  - Settings:
91
125
  - Model preset (Options → Advanced): `auto` | `free` | custom string (e.g. `openai/gpt-5-mini`, `openrouter/...`).
92
- - Length: `short|medium|long|xl|xxl` (or a character target like `20k`).
126
+ - Length: `short|medium|long|xl|xxl` (or a character target like `20k`). Tooltips show target ranges + paragraph guidance (from `packages/core/src/prompts/summary-lengths.ts`).
93
127
  - Language: `auto` (match source) or a tag like `en`, `de`, `pt-BR` (or free-form like “German”).
94
128
  - Prompt override (advanced): custom instruction prefix (context + content still appended).
95
129
  - Auto summarize: on/off.
130
+ - Hover summaries: on/off (side panel drawer, default off).
96
131
  - Typography: font family (dropdown + custom), font size (slider).
97
- - Advanced overrides (collapsed by default; click the section title to expand).
132
+ - Advanced overrides (Options Advanced tab).
98
133
  - Leave blank to use daemon config/defaults; set a value to override.
134
+ - Chat (advanced): enable/disable the side panel chat input (default on; summary is the first message).
135
+ - Summary timestamps (advanced): include `[mm:ss]` links in summaries for media when available (default on).
136
+ - Slides parallel (advanced): show summary first and extract slides in parallel (default on).
137
+ - Slides OCR text (advanced): allow OCR text as a slide text source (default off).
138
+ - Extended logging: send full input/output to daemon logs (requires daemon logging enabled).
139
+ - Hover summary prompt: customize the prompt used for link hover summaries (prefilled; reset to default).
99
140
  - Pipeline mode: `page|url` (default auto).
100
141
  - Firecrawl: `off|auto|always`.
101
142
  - Markdown mode: `readability|llm|auto|off`.
102
- - Preprocess: `off|auto|always`.
103
- - YouTube mode: `no-auto|yt-dlp|web|apify` (default auto).
104
- - Timeout (e.g. `90s`, `2m`), retries, max output tokens (e.g. `2k`).
143
+ - Preprocess: `off|auto|always`.
144
+ - YouTube mode: `no-auto|yt-dlp|web|apify` (default auto).
145
+ - Timeout (e.g. `90s`, `2m`), retries, max output tokens (e.g. `2k`).
146
+ - Process manager: live list of daemon-spawned tools (ffmpeg, yt-dlp, tesseract, etc.) with logs.
105
147
  - Extension includes current settings in request; daemon treats them like CLI flags (`--model`, `--length`, `--language`, `--prompt`).
106
148
 
107
149
  ## Token Pairing / Setup Mode
@@ -134,10 +176,46 @@ Problem: daemon must be secured; extension must discover and pair with it.
134
176
  - `language?: string` (e.g. `auto`, `en`, `de`, `pt-BR`)
135
177
  - `prompt?: string` (custom instruction prefix)
136
178
  - `mode?: "auto" | "page" | "url"` (default: `"auto"`)
137
- - `maxCharacters?: number | null` (caps URL-mode extraction before summarization)
179
+ - `maxCharacters?: number | null` (caps URL-mode extraction before summarization; ignored for extract-only unless explicitly provided)
180
+ - `format?: "text" | "markdown"` (default: `"text"`)
181
+ - `markdownMode?: "readability" | "auto" | "llm" | "off"` (only when `format: "markdown"`)
182
+ - `preprocess?: "off" | "auto" | "always"` (markitdown/HTML preprocess)
183
+ - `extractOnly?: boolean` (when `true`, returns extracted content without summarizing; requires `mode: "url"`)
138
184
  - `text?: string` (required for `mode: "page"`; optional for `auto`)
139
185
  - `truncated?: boolean` (optional; indicates extracted `text` was shortened)
140
186
  - 200 JSON: `{ ok: true, id }`
187
+ - `GET /v1/summarize/<id>/slides/events`
188
+ - Headers: `Authorization: Bearer <token>`
189
+ - SSE stream of slide updates (`slides`, `status`, `done`, `error`) independent of summary stream.
190
+ - `POST /v1/agent` (SSE by default; JSON via `Accept: application/json` or `?format=json`)
191
+ - Headers: `Authorization: Bearer <token>`
192
+ - Body:
193
+ - `url: string` (required)
194
+ - `title?: string | null`
195
+ - `pageContent: string`
196
+ - `cacheContent?: string` (used for cache key; defaults to `pageContent`)
197
+ - `messages: Array<Message>` (pi-ai format)
198
+ - `model?: string`
199
+ - `length?: string` (e.g. `short`, `xl`, `20k`)
200
+ - `language?: string` (e.g. `auto`, `en`, `de`)
201
+ - `tools?: string[]`
202
+ - `automationEnabled?: boolean`
203
+ - SSE events:
204
+ - `event: chunk` `data: { text }`
205
+ - `event: assistant` `data: { ...assistant }`
206
+ - `event: done` `data: {}`
207
+ - `event: error` `data: { message }`
208
+ - `POST /v1/agent/history`
209
+ - Headers: `Authorization: Bearer <token>`
210
+ - Body:
211
+ - `url: string` (required)
212
+ - `pageContent: string`
213
+ - `cacheContent?: string` (used for cache key; defaults to `pageContent`)
214
+ - `model?: string`
215
+ - `length?: string`
216
+ - `language?: string`
217
+ - `automationEnabled?: boolean`
218
+ - 200 JSON: `{ ok: true, messages }`
141
219
  - `GET /v1/summarize/:id/events` (SSE)
142
220
  - `event: chunk` `data: { text }`
143
221
  - `event: meta` `data: { model }`
package/docs/config.md CHANGED
@@ -36,6 +36,13 @@ For prompt:
36
36
  1. CLI flag `--prompt` / `--prompt-file`
37
37
  2. Config file `prompt`
38
38
  3. Built-in default prompt
39
+
40
+ For UI theme:
41
+
42
+ 1. CLI flag `--theme`
43
+ 2. Env `SUMMARIZE_THEME`
44
+ 3. Config file `ui.theme`
45
+ 4. Built-in default (`aurora`)
39
46
  ## Format
40
47
 
41
48
  `~/.summarize/config.json`:
@@ -44,7 +51,8 @@ For prompt:
44
51
  {
45
52
  "model": { "id": "google/gemini-3-flash-preview" },
46
53
  "output": { "language": "auto" },
47
- "prompt": "Explain like I am five."
54
+ "prompt": "Explain like I am five.",
55
+ "ui": { "theme": "ember" }
48
56
  }
49
57
  ```
50
58
 
@@ -94,11 +102,75 @@ Configure the on-disk SQLite cache (extracted content, transcripts, summaries).
94
102
  "enabled": true,
95
103
  "maxMb": 512,
96
104
  "ttlDays": 30,
97
- "path": "~/.summarize/cache.sqlite"
105
+ "path": "~/.summarize/cache.sqlite",
106
+ "media": {
107
+ "enabled": true,
108
+ "maxMb": 2048,
109
+ "ttlDays": 7,
110
+ "path": "~/.summarize/cache/media",
111
+ "verify": "size"
112
+ }
113
+ }
114
+ }
115
+ ```
116
+
117
+ Notes:
118
+
119
+ - `cache.media` controls the **media file** cache (yt-dlp downloads).
120
+ - `--no-cache` bypasses summary caching only (LLM output); extract/transcript caches still apply. Use `--no-media-cache` for media.
121
+ - `verify`: `size` (default), `hash`, or `none`.
122
+
123
+ ## UI theme
124
+
125
+ Set a default CLI theme:
126
+
127
+ ```json
128
+ {
129
+ "ui": { "theme": "moss" }
130
+ }
131
+ ```
132
+
133
+ ## Slides defaults
134
+
135
+ Enable slides by default and tune extraction parameters:
136
+
137
+ ```json
138
+ {
139
+ "slides": {
140
+ "enabled": true,
141
+ "ocr": false,
142
+ "dir": "slides",
143
+ "sceneThreshold": 0.3,
144
+ "max": 20,
145
+ "minDuration": 2
98
146
  }
99
147
  }
100
148
  ```
101
149
 
150
+ ## Logging (daemon)
151
+
152
+ Enable JSON log files for the daemon:
153
+
154
+ ```json
155
+ {
156
+ "logging": {
157
+ "enabled": true,
158
+ "level": "info",
159
+ "format": "json",
160
+ "file": "~/.summarize/logs/daemon.jsonl",
161
+ "maxMb": 10,
162
+ "maxFiles": 3
163
+ }
164
+ }
165
+ ```
166
+
167
+ Notes:
168
+
169
+ - Default: logging is off.
170
+ - `format`: `json` (default) or `pretty`.
171
+ - `maxMb` is per file; `maxFiles` controls rotation (ring).
172
+ - Extension “Extended logging” sends full input/output to daemon logs (large). Cache hits skip content logging.
173
+
102
174
  ## Presets
103
175
 
104
176
  Define presets you can select via `--model <preset>`:
@@ -13,13 +13,21 @@ Deprecated alias: `--extract-only`.
13
13
  ## Notes
14
14
 
15
15
  - No summarization LLM call happens in this mode.
16
- - `--format md` may still convert HTML Markdown (depending on `--markdown-mode` and available tools).
16
+ - No extraction cap is applied. Use `--max-extract-characters <count>` to cap output if needed.
17
+ - `--format md` may still convert HTML to Markdown (depending on `--markdown-mode` and available tools).
17
18
  - `--length` is intended for summarization guidance; extraction prints full content.
19
+ - `--timestamps` keeps the plain transcript text but also exposes `transcriptSegments` and `transcriptTimedText` (JSON) and prints a timed transcript block when available.
20
+ - `--slides` runs slide detection (YouTube/direct video URLs). Slide metadata is included in JSON output and written to `slides.json` in the slide directory.
21
+ - When combined with `--extract` for videos that have timed transcripts, the CLI interleaves slide images inline at matching timestamps.
22
+ - Scene detection auto-tunes using sampled frame hashes.
18
23
  - For non-YouTube URLs with `--format md`, the CLI uses Readability article HTML as the default Markdown input (`--markdown-mode readability`).
19
24
  - Use `--markdown-mode auto` to prefer LLM/markitdown conversion without Readability preprocessing.
20
25
  - Use `--markdown-mode llm` to force an LLM conversion.
21
26
  - Use `--firecrawl always` to try Firecrawl first.
22
- - For non-YouTube URLs with `--format md`, `--markdown-mode auto` can convert HTML Markdown via an LLM when configured.
27
+ - For non-YouTube URLs with `--format md`, `--markdown-mode auto` can convert HTML to Markdown via an LLM when configured.
23
28
  - Force it with `--markdown-mode llm`.
24
29
  - If no LLM is configured, `--markdown-mode auto` may fall back to `uvx markitdown` when available.
25
30
  - `--markdown-mode readability` uses Readability to extract article HTML before Markdown conversion.
31
+
32
+ Daemon note:
33
+ - `/v1/summarize` supports `format: "markdown"` + `markdownMode` for extract-only output (use `extractOnly: true`).
@@ -0,0 +1,205 @@
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>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
+ />
12
+ <link rel="canonical" href="https://summarize.sh/" />
13
+ <meta property="og:title" content="summarize" />
14
+ <meta property="og:description" content="Fast summaries, in the CLI and the Chrome Side Panel." />
15
+ <meta property="og:type" content="website" />
16
+ <meta property="og:url" content="https://summarize.sh/" />
17
+ <meta name="theme-color" content="#0b0f12" />
18
+
19
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
20
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
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
+ />
25
+ <link rel="stylesheet" href="./assets/site.css" />
26
+ </head>
27
+ <body>
28
+ <main class="shell">
29
+ <header class="top">
30
+ <a class="brand" href="./index.html" aria-label="summarize home">
31
+ <span class="brand__mark" aria-hidden="true">s</span>
32
+ <span class="brand__word">summarize</span>
33
+ </a>
34
+ <nav class="nav" aria-label="Primary">
35
+ <a data-nav="home" href="./index.html">Home</a>
36
+ <a data-nav="docs" href="./docs/index.html">Docs</a>
37
+ <a href="https://github.com/steipete/summarize">GitHub</a>
38
+ </nav>
39
+ </header>
40
+
41
+ <section class="hero">
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>
60
+ </div>
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>
64
+ </div>
65
+ </div>
66
+ </div>
67
+
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>
80
+
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>
106
+
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>
111
+ </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>
129
+ </section>
130
+
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>
136
+ </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>
141
+ </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>
146
+ </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>
151
+ </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>
180
+ </div>
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>
193
+ </div>
194
+ </div>
195
+ </section>
196
+
197
+ <footer class="footer">
198
+ <span>Canonical: <a href="https://summarize.sh">summarize.sh</a></span>
199
+ <span><a href="./docs/index.html">Docs</a> · <a href="https://github.com/steipete/summarize">GitHub</a></span>
200
+ </footer>
201
+ </main>
202
+
203
+ <script type="module" src="./assets/site.js"></script>
204
+ </body>
205
+ </html>
package/docs/index.md ADDED
@@ -0,0 +1,25 @@
1
+ ---
2
+ summary: "Docs index for summarize behaviors and modes."
3
+ ---
4
+
5
+ # Docs
6
+
7
+ - [Chrome extension](chrome-extension.md)
8
+ - [Cache](cache.md)
9
+ - [CLI](cli.md)
10
+ - [Config](config.md)
11
+ - [Extract](extract-only.md)
12
+ - [Firecrawl](firecrawl.md)
13
+ - [Language](language.md)
14
+ - [LLM](llm.md)
15
+ - [Manual tests](manual-tests.md)
16
+ - [Model auto](model-auto.md)
17
+ - [OpenAI](openai.md)
18
+ - [Releasing](releasing.md)
19
+ - [Smoke test](smoketest.md)
20
+ - [Website](website.md)
21
+ - [YouTube](youtube.md)
22
+
23
+ ## Website
24
+
25
+ - Jekyll site source: `docs/` (Markdown → HTML via GitHub Pages Actions)