shapeshift README

The project's README from github.com/anishfn/shapeshift. As one markdown file: README.md.

Shapeshift

An input that becomes what you mean. One text box that morphs into the right UI as you type — an event card, a checklist, a timer, a color picker, a bill splitter, a poll, a converter and more.

Typing 'dinner with priya friday 8pm on zoom' morphs the text box into an event card, then a shopping checklist
Try it live · Watch the full 60-second demo (1080p60)

dinner with priya friday 8pm on zoom   →  Event card · Friday · 8 PM · Priya · Video call
buy milk, eggs, bread and coffee       →  Shopping checklist
split 2400 between 3                   →  ₹800 each
minecraft diamond                      →  #4AEDD9

Intent is classified by TypeSafe AI's Jev model: one call answers 14 typed questions in parallel (which card, plus signals like "is it a video call?", "is it urgent?"). Everything else — dates, amounts, units, math — is deterministic code. Jev decides, code computes.

One Jev call answers 14 questions in parallel; a deterministic parser reads the same text for values

It works fully offline by default with a built-in keyword classifier, so you can run it without an account.

Quick start

Requires Bun 1.2+.

bun install
bun dev

Open http://localhost:3000 and start typing. Press / to see every card type.

Use the online Jev model (optional)

cp .env.example .env.local
# then set TYPESAFE_API_KEY=... (get one at https://console.typesafe.ai/keys)

Restart bun dev. The latency readout in the bottom-right corner switches from jev-offline to jev-1.13.0. The key is only ever read on the server (/api/intent); it never reaches the browser. If the API is unreachable or rate-limited, Shapeshift quietly falls back to offline mode.

Variable Default What it does
TYPESAFE_API_KEY (empty) Enables the online model. Empty or placeholder values keep you offline.
JEV_MODEL jev-1.13.0 Pinned model version.
NEXT_PUBLIC_USE_MOCK false true forces offline even with a key.
NEXT_PUBLIC_SITE_URL http://localhost:3000 Used for Open Graph metadata.

Card types

Card Try
Event lunch with rahul and anna tomorrow
Reminder remind me to pay rent tomorrow urgent
Checklist buy milk, eggs, bread and coffee
Timer 25 min focus
Habit gym 3x a week
Color #ff6b35, tiffany blue, minecraft diamond
Split split 2400 between 3
Expense spent 450 on uber
Convert 5 miles in km, 72f to c
Calculate 18% of 3450
Trip flight to goa next weekend
Poll pizza or burgers for friday?
Contact rahul 98200 12345 [email protected]
Bookmark https://vercel.com/blog check later
Countdown days until christmas
Time zone 3pm pst in ist, what time is it in tokyo
Random roll 2d6, flip a coin, pick one: tacos, sushi or pizza
Goal read 12 books this year, 4 done
Note anything else

Saved cards live in your browser (localStorage) until you delete them. Click one to edit it.

Keyboard

Key Action
Enter Save the card
Esc Clear (or cancel an edit)
Tab Keep a faint preview
← → Choose between "Did you mean" chips
/ Open every card type

URL flags: ?debug=1 shows every probability; ?demo=1&loop=1 plays a scripted demo.

How it works

Keystroke, debounced hook, server route, Jev or offline classifier, decide, gate signals, parse, card

Raw model output flickers as you type, so a small state machine turns confidence into calm UI states. A card only changes when a challenger wins twice in a row (or is very sure), and signal badges use an on/off hysteresis band.

States: input, ghost preview, choose between two chips, committed card, with the thresholds between them

The diagrams are Excalidraw files — open any docs/diagrams/*.excalidraw at excalidraw.com to edit them.

Path What lives there
src/components/intents/registry.ts The extension point. One entry per card type.
src/lib/jev/questions.ts The Jev question schema
src/lib/jev/mock.ts Offline keyword classifier (same output shape)
src/lib/parse/ One deterministic parser per card type
src/lib/decide.ts, src/lib/signals.ts The calm-UI state machine
src/components/shapeshift/ Shell, chips, palette, saved list, HUD

Adding a card type

  1. Add the key to INTENT_KEYS in src/lib/jev/types.ts.
  2. Add a non-overlapping criterion to intent in src/lib/jev/questions.ts.
  3. Write a parser in src/lib/parse/ and register it in src/lib/parse/index.ts.
  4. Write a card component in src/components/intents/ and add a registry entry.
  5. Teach the offline classifier in src/lib/jev/mock.ts, and add tests.

TypeScript will point at anything you missed.

Development

bun run check    # typecheck + lint + tests
bun test         # parser, decision, signal and classifier tests
bun run build

Stack: Next.js (App Router) · React 19 · TypeScript (strict) · Tailwind CSS v4 · shadcn/ui · Motion · chrono-node · zod.

License

MIT

shapeshift (anishfn/shapeshift)

Searching Database…

What is this?Shapeshift is a single text input that morphs into the right UI widget as you type — an event card, checklist, timer, color picker, bill splitter, poll, converter and more — based on what it thinks you mean.
Is this a web app I open in a browser, or an installed program?It is a Next.js web app (App Router, React 19) that you run locally and open in a browser.
How do I get it running?Install Bun 1.2+, then run the dev server and open it in your browser to start typing — no account needed.
Do I need an online API key to use it?No — it works fully offline out of the box using a built-in keyword classifier. Adding a TYPESAFE_API_KEY is optional and only enables the online Jev model.
How reliable is the card detection as you type?Raw model output can flicker mid-typing, so a state machine only switches cards once a challenger wins twice in a row (or is very confident), and it silently falls back to offline mode if the online API is unreachable.
What types of UI cards can it generate?Nineteen card types, including event, reminder, checklist, timer, habit, color, split, expense, convert, calculate, trip, poll, contact, bookmark, countdown, time zone, random, goal, and note.
How does the Jev model work alongside deterministic code?One Jev call answers 14 parallel typed questions to classify intent (which card, plus signals like urgency); everything else — dates, amounts, units, math — is handled by deterministic parsing code, not the model.
Can I add my own card type?Yes — add a key to INTENT_KEYS, write a classification criterion, a parser, a card component, and teach the offline mock classifier; TypeScript flags anything you miss.
What does the shortcut row let me do while typing?Enter saves the card, Esc clears or cancels an edit, Tab keeps a faint preview, arrow keys cycle 'Did you mean' chips, and / opens every card type.
Creator
anishfn
Size
11.8 MB
Stars
970
Updated
CommitSep 23
Age
25d
Commits · 90 Days