---
title: Typing Insights (typing-speed stat)
---

# Typing Insights (typing-speed stat)

## What it is

A small, passive feature that measures how fast you actually type in the session composer
and shows it as a **"Typing Speed"** stat in the Statistics view. It runs while you type
normally — there's nothing to start — and is built to add **zero** typing latency.
On by default; fully local; no AI, no internet, no cost.

## Where to find it

The stat lives in **Statistics → Overview**, where a **Typing Speed** card sits alongside the other cards. The switch that turns the measuring off is in **Settings → System**, as "Track my typing speed" (searchable as "typing speed", "WPM").

## How it behaves

### What you see

Open **Statistics → Overview** and, alongside the other cards (Total Cost, Tokens, Sessions,
…), there's a **Typing Speed** card: your **average WPM** for the selected time range, with
your **peak WPM** as the subtitle. It follows the range picker (Today / 7 Days / 30 Days /
etc.). Before you've typed enough, it reads "No data yet".

Distinct from the **Typing Tutor** (the practice game): that's where you _train_ your speed;
this just reports the speed of your _real_ typing in the app. The two are independent — this
never feeds the tutor's lessons (real typing is too noisy to train the drills on).

### How the measurement works

- It measures only **genuine typing bursts** — a run of single characters you type. Thinking
  pauses, backspaces/edits, pastes, and non-Latin input methods (IME) are all excluded, so the
  number reflects real typing speed, not "how long the box was open."
- Speed uses the standard formula (a "word" is 5 characters): `WPM = (characters / 5) / minutes`,
  the same formula as the Typing Tutor.
- Each finished burst is saved once (when you pause), rolled into a **per-day tally**. The stat
  aggregates those days: the average is character-weighted, the peak is your best single burst.

### Turning it off

**Settings → System → "Track my typing speed"** (searchable as "typing speed", "WPM"). Off
stops all measuring. There's also a developer kill switch, the `AMC_DISABLE_TYPING_INSIGHTS=1`
environment variable, which additionally stops the main process from storing any samples.

### Privacy & cost

100% local — the raw counts and the daily tallies live only in Omniscio's local database, nothing is
sent anywhere, and no AI/network calls are made. It costs nothing to run.

### Limitations (this version)

Measures the **main session composer** only (local-chat / scratchpad could follow); English/Latin
typing (IME input isn't counted); one local profile; desktop typing (the stat card is desktop-first).

## For agents

### Under the hood (for agents)

- **Pure core** — [composer-typing-wpm-core.ts](../../src/renderer/src/lib/composer-typing-wpm-core.ts):
  the burst accumulator (counts single-char deltas; excludes paste/delete/IME/idle). No DOM/IPC;
  unit-tested.
- **Wiring** — [composer-typing-wpm.ts](../../src/renderer/src/lib/composer-typing-wpm.ts) rides the
  composer's existing per-keystroke hook ([useComposerTypingPing.ts](../../src/renderer/src/hooks/useComposerTypingPing.ts))
  and flushes one fire-and-forget sample per burst on idle. Per-keystroke work is O(1) with no React
  state — the reason it can't add typing lag.
- **Persistence** — [typing-insights-service.ts](../../src/main/services/typing-insights/typing-insights-service.ts)
  recomputes WPM authoritatively and upserts a per-day row (`composer_typing_daily`, migration
  `20260711133626`). The setting is `typingInsightsEnabled` (default true).
- **Invariants** — [.claude/memory/contracts/typing-insights-contract.md](../../.claude/memory/contracts/typing-insights-contract.md).

## Related

The Statistics view this card joins is described on [Statistics](stats.md). The practice game that trains your speed rather than reporting it is on [Typing Tutor](typing-tutor.md), and the custom model instructions that shape what an agent writes into the composer are on [Custom model instructions](custom-model-instructions.md).
