Hey Pepper

Your AI chief of staffDocs

Hey Pepper
Make it yours

Change what Pepper decides

What leads your brief and what counts as a task are the choices people most want to make their own. Try a setting first. Use code only when a setting can't do what you need.

npm run pepper -- settings                                       # everything, with its value
npm run pepper -- settings briefMaxItems 8                       # at most this many in Yours, and this many in Needs you
npm run pepper -- settings briefWeights '{"dueToday":5,"dueSoon":2,"vip":9,"promise":1,"agePerDay":0.2}'
npm run pepper -- settings taskCapture prefixed                  # only lines starting "todo:", "task:" or "remind me:" become tasks
npm run pepper -- settings taskNudges false                      # no message when a task comes due
npm run pepper -- settings taskCheckInMax 0                      # no check-in in the evening brief

briefWeights is what puts an item at the top. An item earns points for being overdue or due within a day, for being due within three days, for coming from a VIP, for being a promise you made, and a little for each day it has waited, up to two weeks. Raise vip and VIP items climb. Mark a person with /vip <name> in Telegram.

A part, your own folder in src/parts/ (see Make Pepper yours), can replace either decision: what leads your brief, or what counts as a task. Only one part may replace each decision, and one part may replace both, as the example below does. The code that replaces a decision is called a policy. A policy stays small on purpose: it gets the facts and returns an answer. It is given no database, keys or way to send messages, and it shouldn't import them. Pepper's own code keeps the rest: the numbering, so a reply like "2 done" always lands on the right item; the minimum confidence and the duplicate check on new tasks; and delivery.

import type { Part } from "../contract.js";

const FAMILY = new Set(["Mina Holt", "Tavi Reed"]);

export const part: Part = {
  name: "family-first",
  about: "family first in Needs you; task nudges wait until 16:00 UTC",
  briefPolicy: {
    pick: (items, { max }) => [...items].sort((a, b) => Number(FAMILY.has(b.person ?? "")) - Number(FAMILY.has(a.person ?? ""))).slice(0, max),
  },
  taskPolicy: {
    looksLikeTask: (text, shipped) => shipped && !/^fyi\b/i.test(text),
    keep: (draft) => draft.confidence >= 0.7,
    nudge: (task, at) => at.getUTCHours() >= 16,
  },
};

Save it as src/parts/family-first/index.ts, then add one line to src/parts/mine.ts: "family-first": () => import("./family-first/index.js"),.

pick gets the open items you owe that Pepper found in your chats, ordered by your weights with the best first. The tasks you gave Pepper yourself, what you're waiting on from others and the evening check-ins are not in it. Return the ones you want, in your order. Leave one out and it stays off the brief but still shows on the dashboard.

looksLikeTask runs on each message you send Pepper, before the model is asked; shipped is Pepper's own answer, for you to build on. looksLikeTask is not used while taskCapture is prefixed, so set taskCapture back to anything first. keep sees each task the model drafted, with its confidence from 0 to 1, once it has passed Pepper's own minimum. nudge is asked when a task comes due, with the time in UTC; return false to leave it for a later check.

If a policy fails, the brief still goes out in Pepper's usual order and says so at the foot, and tasks fall back to Pepper's usual rules. Once your policy makes a choice, later changes to how Pepper makes that same choice reach you only through the shipped answer and the order your policy builds on. Every other fix still arrives.

On this page