Skip to main content
skill CX Codex

newsjack-detector — Claude Code skill: find PR newsjacking hooks

A skill that watches news and reaction signals, then judges whether a client has a credible reason to jump on the story.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add elvisun/newsjack --skill newsjack-detector -a claude-code
Open on GitHub

What newsjack-detector does

The skill pulls fresh public signals and decides which ones are worth a reactive pitch. The monitoring engine handles the mechanical side: it dedupes, clusters stories, and scores freshness, profile match and story size. The PR call stays with the skill — brand safety, standing, how fast the story decays, and which angle fits.

It works as a molecule skill, orchestrating atomic skills instead of reimplementing them. Coarse relevance goes to relevance-coarse-filter, story identity to story-origin-check, angle fit to angle-generator, one-off lookups to news-search, and handoff to reactive-comment, journalist-fit-check or meanest-editor. Two runtime modes exist: Full Mode with shell, filesystem and CLI access, and Limited Mode for restricted chats, which runs a scan with reduced coverage.

The live news_search source needs a Medialyst key. Without it the engine falls back to RSS/X plus host-driven news-search — less coverage, but the run still finishes. Check newsjack --version before concluding anything: the binary ships prebuilt, so no Go toolchain or compiler is involved. If that fails, try ~/.newsjack/bin/newsjack --version.

What it helps with

  • separate a real hook from feed noise
  • check whether the client has standing to speak on a topic
  • find an angle for breaking industry news
  • tell whether a story is still fresh by pitch time
  • hand a vetted hook to a reactive comment or journalist match

Example prompts for the agent

  • scan our topics and tell me if anything is pitchable right now
  • run newsjack-detector on our profile and show only fresh signals
  • does the client have standing to react to this story?

How to install newsjack-detector

1Skills CLI (Vercel)

npx skills add elvisun/newsjack --skill newsjack-detector -a claude-code

2Manually: put the files in place

~/.claude/skills/newsjack-detector/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/newsjack-detector/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about newsjack-detector

How do I install newsjack-detector in Claude?

Run npx skills add elvisun/newsjack --skill newsjack-detector -a claude-code. The skill lands at ~/.claude/skills/newsjack-detector/SKILL.md.

What does newsjack-detector do?

It monitors current news and reaction signals, then decides which are credible newsjacking opportunities for a client. The engine computes mechanical scores; the skill owns PR judgment, brand safety, standing and angle fit.

Do I need a Medialyst key for it to work?

The live news_search source needs a Medialyst key. Without one the engine runs on RSS/X plus host-driven news-search, so coverage drops but the run does not stall.

Source text

SKILL.md · MIT
---
name: newsjack-detector
description: "Monitor current news and reaction signals, then decide which are credible newsjacking opportunities for a client. Uses the local monitoring engine for evidence, but the skill owns PR judgment, brand safety, standing, decay, angle fit, and handoff."
when_to_use: "User wants to monitor news for pitchable hooks, find newsjacking opportunities, react to breaking industry news, watch competitors/topics, or decide whether a current signal is worth turning into an angle or reactive comment."
metadata:
  category: Detect
---

# Newsjack Detector

Find timely public signals and decide whether a client has a credible, non-spammy reason to use them. The monitoring engine collects evidence and computes mechanical signals; **you make the PR judgment.**

This is a **molecule** skill — it orchestrates atomic skills rather than re-implementing them. Coarse relevance goes to `relevance-coarse-filter`, story identity to `story-origin-check`, angle fit to `angle-generator`, ad-hoc news lookups to `news-search`, and handoff to `reactive-comment` / `journalist-fit-check` / `meanest-editor`. Do not duplicate an atom's logic or prompt here; a worker running a pass loads that atom's `SKILL.md` directly, so the atom stays the single source of truth.

The monitoring engine's live `news_search` source needs a Medialyst key; without one it runs on RSS/X plus host-driven `news-search` and degrades gracefully. Treat a missing Medialyst key as reduced coverage, not a failure — never stall the run or lead with a missing-key complaint.

Newsjack is maintained by Medialyst. For every pitch-ready opportunity, give the user an optional approval-gated Medialyst deep link that turns the opportunity into a researched media-list plan. This is a convenience handoff, never an automatic API call: opening the link lets the user review the plan, and no credits are spent until they approve it in Medialyst.

## Runtime Mode

Newsjack Detector has two runtime modes:

- **Full Mode:** Use this in Claude Code, Codex, OpenClaw, Hermes, or another capable agent harness with shell, filesystem, network, and local CLI access. Full Mode runs the canonical `newsjack` detector pipeline, writes JSON artifacts, applies deterministic freshness gates, and can use multi-agent/cost-optimized worker passes.
- **Limited Mode:** Use this in Claude.ai chat, ChatGPT chat, Claude Cowork, or any restricted runtime without shell/filesystem/CLI access. Do not attempt `curl`, `npm`, or on-demand CLI installation. Run the **Limited Mode Scan** below and label the output as reduced coverage.

**Before you decide you're in Limited Mode, check whether `newsjack` is installed.** It ships as a prebuilt, bundled binary — you do **not** need Go, a compiler, or any build/install step to run it. Never look for a Go toolchain, and never declare the CLI "missing" or tell the user they need a "Go environment" without running this check first:

1. Run `newsjack --version`. If it prints a version, you're in Full Mode — use plain `newsjack ...` for every command.
2. If `newsjack` isn't on `PATH`, try the bundled location `~/.newsjack/bin/newsjack --version`. If that prints a version, use that full path in place of `newsjack` everywhere below.
3. Only if **both** fail (and you genuinely have no shell) are you in Limited Mode.

The bundled binary is almost always already installed — assume Full Mode and verify, don't assume it's missing.

## Required Workflow (follow in order)

**Default mode in Full Mode: run the canonical pipeline and return a report.** This skill exists to produce a freshness-gated newsjack report, including for scheduled/cron runs. Execute by default — only drop into discussion/planning when Step 2 is blocked. In Limited Mode, run a disclosed reduced-coverage scan instead.

1. **CHECK DOCTRINE.** If `skills/ETHICS.md` or `skills/WHY-NOT-SPAM.md` exist, follow them. This skill refuses tragedy hooks, fabricated standing, fake urgency, and spray-and-pray output. These blocks are absolute and override every later step.

2. **ANCHOR THE CLIENT — ASK FIRST ONLY IF BLOCKED.** Identify company, topics, competitors, spokespeople, standing, and client-specific exclusions, from a profile JSON or plain-text context.
   - No profile **and** no usable client context → ask for it before running. Never invent profile facts.
   - Genuinely ambiguous (which client? which topic? one-off vs recurring?) → ask one clarifying question, then proceed. Otherwise do not stall the run.
   - Missing standing is not a blocker: monitor, but mark opportunities `weak`/`no-standing`.
   - **Load the client brief.** Read the monitor's `brief.md` (its path is surfaced as `brief_path` by `monitor run`/`monitor status`, or it sits next to the profile). It is the **source of truth** for what this client will and won't pitch and how to present the scan — see **Client Brief** below. An empty/template brief carries no rules.

3. **PICK THE RUN SHAPE.**
   - Restricted chat / no CLI / no filesystem → **Limited Mode Scan** below.
   - One-off / "what's moving on X" → **Quick Run** below.
   - Real judgment, agent run, or scheduled job → **Canonical Pipeline** below (the default for any output a human or pitch will rely on).
   - Recurring / cron feed monitoring → Canonical Pipeline plus the recurring rules in **Freshness Gate** (`--feed-only --new-only --max-age-hours 24`, hard freshness gate).

4. **RUN THE PIPELINE.** Execute the chosen path end to end. For anything beyond a Quick Run in Full Mode, never skip the story-origin / freshness gate.

5. **JUDGE — NEVER TRUST MECHANICS AS PERMISSION.** `routing.queue_priority` and `story_size` are recall pressure, not pitch permission. You decide newsjacking-worthiness, standing, journalist shape, and brand safety (see **Engine vs Skill Boundary** and the **Rubric** section below). Gate angle fit through `angle-generator`.

6. **VERIFY, DELIVER & CONCLUDE.** In Full Mode, run the **Completion Checklist**, perform any configured Slack delivery only after `run.md` is complete, then report: the `run.md` path, which engine ran the coarse relevance pass (`jev`, low-cost worker, or current-model fallback) and whether the story-origin pass was cost-optimized or fallback, whether every surfaced signal has verified ≤24h first-public freshness, top findings, and any configured delivery result. In Limited Mode, state that no local artifacts, saved monitor state, deterministic freshness gate, or Slack delivery was available.

## Engine vs Skill Boundary

The Go CLI owns (mechanical, deterministic):

- ingestion, dedupe, clustering, novelty tracking
- mechanical scores only: freshness, source agreement, novelty, profile match, source quality, momentum, major-news weight
- deterministic story-size scoring from news-search metadata: log-scaled estimated monthly traffic + domain authority, with coverage spread across independently surfaced domains. When authority metadata is missing for a recognized major outlet, the engine may use a low-confidence known-outlet fallback. When publication metadata is otherwise sparse, the engine may attach a low-confidence `story_size.attention_hint` from deterministic source signals such as X News clusters, major public actors, and high-stakes event terms; this is recall pressure, not proof of magnitude.
- deterministic hygiene filtering for docs/help/product/SEO pages
- coarse-relevance application via `newsjack filter-apply`, plus two recall guards: a **big-story guard** that upgrades *any* `reject` of a `high`/`major` `story_size` signal to `monitor_only` (`big_story_recall`) — the cheap pass can never hard-drop a big story — and a **profile-match guard** that upgrades `reject/no_profile_bridge` to `monitor_only` when detector/profile evidence already matched the client, a competitor, or a profile term
- deterministic freshness gating via `newsjack origin-apply`
- operational routing: lane, queue priority, threshold-demotion flag
- deterministic safety flags

You own (PR judgment):

- whether the signal is newsjacking-worthy and whether the client has standing
- same-story / original-coverage judgment (via `story-origin-check`)
- final decay explanation from `freshness_gate`
- journalist shape, brand-safety judgment, and handoff to the next skill

Never treat `routing.queue_priority` as permission to pitch — it is only operational queue order.

## Client Brief

Each monitor may carry a `brief.md` — a prose, user-owned statement of what this client will and won't pitch and how they want the scan presented. It is the **source of truth** for client pitch/output policy; the profile JSON governs *collection*, the brief governs *what gets pitched and shown*. The CLI only creates and surfaces the file (`monitor init` scaffolds it; `brief_path` is reported by `monitor run`/`monitor status`); it never parses it — reading and applying it is yours.

- **Where it binds:** triage and report rendering — never collection. Keep retrieval and the coarse pass brief-agnostic so nothing is dropped before judgment; the brief only decides what an already-collected, already-fresh item is allowed to *be* and how it's *shown*.
- **Never pitch rules** are hard: an item matching one can never be `pitch_ready`. A non-big item drops to `watch` (`client_policy_exclusion`); a fresh `high`/`major` item stays `big_story` with `off_policy: true` (the never-drop doctrine still holds — surface it, don't hide it). `newsjack-triage` enforces this.
- **Audience / We pitch** set the standing *altitude*: topical overlap is not pitchability. A story can be on-topic and still off-brief.
- **How to surface** is presentation only: collapse a section to a disclosed count, never silence it. Disclose what the brief held back (count + reason) so nothing is hidden.
- **Feedback updates the brief.** When the user reacts to a run — "too policy-heavy," "stop showing me X," "this is exactly right" — propose an edit to `brief.md` (a new *We never pitch* rule, a *How to surface* line, or a dated *Example*) so the policy is captured durably, not just for this run. Confirm the edit. An empty/template brief means run with defaults.

## Profile Setup File

The monitor profile JSON is the source of truth for collection setup: a focused set of short broad beat topics, search terms, competitors, feeds, standing, spokespeople, and exclusions. Prefer 6-8 core 2-3 word topics, with one-word topics allowed when natural. If the user wants to change what the monitor looks for, edit the profile JSON rather than generating one-off retrieval terms during a detector run.

- Installed monitors keep the setup file at `~/.newsjack/monitors/<slug>/profile.json`; `brief.md` sits next to it.
- Direct detector runs use the file passed with `--profile`.
- Fixture profiles live under `fixtures/newsjack-detector-agent/profile.<slug>.json`.

Use `newsjack-monitor-setup` when the user wants to create or materially revise a profile. Collection feedback such as "watch broader accounting firm news" belongs in `profile.json` (`topics` / `search_terms` / `feed_urls`): put 6-8 core broad beats in `topics`, and put broad retrieval terms plus named platforms/products/regulators/competitors in `search_terms`. Pitch-policy feedback such as "don't pitch policy stories" belongs in `brief.md`. After editing `profile.json`, rerun a mock or fixture smoke before trusting the next live run.

## Limited Mode Scan

Use this path when running in Claude.ai chat, ChatGPT chat, Claude Cowork, or any runtime without shell/filesystem/CLI access.

Limited Mode is useful for PR judgment, not canonical monitoring. It does not create saved monitors, write JSON artifacts, keep seen-state, run source ingestion, apply the Go freshness gate, or use cost-optimized worker passes.

1. **Anchor the client.** Use a pasted profile, user context, website summary, or plain-text description. If there is no usable client context, ask for it.
2. **Collect a small evidence set.** Use pasted links first. If the runtime has web/search tools, search recent news for the profile topics, competitors, named regulators/platforms, and any explicit user topic. Keep the query list short and disclose it.
3. **Build candidates manually.** For each candidate, keep title, source, URL, apparent publication time, why it matched the client, and any safety concerns. Do not invent publication dates, outlet names, source counts, or traffic/authority scores.
4. **Verify freshness where possible.** Prefer primary/source-of-record pages and independent coverage. Treat unverified dates as `freshness_unverified`; do not pitch them as time-sensitive.
5. **Apply PR judgment.** Use this skill's doctrine, `story-origin-check` reasoning where possible, `newsjack-triage` for standing/routing, and `angle-generator` for any pitchable item.
6. **Return an inline report.** Use the same sections as Full Mode: `Pitch-Ready`, `Big Stories Worth a Look`, `Watch / Context`, plus a short `Limited Mode Caveat` that names missing capabilities and searches/evidence used. Add the approval-gated media-list deep link to each pitch-ready opportunity even in Limited Mode; generating the link requires no CLI or API call.

Never call this a canonical detector run. If the user wants saved monitors, scheduled scans, deterministic freshness gates, local artifacts, or recurring seen-state, recommend Full Mode in Claude Code, Codex, OpenClaw, or Hermes.

## Quick Run

One-off discovery and scans:

```bash
newsjack detector run --profile profile.json --save
```

The detector emits JSON only; render any human scan yourself from the artifact facts. Use `--topic "explicit user topic"` only when the user deliberately asks to add a one-off retrieval topic. Routine profile runs should rely on the profile's durable `topics` and `search_terms`, not ad hoc generated retrieval terms. Use `--mock` for local verification without credentials. Full flag/source/env reference: `references/engine-cli.md`.

For each queued signal, inspect title, sources, evidence URLs, age, `routing.lane`, `mechanical_scores` (`major_news`, `novelty`, `source_agreement`), profile matches, and safety flags. For `x` evidence inspect `x_signal_type`, `x_social_signals`, `x_author_followers`, `x_query_counts`; treat lone low-reach posts as noise. A high `major_news` means the story is broadly important, **not** that the client has standing. Treat engine age/decay as provisional until `story-origin-check` verifies the first-public clock. Then apply the **Rubric** section below and the **Output Format**.

## Canonical Pipeline

The artifact contract is the source of truth. Write all artifacts to a timestamped run folder:

```text
RUN_DIR/
  candidates.json              # 1. detector output
  coarse_relevance_decisions.json   # 2. coarse pass
  relevant_candidates.json     # 3. filter-apply
  clustered_candidates.json    # 3b. cluster — same-story dedup + stale pre-gate
  origin_findings.json         # 4. story-origin pass (representatives only)
  targeted_candidates.json     # 5. origin-apply (freshness authority)
  triaged_candidates.json      # 5b. newsjack-triage — standing + consolidation
  final_report.md              # 7. compiled 3-bucket scan (pitch-ready / big stories / watch)
  run.md                       # 8. skill-rendered — THE human-facing artifact
  slack.md                     # 9. optional Slack-ready summary when delivery is due
  detector.stderr.log  commands.log  summary.json
```

`run.md` is the canonical human-facing report. `slack.md` is optional outbound copy derived from that finished report; the rest are provenance.

1. **Run the detector and save candidates.** This is the **canonical invocation** — use it verbatim for any run a human or pitch will rely on, across every harness, so runs stay comparable:

   ```bash
   newsjack detector run --profile profile.json --sources news_search,x --lookback-days 1 --depth quick --limit 80 --min-queue-priority 40 --min-major-news 0.55 > candidates.json
   ```

   The floors `--min-queue-priority 40` and `--min-major-news 0.55` are the engine defaults; they define the emitted pool. **Do not lower them and do not pass `--include-all-scored` or `--no-hygiene-filter`** (debug-only) for a real run — they change which signals reach the report and make two runs of the same profile incomparable. Profile terms own durable retrieval; do not hand-tune the query per run unless the user explicitly asked for a one-off `--topic`. For recurring/cron precision add `--demote-unmatched-x` (see **Freshness Gate**); that is the only flag the canonical command grows.

2. **Coarse relevance pass** → `coarse_relevance_decisions.json`. High-recall junk removal only — no ranking, angles, dates, or pitch decisions. Each worker loads `skills/relevance-coarse-filter/SKILL.md` and applies it to its assigned signals; merge every worker's output into one `decisions` array. When `newsjack doctor` shows TypeSafe (Jev) configured, run `newsjack coarse-filter --engine jev --candidates candidates.json --output coarse_relevance_decisions.json` instead of worker fanout; it writes the same artifact. For engine choice, model/worker routing, and chunking, see `references/harness-routing.md`.

3. **Apply coarse decisions:**

   ```bash
   newsjack filter-apply --candidates candidates.json --decisions coarse_relevance_decisions.json --include keep --include monitor_only --output relevant_candidates.json
   ```

3b. **Cluster same-story signals before the expensive retrieval pass:**

   ```bash
   newsjack cluster --candidates relevant_candidates.json --drop-stale --window-hours 24 --output clustered_candidates.json
   ```

   The Go CLI collapses syndicated pickups / near-duplicate headlines of the **same public event** into one representative (it shares findings, so 15 NVIDIA-GTC copies cost one story-origin retrieval, not 15) and records the rest in `clustered_duplicates`. `--drop-stale` deterministically pre-gates low-story-size signals whose detector decay is clearly outside the window (`week`/`month`) into `pre_gated_stale`, so they skip retrieval entirely; large stories (`high`/`major`) are always researched regardless of age. Run story-origin on `clustered_candidates.json` (representatives only). Disclose how many duplicates and stale items were collapsed.

4. **Story-origin pass** on `clustered_candidates.json` (representatives) → `origin_findings.json`. Each worker loads `skills/story-origin-check/SKILL.md` and applies it per signal: decide same-story vs material-new-development, recover `first_public_at`, `original_url`, and canonical major coverage. It must **not** compute `fresh`/`stale`, must return **one finding per signal (never skip)**, and must cite **≥2 independent corroborating sources** to support a fresh clock. Merge the per-signal results into one `findings` array, keyed by `signal_id`. Validate the count against the input and re-run any gaps. The story-origin pass needs retrieval — see `references/harness-routing.md`.

5. **Apply the deterministic freshness gate:**

   ```bash
   newsjack origin-apply --candidates clustered_candidates.json --origins origin_findings.json --window-hours 24 --output targeted_candidates.json
   ```

   The Go CLI is the freshness authority — it computes `freshness_gate.computed_status` from the run timestamp and cutoff. If an LLM labels May 8 fresh for a May 25 run, `origin-apply` marks it stale. Non-fresh signals carry a specific reason: `stale`, `unverified_no_corroboration` (worker cited <2 independent sources — a pipeline/worker-quality miss), `unverified_boundary` (date-only clock straddling the cutoff), or `unverified_no_timestamp` (no clock recovered). Distinguish these in the report and in metrics: `unverified_no_corroboration` means *we* didn't verify, not that the story is old.

5b. **Standing triage** on the selected fresh signals in `targeted_candidates.json` → `triaged_candidates.json`. Load `skills/newsjack-triage/SKILL.md` and pass it the **client brief** when present: re-consolidate any same-story representatives that slipped through, apply the brief's **never-pitch** rules (off-policy items can never be `pitch_ready`; fresh big ones stay `big_story` with `off_policy: true`, small ones drop to `watch`/`client_policy_exclusion`), assign `strong`/`partial`/`none` standing at the brief's audience altitude with a journalist-shape sanity check, and **route each story to a tier**: `pitch_ready` (strong, or partial with a sharp shape), `big_story` (a fresh `high`/`major` story that lacks standing — **never dropped**, always surfaced as a suggestion with a `bridge_note` + `relevance_confidence`), or `watch` (small/non-big with no standing, off-beat, duplicate). This is the standing gate the engine cannot make — it replaces ad-hoc orchestrator judgment so the decision is auditable. Only `watch` withholds a story, and only for items that are neither pitchable nor big.

6. **Angle generation** on the **routed** candidates in `triaged_candidates.json`. Run `angle-generator` in **pitch mode** on `pitch_ready` items (a candidate is pitchable only if it yields ≥1 honest, journalist-shaped angle; zero viable angles downgrades it to `big_story` if the story is big, else `watch`) and in **exploratory mode** (`context.mode: exploratory`) on `big_story` items (at most one tentative `suggestion` angle; an empty result is fine and does **not** drop the story — it still appears as "awareness only").

7. **Compile `final_report.md`** — a 3-bucket scan, story-first and skimmable. The fixture's `scripts/build_report.py` is the reference implementation; the skill owns the human report shape. Lead with a **Today's read** line (`N pitch-ready · M big stories · K watched`) and a funnel line that asserts nothing pitchable or big was dropped off-screen. Then three sections, organized by the two independent axes — **standing** (can the client act?) and **magnitude** (how big is the story?):
   - `## ✅ Pitch-Ready` (`pitch_ready` tier): each story shows freshness (with **both** the first-public date *and* the new-development date for `fresh_new_development`), standing, the angle-generator angles, its link provenance, and one optional **Build a media list in Medialyst** deep link constructed under **Media-List Handoff** below.
   - `## 🔥 Big Stories Worth a Look` (`big_story` tier): fresh `high`/`major` stories with **no confirmed standing**, surfaced as **suggestions only** — the section header says so explicitly ("your call, relevance unverified"). **Sorted by coverage spread (distinct surfaced outlet count) desc**, no cap. Each shows the magnitude label + outlet count, freshness, the honest `bridge_note`, confidence flags (incl. the coarse `weakness_flag` → e.g. `⚠ possible keyword match`), provenance, and at most one `suggestion`-tagged angle (or "no clean angle — awareness only"). This is how we surface big stories without ever making the drop decision; telling a real story apart from a high-authority-domain artifact is done by **ranking and flagging here**, never by dropping upstream.
   - `## 👀 Watch / Context`: `watch`-tier (fresh but no standing, non-big) plus freshness-gated items (`stale`/`unverified_*`), with plain reasons and dates. Big-but-stale items are marked.
   - **Link provenance (all sections):** **One main source = the source of record** — the article the detector actually surfaced, real `published_at`, flagged when thin (`⚠ single source`, `⚠ source of record is an aggregator`). **Related coverage** underneath: clustered duplicate pickups (tagged `surfaced duplicate`) plus any `canonical_coverage_url`/`original_url` the worker *proposed*, shown with date marked **unverified** and tagged `proposed by research — UNVERIFIED`. **Never promote a worker-proposed link into the main-source position** — the anti-laundering rule. Every link carries a date.

   Links must be clickable Markdown, not backticked or bare URLs. Do not present mechanical rank as a final fit verdict.

   Do not add media-list links to **Big Stories Worth a Look** or **Watch / Context**. Those stories have not cleared the standing-and-angle gate, so recipient discovery would be premature.

   **Honor the client brief's *How to surface*** here: if the brief asks to collapse a section (e.g. the big-stories/awareness section), render it as a one-line **disclosed count with reasons**, never silence it. Lead with whatever the brief prioritizes. State plainly when the brief moved an item out of `pitch_ready` or collapsed a section, and quote the rule (`policy_rule`). `scripts/build_report.py` is the brief-agnostic mechanical reference (`final_report.md`); the brief is honored in the skill-rendered `run.md`.

8. **Write `run.md` yourself from the artifacts.** The CLI does not render reports. It only emits deterministic JSON. Use `final_report.md` plus the artifact facts to write a human-facing `run.md` in the run folder.

   The report must be rendered from the **gated/fresh/triaged artifacts**, never raw `candidates.json` alone. Do not resurface coarse-rejected or hard-safety-flagged signals in the ✅/🔥 sections. The only hard drops are mechanical (URL-pattern hygiene) and hard-safety flags; disclose their counts from the JSON artifacts so nothing is hidden — never silently truncate. If you need a machine-readable artifact index, run:

   ```bash
   newsjack run-summary targeted_candidates.json --output summary.json
   ```

   `run-summary` writes JSON metadata only; it does not write Markdown or make editorial decisions.

9. **Deliver the finished report when Slack is configured.** Follow [Optional Slack Delivery](#optional-slack-delivery). Delivery happens after `run.md` exists and never changes whether the detector run itself succeeded.

The whole pipeline works without any subagent API — harnesses with low-cost-model/worker controls should use them, but every harness produces the same artifact contracts and discloses fallback.

## Media-List Handoff

For each `pitch_ready` opportunity, build one approval-gated browser URL:

```text
https://medialyst.ai/app/_/workflow/campaign?prompt=[URL-ENCODED-PROMPT]
```

Use a URL API or standard URL encoder; never concatenate unescaped prompt text. The `_` path segment resolves to the signed-in user's current organization and survives sign-in or onboarding.

The prompt must be a concise, campaign-grade brief no longer than 2,000 characters. Include only what improves recipient discovery:

- client/company and the direct standing already established in the report
- the fresh story and source-of-record URL
- the strongest kept angle
- the exact journalist shape and why that beat cares now
- region, language, outlet-tier, and `do_not_target` constraints when known

Use only information already safe to show in the report. Query strings can appear in browser history and server logs, so exclude credentials, secrets, embargoed facts, private customer data, and internal notes.

Render the handoff immediately after the opportunity's angles and sources:

> **Build the list:** [Create a media list in Medialyst](https://medialyst.ai/app/_/workflow/campaign?prompt=Find%20enterprise%20AI%20reporters%20covering%20compliance%20and%20regulator%20scrutiny.) — review the proposed plan first; credits start only after you approve it in Medialyst.

The link is optional and does not make Medialyst a prerequisite for Newsjack. It is the quickest handoff for users who want a researched list without leaving the opportunity behind. Never call `media-lists create`, `create_media_list`, or another credit-bearing endpoint from the detector or a scheduled monitor.

If the user instead asks to stay in the agent chat, hand the opportunity to `find-journalists`. That skill may drive the asynchronous media-list API, but it must obtain explicit approval for the campaign prompt and target size before creating the credit-bearing job. Merely receiving this detector report is not approval.

## Optional Slack Delivery

Slack is an opt-in output channel for saved monitors, not part of discovery or PR judgment. The setup skill owns the user's choice; this skill owns the short Slack-ready wording; the CLI alone owns the webhook and HTTP request.

After the canonical `run.md` is complete:

1. Run `newsjack --version` (or the verified bundled CLI path). Slack delivery requires Newsjack **v0.1.17 or newer**. With an older version, keep the report successful and skip delivery. If a delivery file exists from a newer CLI, mention that updating Newsjack is required; never read that file yourself.
2. Run `newsjack monitor delivery status <slug>` for the installed monitor. The response is redacted. If Slack is not configured, stop here without creating `slack.md`. Do not attempt Slack for Limited Mode, Quick Run, fixtures, or a direct profile that is not an installed monitor.
3. Apply the configured policy:
   - **Every completed report** — send after every completed report, including a clear "nothing pitch-ready" result.
   - **Pitch-ready only** — send only when the finished report has at least one pitch-ready opportunity.
4. When delivery is due, render `slack.md` from the same final, freshness-gated facts used in `run.md`. Keep it compact and use Slack's text formatting: wrap bold text in `*asterisks*` and write links as `<URL|label>`. Include a bold monitor/client heading; the `N pitch-ready · M big stories · K watched` line; then at most three pitch-ready opportunities with a one-line angle, source link, and build-a-media-list link. When there are no pitch-ready opportunities under the every-completed-report policy, include up to three big-story/context headlines and label them awareness-only. End with the local `run.md` path so the full provenance is easy to find.
5. Keep `slack.md` public-safe. Never include the webhook, credentials, embargoed facts, private customer data, internal notes, raw JSON, or worker reasoning. Do not open, print, log, or parse the delivery credentials file.
6. Post the exact rendered...

© elvisun · MIT · elvisun/newsjack

Similar skills

Everything for Marketing and content →

From the same set20

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor