Webhook Subscriptions
Tommy-yw/RunbookHermes
Create and manage webhook subscriptions for event-driven agent activation, or for direct push notifications (zero LLM cost).
A skill your agent uses when designing event-driven workflows, decoupling services, implementing fan-out patterns (one trigger, many downstream handlers), implementing idempotent event handling with…
$ npx skills add Asymmetric-al/core --skill inngest-events -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install Asymmetric-al/core inngest-events --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/Asymmetric-al/core.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/inngest-events .claude/skills/inngest-events && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "inngest-events" agent skill from https://github.com/Asymmetric-al/core/tree/develop/.agents/skills/inngest-events into .claude/skills/inngest-events/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "inngest-events", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/Asymmetric-al/core/tree/develop/.agents/skills/inngest-eventsType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add Asymmetric-al/core --skill inngest-events -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install Asymmetric-al/core inngest-events --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Asymmetric-al/core.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/inngest-events .agents/skills/inngest-events && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "inngest-events" agent skill from https://github.com/Asymmetric-al/core/tree/develop/.agents/skills/inngest-events into .agents/skills/inngest-events/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "inngest-events", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Asymmetric-al/core --skill inngest-events -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install Asymmetric-al/core inngest-events --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Asymmetric-al/core.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/inngest-events .cursor/skills/inngest-events && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "inngest-events" agent skill from https://github.com/Asymmetric-al/core/tree/develop/.agents/skills/inngest-events into .cursor/skills/inngest-events/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "inngest-events", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/Asymmetric-al/core.git --path .agents/skills/inngest-events--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add Asymmetric-al/core --skill inngest-events -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install Asymmetric-al/core inngest-events --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Asymmetric-al/core.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/inngest-events .gemini/skills/inngest-events && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "inngest-events" agent skill from https://github.com/Asymmetric-al/core/tree/develop/.agents/skills/inngest-events into .gemini/skills/inngest-events/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "inngest-events", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install Asymmetric-al/core inngest-eventsInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add Asymmetric-al/core --skill inngest-events -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/Asymmetric-al/core.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/inngest-events .github/skills/inngest-events && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "inngest-events" agent skill from https://github.com/Asymmetric-al/core/tree/develop/.agents/skills/inngest-events into .github/skills/inngest-events/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "inngest-events", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Asymmetric-al/core --skill inngest-events -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install Asymmetric-al/core inngest-events --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Asymmetric-al/core.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/inngest-events .opencode/skills/inngest-events && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "inngest-events" agent skill from https://github.com/Asymmetric-al/core/tree/develop/.agents/skills/inngest-events into .opencode/skills/inngest-events/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "inngest-events", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
inngest-eventsA skill your agent uses when designing event-driven workflows, decoupling services, implementing fan-out patterns (one trigger, many downstream handlers), implementing idempotent event handling with…
Inngest Events is an agent skill from Asymmetric-al/core. Use when designing event-driven workflows, decoupling services, implementing fan-out patterns (one trigger, many downstream handlers), implementing idempotent event handling with IDs (24-hour dedupe window), or handling at-least-once delivery from external sources like Stripe webhooks. Covers Inngest event schema, payload format, naming conventions, IDs for idempotency, the ts param, fan-out patterns, and system events like inngest/function.failed.
Its SKILL.md is about 3.3k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Backend & APIs, covering Webhooks and Event-driven systems. It works with Stripe. The repository describes itself as: A high-performance, enterprise-grade Next.js 16 application for mission-focused non-profit organizations. Built for high impact teams. The licence is AGPL-3.0.
5 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit c30c8ff. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript).
From the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
inngest.comFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
INNGEST_EVENT_KEYFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Inngest Events loads about 3.3k tokens when it runs. Until then it costs about 117 tokens; SKILL.md has 476 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from Asymmetric-al/core at commit c30c8ff, republished under its AGPL-3.0 licence (© Asymmetric-al). 476 words, ~3,334 tokens.
.claude/skills/inngest-events/SKILL.md (or your agent's skills folder).Master Inngest event design and delivery patterns. Events are the foundation of Inngest - learn to design robust event schemas, implement idempotency, leverage fan-out patterns, and handle system events effectively.
These skills are focused on TypeScript. For Python or Go, refer to the Inngest documentation for language-specific guidance. Core concepts apply across all languages.
Every Inngest event is a JSON object with required and optional properties:
type Event = {
name: string; // Event type (triggers functions)
data: object; // Payload data (any nested JSON)
};type EventPayload = {
name: string; // Required: event type
data: Record<string, any>; // Required: event data
id?: string; // Optional: deduplication ID
ts?: number; // Optional: timestamp (Unix ms)
v?: string; // Optional: schema version
};await inngest.send({
name: "billing/invoice.paid",
data: {
customerId: "cus_NffrFeUfNV2Hib",
invoiceId: "in_1J5g2n2eZvKYlo2C0Z1Z2Z3Z",
userId: "user_03028hf09j2d02",
amount: 1000,
metadata: {
accountId: "acct_1J5g2n2eZvKYlo2C0Z1Z2Z3Z",
accountName: "Acme.ai",
},
},
});Use the Object-Action pattern: domain/noun.verb
// ✅ Good: Clear object-action pattern
"billing/invoice.paid";
"user/profile.updated";
"order/item.shipped";
"ai/summary.completed";
// ✅ Good: Domain prefixes for organization
"stripe/customer.created";
"intercom/conversation.assigned";
"slack/message.posted";
// ❌ Avoid: Unclear or inconsistent
"payment"; // What happened?
"user_update"; // Use dots, not underscores
"invoiceWasPaid"; // Too verbosecreated, updated, failed)billing/invoice.paid)api/user.created, webhook/stripe.received)When to use IDs: Prevent duplicate processing when events might be sent multiple times.
await inngest.send({
id: "cart-checkout-completed-ed12c8bde", // Unique per event type
name: "storefront/cart.checkout.completed",
data: {
cartId: "ed12c8bde",
items: ["item1", "item2"],
},
});// ✅ Good: Specific to event type and instance
id: `invoice-paid-${invoiceId}`;
id: `user-signup-${userId}-${timestamp}`;
id: `order-shipped-${orderId}-${trackingNumber}`;
// ❌ Bad: Generic IDs shared across event types
id: invoiceId; // Could conflict with other events
id: "user-action"; // Too generic
id: customerId; // Same customer, different eventsDeduplication window: 24 hours from first event reception
See inngest-durable-functions for idempotency configuration.
ts Parameter for Delayed DeliveryWhen to use: Schedule events for future processing or maintain event ordering.
const oneHourFromNow = Date.now() + 60 * 60 * 1000;
await inngest.send({
name: "trial/reminder.send",
ts: oneHourFromNow, // Deliver in 1 hour
data: {
userId: "user_123",
trialExpiresAt: "2024-02-15T12:00:00Z",
},
});// Events with timestamps are processed in chronological order
const events = [
{
name: "user/action.performed",
ts: 1640995200000, // Earlier
data: { action: "login" },
},
{
name: "user/action.performed",
ts: 1640995260000, // Later
data: { action: "purchase" },
},
];
await inngest.send(events);Use case: One event triggers multiple independent functions for reliability and parallel processing.
// Send single event
await inngest.send({
name: "user/signup.completed",
data: {
userId: "user_123",
email: "user@example.com",
plan: "pro",
},
});
// Multiple functions respond to same event
const sendWelcomeEmail = inngest.createFunction(
{ id: "send-welcome-email", triggers: [{ event: "user/signup.completed" }] },
async ({ event, step }) => {
await step.run("send-email", async () => {
return sendEmail({
to: event.data.email,
template: "welcome",
});
});
},
);
const createTrialSubscription = inngest.createFunction(
{ id: "create-trial", triggers: [{ event: "user/signup.completed" }] },
async ({ event, step }) => {
await step.run("create-subscription", async () => {
return stripe.subscriptions.create({
customer: event.data.stripeCustomerId,
trial_period_days: 14,
});
});
},
);
const addToCrm = inngest.createFunction(
{ id: "add-to-crm", triggers: [{ event: "user/signup.completed" }] },
async ({ event, step }) => {
await step.run("crm-sync", async () => {
return crm.contacts.create({
email: event.data.email,
plan: event.data.plan,
});
});
},
);waitForEventIn expressions, event = the original triggering event, async = the new event being matched. See Expression Syntax Reference for full details.
const orchestrateOnboarding = inngest.createFunction(
{
id: "orchestrate-onboarding",
triggers: [{ event: "user/signup.completed" }],
},
async ({ event, step }) => {
// Fan out to multiple services
await step.sendEvent("fan-out", [
{ name: "email/welcome.send", data: event.data },
{ name: "subscription/trial.create", data: event.data },
{ name: "crm/contact.add", data: event.data },
]);
// Wait for all to complete
const [emailResult, subResult, crmResult] = await Promise.all([
step.waitForEvent("email-sent", {
event: "email/welcome.sent",
timeout: "5m",
if: `event.data.userId == async.data.userId`,
}),
step.waitForEvent("subscription-created", {
event: "subscription/trial.created",
timeout: "5m",
if: `event.data.userId == async.data.userId`,
}),
step.waitForEvent("crm-synced", {
event: "crm/contact.added",
timeout: "5m",
if: `event.data.userId == async.data.userId`,
}),
]);
// Complete onboarding
await step.run("complete-onboarding", async () => {
return completeUserOnboarding(event.data.userId);
});
},
);See inngest-steps for additional patterns including step.invoke.
Inngest emits system events for function lifecycle monitoring:
// Function execution events
"inngest/function.failed"; // Function failed after retries
"inngest/function.finished"; // Function finished - completed or failed
"inngest/function.cancelled"; // Function cancelled before completionconst handleFailures = inngest.createFunction(
{
id: "handle-failed-functions",
triggers: [{ event: "inngest/function.failed" }],
},
async ({ event, step }) => {
const { function_id, run_id, error } = event.data;
await step.run("log-failure", async () => {
logger.error("Function failed", {
functionId: function_id,
runId: run_id,
error: error.message,
stack: error.stack,
});
});
// Alert on critical function failures
if (function_id.includes("critical")) {
await step.run("send-alert", async () => {
return alerting.sendAlert({
title: `Critical function failed: ${function_id}`,
severity: "high",
runId: run_id,
});
});
}
// Auto-retry certain failures
if (error.code === "RATE_LIMIT_EXCEEDED") {
await step.run("schedule-retry", async () => {
return inngest.send({
name: "retry/function.requested",
ts: Date.now() + 5 * 60 * 1000, // Retry in 5 minutes
data: { originalRunId: run_id },
});
});
}
},
);// inngest/client.ts
import { Inngest } from "inngest";
export const inngest = new Inngest({
id: "my-app",
});
// You must set INNGEST_EVENT_KEY environment variable in productionconst result = await inngest.send({
name: "order/placed",
data: {
orderId: "ord_123",
customerId: "cus_456",
amount: 2500,
items: [
{ id: "item_1", quantity: 2 },
{ id: "item_2", quantity: 1 },
],
},
});
// Returns event IDs for tracking
console.log(result.ids); // ["01HQ8PTAESBZPBDS8JTRZZYY3S"]const orderItems = await getOrderItems(orderId);
// Convert to events
const events = orderItems.map((item) => ({
name: "inventory/item.reserved",
data: {
itemId: item.id,
orderId: orderId,
quantity: item.quantity,
warehouseId: item.warehouseId,
},
}));
// Send all at once (up to 512kb)
await inngest.send(events);inngest.createFunction(
{ id: "process-order", triggers: [{ event: "order/placed" }] },
async ({ event, step }) => {
// Use step.sendEvent() instead of inngest.send() in functions
// for reliability and deduplication
await step.sendEvent("trigger-fulfillment", {
name: "fulfillment/order.received",
data: {
orderId: event.data.orderId,
priority: event.data.customerTier === "premium" ? "high" : "normal",
},
});
},
);// Use version field to track schema changes
await inngest.send({
name: "user/profile.updated",
v: "2024-01-15.1", // Schema version
data: {
userId: "user_123",
changes: {
email: "new@example.com",
preferences: { theme: "dark" },
},
// New field in v2 schema
auditInfo: {
changedBy: "user_456",
reason: "user_requested",
},
},
});// Include enough context for all consumers
await inngest.send({
name: "payment/charge.succeeded",
data: {
// Primary identifiers
chargeId: "ch_123",
customerId: "cus_456",
// Amount details
amount: 2500,
currency: "usd",
// Context for different consumers
subscription: {
id: "sub_789",
plan: "pro_monthly",
},
invoice: {
id: "inv_012",
number: "INV-2024-001",
},
// Metadata for debugging
paymentMethod: {
type: "card",
last4: "4242",
brand: "visa",
},
metadata: {
source: "stripe_webhook",
environment: "production",
},
},
});Event design principles:
These upstream Inngest instructions are vendored for agent tooling and integration work in this monorepo.
Use this skill when inngest-events matches the current Inngest task. If the
right skill is unclear, start with docs/ai/skills/inngest/SKILL.md.
inngest-brownfield-audit before changing existing app workflows or
fragile background work.AGENTS.md, repo
rulebooks, framework docs, and runtime evidence.INNGEST_* env
requirements out of agent-tooling-only changes.docs/ai/skills/inngest/references/upstream.md.© Asymmetric-al, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .agents/skills/inngest-events of Asymmetric-al/core.
Open the folder on GitHubat commit c30c8ff
Inngest Events next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Inngest Events this skillAsymmetric-al/core | 381 | — | ~3.3k | Automated safety check: Pass | AGPL-3.0 | |
| Webhook SubscriptionsTommy-yw/RunbookHermes | 546 | 1 repos | ~1.7k | Automated safety check: Notes | MIT | |
| Webhook Subscriptionsmateaix/mateclaw | 1.2k | — | ~1.7k | Automated safety check: Notes | Apache-2.0 | |
| Webhook SubscriptionsRedWoodOG/Hermes-Desktop | 177 | — | ~1.4k | Automated safety check: Notes | None | |
| Stripe Projectsfossasia/eventyay | 1.7k | 5 repos | ~2k | Automated safety check: Notes | Apache-2.0 | |
| Stripe Appsfossasia/eventyay | 1.7k | 1 repos | ~3.6k | Automated safety check: Pass | Apache-2.0 |
Tommy-yw/RunbookHermes
Create and manage webhook subscriptions for event-driven agent activation, or for direct push notifications (zero LLM cost).
mateaix/mateclaw
Webhook subscriptions: event-driven agent runs. An agent skill from mateaix/mateclaw.
RedWoodOG/Hermes-Desktop
Create and manage webhook subscriptions for event-driven agent activation.
fossasia/eventyay
A skill your agent uses when the user wants to provision infrastructure or third-party services using Stripe Projects.
fossasia/eventyay
A skill your agent uses when building, modifying, or reviewing a Stripe App — or when the user describes something that implies one (e.g.
kanchengw/cnllm
Guides Stripe integration decisions — API selection (Checkout Sessions vs PaymentIntents), Connect platform setup (Accounts v2, controller properties), billing/subscriptions, Treasury financial…
Asymmetric-al/core
Implement idempotency keys and handling to ensure operations can be safely retried without duplicate effects.
Asymmetric-al/core
Audit and fix accessibility in Core UI. An agent skill from Asymmetric-al/core.
Asymmetric-al/core
A skill your agent uses when building any system where email content triggers actions — AI agent inboxes, automated support handlers, email-to-task pipelines, or any workflow processing untrusted…
Asymmetric-al/core
Build modern, composable, and accessible React UI components following the components.build specification.
Asymmetric-al/core
Guides a one-question-at-a-time design interview, captures alignment in agent/EVE-BRIEF.md, then scaffolds and implements a runnable eve agent with verbose teaching comments.
Asymmetric-al/core
Design engineering principles and patterns for building polished, accessible web interfaces.
Works with
Categories
A skill your agent uses when designing event-driven workflows, decoupling services, implementing fan-out patterns (one trigger, many downstream handlers), implementing idempotent event handling with…. Inngest Events is an agent skill from Asymmetric-al/core. Use when designing event-driven workflows, decoupling services, implementing fan-out patterns (one trigger, many downstream handlers), implementing idempotent event handling with IDs (24-hour dedupe window), or handling at-least-once delivery from external sources like Stripe webhooks.
Inngest Events fits situations like: designing event-driven workflows; decoupling services; implementing fan-out patterns (one trigger; many downstream handlers).
Run `npx skills add Asymmetric-al/core --skill inngest-events -a claude-code`. Or copy the skill folder (.agents/skills/inngest-events in Asymmetric-al/core) into .claude/skills/inngest-events in your project. Claude Code loads it when a task matches its description.
Run `npx skills add Asymmetric-al/core --skill inngest-events -a codex`. Or copy the skill folder (.agents/skills/inngest-events in Asymmetric-al/core) into .agents/skills/inngest-events in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Asymmetric-al/core --skill inngest-events -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/inngest-events, .gemini/skills/inngest-events, .github/skills/inngest-events and .opencode/skills/inngest-events in your project.
Going by SKILL.md and its folder, Inngest Events needs credentials named INNGEST_EVENT_KEY. Our summary lists: Python 3; A credential in INNGEST_EVENT_KEY.
SKILL.md names 1 domain. As links in the text: inngest.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Inngest Events is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.3k tokens (SKILL.md is roughly 13k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Inngest Events: Webhook Subscriptions (Tommy-yw/RunbookHermes, 546 stars), Webhook Subscriptions (mateaix/mateclaw, 1.2k stars), Webhook Subscriptions (RedWoodOG/Hermes-Desktop, 177 stars) and Stripe Projects (fossasia/eventyay, 1.7k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Asymmetric-al (a GitHub organization) maintains it in Asymmetric-al/core, which has 381 GitHub stars. The repository holds 43 skills in this directory. The repository was last updated on October 9, 2026.
Source: Asymmetric-al/core on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.