@degreesign/chat

Plug and play · automatic engine

Plug and play.
Unlimited replies.
Yours offline.

One download, then unlimited offline replies in any UI. It picks the engine, manages the download, fits the prompt and reuses the cache. No key, no account, no server, no bill.

In production at DoListy

MIT · Node 24 or newer · one download: 1.5 GB CPU, 2.0 GB GPU · no quotas

qwen3-vl-2b / on device local

Why keep the model on the device?

No key, no upload. One download, then it picks the engine, fits the prompt and answers offline. The weights stay cached until you clear them.

auto engine auto prompt cached weights offline
1 download
0 API keys
0 uploads
∞ unlimited offline replies

Why local

The cloud is a dependency. This isn't.

A key, an account, a server, a signal, a bill. Local chat removes all five. The only thing left is the download.

01

No key.

Nothing to leak, rotate or bill.

02

No server.

The model is the backend.

03

No signal.

Airplane mode is a supported state.

Live demo

Pull the plug. Ask again.

The first reply downloads the model once. Then turn off Wi-Fi and keep chatting. The answer is generated in this tab.

  1. 01 Send a question.
  2. 02 Turn off Wi-Fi.
  3. 03 Ask another.

This is the instruction the demo sends before your question. Edit it and watch the answer change.

chat / nothing loaded on device

Ask something. The first reply downloads the model once, then answers locally.

Idle. No model loaded.

First send downloads the weights once. About 1.5 GB on CPU or 2.0 GB on GPU. They stay cached and later replies run offline.

What you get

Everything handled. Nothing sent.

Plug and play: the engine, the download, the context window and the cache are the package's job. Bring any UI; your messages, markup and styles stay yours.

GPU when it's there. CPU when it isn't.

WebGPU runs the Gemma 4 E2B build. Without an adapter, the same call falls back to the CPU build. You never branch, detect or configure.

WebGPU CPU fallback automatic

Download once. Reply forever.

About 1.5 GB on CPU or 2.0 GB on GPU. It resumes after a reload, stays cached until you clear it, and then every token is generated on the device.

one download resumable offline

Your prompt never gets a ticket number.

No key to leak and no server to trust. The image, the prompt and the reply stay in the tab, the worker or the Node process. The package writes no history.

no upload no key no server

Your UI. Our stream.

Text arrives through callbacks, so React, Svelte, a worker or a terminal render the same reply. Cancel is one call.

React worker Node

It can look at things.

Describe a photo, translate the description, build tags or turn a voice note into a task. Vision ships in the CPU build with no second download.

describeImage captions tags

The boring parts are done.

Engine choice, context limits, download resume, cache reuse and timeouts are handled. You pass messages and render text.

auto typed cancel

First run

The first reply downloads. The rest are unlimited.

One download, one cache, no server round trip. Every reply after the first is local, offline and unlimited.

01

Install

npm install @degreesign/chat, then call createChat. No key, no account, no config.

02

Download once

The first send fetches the weights and resumes if the connection drops. 1.5 GB on CPU, 2.0 GB on GPU.

03

Reply offline, unlimited

Every later send runs on the device. Stream tokens, stop any time, keep the model warm. There is no reply quota.

Proof

DoListy logo DoListy

DoListy ships chat with the network off.

A no-signup PWA for photos, voice notes and tasks. It captions photos, fills tags and answers questions with no account and no key. The chat is @degreesign/chat.

  • Describe Photos are captioned locally with describeImage.
  • Answer Chat replies stream with no account and no API key.
  • Ship Works in airplane mode, on a plane, in a basement.
See it live Screenshot from dolisty.com
DoListy chat answering an afternoon plan question.
Chat in the DoListy PWA
on device

The network is off. The reply still arrives.

Models

You don't pick. It does.

With no override, the package picks the GPU build when WebGPU exists and the CPU build when it does not. Both are 2B models: small enough for a device, good enough for captions, tags and short answers.

Qwen3-VL 2B

CPU · vision

The default on a CPU. Vision travels with the model, so image turns work without a second download.

Build Reasoning Images Weights
qwen3_vl_2b Yes Yes about 1.5 GB
qwen3_vl_2b_instruct No Yes Q4_K_M
qwen3_vl_2b_instruct_q3 No Yes Q3, 160 MB less

4K token context on a phone, 8K on a desktop. The projector shares the text thread budget.

Gemma 4 E2B

WebGPU

The default on a GPU. A 2.0 GB build with a large context for text turns.

Build Reasoning Images Weights
gemma4_e2b_limited Yes No 2.0 GB

16K token context on a phone, 32K on a desktop. The build ships without vision or audio encoders.

Straight talk.

These are 2B models. They are excellent at captions, tags, summaries, short answers and private drafts. They are not the model you ask to write a novel. The first reply on a phone can take a minute. After that, it is local.

Technical details

Context and budget

  • Reply tokens 250 default
  • Images and audio 2 / 1
  • Prompt characters 10000
  • CPU threads one fifth kept free

Timeouts and transport

  • First chunk 5 min desktop / 50 phone
  • Image prefill 14 min
  • Silence 30 s
  • Download range 32 MB

Compared

Less to download. Longer conversations. No setup.

Both packages can run the same Gemma 4 model right in the browser. The difference is what each one asks of the device and of you: the download, how much of the conversation it remembers, and the setup needed to ship. Here is the practical comparison.

Model download

2.0 GB 2.8 GB

Same base model, 800 MB less before the first token.

GPU context

32K 4K

16K on a phone. web-llm caps both at 4K.

Browser entry

86.2 KB 6.8 MB

Minified. The web-llm entry is 6.2 MB after minification.

Side by side
Question @degreesign/chat @mlc-ai/web-llm
Smallest usable chat build Gemma 4 E2B, 2.0 GB 2.8 GB, smaller builds not usable
GPU context 32K desktop, 16K mobile 4K
Engine and model choice automatic host builds it
Browser entry 86.2 KB minified 6.8 MB, 6.2 MB minified
Package without wasm 1.7 MB, wasm in package 14.4 MB, wasm at load

The honest verdict. Choose @degreesign/chat for plug-and-play chat on mobile PWAs, phones and consumer web apps. Choose @mlc-ai/web-llm for manual, desktop-only setups tuned for shader-f16 GPUs.

Architecture

No black box.

Every function is on one offline HTML page: the entry, the catalog, the prompt budgets, both engines and the stores. Read it before you ship it.

  • 01 Public entry and typed API
  • 02 Chat service and model catalog
  • 03 Prompt budgets and streaming
  • 04 wllama and LiteRT engines
  • 05 Stores, assets and weights
Open the full architecture

Opens in a new tab. One self-contained HTML file. Browse the source .

code structure full map
Public entry createChat / preloadModel / describeImage
Model runtime service / catalog / engine choice
Prompt and engines budgets / streaming / wllama / LiteRT
Tools and assets descriptors / wasm / weights
Stores and types storage / caches / enums
Open full architecture

Install

One command to local.

No key, no account, no server. Add the package, call createChat, render in any UI. Works in React, a worker, a Node script or plain JS.

npm install @degreesign/chat

No config, no key. The first call downloads the weights once; later calls reuse the cache.

Vite Workers Node 24 React Next.js
import {
    LlmRole,
    createChat,
} from "@degreesign/chat";

const cancel = createChat({
    messages: [
        {
            role: LlmRole.system,
            content: "Be brief.",
        },
        {
            role: LlmRole.user,
            content: "Hello",
        },
    ],
    onResponse: (text) => render(text),
    onStatus: (state) => show(state),
});

cancel();

FAQ

The questions you're about to ask.

No jargon, no asterisks. Here is what it does and what it does not.

Do I need a GPU?

No. WebGPU is used when the browser has it. Without an adapter, the CPU engine runs the same call. Phones and older laptops work.

How big is the download?

About 1.5 GB on CPU or 2.0 GB on GPU. It downloads once, resumes after a reload, and stays cached until you clear it.

Does it really work offline?

Yes. After the first download, the weights and the engine run locally. The package makes no network request to answer.

What happens if I clear the cache?

The next send downloads it again. No hidden copy, no account.

How is it free?

The package is MIT and there is no per-reply fee. You pay for the device and the one-time download, not for each answer.

Does it collect anything?

No key, no server and no upload. The package writes no history; your app owns the data.

Start here

Install once. Answer offline.

One package. Two engines. Zero keys. Unlimited offline replies.

MIT · Types included · 1.5 GB CPU / 2.0 GB GPU