Introduction
Watch inboxes, calendars, chats and any other stream, ask Jev your questions about each new item, and act on the answers.
Set it up with your coding agent
Pick what to watch and what should happen, then paste the prompt into Claude Code, Cursor or any other coding agent. It reads these docs, writes the code, and tells you each step that needs you.
What to watchWhere it runsWith your own account. The quickest way to try it.
Add Jev Events (https://jevevents.dev) to this project. It watches a stream, such as an inbox or a chat, asks Jev, TypeSafe's model, questions about each new item, and runs code on the answers.
What should happen: ask me, and suggest questions and actions that fit. What to watch: Gmail (https://jevevents.dev/docs/integrations/gmail) Where it runs: On my machine, with my own account.
How: 1. Read https://jevevents.dev/llms-full.txt. It has every docs page, and each integration's page has complete, working code for both ways of running it. 2. Start from that code. Use the built-in recipes where one fits, and write your own questions with noul() or choice() where none does. 3. Tell me each step that needs me, such as creating an app, signing in or getting a TypeSafe API key, with the exact commands. 4. Keep `dryRun: true`, so native actions only log what they would do. Never set `dryRun: false` unless I say so.
What it does
Jev Events is an open-source TypeScript library. It watches a stream, such as an inbox, a calendar, a Slack workspace or a Twitch chat, asks TypeSafe's Jev your questions about each new item, and turns the answers into events. You handle each event with a built-in action, such as archiving an email or timing out a chatter, or with your own code.
import { monitor, recipes } from "jev-events";
import { google } from "@jev-events/google";
const inbox = monitor({
source: google.gmail.inbox(),
questions: {
kind: recipes.email.kind,
needsReply: recipes.email.needsReply,
},
})
.on("kind:newsletter", { min: 0.9 }, google.gmail.archive())
.on("needsReply", { min: 0.8 }, google.gmail.label("Needs reply"));
await inbox.start();- Source
google.gmail.inbox()emits each new email.slack.messages(),twitch.chat(), a webhook or any async iterable work the same way, and each item has typed fields for its platform, such as an email'ssubject. - Questions
recipes.email.kindis achoicebetween labels. A question can also be a yes/nonoul, or ascoreon your own scale. All of an item's questions go to Jev in one request. - Events Names come from your questions, so
"kind:newsletter"exists only becausekindhas anewsletterlabel. A typo is a compile error. - Actions
google.gmail.archive()only logs what it would do until you turn dry-run off, and never touches protected people, such as colleagues. Your own functions run as soon as an answer fires.
Two ways to run it
| On your machine | For your users | |
|---|---|---|
| Whose account | Yours, signed in once with npx jev-events auth | Each user's, connected from your app |
| Runs as | A script you start, such as npx tsx monitor.ts | Routes in your web app, plus a worker for chat |
| Tokens are kept | In .jev-events/ next to your code | In your Postgres database, encrypted |
| Start with | Quickstart → | For your users → |
Each integration's page, such as Gmail, has a builder that writes the code for either one. To see what Jev says before writing anything, npx jev-events watch prints its answers in your terminal. See the CLI.
Where your data goes
Jev Events is a library, not a service. It runs in your own process or web app, with your own TypeSafe key and your own apps on each platform. Items go to TypeSafe's API to be judged, actions go straight to the platform, and tokens stay on your machine or in your database.