Recipes
Daily Digest
Scheduled Function posts a daily roll-up of your workspace activity to Slack.
A scheduled Function that runs at 9 AM every weekday, pulls open work across Linear, Sentry, and GitHub, and posts a single condensed summary to Slack. Saves your team's morning standup.
defineJob({
name: "daily-digest",
description: "Morning summary of open work to #standup.",
handler: async (ctx) => {
const [issues, errors, prs] = await Promise.all([
ctx.plugins.linearMcp.listIssues({
filter: { state: { type: { in: ["unstarted", "started"] } } },
limit: 20,
}),
ctx.plugins.sentryMcp.listIssues({
status: "unresolved",
limit: 10,
}),
ctx.plugins.githubMcp.searchIssues({
q: "repo:acme/api is:pr is:open draft:false",
}),
]);
const summary = await ctx.orbit.ai.run({
model: "anthropic/claude-3.7-sonnet",
prompt: [
"Write a tight morning standup roll-up in 6-8 lines. Lead with",
"what blocks work; lump similar items.",
`Open Linear: ${issues.length}`,
`Unresolved Sentry: ${errors.length}`,
`Open PRs: ${prs.length}`,
"Top Linear titles: " + issues.slice(0, 5).map((i) => i.title).join("; "),
"Sentry titles: " + errors.slice(0, 5).map((e) => e.title).join("; "),
].join("\n"),
maxTokens: 300,
});
await ctx.plugins.slackMcp.postMessage({
channel: "#standup",
text: `*Morning roll-up*\n\n${summary}`,
});
return { issues: issues.length, errors: errors.length, prs: prs.length };
},
});hrbr inspect -f ./daily-digest.job.ts
hrbr inspect 'return await hrbr.triggers.list({ limit: 20 })'Create or review the weekday schedule in the Harbor control plane; trigger runs appear in the same trace history as manual invocations.
Cost note
Each run = 3 plugin calls + 1 orbit.ai.run. The AI call is the bulk of
the cost — pin the model and watch the tokens in
Billing → Usage.
Variations
- Per-channel topics: filter Linear by team label, post each team's digest to their own channel.
- PR review reminders: extra Slack DM to PR authors whose PRs are
24h old without review.
- Pause on holidays: skip with
if (isHoliday(new Date())) return;at the top.