andronaft/Logbeam

Chrome extension for developers & platform engineers: readable logs, dark mode everywhere, and one-click JSON / JWT / Base64 / timestamp tools. 100% local, no data leaves your browser.

TypeScript

2

27 commits

updated Oct 16, 2026

See the code

README

Logbeam logo

Logbeam

Make logs readable again.

Chrome Web Store version Chrome Web Store users Chrome Web Store rating Firefox Add-ons version CI Manifest V3 TypeScript MIT

A browser extension for Chrome and Firefox, for developers and platform engineers: a fast log viewer that also catches leaked secrets, dark mode for any site, and the text tools you keep opening random websites for (JSON, JWT, Base64, timestamps, cron). All of it runs locally; no data leaves your browser.

➜ Add to Chrome  ·  ➜ Add to Firefox  — free

Logbeam: a raw log opened in the viewer, next error, a field filter, p95 latency, and the new errors between two CI runs

Features

🔦 Log viewer

Open any raw log (a .log file, "View raw logs" in GitHub Actions, Jenkins console output, kubectl logs piped to a file…) with Ctrl+Shift+L (⌃⇧L on Mac) or from the popup:

  • Levels in colour (ERROR, WARN, INFO, DEBUG, TRACE) with counters and one-click filters
  • Stack traces stay with their error: Java at … / Caused by:, Python tracebacks and Go goroutines are grouped with the entry above, so filtering by ERROR shows the whole trace
  • Search as plain text or regex, case-sensitive if you like, with highlighted matches
  • JSON logs (Logback/Logstash, pino, bunyan, zap…) shown as time LEVEL message {fields}, including records pretty-printed over several lines
  • Filter by fields: level=error service=payments duration>500, on JSON logs and key=value lines alike, with !=, >, <, * wildcards, nested paths (http.status>=500) and units (duration>1.5s)
  • Time range: drag across the timeline to keep only the entries from that time
  • Highlights: press Enter in the search box to keep a term highlighted in its own colour (up to five)
  • Pods and containers: kubectl logs --prefix and docker compose logs get a coloured chip per pod
  • Pasted text and files: open a log pasted into the popup, or a .log / .gz file (unpacked in the browser); drop a file onto any viewer to open it
  • Save the visible lines as a file
  • Bookmarks and notes (m, b): Report copies them as Markdown for a ticket, with times and links
  • Field statistics: the most common values of a field (status: 200 ×1520, 502 ×37), one click to filter; for numbers and durations also min, median, p95, p99 and max (took: p95 1.2s), one click to see the slow ones
  • Error groups: each different error once, with its count, pods and first and last time
  • Follow a log that is still being written: new lines are added every 3 seconds
  • JSON table with the columns you choose, and local time instead of UTC
  • ANSI colours from CI and Docker logs, your own level words (ALERT → ERROR), and a light theme
  • Compare this log with another one, e.g. a passing and a failing CI run, with the new errors listed first (see below)
  • Pauses between entries: +5.5s next to lines where the app stalled
  • Collapse repeats: 500 × retry 17 of 50 for job 8123 becomes one line with a ×500 badge
  • Error timeline: a histogram of entries, errors and warnings over time; click a bar to jump there
  • Line inspector: click a line to read it in full, with its time, pause and, for JSON records, all fields
  • Links to lines: click a line number to copy a #L120 link that opens the viewer right on that line
  • Next error (e), search (/), copy visible lines, back to raw; ? lists all the keys
  • Open automatically on sites you choose (opt-in per site, only plain-text pages that look like logs)
  • Fast on 150k+ lines: logs over 1 MB are parsed in a Web Worker with a progress bar, and only the rows on screen are in the DOM

Only errors and warnings, repeated retries collapsed

Two highlights in their own colours

JSON log as a table, with bookmarks

🔑 Secret detection

Credentials in logs are how leaks start. Logbeam marks every line that shows one: AWS keys, GitHub, GitLab, Slack and Stripe tokens, Google API keys, JWTs, private keys, postgres://user:password@… URLs and password=… / "apiKey": "…" settings (placeholders like ${DB_PASSWORD} are ignored).

  • 🔑 next to the line and the value highlighted; s jumps to the next one
  • Mask hides the values on screen and in everything you copy: AKIA****************
  • Mask secrets in the right-click menu cleans up any selected text or input before you paste it into a chat

A leaked AWS key found, masked, and shown in the line inspector

🌙 Dark mode for any site

Toggle it from the popup or with Ctrl+Shift+K (⌃⇧K on Mac). Pages that already have a dark theme are detected and left alone, and turning it off never reloads the page. "Remember for this site" asks for access to that one site only, and from then on the dark theme is applied before the page paints, so there's no white flash. Photos and videos keep their real colours.

🧰 Text tools

Select text on any page → right-click → Logbeam, or paste it into the popup:

ToolExample
Mask secretspassword=hunter2hunter2 → password=********
Format / minify JSON{"a":1} → pretty-printed, or back to one line
Decode JWTheader, payload, iat/exp as dates, "valid for another 59m" / "EXPIRED 3h ago"
Base64 encode / decodeUTF-8 safe, understands URL-safe Base64 without padding
URL encode / decodea b&c ⇄ a%20b%26c
Timestamp ⇄ date1700000000 → 2023-11-14T22:13:20Z, and back
Explain cron0 */15 * * * * → "Every 15 minutes"; catches */900 in the seconds field
Case conversionuserProfileId ⇄ user_profile_id ⇄ user-profile-id ⇄ USER_PROFILE_ID
Sort / de-duplicate lines

In an input, textarea or rich editor, Replace selection writes the result back in place (undo works).

Decoding a JWT from the page Popup with dark mode and text tools

⚖️ Compare

Open Compare from the popup, or use Compare… in the right-click menu (or the log viewer's Compare button) on one text and then on the other:

  • Logs: a line diff with the changed words marked and unchanged parts folded. Ignore timestamps, IDs and durations lines up two runs of the same job, so 2026-10-03T09:00:20Z Tests: 120 passed against 2026-10-04T11:30:20Z Tests: 119 passed, 1 failed shows only the test result as changed
  • New errors: above the diff, the errors that the second run has and the first one doesn't (and those that are gone), matched by message and stack with times and IDs ignored; click one to jump to it
  • JSON: compared by key, so key order doesn't matter, with a list of changed paths ($.env.LOG_LEVEL, $.ports[1]) and exact comparison of numbers too big for JavaScript (12345678901234567890)
  • Open or drop files, swap sides, ignore whitespace, mask secrets in the output

Compare lists the errors that are new in the failing CI run

Privacy and permissions

Logbeam has no server and no analytics, and it makes no network requests.

PermissionWhy
activeTab, scriptingRun the log viewer or a text tool on the tab you clicked, only when you ask
contextMenusThe right-click menu
storageRemember your per-site settings
optional host access, per siteOnly when you turn on "Remember dark mode" or "Open logs automatically" for a site, and only for that site

Logbeam never asks for access to all sites up front. See the privacy policy.

Install

From the Chrome Web Store: Logbeam on the Chrome Web Store, one click and it updates itself. Works in Chrome, Edge, Brave, Opera and other Chromium browsers. From Firefox Add-ons: Logbeam on addons.mozilla.org (Firefox 140 or newer). The dark-mode shortcut there is Ctrl+Shift+., because Ctrl+Shift+K opens Firefox's Web Console.

From source:

npm ci
npm run build

Then open chrome://extensions, turn on Developer mode, click Load unpacked and choose the dist/ folder. To open local file:// logs, also enable Allow access to file URLs on the extension's details page.

In Firefox, open about:debugging#/runtime/this-firefox, click Load Temporary Add-on and pick dist-firefox/manifest.json.

Development

npm run watch         # rebuild on change, then press ↻ on chrome://extensions
npm test              # unit tests (Vitest)
npm run e2e           # load the extension into Chromium with Playwright, click through it, save docs/*.png
npm run e2e:firefox   # the same for the Firefox build, with Selenium (needs Firefox and geckodriver)
npm run lint:firefox  # the checks addons.mozilla.org runs on upload
npm run check         # lint + format + typecheck + unit tests + build (what CI runs)
npm run package       # logbeam-<version>.zip (Chrome), logbeam-firefox-<version>.zip, sources for AMO
npm run store-assets  # Chrome Web Store screenshots and promo tiles from docs/*.png
npm run demo-gif      # docs/demo.gif for this README, recorded in Chromium
npm run icons         # regenerate the PNG icons (drawn in code, no image editor needed)

Releases: bump the version, add a CHANGELOG.md entry and push a vX.Y.Z tag. The release workflow runs every check including the end-to-end test, attaches the ZIPs to a GitHub Release, and uploads them to the Chrome Web Store and addons.mozilla.org for review (it can also be started from the Actions tab). Setup and details: docs/PUBLISHING.md.

src/
├── background.ts        service worker: context menu, keyboard shortcuts, permission events
├── content/
│   ├── logViewer.ts     virtualized log viewer: filters, inspector, timeline, secrets, bookmarks, #L links
│   ├── viewerStyles.ts  its CSS, dark and light
│   ├── shortcuts.ts     the ? list of keys
│   ├── parseAsync.ts    Web Worker parsing with a chunked main-thread fallback
│   ├── parseWorker.ts   the parse worker; searchWorker.ts runs regex search with a timeout
│   ├── autoOpen.ts      opt-in per site: opens plain-text logs automatically
│   └── panel.ts         result panel for the text tools (Shadow DOM, no style clashes)
├── lib/                 pure logic, fully unit-tested
│   ├── logs.ts          incremental parser: levels, timestamps, JSON, stack traces, pods, filters, repeats
│   ├── ansi.ts          ANSI colour codes → plain text and colour spans
│   ├── fields.ts        field filters: level=error duration>1.5s
│   ├── insights.ts      bookmark reports, field statistics and percentiles, error groups, JSON table
│   ├── diff.ts          line and JSON diff for Compare
│   ├── secrets.ts       credential detection and masking
│   ├── regexSafety.ts   rejects regexes prone to catastrophic backtracking
│   ├── timeline.ts      error/warning histogram
│   ├── segments.ts      overlapping highlights (search matches inside secrets)
│   ├── files.ts         .log and .gz files
│   ├── transforms.ts    JSON, JWT, Base64, URL, timestamps, case, lines, mask secrets
│   └── cron.ts          cron → plain English (5 and 6 field, macros, names)
├── shared/
│   ├── settings.ts      the options, in chrome.storage.sync
│   ├── i18n.ts          translations from _locales
│   ├── theme.ts         dark / light / like the system
│   ├── darkMode.ts      per-site dark mode with dynamic content scripts
│   ├── autoOpen.ts      per-site auto-open registration
│   └── inject.ts        on-demand script injection
├── popup/               toolbar popup
├── viewer/              the viewer page for pasted text and files
├── diff/                Compare
├── options/             Settings
└── dark.css             the dark theme itself

Design notes

  • Least privilege. Everything works through activeTab on a click or a shortcut. Remembered dark-mode sites use chrome.permissions.request for a single origin plus chrome.scripting.registerContentScripts, so the extension never holds <all_urls>.
  • Manifest V3 service worker. The worker can be stopped at any time, so state such as remembered sites, tab-only dark mode and pending permission requests lives in chrome.storage, not in variables.
  • Trusted Types safe. The viewer and panel build DOM nodes rather than assigning innerHTML, so they work on sites that enforce Trusted Types, like GitHub and Google.
  • Big logs off the main thread. A content script can't start a worker from the extension's own URL (different origin), so the worker is built separately, inlined as a string and started from a Blob. Pages whose CSP blocks that fall back to parsing in chunks between frames. The e2e test covers both paths.
  • Pure core. Parsing, secret detection and transforms have no DOM or chrome.* dependencies, which keeps them easy to test: 139 unit tests, plus over 100 end-to-end checks in a real Chromium and 28 in Firefox.

Roadmap

  • Open text/plain logs in the viewer automatically (opt-in per site)
  • Secret detection and masking
  • Parsing large logs in a Web Worker
  • Settings page (gap threshold, your own secret patterns, which tools to show)
  • Field filters, time ranges, highlights, pods, .gz files
  • Bookmarks and notes, field statistics, error groups, Follow, JSON table, local time
  • Ukrainian for the popup and menus (help translate the rest)
  • Diff two JSON documents or two logs
  • Multi-line JSON log records
  • Firefox build
  • ANSI colours, your own level words, light theme, percentiles for durations
  • Ukrainian for the log viewer, Compare and Settings (#1)
  • More languages (#2)
  • j / k between lines, context around matches, filters in the link, line ranges (good first issues and more)

License

MIT

andronaft/Logbeam

Chrome extension for developers & platform engineers: readable logs, dark mode everywhere, and one-click JSON / JWT / Base64 / timestamp tools. 100% local, no data leaves your browser.

TypeScript

2

27 commits

updated Oct 16, 2026

See the code

README

Logbeam logo

Logbeam

Make logs readable again.

Chrome Web Store version Chrome Web Store users Chrome Web Store rating Firefox Add-ons version CI Manifest V3 TypeScript MIT

A browser extension for Chrome and Firefox, for developers and platform engineers: a fast log viewer that also catches leaked secrets, dark mode for any site, and the text tools you keep opening random websites for (JSON, JWT, Base64, timestamps, cron). All of it runs locally; no data leaves your browser.

➜ Add to Chrome  ·  ➜ Add to Firefox  — free

Logbeam: a raw log opened in the viewer, next error, a field filter, p95 latency, and the new errors between two CI runs

Features

🔦 Log viewer

Open any raw log (a .log file, "View raw logs" in GitHub Actions, Jenkins console output, kubectl logs piped to a file…) with Ctrl+Shift+L (⌃⇧L on Mac) or from the popup:

  • Levels in colour (ERROR, WARN, INFO, DEBUG, TRACE) with counters and one-click filters
  • Stack traces stay with their error: Java at … / Caused by:, Python tracebacks and Go goroutines are grouped with the entry above, so filtering by ERROR shows the whole trace
  • Search as plain text or regex, case-sensitive if you like, with highlighted matches
  • JSON logs (Logback/Logstash, pino, bunyan, zap…) shown as time LEVEL message {fields}, including records pretty-printed over several lines
  • Filter by fields: level=error service=payments duration>500, on JSON logs and key=value lines alike, with !=, >, <, * wildcards, nested paths (http.status>=500) and units (duration>1.5s)
  • Time range: drag across the timeline to keep only the entries from that time
  • Highlights: press Enter in the search box to keep a term highlighted in its own colour (up to five)
  • Pods and containers: kubectl logs --prefix and docker compose logs get a coloured chip per pod
  • Pasted text and files: open a log pasted into the popup, or a .log / .gz file (unpacked in the browser); drop a file onto any viewer to open it
  • Save the visible lines as a file
  • Bookmarks and notes (m, b): Report copies them as Markdown for a ticket, with times and links
  • Field statistics: the most common values of a field (status: 200 ×1520, 502 ×37), one click to filter; for numbers and durations also min, median, p95, p99 and max (took: p95 1.2s), one click to see the slow ones
  • Error groups: each different error once, with its count, pods and first and last time
  • Follow a log that is still being written: new lines are added every 3 seconds
  • JSON table with the columns you choose, and local time instead of UTC
  • ANSI colours from CI and Docker logs, your own level words (ALERT → ERROR), and a light theme
  • Compare this log with another one, e.g. a passing and a failing CI run, with the new errors listed first (see below)
  • Pauses between entries: +5.5s next to lines where the app stalled
  • Collapse repeats: 500 × retry 17 of 50 for job 8123 becomes one line with a ×500 badge
  • Error timeline: a histogram of entries, errors and warnings over time; click a bar to jump there
  • Line inspector: click a line to read it in full, with its time, pause and, for JSON records, all fields
  • Links to lines: click a line number to copy a #L120 link that opens the viewer right on that line
  • Next error (e), search (/), copy visible lines, back to raw; ? lists all the keys
  • Open automatically on sites you choose (opt-in per site, only plain-text pages that look like logs)
  • Fast on 150k+ lines: logs over 1 MB are parsed in a Web Worker with a progress bar, and only the rows on screen are in the DOM

Only errors and warnings, repeated retries collapsed

Two highlights in their own colours

JSON log as a table, with bookmarks

🔑 Secret detection

Credentials in logs are how leaks start. Logbeam marks every line that shows one: AWS keys, GitHub, GitLab, Slack and Stripe tokens, Google API keys, JWTs, private keys, postgres://user:password@… URLs and password=… / "apiKey": "…" settings (placeholders like ${DB_PASSWORD} are ignored).

  • 🔑 next to the line and the value highlighted; s jumps to the next one
  • Mask hides the values on screen and in everything you copy: AKIA****************
  • Mask secrets in the right-click menu cleans up any selected text or input before you paste it into a chat

A leaked AWS key found, masked, and shown in the line inspector

🌙 Dark mode for any site

Toggle it from the popup or with Ctrl+Shift+K (⌃⇧K on Mac). Pages that already have a dark theme are detected and left alone, and turning it off never reloads the page. "Remember for this site" asks for access to that one site only, and from then on the dark theme is applied before the page paints, so there's no white flash. Photos and videos keep their real colours.

🧰 Text tools

Select text on any page → right-click → Logbeam, or paste it into the popup:

ToolExample
Mask secretspassword=hunter2hunter2 → password=********
Format / minify JSON{"a":1} → pretty-printed, or back to one line
Decode JWTheader, payload, iat/exp as dates, "valid for another 59m" / "EXPIRED 3h ago"
Base64 encode / decodeUTF-8 safe, understands URL-safe Base64 without padding
URL encode / decodea b&c ⇄ a%20b%26c
Timestamp ⇄ date1700000000 → 2023-11-14T22:13:20Z, and back
Explain cron0 */15 * * * * → "Every 15 minutes"; catches */900 in the seconds field
Case conversionuserProfileId ⇄ user_profile_id ⇄ user-profile-id ⇄ USER_PROFILE_ID
Sort / de-duplicate lines

In an input, textarea or rich editor, Replace selection writes the result back in place (undo works).

Decoding a JWT from the page Popup with dark mode and text tools

⚖️ Compare

Open Compare from the popup, or use Compare… in the right-click menu (or the log viewer's Compare button) on one text and then on the other:

  • Logs: a line diff with the changed words marked and unchanged parts folded. Ignore timestamps, IDs and durations lines up two runs of the same job, so 2026-10-03T09:00:20Z Tests: 120 passed against 2026-10-04T11:30:20Z Tests: 119 passed, 1 failed shows only the test result as changed
  • New errors: above the diff, the errors that the second run has and the first one doesn't (and those that are gone), matched by message and stack with times and IDs ignored; click one to jump to it
  • JSON: compared by key, so key order doesn't matter, with a list of changed paths ($.env.LOG_LEVEL, $.ports[1]) and exact comparison of numbers too big for JavaScript (12345678901234567890)
  • Open or drop files, swap sides, ignore whitespace, mask secrets in the output

Compare lists the errors that are new in the failing CI run

Privacy and permissions

Logbeam has no server and no analytics, and it makes no network requests.

PermissionWhy
activeTab, scriptingRun the log viewer or a text tool on the tab you clicked, only when you ask
contextMenusThe right-click menu
storageRemember your per-site settings
optional host access, per siteOnly when you turn on "Remember dark mode" or "Open logs automatically" for a site, and only for that site

Logbeam never asks for access to all sites up front. See the privacy policy.

Install

From the Chrome Web Store: Logbeam on the Chrome Web Store, one click and it updates itself. Works in Chrome, Edge, Brave, Opera and other Chromium browsers. From Firefox Add-ons: Logbeam on addons.mozilla.org (Firefox 140 or newer). The dark-mode shortcut there is Ctrl+Shift+., because Ctrl+Shift+K opens Firefox's Web Console.

From source:

npm ci
npm run build

Then open chrome://extensions, turn on Developer mode, click Load unpacked and choose the dist/ folder. To open local file:// logs, also enable Allow access to file URLs on the extension's details page.

In Firefox, open about:debugging#/runtime/this-firefox, click Load Temporary Add-on and pick dist-firefox/manifest.json.

Development

npm run watch         # rebuild on change, then press ↻ on chrome://extensions
npm test              # unit tests (Vitest)
npm run e2e           # load the extension into Chromium with Playwright, click through it, save docs/*.png
npm run e2e:firefox   # the same for the Firefox build, with Selenium (needs Firefox and geckodriver)
npm run lint:firefox  # the checks addons.mozilla.org runs on upload
npm run check         # lint + format + typecheck + unit tests + build (what CI runs)
npm run package       # logbeam-<version>.zip (Chrome), logbeam-firefox-<version>.zip, sources for AMO
npm run store-assets  # Chrome Web Store screenshots and promo tiles from docs/*.png
npm run demo-gif      # docs/demo.gif for this README, recorded in Chromium
npm run icons         # regenerate the PNG icons (drawn in code, no image editor needed)

Releases: bump the version, add a CHANGELOG.md entry and push a vX.Y.Z tag. The release workflow runs every check including the end-to-end test, attaches the ZIPs to a GitHub Release, and uploads them to the Chrome Web Store and addons.mozilla.org for review (it can also be started from the Actions tab). Setup and details: docs/PUBLISHING.md.

src/
├── background.ts        service worker: context menu, keyboard shortcuts, permission events
├── content/
│   ├── logViewer.ts     virtualized log viewer: filters, inspector, timeline, secrets, bookmarks, #L links
│   ├── viewerStyles.ts  its CSS, dark and light
│   ├── shortcuts.ts     the ? list of keys
│   ├── parseAsync.ts    Web Worker parsing with a chunked main-thread fallback
│   ├── parseWorker.ts   the parse worker; searchWorker.ts runs regex search with a timeout
│   ├── autoOpen.ts      opt-in per site: opens plain-text logs automatically
│   └── panel.ts         result panel for the text tools (Shadow DOM, no style clashes)
├── lib/                 pure logic, fully unit-tested
│   ├── logs.ts          incremental parser: levels, timestamps, JSON, stack traces, pods, filters, repeats
│   ├── ansi.ts          ANSI colour codes → plain text and colour spans
│   ├── fields.ts        field filters: level=error duration>1.5s
│   ├── insights.ts      bookmark reports, field statistics and percentiles, error groups, JSON table
│   ├── diff.ts          line and JSON diff for Compare
│   ├── secrets.ts       credential detection and masking
│   ├── regexSafety.ts   rejects regexes prone to catastrophic backtracking
│   ├── timeline.ts      error/warning histogram
│   ├── segments.ts      overlapping highlights (search matches inside secrets)
│   ├── files.ts         .log and .gz files
│   ├── transforms.ts    JSON, JWT, Base64, URL, timestamps, case, lines, mask secrets
│   └── cron.ts          cron → plain English (5 and 6 field, macros, names)
├── shared/
│   ├── settings.ts      the options, in chrome.storage.sync
│   ├── i18n.ts          translations from _locales
│   ├── theme.ts         dark / light / like the system
│   ├── darkMode.ts      per-site dark mode with dynamic content scripts
│   ├── autoOpen.ts      per-site auto-open registration
│   └── inject.ts        on-demand script injection
├── popup/               toolbar popup
├── viewer/              the viewer page for pasted text and files
├── diff/                Compare
├── options/             Settings
└── dark.css             the dark theme itself

Design notes

  • Least privilege. Everything works through activeTab on a click or a shortcut. Remembered dark-mode sites use chrome.permissions.request for a single origin plus chrome.scripting.registerContentScripts, so the extension never holds <all_urls>.
  • Manifest V3 service worker. The worker can be stopped at any time, so state such as remembered sites, tab-only dark mode and pending permission requests lives in chrome.storage, not in variables.
  • Trusted Types safe. The viewer and panel build DOM nodes rather than assigning innerHTML, so they work on sites that enforce Trusted Types, like GitHub and Google.
  • Big logs off the main thread. A content script can't start a worker from the extension's own URL (different origin), so the worker is built separately, inlined as a string and started from a Blob. Pages whose CSP blocks that fall back to parsing in chunks between frames. The e2e test covers both paths.
  • Pure core. Parsing, secret detection and transforms have no DOM or chrome.* dependencies, which keeps them easy to test: 139 unit tests, plus over 100 end-to-end checks in a real Chromium and 28 in Firefox.

Roadmap

  • Open text/plain logs in the viewer automatically (opt-in per site)
  • Secret detection and masking
  • Parsing large logs in a Web Worker
  • Settings page (gap threshold, your own secret patterns, which tools to show)
  • Field filters, time ranges, highlights, pods, .gz files
  • Bookmarks and notes, field statistics, error groups, Follow, JSON table, local time
  • Ukrainian for the popup and menus (help translate the rest)
  • Diff two JSON documents or two logs
  • Multi-line JSON log records
  • Firefox build
  • ANSI colours, your own level words, light theme, percentiles for durations
  • Ukrainian for the log viewer, Compare and Settings (#1)
  • More languages (#2)
  • j / k between lines, context around matches, filters in the link, line ranges (good first issues and more)

License

MIT