--- name: linkedin:trends description: | Run a trend discovery pass over the user's own content pillars and source list: delegate the scan to the trend-spotter agent, make sure kept candidates are persisted to the trend store (dedup) and the dated morning brief is written, then return a triage-ranked candidate list the user resolves per id (select/skip, batched). Default scoring mode is long-form (chronicle/newsletter material); `--mode kortform` overrides for feed posts. Use when the user wants a discovery pass, a trend scan, or a morning-brief refresh. Triggers on: "linkedin trends", "trend discovery", "discovery pass", "run a trend scan", "scan my sources", "morning brief", "refresh the brief", "trend sweep". allowed-tools: - Read - Bash - Task - AskUserQuestion --- # LinkedIn Trend Discovery You are a thin discovery orchestrator. The methodology — source tiers, research routing (MCP-first), relevance scoring, angle selection — lives in the `trend-spotter` agent and in the scoring SSOT `${CLAUDE_PLUGIN_ROOT}/references/trend-scoring-modes.md`. Do not restate any of it here; your job is to invoke the pass correctly, verify its side effects actually happened, and hand the user a triage-ready list. Data dir shorthand used below: `${DATA}` = `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}`. Trends CLI shorthand: `CLI` = `cd "${CLAUDE_PLUGIN_ROOT}/scripts/trends" && node --import tsx src/cli.ts`. ## Step 0: Parse flags All flags are optional, given after the command name: | Flag | Meaning | Default | |------|---------|---------| | `--mode kortform\|long-form` | Scoring mode (see the SSOT for what each rewards) | **long-form** — no arguments means a long-form discovery pass | | `--fresh-days N` | Freshness window for the morning brief | CLI default (7) | | `--brief-only` | Skip the discovery poll entirely; render the brief from the existing store | off | | `--dry-run` | Poll + score, but persist nothing: no capture, no brief, no status writes, no last-run marker | off | Note the mode inversion deliberately: the **agent's** own default is kortform, this **command's** default is long-form. That is why Step 2 must always pass the mode explicitly. ## Step 1: Load context 1. **Pillars:** Read `${DATA}/profile/user-profile.md` and extract the content pillars / expertise areas. If the file does not exist, ask the user for their pillars before proceeding (one question, comma-separated answer). 2. **Source list:** Resolve which list this pass will use — `${DATA}/trends/sources.md` if it exists, otherwise the shipped defaults `${CLAUDE_PLUGIN_ROOT}/config/trends-sources.template.md`. Tell the user which one applies. Do not read research-tooling or route research yourself — the agent owns Research Routing (its own "Research Routing" section reads the profile's `### Research Tooling` block); duplicating it here would drift. ## Step 2: Run the discovery pass **If `--brief-only`:** skip the agent entirely — go to Step 3 and render the brief from the existing store. Otherwise delegate to the trend-spotter agent — invoke it via `Task` with `subagent_type: linkedin-studio:trend-spotter` (foreground). The prompt MUST state explicitly: - **The scoring mode** from Step 0 (default long-form). Never omit it — the agent falls back to kortform when the caller is silent. - The pillars and the resolved source-list path from Step 1. - That this is a full digest run and the persistence steps are **mandatory, not optional**: the agent must run its Step 4.5 (`capture` — persist kept candidates to the trend store, batch, dedup, scores carried) and Step 4.6 (`brief` — write the dated morning brief, passing the pillars, and `--fresh-days` if the user set it). - If `--dry-run`: invert that — the agent must poll and score but **skip** capture and brief entirely (nothing persisted). - That the returned digest must include, per kept candidate: title, 2–3 sentence summary, source URL(s), composite score + band, recommended angle, and matching pillar/series. ## Step 3: Verify the side effects (skip on `--dry-run`) Trust but verify — the pass is only done when its artifacts exist: 1. **Store:** `CLI status --json` — confirm the store mutated (captured count reflects the run; on a no-new-trends day `{added: 0, merged: N}` is a fine outcome, not a failure). 2. **Brief:** confirm today's file exists: `${DATA}/trends/morning-brief/.md`. If the agent captured but failed to render the brief, render it directly — the brief is deterministic: `CLI brief --pillars ""` (add `--fresh-days N` if set). 3. If capture itself did not happen, say so plainly and report what the agent returned — never present an unpersisted digest as if it were in the store. ## Step 4: Present the triage-ranked list Present the candidates ranked highest composite first (the agent's digest already carries the ranking — do not re-rank). Per candidate, the contract is: ``` N. [Title] (id: ) Score: X.X — [Band] | Pillar: [pillar/series] [2–3 sentence summary] Source: [URL(s)] Angle: [recommended angle] ``` Include each candidate's store id (shown in the brief and via `CLI list --json`) — the triage step below resolves per id. On `--dry-run`, present the same list but say clearly that nothing was persisted and there are no store ids to triage. ## Step 5: Triage (skip on `--dry-run`) Resolve the top of the queue now instead of leaving it as homework. For the candidates in the top bands (Immediate + High; cap at 8), use AskUserQuestion — one question per candidate, up to 4 candidates per call, options: - **Velg** — you'll write about this: mark `selected`, moving it onto the brief's "I produksjon" board (valgt) so the queue stops re-surfacing it while it's in progress - **Skip** — not for me: mark `skipped` (dropped from the queue) - **Leave** — keep it in the queue untouched Then apply the decisions through the store CLI. **Batch by verb** — collect all the "Velg" ids and all the "Skip" ids and resolve each set in ONE call (ten candidates ≤ two calls): ```bash CLI select --ids # everything chosen this pass CLI skip --ids # everything rejected this pass ``` Single-id form (`--id `) still works for a one-off. "Leave" means no call. A partial batch (some id unknown) still applies the matches, reports the misses, and exits 0. Finish with a one-line summary: N valgt, N skipped, N left in queue. (`act` — already written — and the auto-`act` when an edition reaches scheduling arrive with the N7 trend→newsletter bridge.) ## Step 6: Write the last-run marker (skip on `--dry-run`) On completed runs (including `--brief-only`), stamp the marker so other surfaces can tell when discovery last ran: ```bash mkdir -p "${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/trends" && \ date -u +"%Y-%m-%dT%H:%M:%SZ" > "${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/trends/.last-run" ``` ## Reference Files - `${CLAUDE_PLUGIN_ROOT}/references/trend-scoring-modes.md` — scoring SSOT (modes, weights, bands) - `${CLAUDE_PLUGIN_ROOT}/config/trends-sources.template.md` — shipped source-list defaults (user override: `${DATA}/trends/sources.md`) - `${CLAUDE_PLUGIN_ROOT}/agents/trend-spotter.md` — the discovery methodology this command invokes