Jev Events

CLI

See what Jev says about your inbox, calendar, Slack or any live stream in your terminal, and sign in to your accounts.

The jev-events command ships with the library, so npx runs it without installing anything first. It needs a TypeSafe API key: put TYPESAFE_API_KEY=<your key> in a .env file, or paste the key when it asks and it's saved there for you.

npx jev-events watch bluesky

watch

jev-events watch <source> [questions] [options]

It prints one row per item with each answer, its probability and how long Jev took. Stop it with Ctrl-C, and it prints how many requests it made, the tokens they used and the estimated spend. Text Jev finds likely hateful (p ≥ 0.8) is hidden in the table.

Sources

SourceWhat it readsAsks by default
gmailYour 5 latest emails, then new mail as it arrivesemail.needsReply, email.urgent, email.kind
calendar or calendar:<calendar id>Your 5 next events, then new and changed onescalendar.important, calendar.needsPrep
slack or slack:<channel>,<channel>Messages in the channels and DMs your Slack app is inteam.needsAnswer, team.urgent, team.kind
twitchChat in your own channel, read as your accountchat.kind, chat.hateful
twitch:<channel>Any public Twitch chat, with no sign-inchat.kind, chat.hateful
bluesky or bluesky:<word>,<word>New Bluesky posts, optionally only ones with these wordsWhat each post is about
stdinOne item per line, such as tail -f app.log | npx jev-events watch stdin -a "..."Nothing, so ask at least one question
webhook or webhook:<port>POSTs of {"text": "..."} to http://127.0.0.1:8787/Nothing, so ask at least one question

The default questions are recipes. gmail, calendar, slack and twitch read an account you signed in with auth. They also need the integration installed in the folder you run the command from:

npm i jev-events @jev-events/google # for gmail and calendar
npm i jev-events @jev-events/slack # for slack
npm i jev-events @jev-events/twitch # for twitch

Questions

Questions you pass replace the defaults.

Flag
-a, --ask "label=Question?"A yes/no question. The label is optional. Repeat for more
-c, --choice "Question?" -o a,b,cPick one of these labels
-r, --recipe email.urgentA built-in recipe. Repeatable

Options

FlagDefault
-f, --filter <regex>Only judge items that match
--min <0-1>0.5Yes/no answers count from this probability
--onlyOnly print items where something fired
--rate <n>8Jev requests per second
--context <n>per sourcePreceding items shown to Jev as context
--lang <codes>Bluesky only: posts in these languages, such as en
-m, --model <id>jev-latestThe Jev model
--jsonPrint JSON lines instead of a table

Examples

# Does any of your mail need a reply, or is it urgent? (the default questions)
npx jev-events watch gmail

# Only the events that matter or need preparing for
npx jev-events watch calendar --only

# One Slack channel
npx jev-events watch slack:support

# Your own Twitch chat, as it happens
npx jev-events watch twitch

# Any live channel: what is chat doing, and is any of it hateful?
npx jev-events watch twitch:<channel>

# Your own question, only showing hits
npx jev-events watch twitch:<channel> --only \
  --ask "streamIssue=Is this about the stream's audio or video?"

# Pick a label
npx jev-events watch twitch:<channel> \
  -c "What is this message about?" -o "gameplay,streamer,other"

# Logs
tail -f app.log | npx jev-events watch stdin \
  --ask "Is this an error a human should look at?"

# Bluesky posts about a topic, as JSON lines
npx jev-events watch bluesky:typescript --lang en --json \
  --ask "Is this person asking for help?"

auth

npx jev-events auth google
npx jev-events auth slack
npx jev-events auth twitch

Signs in to an account once and saves it in .jev-events/store.json, in the folder you ran it from. The folder has its own .gitignore, so git leaves it out. watch reads the account from there, and so does a monitor you start on your machine.

The first time, each one walks you through creating your own app on the platform, one step at a time:

  • auth google asks for a Google OAuth client, then opens Google in your browser to approve access to Gmail and Calendar. See Gmail.
  • auth slack prints a link that creates the Slack app with everything filled in, then asks for its two tokens. See Slack.
  • auth twitch asks for a Twitch app's Client ID, then shows a code to approve on Twitch. See Twitch.

auth google and auth twitch remember your app, so signing in to another account later skips the setup. Signing in to the same account again replaces its saved sign-in.

Flag
--client-id <id> --client-secret <secret>Google: use this OAuth client instead of asking. Defaults to GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET
--token <xoxb-…> --app-token <xapp-…>Slack: use these tokens instead of asking
--client-id <id>Twitch: use this app instead of asking. Defaults to TWITCH_CLIENT_ID
--client-secret <secret>Twitch: only for an app registered as Confidential
--scopes "<scope> <scope>"Google and Twitch: ask for fewer permissions. For Google, gmail, calendar or scope URLs

Accounts from the environment

On a server or in CI, where no one can approve a sign-in, watch also reads one account from environment variables. When they're set, it uses them instead of .jev-events/:

IntegrationVariables
GoogleGOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET and GOOGLE_REFRESH_TOKEN
SlackSLACK_BOT_TOKEN and SLACK_APP_TOKEN
TwitchTWITCH_CLIENT_ID and TWITCH_ACCESS_TOKEN, plus TWITCH_REFRESH_TOKEN to renew it

key

npx jev-events key

Prints a new random JEV_EVENTS_KEY. postgresStore() uses it to encrypt the tokens it keeps for your users, so set it once where your app runs and keep it as safe as the database. See the store.

On this page