madforstrength/kalam

Private on-device push-to-talk dictation for Chrome. Hold a key, speak, release - 100% local ASR (Whisper, Cohere, Parakeet, Gemma), no cloud, no account.

0

stars

45

commits

JavaScript

primary language

Aug 6, 2026

updated

README

Kalam — Private On-Device Dictation for Chrome

Hold Ctrl+Space. Speak. Release. Your words appear where you were typing.

Kalam (Arabic: كلام, "speech") is an open-source push-to-talk dictation extension that runs state-of-the-art speech recognition entirely on your computer. No cloud, no account, no API key, no subscription — and no audio or transcript ever leaves your device. Turn on airplane mode and it still works (after the one-time model download).

Beta. Kalam works end-to-end and has been hardened against a long list of real-world failures — but so far on a small set of hardware. Reports from Macs, Linux, discrete GPUs, and Chromebooks are exactly what this beta is for. Open an issue with your hardware and what happened.

How it works

  • Focus any text field on any website, hold Ctrl+Space (configurable: Ctrl+Shift+Space, Right Ctrl, F8; F9 always works as a fallback), and speak.
  • Release the key — the transcript is inserted at your cursor.
  • If no text field is focused, the transcript is copied to your clipboard.

Speech recognition runs locally via Transformers.js and ONNX Runtime Web (WebGPU with WASM fallback).

Engines

All 100% on-device, selectable in the popup, downloadable/deletable from the Models tab:

EngineSizeLanguagesNotes
Cohere Transcribe~1.2 GB14 (EU/APAC/MENA incl. Arabic)Top leaderboard accuracy; GPU only; no auto language detect
Whisper Large v3 Turbo~600 MB~100Best language coverage
Whisper Base~80 MB~100Light; CPU-friendly
Parakeet CTC 0.6B0.6–1.2 GBEnglishFastest; CTC architecture cannot hallucinate
Gemma 4 E2B~3 GBmanyExperimental LLM engine + optional transcript polish (spoken punctuation, corrections, list formatting); GPU only

"Auto" measures your hardware and picks accordingly, downgrading automatically if a model proves too slow on your machine.

GPU memory note: running a large engine and Gemma polish together can exceed integrated-GPU memory. Sustainable combos: a big engine with polish off, or Whisper Base + polish. Kalam recovers automatically from GPU session loss, but not needing recovery is better.

Privacy, verifiably

  • All inference happens in an extension-local worker; the ONNX runtime and WASM binaries ship inside the extension — no CDN.
  • The only network traffic ever is the one-time model download from huggingface.co. Watch the network panel, or go offline: dictation keeps working.
  • The microphone is captured only while the key is held, released the moment you let go (Chrome's mic indicator confirms it), and a silence detector tells you which input device is misbehaving rather than hallucinating.
  • Web pages get nothing: they can't access your mic through Kalam, can't read its status, and can't spoof its UI (cross-frame messages are authenticated).
  • No analytics, no telemetry, MIT licensed.

Install (beta)

  1. Download kalam-extension.zip from the latest release and unzip it.
  2. chrome://extensions → enable Developer modeLoad unpacked → select the unzipped folder.
  3. Click the Kalam toolbar icon → Allow microphone → choose "Allow while visiting this site" (the persistent option).
  4. Open the Models tab in the popup and download an engine (Whisper Base is the quick start; Cohere Transcribe is the accuracy pick on a GPU).
  5. Hold Ctrl+Space (or F9) in any text field. Speak. Release.

Requires Chrome 124+. Works best with a GPU Chrome can use (chrome://gpu → WebGPU); falls back to multi-threaded CPU inference.

Why these permissions?

  • Access to all sites — dictation must insert text into whatever page you're using; the content script only listens for the hotkey and inserts transcripts. No page data is read or sent anywhere.
  • Microphone — captured in an extension-private page only while the key is held.
  • Unlimited storage — speech models are large and cached locally.

Troubleshooting

  • Nothing happens on Ctrl+Space — refresh the page once after installing; check the popup's "Active on this page" line. Some keyboard layouts intercept Ctrl+Space (IMEs) — use F9 or change the hotkey.
  • "Only silence was captured from …" — Windows is delivering silence from that input device: check the mic-mute key, Windows Sound input settings, and the mic meter on Kalam's permission page.
  • Whisper types "Thank you" on silence — that's a known Whisper hallucination; Kalam's silence guard catches most of it.
  • Model stuck downloading — reload the extension and download again from the Models tab; completed files resume from cache.
  • "GPU session was lost — rebuilding…" — the GPU was reclaimed (sleep/resume, memory pressure); Kalam rebuilds and retries automatically.

Development

npm install
npm run build        # -> dist/, load unpacked
npm run package      # -> kalam-extension.zip
npm run test:gemma   # validate the Gemma recipe against the installed transformers.js

Manual model checks live in test/ — they run the extension's exact model recipes in Node to separate our bugs from upstream ones. Read test/README.md before trusting a "bug": its first lesson is that we once blamed a healthy model for our own WAV decoding (transformers.js#1726).

Icons are generated by tools/gen-icons.ps1.

Architecture

content script (per page)          offscreen document (extension origin)
┌─────────────────────────┐        ┌──────────────────────────────────┐
│ hotkey hold/release     │  msgs  │ getUserMedia → MediaRecorder      │
│ status overlay          │◄──────►│ decode → 16 kHz mono Float32      │
│ insert text at caret    │  (SW   │ ┌──────────────────────────────┐ │
└─────────────────────────┘ router)│ │ ASR worker: Transformers.js  │ │
                                   │ │ engines on WebGPU / WASM     │ │
                                   │ └──────────────────────────────┘ │
                                   └──────────────────────────────────┘

Audio never crosses the extension messaging boundary — capture and inference both live in the offscreen document; only the finished text is routed back (tagged with a per-dictation id, ordered through a FIFO, and guarded by watchdogs and automatic engine recovery).

Contributing

Bug reports with your hardware (OS, GPU, chrome://gpu WebGPU status) are the most valuable contribution right now. PRs welcome — keep the privacy invariant absolute: nothing leaves the machine.

Roadmap

  • First-run onboarding
  • Automated end-to-end smoke test (Puppeteer)
  • Chrome Web Store listing
  • Parakeet TDT v3 (multilingual) when upstream support lands
  • Custom vocabulary (names, jargon)
  • Streaming partial transcripts while the key is held
  • Insert-then-polish (instant raw text, replaced by the polished version)
  • GPU memory budget warnings for engine combinations

License

MIT. Model weights retain their own licenses (Whisper: MIT; Parakeet: CC-BY-4.0; Cohere Transcribe: Apache 2.0; Gemma 4: Apache 2.0) and download directly from their Hugging Face repositories.

Contributors

madforstrength

45 commits

madforstrength/kalam

Private on-device push-to-talk dictation for Chrome. Hold a key, speak, release - 100% local ASR (Whisper, Cohere, Parakeet, Gemma), no cloud, no account.

0

stars

45

commits

JavaScript

primary language

Aug 6, 2026

updated

README

Kalam — Private On-Device Dictation for Chrome

Hold Ctrl+Space. Speak. Release. Your words appear where you were typing.

Kalam (Arabic: كلام, "speech") is an open-source push-to-talk dictation extension that runs state-of-the-art speech recognition entirely on your computer. No cloud, no account, no API key, no subscription — and no audio or transcript ever leaves your device. Turn on airplane mode and it still works (after the one-time model download).

Beta. Kalam works end-to-end and has been hardened against a long list of real-world failures — but so far on a small set of hardware. Reports from Macs, Linux, discrete GPUs, and Chromebooks are exactly what this beta is for. Open an issue with your hardware and what happened.

How it works

  • Focus any text field on any website, hold Ctrl+Space (configurable: Ctrl+Shift+Space, Right Ctrl, F8; F9 always works as a fallback), and speak.
  • Release the key — the transcript is inserted at your cursor.
  • If no text field is focused, the transcript is copied to your clipboard.

Speech recognition runs locally via Transformers.js and ONNX Runtime Web (WebGPU with WASM fallback).

Engines

All 100% on-device, selectable in the popup, downloadable/deletable from the Models tab:

EngineSizeLanguagesNotes
Cohere Transcribe~1.2 GB14 (EU/APAC/MENA incl. Arabic)Top leaderboard accuracy; GPU only; no auto language detect
Whisper Large v3 Turbo~600 MB~100Best language coverage
Whisper Base~80 MB~100Light; CPU-friendly
Parakeet CTC 0.6B0.6–1.2 GBEnglishFastest; CTC architecture cannot hallucinate
Gemma 4 E2B~3 GBmanyExperimental LLM engine + optional transcript polish (spoken punctuation, corrections, list formatting); GPU only

"Auto" measures your hardware and picks accordingly, downgrading automatically if a model proves too slow on your machine.

GPU memory note: running a large engine and Gemma polish together can exceed integrated-GPU memory. Sustainable combos: a big engine with polish off, or Whisper Base + polish. Kalam recovers automatically from GPU session loss, but not needing recovery is better.

Privacy, verifiably

  • All inference happens in an extension-local worker; the ONNX runtime and WASM binaries ship inside the extension — no CDN.
  • The only network traffic ever is the one-time model download from huggingface.co. Watch the network panel, or go offline: dictation keeps working.
  • The microphone is captured only while the key is held, released the moment you let go (Chrome's mic indicator confirms it), and a silence detector tells you which input device is misbehaving rather than hallucinating.
  • Web pages get nothing: they can't access your mic through Kalam, can't read its status, and can't spoof its UI (cross-frame messages are authenticated).
  • No analytics, no telemetry, MIT licensed.

Install (beta)

  1. Download kalam-extension.zip from the latest release and unzip it.
  2. chrome://extensions → enable Developer modeLoad unpacked → select the unzipped folder.
  3. Click the Kalam toolbar icon → Allow microphone → choose "Allow while visiting this site" (the persistent option).
  4. Open the Models tab in the popup and download an engine (Whisper Base is the quick start; Cohere Transcribe is the accuracy pick on a GPU).
  5. Hold Ctrl+Space (or F9) in any text field. Speak. Release.

Requires Chrome 124+. Works best with a GPU Chrome can use (chrome://gpu → WebGPU); falls back to multi-threaded CPU inference.

Why these permissions?

  • Access to all sites — dictation must insert text into whatever page you're using; the content script only listens for the hotkey and inserts transcripts. No page data is read or sent anywhere.
  • Microphone — captured in an extension-private page only while the key is held.
  • Unlimited storage — speech models are large and cached locally.

Troubleshooting

  • Nothing happens on Ctrl+Space — refresh the page once after installing; check the popup's "Active on this page" line. Some keyboard layouts intercept Ctrl+Space (IMEs) — use F9 or change the hotkey.
  • "Only silence was captured from …" — Windows is delivering silence from that input device: check the mic-mute key, Windows Sound input settings, and the mic meter on Kalam's permission page.
  • Whisper types "Thank you" on silence — that's a known Whisper hallucination; Kalam's silence guard catches most of it.
  • Model stuck downloading — reload the extension and download again from the Models tab; completed files resume from cache.
  • "GPU session was lost — rebuilding…" — the GPU was reclaimed (sleep/resume, memory pressure); Kalam rebuilds and retries automatically.

Development

npm install
npm run build        # -> dist/, load unpacked
npm run package      # -> kalam-extension.zip
npm run test:gemma   # validate the Gemma recipe against the installed transformers.js

Manual model checks live in test/ — they run the extension's exact model recipes in Node to separate our bugs from upstream ones. Read test/README.md before trusting a "bug": its first lesson is that we once blamed a healthy model for our own WAV decoding (transformers.js#1726).

Icons are generated by tools/gen-icons.ps1.

Architecture

content script (per page)          offscreen document (extension origin)
┌─────────────────────────┐        ┌──────────────────────────────────┐
│ hotkey hold/release     │  msgs  │ getUserMedia → MediaRecorder      │
│ status overlay          │◄──────►│ decode → 16 kHz mono Float32      │
│ insert text at caret    │  (SW   │ ┌──────────────────────────────┐ │
└─────────────────────────┘ router)│ │ ASR worker: Transformers.js  │ │
                                   │ │ engines on WebGPU / WASM     │ │
                                   │ └──────────────────────────────┘ │
                                   └──────────────────────────────────┘

Audio never crosses the extension messaging boundary — capture and inference both live in the offscreen document; only the finished text is routed back (tagged with a per-dictation id, ordered through a FIFO, and guarded by watchdogs and automatic engine recovery).

Contributing

Bug reports with your hardware (OS, GPU, chrome://gpu WebGPU status) are the most valuable contribution right now. PRs welcome — keep the privacy invariant absolute: nothing leaves the machine.

Roadmap

  • First-run onboarding
  • Automated end-to-end smoke test (Puppeteer)
  • Chrome Web Store listing
  • Parakeet TDT v3 (multilingual) when upstream support lands
  • Custom vocabulary (names, jargon)
  • Streaming partial transcripts while the key is held
  • Insert-then-polish (instant raw text, replaced by the polished version)
  • GPU memory budget warnings for engine combinations

License

MIT. Model weights retain their own licenses (Whisper: MIT; Parakeet: CC-BY-4.0; Cohere Transcribe: Apache 2.0; Gemma 4: Apache 2.0) and download directly from their Hugging Face repositories.

Contributors

madforstrength

45 commits

Languages

JavaScript

81.5%

HTML

8.4%

CSS

7.1%

PowerShell

3.0%