
Ce Product Pulse
- 2.2k installs
- 23.9k repo stars
- Updated August 5, 2026
- everyinc/compound-engineering-plugin
ce-product-pulse is an agent skill that Generate a time-windowed pulse report on what users experienced and how the product performed - usage, quality, errors, .
About
ce product pulse queries the product s data sources for a given time window and produces a compact single page report covering usage performance errors and followups The report is saved to docs pulse reports and the key points are surfaced in chat The skill does not mutate the product the database or any external system Its only writes are pulse settings appended to compound engineering config local yaml the unified CE local config gitignored machine local and the report file docs pulse reports MCP and other data source tools are invoked read only if a tool offers write modes do not use them Default to the platform s blocking question tool AskUserQuestion in Claude Code call ToolSearch with select AskUserQuestion first if its schema isn t loaded request_user_input in Codex ask_question in Antigravity CLI agy ask_user in Pi requires the pi ask user extension Fall back to numbered options in chat only when no blocking tool exists in the harness or the call errors e g Codex edit modes
- description: "Generate a time-windowed pulse report on what users experienced and how the product performed - usage, qua
- argument-hint: "[lookback window, e.g. '24h', '7d', '1h'; default 24h]"
- `ce-product-pulse` queries the product's data sources for a given time window and produces a compact, single-page report
- Follow ce-product-pulse SKILL.md steps and documented constraints.
- Follow ce-product-pulse SKILL.md steps and documented constraints.
Ce Product Pulse by the numbers
- 2,161 all-time installs (skills.sh)
- +67 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #542 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
ce-product-pulse capabilities & compatibility
- Capabilities
- description: "generate a time windowed pulse rep · argument hint: "[lookback window, e.g. '24h', '7 · `ce product pulse` queries the product's data so · follow ce product pulse skill.md steps and docum
- Use cases
- orchestration
What ce-product-pulse says it does
description: "Generate a time-windowed pulse report on what users experienced and how the product performed - usage, quality, errors, signals worth investigating. Use when the user says 'run a pulse',
argument-hint: "[lookback window, e.g. '24h', '7d', '1h'; default 24h]"
`ce-product-pulse` queries the product's data sources for a given time window and produces a compact, single-page report covering usage, performance, errors, and followups. The report is saved to `doc
npx skills add https://github.com/everyinc/compound-engineering-plugin --skill ce-product-pulseAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2.2k |
|---|---|
| repo stars | ★ 23.9k |
| Security audit | 3 / 3 scanners passed |
| Last updated | August 5, 2026 |
| Repository | everyinc/compound-engineering-plugin ↗ |
When should an agent use ce-product-pulse and what problem does it solve?
Generate a time-windowed pulse report on what users experienced and how the product performed - usage, quality, errors, signals worth investigating. Use when the user says 'run a pulse', 'show me the
Who is it for?
Developers invoking ce-product-pulse as documented in the skill source.
Skip if: Skip when requirements fall outside ce-product-pulse documented scope.
When should I use this skill?
Generate a time-windowed pulse report on what users experienced and how the product performed - usage, quality, errors, signals worth investigating. Use when the user says 'run a pulse', 'show me the
What you get
Outputs aligned with the ce-product-pulse SKILL.md workflow and stated deliverables.
- .compound-engineering/config.local.yaml
- pulse_* configuration keys
By the numbers
- Allows one pushback round per interview section maximum
Files
Product Pulse
ce-product-pulse queries the product's data sources for a given time window and produces a compact, single-page report covering usage, performance, errors, and followups. The report is saved to docs/pulse-reports/ and the key points are surfaced in chat.
The skill does not mutate the product, the database, or any external system. Its only writes are pulse settings appended to .compound-engineering/config.local.yaml (the unified CE local config, gitignored, machine-local) and the report file (docs/pulse-reports/...). MCP and other data-source tools are invoked read-only; if a tool offers write modes, do not use them.
Interaction Method
Default to the platform's blocking question tool: AskUserQuestion in Claude Code (call ToolSearch with select:AskUserQuestion first if its schema isn't loaded), request_user_input in Codex, ask_question in Antigravity CLI (agy), ask_user in Pi (requires the pi-ask-user extension). Fall back to numbered options in chat only when no blocking tool exists in the harness or the call errors (e.g., Codex edit modes) — not because a schema load is required. Never silently skip the question.
Ask one question at a time. Reserve multi-select for first-run configuration only.
Lookback Window
<lookback> #$ARGUMENTS </lookback>
Interpret the argument as a time window. Common forms:
24h,48h,72h- trailing hours7d,30d- trailing days1h- short-window (useful during launches)
If the argument is empty, default to pulse_lookback_default from config (resolved in Phase 0); if that is also unset, fall through to the hard default of 24h. If the argument is unparseable, ask the user to clarify.
Apply a 15-minute trailing buffer to the window's upper bound. Many analytics and tracing tools have ingestion lag; querying right up to now under-reports the most recent events. For a 24h window, query [now - 24h - 15m, now - 15m].
Core Principles
1. Read it like a founder. No hardcoded thresholds. Do not label things "bad" or "good" by default - present the numbers and let the reader judge. 2. Single page. Target 30-40 lines of terminal output. If the report is getting long, cut. 3. No PII in saved reports. Do not include user emails, account IDs, or message content in the report written to disk. 4. Parallel where safe, serial where it matters. Analytics and tracing queries run in parallel. Database queries run serially to avoid load. 5. Memory through saved reports. Every run writes to docs/pulse-reports/ so past pulses are browseable as a timeline. 6. Read-only database access only. If a database is used as a data source, the connection must be read-only. The interview refuses to accept read-write credentials. Database access is optional - many products complete the pulse with analytics and tracing alone. 7. Strategy-seeded when available. If STRATEGY.md exists, the interview reads it before asking questions and carries forward the product name and key metrics as seeds. The goal of data-source setup is to wire up whatever connections are needed to actually measure those metrics.
Execution Flow
Phase 0: Route by Config State
Read config. The repo root is pre-resolved at skill load: !git rev-parse --show-toplevel 2>/dev/null || true
If the line above is an absolute path, use it as <repo-root>. If it is empty or still shows a backtick command string (a non-Claude harness that did not run the pre-resolution), resolve <repo-root> at runtime by running git rev-parse --show-toplevel with the shell tool. Then read <repo-root>/.compound-engineering/config.local.yaml with the native file-read tool (e.g., Read in Claude Code, read_file in Codex). If the root cannot be resolved or the file does not exist, treat this as a first run. Otherwise extract values for the pulse_* keys listed under "Config keys" below.
Config keys:
pulse_product_name-- string, used in report titles. Required for routing: if unset, skill is unconfigured.pulse_lookback_default-- one of1h,24h,7d,30d(default:24h)pulse_primary_event-- string, the engagement event namepulse_value_event-- string, the value-realization event namepulse_completion_events-- comma-separated string of 0-3 event namespulse_quality_scoring--trueor defaultfalse(AI products only)pulse_quality_dimension-- string scored 1-5 whenpulse_quality_scoringis true; ignored otherwisepulse_analytics_source-- string identifying analytics provider (e.g.,posthog,mixpanel,custom)pulse_tracing_source-- string identifying tracing provider (e.g.,sentry,datadog,custom)pulse_payments_source-- string identifying payments provider (e.g.,stripe,custom); omit if not usedpulse_db_enabled--trueor defaultfalse; whentrue, read-only DB access is part of the pulsepulse_metric_sources-- comma-separatedmetric=sourcepairs giving per-strategy-metric source overrides (e.g.,retention_d7=posthog,nps=delighted). Strategy metrics not listed fall back topulse_analytics_sourceand are rendered with a(default source)marker so the implicit routing is visible.pulse_pending_metrics-- comma-separated string of strategy-doc metric names awaiting instrumentation; rendered asno datain each pulse report until instrumentation landspulse_excluded_metrics-- comma-separated string of strategy-doc metric names intentionally excluded from the pulse; the metric stays inSTRATEGY.mdbut is not surfaced in pulse reports
Routing:
- `pulse_product_name` is unset (or config file missing) -> First run. Go to Phase 1 (interview), then Phase 2.
- `pulse_product_name` is set -> Skip to Phase 2.
If the argument was setup, reconfigure, or edit config, go to Phase 1 regardless of config state.
Phase 1: First-Run Interview
1.0 Seed from strategy (if available)
Before asking any questions, read STRATEGY.md using the native file-read tool. If the file exists, extract:
- The product name from the
namekey in the YAML frontmatter, falling back to the H1 title (stripping the trailingStrategysuffix, e.g.,# Spiral Strategy->Spiral) if frontmatter is missing - The list of key metrics from the
## Key metricssection, one per line
Open the interview by surfacing what was extracted: announce that a strategy doc was found, show the seeded product name and the list of key metrics that will be carried into event/data setup, and invite the user to correct any of it before continuing.
If STRATEGY.md does not exist, note that explicitly in chat: no strategy doc on file, running setup from scratch, and mention that ce-strategy can seed pulse later if run first.
1.1 Interview
Read references/interview.md. This load is non-optional - the pushback rules, anti-pattern examples, and metric-to-source mapping logic live there.
Run the interview in this order:
1. Product name (confirm or edit the seeded value) 2. Primary engagement event 3. Value-realization event 4. Completions or conversions (0-3) 5. Quality scoring (opt-in, AI products only) 6. Data sources - wire up connections for each agreed metric and event. Nudge toward MCP. Reject read-write database access. DB entirely optional. 7. System performance - a short recommended setup for top errors and latency. Users rarely have strong opinions here; present defaults and accept. 8. Default lookback window
Apply the pushback rules in references/interview.md for each section. Treat every metric, event, and signal the user proposes against the SMART bar (specific, measurable, actionable, relevant, timely) spelled out in references/interview.md under "Overall Rules" - push back on anything vague, vanity, or unactionable.
If the user offers read-write database access, refuse and offer the alternatives documented in references/interview.md section 6.
Write the captured config to <repo-root>/.compound-engineering/config.local.yaml as flat pulse_* keys, using the schema in references/interview.md under "Config file shape". Resolve the repo root with git rev-parse --show-toplevel. To write: (1) if the file or directory does not exist, create .compound-engineering/ and write the YAML file; (2) if the file exists, merge new keys into the existing YAML, preserving any non-pulse keys (e.g., work_delegate_*) untouched. If .compound-engineering/config.local.yaml is not already covered by the repo's .gitignore, offer to add the entry before writing. Show the resulting pulse block to the user in chat and offer one round of edits.
After the config is written, run the scheduling recommendation from references/interview.md section 9: offer to set up a recurring run so the user gets the pulse on a cadence instead of having to remember to run it. Accept yes/no/later. If yes, hand off to whichever scheduling primitive the current harness exposes — the in-plugin schedule skill if it is installed, otherwise note that scheduling is platform-specific (cron, GitHub Actions, the host's own automation) and emit a brief hint covering what would need to run. Do not schedule inline. Then proceed to Phase 2.
Phase 2: Run the Pulse
If Phase 1 ran (first run, or setup/reconfigure argument), re-read .compound-engineering/config.local.yaml from the repo root using the native file-read tool to pick up any edits accepted during the Phase 1 review step. Otherwise, use the pulse_* values already extracted in Phase 0. Apply hard defaults for any unset settings (see Phase 0 "Config keys").
2.1 Dispatch Queries
Run these in parallel (different tools, no shared load):
- Product analytics query (primary event count, value-realization count, completions, conversion ratios) over the window
- Application tracing query (error counts by category, latency distribution, top error signatures) over the window
- Payments query, if configured (new customers, churn, revenue delta) over the window
Run these serially, after the parallel batch:
- Read-only database queries. One at a time. Tight, scoped queries only. Never full-table scans on large tables. If a DB query would be expensive, skip it and note "DB query skipped (estimated cost too high)".
2.2 Optional: Sample Quality Scoring
If pulse_quality_scoring is true (AI products only), sample up to 10 sessions or conversations from the window and score each 1-5 on the dimension recorded in pulse_quality_dimension.
Scoring discipline: Default to 4 or 5 when the session looks normal. Reserve 1-3 for sessions with a clear failure mode (product gave wrong answer, user got stuck, error surfaced). If every session is scoring 3, the bar is too strict; if every session is scoring 5, the bar is too loose.
No PII in the score summary. Capture a count distribution (e.g., "8x 5, 1x 4, 1x 2") and a short anonymized note on any session scored below 4. Do not include message content or user identifiers in the saved report.
2.3 Assemble the Report
Read references/report-template.md. Fill in the template using the query results. Four sections, in order:
1. Headlines - 2-3 lines summarizing the window 2. Usage - primary engagement, value realization, completions, quality sample 3. System performance - latency (p50/p95/p99) and top 5 errors by count with one-line explanation each 4. Followups - 1-5 things worth investigating
Keep the total to 30-40 lines. If a section is thin, leave it thin; do not pad.
2.4 Write the Report
Save to docs/pulse-reports/YYYY-MM-DD_HH-MM.md using the local time of the run. Create docs/pulse-reports/ if it does not exist.
Surface the Headlines and top Followup in chat. Provide the full file path so the user can open the saved report.
Phase 3: Routine Hook
First-run setup already offered scheduling (see Phase 1.1 end). Phase 3 is a lighter re-surface for ad-hoc runs:
- If the argument was a known schedule keyword (
daily,hourly,weekly), note that this run is ad-hoc and suggest scheduling via the harness's available primitive (the in-pluginscheduleskill where present; otherwise a platform-native option) for recurring runs. - If no schedule is on file and this is the third or later pulse run the user has done, mention once that scheduling is available. Don't nag on every run.
Never schedule automatically. Any scheduling handoff requires explicit confirmation.
What This Skill Does Not Do
- Does not report "what shipped." Shipped work lives in the issue tracker and commit history, not here. Pulse is strictly about user experience and system performance.
- Does not set thresholds or alert the user. The reader interprets.
- Does not persist PII in saved reports.
- Does not mutate the database or any external system. All queries are read-only.
- Does not replace tracing dashboards or analytics tools. It consolidates a single-page read; deep investigation still uses the native tools.
Learn More
The "read like a founder" posture and the single-page constraint are deliberate. Dashboards with 40 metrics produce attention sprawl; one page with the right four sections forces the reader to notice what matters. The saved-reports folder is designed to be a team's working memory, not a data warehouse - past pulses are grepable, diffable, and disposable.
Product Pulse First-Run Interview
Loaded by SKILL.md at the start of Phase 1. Captures the configuration that will be merged into .compound-engineering/config.local.yaml (the unified CE local config, gitignored, machine-local) as pulse_* keys and re-read on every subsequent run.
For each section: ask the opening question, evaluate the answer against the quality bar, push back when it falls into a named anti-pattern, and capture the final answer in the user's own language.
Overall Rules
1. Push back, but don't spiral. One round of pushback per section max. If the second answer still isn't usable, capture what the user gave, flag it in the config as needs-review, and move on. 2. Name events in the user's own words. The config will be readable by the whole team - use the terms they actually use, not a generic template. 3. Ask about tools, not credentials. The interview captures which tool and what shape of query. It does not collect API keys, tokens, or database passwords. Those stay in the user's environment. 4. Honor strategy seeds. If SKILL.md Phase 1.0 surfaced a product name or a list of key metrics from STRATEGY.md, start with those as defaults and let the user edit. Do not re-ask questions that the strategy doc already answered unambiguously. 5. Evaluate metrics against the SMART bar. Every event, metric, and signal the user proposes should be:
- Specific - a named event or a named metric, not a category.
message_sentpasses; "engagement" does not. - Measurable - you can point to the tool and query that returns a number. "Users like it" does not pass; "NPS score from Delighted" does.
- Actionable - if the number moves, the team knows what to do next. "Daily active users" alone usually fails this - pair it with a conversion or retention signal that surfaces a decision.
- Relevant - ties to the product's target problem and persona (from the strategy doc if seeded). Generic funnel metrics that don't connect to the strategy are suspect.
- Timely - reads in the pulse window (24h, 7d, etc.) and reflects the current state. Lagging metrics that only move quarterly don't belong in a daily pulse.
When a user proposes a metric that fails one of these, push back by naming the specific dimension: "That sounds more like a vanity metric than an actionable one - if it moves, what do we do? Is there a tighter signal that would drive a decision?" Do not use the word "SMART" with the user; use the plain-English question.
---
1. Product Name
Opening question:
- If seeded from strategy: "Product name from strategy is
{{name}}. Keep it or edit?" - Otherwise: "What's the product called?"
No pushback needed. Capture verbatim.
---
2. Primary Engagement Event
Opening question: "When someone is using your product, what single event fires? The one that tells you a user is active right now."
This is the heartbeat of the pulse. Pick one event - the one that represents a user actually using the product, not opening a page.
Apply the SMART bar (see Overall Rules). The event must be specific (a named event), measurable (the analytics tool returns a count), actionable (if it moves, the team notices), relevant (ties to the product's job), and timely (reads cleanly in short windows).
Engagement vs value test. After the user names an event, ask yourself: does this event fire when the user is using the product, or when the user has gotten value from it? Engagement is earlier (they're in it). Value is later (it worked). If the candidate is really value-realization, push back: "That sounds like the moment the product worked for them. What event happens earlier - when they're in the middle of using it? The value event belongs in section 3." Common slips: agent_accepted_draft (value) vs agent_received_draft (engagement); ride_completed (value) vs ride_started (engagement); question_answered_correctly (value) vs question_asked (engagement).
Anti-patterns and pushback:
- Page view or visit ("pageview", "app opened", "login") -> "Those tell you someone showed up. I'm looking for the event that says they actually used the product. What fires when a user is doing the thing the product is for?"
- Multiple events with no clear primary ("well, it could be X or Y or Z depending on the flow") -> "For the pulse, pick the one that's closest to 'a user is active using the core product.' If two candidates are genuinely tied, pick the one that happens when the user spends time in exchange for value - for async products that's usually 'contributed content' over 'opened app'."
- Too deep in the funnel ("purchase_completed") -> "That's a conversion event - we'll capture that separately. For the primary engagement event, what happens earlier - when they're using the product, not when they've already converted?"
- Vague ("interaction", "activity") -> "Is there a specific event name in your analytics tool? I want to write down the literal event name so this is repeatable."
Capture: Event name verbatim (e.g., message_sent, document_edited, ride_started). Plus a one-line description of what it means.
---
3. Value-Realization Event
Opening question: "What event fires when a user actually gets value - when the product delivered what they came for?"
Different from engagement. Engagement says "they're using it"; value-realization says "they got what they wanted." Some products have a clear distinction (engagement: typed_in_box; value: got_useful_answer); for others it's the same event (engagement: ride_requested; value: ride_completed).
Apply the SMART bar. The bar here is the same - specific, measurable, actionable, relevant, timely - and the proxy test is especially important because value-realization is often felt, not fired.
Anti-patterns and pushback:
- Same as engagement event, accidentally -> "Is that the same as the engagement event you gave me? If so, that's fine - some products have one event that covers both. Want to confirm, or is there a later signal that says 'this user got the thing they came for'?"
- Revenue event ("purchase") -> "Purchase is a conversion event - we'll capture that separately. For value-realization, I'm looking for the moment a user knows the product worked for them, which is usually before or separate from payment."
- Value is a feeling, not an event ("they feel like the team aligned", "they trust the output") -> "That's real, but we can't measure a feeling directly in the pulse. What's a proxy event that correlates? Common patterns: a completion event (workflow finished), a time-to-first-X metric (seconds from open to output), a short-window return rate (came back the next day), or a copy/share/export event (took the output into their actual work). Pick the one closest to the feeling."
- Can't name one -> "That's useful to know. If there's no discrete event, is there a session or workflow completion that stands in? Something like 'they finished the task they opened the product to do.' If not, we'll treat engagement as the value proxy and note it in the config."
Capture: Event name verbatim, or same-as-engagement with a note, or not-defined with a note.
---
4. Completion or Conversion Events
Opening question: "Any conversion or completion events worth tracking - signups, upgrades, trial starts, purchases?"
Optional section. 0-3 events is typical.
Apply the SMART bar (see Overall Rules). Each conversion event should tie to a decision: if trial_started moves ±20%, what would the team do? If the answer is "nothing", the event is a vanity metric and shouldn't be in the pulse.
Anti-patterns and pushback:
- Long list ("we have 12 of them") -> "Pick the top 3 that move the business. The others can be queried ad-hoc when you want; the pulse keeps the top 3."
- Non-actionable conversion ("email_opens", "logo_impressions") -> "If that number swings, what do we do? If the answer is 'nothing,' it's a vanity metric. What's a tighter signal further down the funnel?"
Capture: List of 0-3 event names with one-line descriptions each.
---
5. Quality Scoring (optional, AI products)
Opening question: "Is this an AI product where a conversation or session could be rated for quality? If yes, I'll sample up to 10 sessions per run and score each 1-5 on a dimension you define. Say no if this isn't applicable."
If the user opts in, ask: "What dimension should sessions be scored on? (e.g., 'got to a useful answer', 'response was accurate', 'no hallucinations')."
Pushback:
- Vague dimension ("quality", "goodness", "helpful", "good response") -> "Quality on what axis specifically? The dimension should be something a human could look at a transcript and judge consistently."
- Multiple dimensions ("accurate AND actionable") -> "Start with one. You can add dimensions by editing the config later. Keeping it at one keeps the scores comparable across runs. Which matters more right now?"
- Reviewability test - after the user names a dimension, apply this check silently: could two separate reviewers look at the same session and agree on the score? If no, push back once: "Let's tighten this - what would make a reviewer score this a 5 vs a 3? If you can name the distinction in one sentence, the dimension is tight enough." If the user can answer, capture it as a scoring note alongside the dimension. If they can't, flag the dimension
needs-reviewand move on.
Capture: opt-in (yes/no), dimension (if opted in), scoring note (1 sentence distinguishing 5 from 3), scoring discipline reminder ("default to 4-5; reserve 1-3 for clear failures").
---
6. Data Sources
Opening framing: "Now we wire up the connections needed to actually report on the events and metrics you've named. The goal is the smallest set of sources that covers everything above - one source can be enough. Let's walk through each metric."
6.0 Build the metric-to-source list
Compile the full list of signals that need a source:
- The primary engagement event (section 2)
- The value-realization event (section 3), if different from engagement
- Each completion/conversion event (section 4)
- Each key metric carried from the strategy doc, if strategy was seeded
For each entry, ask one question: "Where does {{event or metric}} live? Name the tool (e.g. Mixpanel, PostHog, Amplitude, Stripe, internal DB) and how the agent would query it."
The answer produces (tool name, query shape). If multiple entries land in the same tool, consolidate them into one source entry.
Persist per-strategy-metric source mapping. For each strategy metric whose source differs from the default (pulse_analytics_source for analytics-class metrics, pulse_payments_source for revenue/payments-class metrics, etc.), record the override in pulse_metric_sources as a metric=source pair. Example: if pulse_analytics_source is posthog but nps is captured in Delighted, write pulse_metric_sources: "nps=delighted". Strategy metrics whose source matches the class default do not need an entry. Without this mapping, multi-source setups silently lose the per-metric routing between runs.
Dual-source arbitration. If a single signal could be answered from two different sources (e.g., both PostHog and a read-only DB replica have the search events), pick one as canonical and name it in the config. Ask: "Both {{source A}} and {{source B}} can cover this - which is the source of truth? The pulse queries one per signal so numbers stay consistent across runs." Capture the canonical source. The other tool may still be used for ad-hoc investigation but is not wired into the pulse.
If the user says "we don't have that instrumented yet" (common for strategy-seeded metrics like retention or NPS): offer two off-ramps and let them pick.
- Defer - append the metric name to
pulse_pending_metrics(CSV). The metric renders asno datain each pulse report until instrumentation lands. Right call when the metric matters and the team will instrument it. - Drop from pulse - append the metric name to
pulse_excluded_metrics(CSV). The metric stays inSTRATEGY.mdbut the pulse skips it entirely. Right call when the metric is aspirational and won't have data any time soon.
Do not silently skip. Every un-instrumented strategy metric must land in exactly one of pulse_pending_metrics (visible as no data) or pulse_excluded_metrics (omitted from the report).
6.1 MCP nudge
After each unique source is named, check MCP coverage:
1. Call search_mcp_registry with the tool name to see if an official or community MCP exists. Do not guess from memory. 2. If one exists and the user already has it connected (ask: "Is the {{tool}} MCP already connected?"), note using MCP for {{tool}} in the config. 3. If one exists but the user hasn't connected it, suggest: "There's an MCP for {{tool}}. Connecting it is the fastest way to let the agent query on each run - I can call suggest_connectors to walk you through it, or we can skip and I'll note the source as manual - agent will need credentials or another path." 4. If no MCP exists, capture manual and note what shape of query the agent should use (CLI, API, etc.).
Do not set up MCP connections inside this interview - that's a separate flow. Just record which tools have MCP coverage and which do not.
6.2 Database access (optional, read-only only)
Ask explicitly: "Do you have a read-only database connection you'd like the agent to use for any signals that live in the DB? Read-only only - I will refuse a read-write connection."
Handling the answer:
- "No" or "skip" -> capture
database: not usedand move on. DB is entirely optional; many products report the pulse from analytics and tracing alone. - "Yes, read-only" (read replica, read-only user, row-level-security enforced) -> capture connection shape and which tables are available. Ask about cost: "For pulse queries, scans need to be cheap - what indexed columns are available, and are there any tables to avoid?"
- "Yes, but it's my prod credential" or any indication the connection has write access -> refuse: "For safety the pulse will not query a database with write access, even read-only in intent. The options are: (a) set up a read-only replica or a read-only user, (b) skip the DB entirely - analytics usually covers the pulse. Which do you want?" Do not proceed until the user picks (a) with verified read-only scope or (b) skip. Do not capture a read-write connection under any framing.
6.3 Consolidated source list
When every signal has a source (or is marked "covered by analytics above"), summarize the source list back to the user: "Here's what we'll wire up: {{sources}}. Any source missing for a signal you care about?"
Capture the final list in the config. A minimum of one source is acceptable.
Source-count check - judge by ratio, not absolute count:
- If the config has 3-4 metrics and every source covers a distinct one, 3-4 sources is the floor and not a warning. Accept without flagging.
- If the config has 1-2 metrics spread across 4+ sources, the setup is over-instrumented - flag for review and ask: "We have {{N}} sources but only {{M}} metrics. Is there a single tool that could cover most of this?"
- Above 5 sources regardless of metric count, flag for review. Lots of sources means lots of auth, latency, and failure modes on every run.
---
7. System Performance
Opening framing: "The system performance portion of the pulse is pretty standard - most teams want the same thing: top errors with context, and latency percentiles. Unless you have strong opinions, I'll set up the recommended default."
Recommended default (confirm or override):
- Top errors: top 5 error signatures from the tracing tool, by count, descending. Each entry includes the signature and a one-line explanation of what it likely means.
- Latency: p50, p95, p99 over the window, compared to the prior equal-length window.
- Tracing tool: {{capture tool name if not already named in section 6}}
Ask one confirmation question: "Keep the recommended setup, or customize?"
- Keep -> capture defaults.
- Customize -> ask what they want to change. Common adjustments: "top 3 instead of 5", "skip latency", "add a specific error signature to always surface". Accept and record.
If no tracing tool was named in section 6, ask: "What tool do you use for application tracing and errors? (e.g., Datadog, Sentry, Honeycomb, New Relic.) Skip if you don't have one - I'll omit the system performance section from the report." Skipping is fine - the pulse will just report usage and followups in that case.
Capture: tool name (or "none"), top-error count (default 5), latency opt (default on).
---
8. Default Lookback Window
Opening question: "What should the default lookback window be when no time window is specified? Common: 24h for daily ops, 7d for weekly review, 1h for launches."
Capture: single default (e.g., 24h).
---
9. Scheduling Recommendation
After the config is written and shown to the user, make a scheduling offer before handing back to Phase 2.
Opening framing: "Pulses are most useful on a cadence - a report once a day (or once a week) catches drift you'd miss otherwise. Want me to set up a recurring run?"
Ask one question:
- "Yes, daily" - at a time they pick
- "Yes, weekly" - day + time they pick
- "Not now - I'll run it manually"
- "Later - remind me after a few manual runs"
Handling the answer:
- Yes (daily or weekly) -> "I'll hand this to the
scheduleskill. Confirm the time/day and it'll set up the recurring job." Do not schedule inline - hand off to thescheduleskill explicitly, which is the single source of truth for recurring tasks. On Claude Code, this uses the Routines feature. - Not now -> capture
schedule: manualin the config. No nag. - Later -> capture
schedule: ask-again-after-3-runsin the config. The SKILL.md Phase 3 logic re-surfaces the offer after 3 manual runs.
Skipping this entirely is fine - the skill does not require a schedule to function. But recommending one is the right default because the value of pulse compounds through the saved-reports timeline; one-off runs lose most of that value.
Capture: schedule: daily | weekly | manual | ask-again-after-3-runs plus time/day if applicable.
---
Config File Shape
After the interview completes, merge a pulse_* block into <repo-root>/.compound-engineering/config.local.yaml. Resolve the repo root with git rev-parse --show-toplevel. Preserve any non-pulse keys that already exist in the file (e.g., work_delegate_*); only add or update pulse_* keys.
If the file does not yet exist, create the directory and file. If .compound-engineering/config.local.yaml is not already covered by .gitignore, offer to add the entry before writing.
The pulse block uses these flat keys (matches the work_delegate_* precedent for consistency):
~~~yaml
--- Product pulse ---
pulse_product_name: "{{product_name}}" pulse_lookback_default: {{24h | 7d | 1h | other}} # default 24h if omitted pulse_primary_event: "{{event_name}}" pulse_value_event: "{{event_name}}" # may equal pulse_primary_event; omit if not defined pulse_completion_events: "{{event,event,event}}" # comma-separated, 0-3 events; omit if none pulse_quality_scoring: {{true | false}} # AI products only; default false pulse_quality_dimension: "{{dimension}}" # only meaningful when pulse_quality_scoring is true pulse_analytics_source: {{posthog | mixpanel | custom | omit}} pulse_tracing_source: {{sentry | datadog | custom | omit}} pulse_payments_source: {{stripe | custom | omit}} # omit if not used pulse_db_enabled: {{true | false}} # default false; read-only DB access only pulse_metric_sources: "{{metric=source,metric=source}}" # strategy-metric -> source overrides; omit metrics that use the class default (pulse_analytics_source for analytics-class, pulse_payments_source for revenue, etc.) pulse_pending_metrics: "{{metric,metric}}" # strategy metrics deferred for instrumentation; render as 'no data'; omit if none pulse_excluded_metrics: "{{metric,metric}}" # strategy metrics intentionally not in pulse; omit if none ~~~
Notes on what is NOT persisted in config:
- Strategy metrics carried forward: surfaced in the report, not stored as config — they live in
STRATEGY.mdand are re-read each run from there. - Per-source connection details (URLs, API keys, query specifics): live with the user's MCP configuration, not in this config.
- Hardcoded operational settings (15-minute trailing buffer, top-N error count, p50/p95/p99 latencies, "no PII in reports", "parallel analytics + tracing, serial DB"): these are skill behavior, not user config; they live in
SKILL.mdand stay constant. - Schedule cadence: handled by the
scheduleskill (or platform-native cron), not pulse config. The pulse skill only hands off; it does not own the cadence record. - Tracing top-N count and latency on/off: not configurable in this version. The report always includes top 5 errors and full p50/p95/p99 latency. Add config keys later if a real need surfaces.
After writing, surface the resulting pulse_* block to the user in chat. Offer one round of edits. Then return to SKILL.md Phase 2.
Pulse Report Template
Loaded by SKILL.md at Phase 2.3 after queries have returned. Fill the template using the query results. Target total length: 30-40 lines.
Rules for filling in
- Use real numbers, not ranges or hedges. If a number is uncertain, note the source inline.
- Percent deltas compare the current window to the previous equal-length window (e.g., for
24h, compare to the prior24h). If no comparison is possible, omit the delta rather than inventing one. - No hardcoded thresholds. Do not label things "high" or "low" or color anything red unless the reader asked for threshold-based annotation at setup.
- No PII. No emails, no account IDs, no message content.
- Headlines are the top of the page. If a reader only reads the first 3 lines, they should know the most important thing that happened.
- If
STRATEGY.mdexists, re-read its## Key metricssection before assembling the report. For each strategy metric, decide what to render: - If the metric name appears in
pulse_excluded_metrics, omit it from the report. - If the metric name appears in
pulse_pending_metrics, include it in the Usage section markedno data (instrumentation pending). - Otherwise, resolve the source for this metric: look it up in
pulse_metric_sources(CSV ofmetric=sourcepairs); if present, use that source. If absent, fall back topulse_analytics_sourceand append(default source)to the metric line so the implicit routing is visible. Then query and render the metric with its current value and delta. If the query returns no value, include it anyway and mark itno data.
Template
The block below is the literal content to write. Replace every {{placeholder}} with query output. Delete lines whose data isn't available for this run.
~~~markdown
{{product_name}} Pulse - {{window}} - {{YYYY-MM-DD HH:MM}} {{TZ}}
Headlines
- {{one-line headline capturing the most notable thing in the window}}
- {{optional second headline}}
- {{optional third headline}}
Usage
- Primary engagement: {{N events}} ({{delta vs prior window}})
- Value realization: {{N events}} ({{delta}}) - {{ratio vs engagement}}
- Completions / conversions:
- {{conversion event 1}}: {{N}} ({{delta}})
- {{conversion event 2}}: {{N}} ({{delta}})
- Strategy metrics (if carried forward):
- {{metric name}}: {{value}} ({{delta}})
- Quality sample (if configured): {{distribution e.g. "8x 5, 1x 4, 1x 2"}}
System performance
- Latency: p50 {{ms}}, p95 {{ms}}, p99 {{ms}} ({{delta vs prior window}})
- Top errors (top 5 by count, descending):
1. {{error signature}} - {{N occurrences}} - {{one-line context, no PII}} 2. {{error signature}} - {{N occurrences}} - {{one-line context}} 3. {{error signature}} - {{N occurrences}} - {{one-line context}} 4. {{error signature}} - {{N occurrences}} - {{one-line context}} 5. {{error signature}} - {{N occurrences}} - {{one-line context}}
Followups
- {{One thing worth investigating next - specific enough to act on}}
- {{Another thing worth investigating}}
- {{3-5 items max; trim if thin}}
--- _Source windows: analytics [{{start}} -> {{end}}], tracing [{{start}} -> {{end}}], payments [{{start}} -> {{end}}]. Trailing buffer: 15m. Saved to docs/pulse-reports/{{YYYY-MM-DD}}_{{HH-MM}}.md._ ~~~
Variations
- No system performance tool configured: omit the entire
## System performancesection. The report stays Headlines / Usage / Followups. - Quality scoring not opted in: omit the quality sample line.
- Single-source setup (analytics only): omit the tracing and payments source windows from the footer.
- Error count customized at setup (e.g., top 3 instead of top 5): follow the configured count. Do not pad or trim beyond what the query returned.
Post-write checklist
Before saving and surfacing to chat:
- [ ] Total length is 30-40 lines (give or take 5).
- [ ] Headlines exist and lead with the most notable item.
- [ ] No hardcoded thresholds ("high error rate", "low conversion").
- [ ] No PII. Scan error signatures and followups for user emails, IDs, or message snippets.
- [ ] Top 5 errors (or the configured count), not top 10. Trim if the query returned more.
- [ ] Strategy metrics carried forward from config are rendered in Usage, or marked
no data. - [ ] Followups are specific - each one should be actionable as a sentence.
- [ ] Filename and in-file timestamp use the same wall-clock time.
What to surface in chat
After writing the file, post back:
- The Headlines section verbatim
- The top Followup, if action looks urgent
- The saved file path so the user can open the full report
Do not paste the full report into chat - the file is the artifact.
Related skills
How it compares
Pick ce-product-pulse when you need persistent pulse_* product context for Compound Engineering rather than a one-time research or documentation pass.
FAQ
What is ce-product-pulse?
Generate a time-windowed pulse report on what users experienced and how the product performed - usage, quality, errors, signals worth investigating. Use when the user says 'run a p
When should I use ce-product-pulse?
Generate a time-windowed pulse report on what users experienced and how the product performed - usage, quality, errors, signals worth investigating. Use when the user says 'run a p
Is ce-product-pulse safe to install?
Review the Security Audits panel on this page before production use.