CLI tool
steipete/summarize avatar
steipete/summarize

Summarize pulls clean text out of a URL, then hands the summary to a provider you configure

Point at any URL/YouTube/Podcast or file. Get the gist. CLI and Chrome Extension.

6,808 stars454 forksTypeScriptMIT

At a glance

What is it?
Summarize is a TypeScript CLI plus a Chrome and Firefox side panel that extracts readable text from pages, files, YouTube and podcasts, then summarizes it with a provider you configure yourself. Extraction runs without an API key, summaries do not.
Who is it for?
Summarize fits a developer who already holds a model provider key and wants the extraction step under their own control. A reader who wants a summary from a pasted link with nothing to configure will stop at extracted text, because every model path needs a provider or an authenticated coding CLI.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • steipete/summarize6,808 ★ · +304
Star history
Repository2026-08-022026-11-14
steipete/summarize6.5k6.8k

304 Stars in the last 104 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Node.js 24 is the floor for the npm package

The fastest way to see the tool is to run it once without installing anything, which is the first option in the README. The npm package requires Node.js 24 or newer, so this doubles as a version check:

bash
npx -y @steipete/summarize --version

If that floor is a problem, Homebrew/core and the macOS archives on GitHub Releases ship standalone builds, so Node.js is not involved at all:

bash
brew install summarize

A permanent install through npm goes under the global prefix:

bash
npm install --global @steipete/summarize

The first real run extracts readable text from a URL and prints it plain, with no API key involved:

bash
summarize "https://example.com" --extract --plain

What that command cannot tell you is whether extraction is any good on the pages you actually care about. example.com is a documentation placeholder that resolves to a short page about reserved domains, so a clean result there says nothing about a JavaScript dashboard, a paywalled article, or a docs site built as a single page app. Run it on your own URLs before you script anything around the output. Optional media tools and per-platform notes live in docs/install.md rather than in the install section.

Readability first, with Markdown and Firecrawl behind it

Web pages take the readability path, with two named fallbacks behind it: Markdown extraction and Firecrawl. That ordering is the mechanism worth understanding, and it is also the first place expectations break. Both fallbacks are described as optional. `--extract` returns clean content and needs no key. `--json` puts the same result into a stable automation envelope, which is the form to script against rather than the plain text.

The table of input types reads as a routing chart. PDFs, images and text files go through file-aware extraction with model attachments where supported. YouTube and podcasts take published transcripts first, then fall back to transcription you have configured. Audio and video take local or cloud transcription, with optional speaker labels. Video slides take scene-based frames, optional OCR and timestamped output.

So every input has two paths: the default one that needs nothing configured, and a deeper one that needs a provider or a local model and can fail somewhere else entirely. The README does not say how often readability fails on a given site, so fallback behavior is something you discover by trying rather than by reading.

The auto model only chooses among providers you configured

Model IDs are written as `provider/model`. Summarize works with configured API providers, OpenAI-compatible endpoints, Ollama, OpenRouter free models, and authenticated coding CLIs such as Codex, Claude, Gemini, OpenClaw, GitHub Copilot and Grok. The default `auto` model picks among the ones present in your own configuration, which means the selection rules cannot help you on a machine where nothing is configured yet.

An already authenticated coding CLI is the shortest route to a real summary:

bash
summarize "https://example.com" --cli codex

Configuration lives at `~/.summarize/config.json`, and command-line flags take precedence over it. To see what a run would resolve to without printing keys:

bash
summarize status

Here is the boundary worth stating plainly. With no provider key and no authenticated CLI, every summary path ends at extracted text and `--extract` becomes the whole tool. The other route, a hosted summarizing site, holds the provider keys for you and hands back finished text in a browser tab. Summarize keeps the choice and the key in your own configuration instead, and charges you the setup step for that. Selection rules, the provider guide and the configuration reference are three separate documents: docs/model-auto.md, docs/cli.md and docs/config.md.

Fourteen interface languages and a separate output language

The CLI and the extension ship fourteen interface languages: English, German, French, Spanish, Italian, Brazilian Portuguese, Dutch, Polish, Russian, Japanese, Simplified Chinese, Traditional Chinese, Korean and Turkish. The interface follows your system or browser language, with English as the fallback.

The two language settings are separate, and that is where people get stuck. `--locale` sets the CLI's own help and progress text, while `--language` sets what the summary comes back in:

bash
summarize "https://example.com" --locale de --language japanese

The interface choice also has an environment variable form, `SUMMARIZE_LOCALE=de`, which is what you want in a container or CI job with no system locale to follow. In the extension the equivalent control is an option named Interface language.

Adding a language is a catalog change rather than a flag change. docs/localization.md covers locale selection, translation glossaries, adding languages, and the CI checks that keep catalogs complete. Those checks run as part of `pnpm check`, which the package manifest defines as formatting, the localization check, linting, typecheck and coverage tests. A half-finished language therefore fails the repository's own gate instead of shipping quietly, but it also means the language list above is the list of intended catalogs rather than a promise about every runtime string.

Direct mode, the pairing daemon, and what Firefox loses

The browser extension is called Summarize Side Panel. It summarizes the active tab, chats with the page content, and works with video transcripts and slides. Its architecture has two modes, and the difference decides what you install on a work machine.

Direct mode runs with no companion service at all. Browser media then uses Chrome's own capabilities for local transcription and slide extraction. The optional daemon adds CLI model backends, native media tools, OCR, shared caches and Firefox media support. Pairing an already installed CLI to the extension means copying the token the extension shows you and running:

bash
summarize daemon install --token <TOKEN>

So the honest answer to why Firefox behaves differently is that the extension is available in a Firefox sidebar, yet its media path depends on the daemon, while on Chrome the same work runs directly in the browser. Direct mode is the smaller deployment and covers the Chrome media cases. The daemon is what makes OCR, native media tools and a shared cache available, and the daemon is also a process you have to run and keep running.

Treat that as the real cost: there is no single install that covers every browser and every input type in the table. The extension's own setup notes are in apps/chrome-extension/README.md, and docs/chrome-extension.md covers architecture and troubleshooting.

Native ffmpeg, yt-dlp and tesseract, or the bundled FFmpeg

Media and slides carry the largest dependency footprint, and the order of preference is explicit. Summarize looks for existing captions and podcast transcripts before it transcribes anything, so a podcast with a good transcript never reaches a transcription model at all. That ordering is both the cheapest path and the one that will surprise you, because transcript quality then belongs to whoever published the media.

Past that point, native `ffmpeg`, `yt-dlp` and `tesseract` extend codec support, YouTube slide extraction and OCR respectively. A bundled WebAssembly FFmpeg path covers common media with no native install at all. The trade is coverage against setup: the WebAssembly path needs nothing on the machine, while the native tools widen the set of codecs, sources and OCR you can handle. `--slides` produces video frames, and `--extract` returns clean content.

The docs split this into four focused files rather than one page: docs/youtube.md, docs/media.md, docs/slides.md and docs/nvidia-onnx-transcription.md. That last file covers local ONNX transcription, which is the path for running transcription outside a cloud service.

The core package exports three entry points, not a command

For programmatic work there is a second package, `@steipete/summarize-core`, described as the route to extraction without the CLI dependency surface:

bash
npm install @steipete/summarize-core

The exports block shown in the repository's root package.json, for the main @steipete/summarize package, publishes three entry points alongside its binaries. Each subpath carries its own types file and its own ESM build:

json
"exports": {
  ".": {
    "import": "./dist/esm/index.js"
  },
  "./content": {
    "import": "./dist/esm/content/index.js"
  },
  "./prompts": {
    "import": "./dist/esm/prompts/index.js"
  }
}

The split matters for dependency hygiene. Content and prompts are separate subpaths, so a consumer that only wants extraction does not have to import the prompt layer. What the top-level README does not give you is the API itself: it points at packages/core/README.md for usage and describes the exports only as focused content and prompt entry points. If you are embedding this, that file is the contract to read before you write the first import.

A pnpm workspace releasing every few days

The main package maps two binary names onto one file, which is worth knowing before you write a script that assumes a single command name:

json
"bin": {
  "summarize": "./dist/cli.js",
  "summarizer": "./dist/cli.js"
}

The repository is a pnpm workspace with `apps/`, `packages/`, `patches/`, `docs/`, `completions/` and `tests/` at the top level, plus a `Dockerfile.test`. Development needs Node.js 24 and the workspace's pinned pnpm through Corepack:

bash
pnpm install --frozen-lockfile

followed by `pnpm build` and `pnpm check`. The build script chains a clean, the core package build, the library build and the CLI build, so `pnpm build` always runs all four steps.

Two limits worth naming. The version numbers are pre-1.0 and moving quickly: v0.25.1 on 2026-10-04, v0.25.2 on 2026-10-11 and v0.25.3 on 2026-10-21, three releases in seventeen days, with the last push on 2026-10-28. CHANGELOG.md and RELEASING.md are both in the repository root, so the detail exists; the cost is that pinning a version in automation matters more than it would at 1.0. The licence is MIT.

Editorial conclusion

Summarize fits a developer who already holds a model provider key and wants the extraction step under their own control. A reader who wants a summary from a pasted link with nothing to configure will stop at extracted text, because every model path needs a provider or an authenticated coding CLI. Before adopting it, check the Node.js 24 floor on every machine that will run it, decide whether your media work needs native ffmpeg, yt-dlp and tesseract installed, and read docs/install.md before promising support for any platform the install options do not name.

Frequently asked questions

What does Summarize need before it can produce a model summary?

Extraction needs no API key: `summarize "https://example.com" --extract --plain` returns clean text with no key. A model summary needs a configured provider or an already authenticated coding CLI, which is what the `--cli codex` form uses. Without either, every summary path stops at extracted text.

What are Summarize's install options?

The README names three routes. npx and npm both go through the package, which requires Node.js 24 or newer, and Homebrew and the macOS archives on GitHub Releases provide standalone builds with no Node.js involved. Platform-specific notes are in docs/install.md rather than in the install section.

Why does Summarize need its daemon for media on Firefox?

Direct mode runs with no companion service and uses Chrome's own capabilities for local transcription and slide extraction. The optional daemon is what adds CLI model backends, native media tools, OCR, shared caches and Firefox media support, so on Firefox that media path depends on it. Pairing an installed CLI means running `summarize daemon install` with the token the extension displays.

How does Summarize handle a video or a podcast?

It prefers published captions and podcast transcripts before it transcribes anything, then falls back to transcription you have configured. Native ffmpeg, yt-dlp and tesseract extend codec, YouTube slide and OCR support, while a bundled WebAssembly FFmpeg path covers common media with no native install. docs/nvidia-onnx-transcription.md covers local transcription.

Can Summarize write its summary in a different language from its interface?

Yes, and the two are separate settings. `--locale de` sets the CLI's own help and progress text, `--language japanese` sets the output language, and `SUMMARIZE_LOCALE=de` is the environment variable form for the interface. Fourteen interface languages are listed, with English as the fallback.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/steipete-summarize.svg)](https://hysenlabs.com/projects/steipete-summarize)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/steipete-summarize.svg)](https://hysenlabs.com/projects/steipete-summarize)

Was this useful?