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 watch
Where it runs

With your own account. The quickest way to try it.

The prompt

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.

monitor.ts
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's subject.
  • Questions recipes.email.kind is a choice between labels. A question can also be a yes/no noul, or a score on 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 because kind has a newsletter label. 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 machineFor your users
Whose accountYours, signed in once with npx jev-events authEach user's, connected from your app
Runs asA script you start, such as npx tsx monitor.tsRoutes in your web app, plus a worker for chat
Tokens are keptIn .jev-events/ next to your codeIn your Postgres database, encrypted
Start withQuickstart →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.