Inspiration

I volunteer with teachers in Colorado, and they can be suspicious of AI. Specifically. It floods them with work they have to adjudicate, it threatens parts of the job they enjoy, and it usually arrives as surveillance wearing a helpful face. So when I started thinking about the AI for education category, I treated their hostility as the design constraint instead of the obstacle.

Basic computer skills are in decline. Many of their students struggle with mice, typing, and file systems. The kids who arrive fluent had a computer at home. The kids who don't had a phone or tablet, and phones have no cursor, no file system, and no keyboard worth the name. The gap is exposure, not aptitude, and it compounds across every subject, every year. While administrations wave this gap away due to students being "digital natives", they are ill-prepared to do the serious work college and the workplace will expect of them.

Teachers can't see where every student is struggling every time they crack open their Chromebook. Computer classes are disappearing, adding more onto the plate of already overworked teachers. And their only realistic intervention is a short whole-class demo, a few minutes at the front of the room. They have no data telling them what to demo based on where students are actually struggling, so they guess.

Meanwhile the software districts actually bought to watch student screens is punitive monitoring software that teachers despise. Same underlying need, opposite valence.

What it does

Mermaid diagram

ColdOpen is a Chrome Extension plus a teacher page. The extension observes interaction timing and event shape on classroom Chromebooks and laptops: hesitation before clicks, abandoned drags, file dialogs opened and dismissed without a selection, keystroke intervals. It cannot see content. Not keystrokes, not screenshots, not filenames, not page text. That is a structural property of the code! There is actually a test in the repo that fails the build if the content script ever references DOM text, selectors, or key identity. Teachers whitelist sites they want telemetry from, letting them collect behavior data on specific activities they are interested in.

Individual sessions are collapsed into a single class-level feature vector. Identity is discarded at aggregation. There are no per-student records anywhere in the system, because there is nothing per-student to record.

The teacher page uses the OpenAI API to turn that class vector into a five-minute demo script they can run cold on Monday morning. Diagnosis, the evidence behind it in plain language, setup, steps, and a quick comprehension check. The model call happens server-side in a Cloudflare Pages Function. The page loads committed fixture recommendations instantly, so nothing hangs, and a button generates a fresh recommendation live to show the pipeline is real.

The design decision that matters

Class-level aggregation is not a privacy compromise, it actually is the correct product.

A teacher with 30 students and no aide cannot act on "Marcus is struggling with drag and drop." They do not have ten minutes per kid. They have five minutes per class. So per-student data would be both a privacy liability and unactionable noise. The useful resolution of the data is set by the teacher's intervention capacity, and that resolution happens to be anonymous. The privacy win comes free with getting the product right.

This also changes what the monitoring is for. District surveillance software exists to catch kids. ColdOpen exists to diagnose what a class is missing. Flipping the gaze from catching to diagnosing is the difference between the tool teachers got and the tool they wanted.

Where the model earns its place

A rules engine can detect a slow click. It cannot infer a missing mental model, and it cannot write the lesson.

The OpenAI model's job is the interpretation step: turning noisy aggregate behavior into a claim like "this class does not understand that a file has a location," then into a concrete demo with steps a teacher can narrate. The system prompt forbids inference about any individual child, requires hedged language calibrated to a confidence field, and returns structured JSON validated against a schema. If the model output fails validation, the page falls back to a deterministic fixture recommendation, so the teacher always gets something usable.

Equity

The Chromebooks in these classrooms are often base-model Lenovos, Samsungs, etc. and several years old. Google's built-in AI requires Chromebook Plus hardware, 22GB of free storage, and specs this fleet will not have any time soon. This hardware tier is structurally excluded from on-device AI.

ColdOpen's answer is architectural. The classroom device does almost nothing: it emits a tiny stream of timing events. The one model call happens server-side, once per class per week, against a cached pool of shared context. The cost floor is fractions of a cent per classroom.

How I built it

ColdOpen was built spec first, agent second. I wrote a design document before any code existed, and the most important part wasn't the feature list. It was the non-goals.

A coding agent given "build a classroom web app" will cheerfully scaffold a database, user accounts, and per-student dashboards, because that's what the pattern looks like. Every one of those defaults would have broken this project's privacy architecture. So the doc said explicitly: no per-student state, no content capture, key server-side only. It also said why, so the constraints read as design decisions rather than arbitrary rules.

Then I handed the doc to Codex and reviewed everything it produced against it. The constraint I cared most about was that the extension be structurally incapable of reading content, and this is where the workflow paid off. That requirement traveled from a sentence in the design doc, through the agent, into a test in the repo: it reads the content script's source and fails if it ever references DOM selectors, text content, or key identity. The keydown handler uses the event purely as a timing pulse and never touches a property. A constraint I wrote in prose on day one is now enforced by the build.

Stack: MV3 Chrome extension, TypeScript aggregation and generation, Zod contracts shared across the pipeline, Cloudflare Pages plus one Pages Function, static fixtures committed to the repo, and a test suite covering contracts, rollup, the privacy invariant, and the deployed function.

Accomplishments that I'm proud of

The pipeline is proven. The fixture traces produce sharply separated feature vectors: novice sessions show a median hesitation nine times longer than competent sessions, key intervals three times longer, and abandoned drags and dead-end dialogs that competent sessions simply do not produce. The rollup, the generator, and the page all behave correctly on that separation.

The signal in real children is not proven, and where I live school is out in July. I could not collect classroom traces, so the demo runs on fixtures I authored and traces I captured from my own deliberate novice behavior. The open empirical question is whether real students separate the way the fixtures do. That is something I'm hoping to learn this fall.

What's next for ColdOpen - Teaching Computer Skills Made Easy

Grade-level and school-level aggregation, which strengthens the small-n statistics and costs nothing in privacy. Easier deployment with fewer manually-configured steps will be a key part of productization. A library of demo scripts that improves as teachers rate whether a recommendation landed. And the district conversation about force-install deployment, which is the only real path onto managed Chromebooks, and which is a much easier ask when the extension provably cannot read content.

Built With

Share this project:

Updates