Skip to content

Repository files navigation

trendvane - claude code skill

a claude code skill that runs every morning, fetches what's actually trending across hackernews, reddit, tiktok, youtube, product hunt, and google trends, scores each trend against your content niches, and drops 3 shootable video briefs into a notion database, complete with hooks, timestamped scripts, shot lists, captions, and hashtag stacks.

built to be cloned and configured for any creator. all the personalization lives in a handful of json and markdown files.

a note on the name: this project launched as trendradar, but the old name was already taken by so many other projects that it was rebranded to trendvane.


quick start

install with one command:

npx skills add codemathics/trendvane -g -a claude-code

when the installer says Done!, here's what to do next:

  1. open claude code (the app, or run claude in your terminal)
  2. type /trendvane and hit enter
  3. the skill greets you and walks you through a one-time setup, about 10-15 minutes: python deps, notion connection, database creation, your niches, your voice, and a test run

that's it. the install only copies the skill onto your machine, so the terminal won't tell you to do this - the real start is typing /trendvane inside claude code. every run after the first goes straight to generating your daily briefs (just ask "what's trending today?").

works for both technical and non-technical users.

npx skills add uses the open skills cli, which installs the skill files into ~/.claude/skills/. your own config and data live separately in ~/.claude/trendvane/, so running npx skills update later never overwrites them.

prefer to clone instead?

git clone https://github.com/codemathics/trendvane.git
cd trendvane
python3 setup.py      # installs deps + the skill, then run /trendvane

table of contents


how it works

the skill runs in two stages:

stage 1: python fetchers (runs in your terminal)

python3 scripts/run_all.py

six fetchers hit their respective apis and public endpoints, normalize every item into the same shape, and write raw candidate lists to cache/. the scoring engine then clusters cross-platform duplicates, applies your niche weights and brand-safe filters, and picks the top 3. the picks land in cache/picks_YYYYMMDD.json.

stage 2: claude generates and publishes (runs inside claude code)

claude reads the picks file, generates a full content brief for each trend in your voice (using memory/voice_examples.md), self-audits for ai-tell phrases, and pushes everything to your notion database via the notion mcp tool. it also saves a local archive to briefings/YYYY-MM-DD.md and posts a summary to the chat.


what you get

for each of the 3 daily trend picks, claude produces:

field what it contains
trend a one-line framing of the trend
hook variants 3 hooks from different archetypes, ranked best to worst
script beat-by-beat 45/60/90s script with timestamps, vo lines, and visual cues
shot list scene-by-scene visual direction assuming a solo shoot
trending audio a direct tiktok/ig sound link in the right category
captions platform variants for tiktok, instagram, youtube shorts, and x
hashtags 3-tier stacks (broad / mid / niche) per platform
source urls raw links from the fetcher cluster
reference clips the actual viral posts driving the trend
score 0-100 composite score from the scoring engine
velocity rising / peaking / fading
time-to-stale how long before the window closes

everything lands in notion as both table properties (so your database view is filled) and as a full-length page body (so you can read it top to bottom without opening the properties panel).


requirements

  • claude code: claude.ai/code or the cli (npm install -g @anthropic-ai/claude-code)
  • notion mcp configured in your claude code setup (see step 5)
  • python 3.10+
  • a notion workspace with two databases: trendvane and hook library (templates below)

optional (improves results but not required):

  • youtube data api v3 key
  • product hunt developer token
  • reddit script-app credentials (client id + secret)

manual setup (advanced)

if you prefer to set everything up yourself without the guided flow, here are the full steps. most users should use npx skills add codemathics/trendvane -g -a claude-code (or python3 setup.py from a clone) then /trendvane instead.

1. clone the repo

git clone https://github.com/codemathics/trendvane.git
cd trendvane

2. install python dependencies

the only external dependency is pytrends for google trends. all other fetchers use python's standard library.

pip install -r requirements.txt

if you're on a system python (macos, ubuntu), add --break-system-packages:

pip install -r requirements.txt --break-system-packages

test that the fetchers can run:

python3 scripts/run_all.py

you should see log output ending with N picks ready for brief generation. if a source fails (e.g., tiktok rate-limiting), it logs a warning and continues. one dead source does not stop the run.

3. configure your niches

open memory/my_niches.json. the key fields:

{
  "owner": "your-name",
  "priority_niche_id": "ai",
  "min_score_for_pick": 60,
  "trends_per_day": 3,
  "niches": [
    {
      "id": "ai",
      "label": "ai / llms / models",
      "category": "AI",
      "weight": 3.0,
      "keywords": ["ai", "llm", "claude", "agent", "..."],
      "sources_priority": ["hackernews", "reddit_ai", "youtube"],
      "subreddits": ["localllama", "chatgpt", "claudeai"]
    }
  ]
}

weight: how much to boost this niche's score relative to others. in the default config, ai is 3x, product design and filmmaking are 2x, and everything else is 1x. adjust to match your actual posting priorities. the niche_fit score is normalized against the highest weight you've configured, so re-weighting (or dropping a niche entirely) never silently caps your top niche below a full score.

category: the notion category select value written for trends matched to this niche. set this to whatever options your notion database uses - the taxonomy is fully data-driven, so a different creator's categories work with no code change. (omit it and trendvane falls back to the built-in label map.)

keywords: the terms the scoring engine matches against trend text. be specific. "ai coding" catches more signal than just "ai".

subreddits: which subreddits the reddit fetcher hits for this niche.

priority_niche_id (top level): the niche id that always gets at least one of the daily picks when a qualifying trend exists in it. defaults to your highest-weighted niche if unset. min_score_for_pick and trends_per_day (top level) control the qualifying-score threshold and how many trends are picked each day.

brand_safe_exclusions: at the bottom of the file, a list of blocked topics (politics, alcohol, gambling) and regex patterns. add anything you'd never want to post about.

scoring_weights: the five scoring dimensions and their weights:

dimension default weight what it measures
niche_fit 0.40 how well the trend matches your keywords and niche weights
velocity 0.25 how fast the trend is growing (rank movement, mention percentile)
cross_platform 0.15 bonus for appearing on multiple platforms simultaneously
recency 0.10 how fresh the content is (7-day decay)
originality 0.10 penalty for trends you've already covered in the last 30 days

4. write your voice profile

open memory/voice_examples.md. this is the most important file for output quality. it tells claude how you actually write: your opening patterns, sentence rhythm, casing rules, what you never say, emoji habits, and real examples from your posts.

the template has a section-by-section guide. the more real examples you paste in (actual captions from your posts), the closer the briefs will sound like you.

claude reads this file before generating every brief and audits every line against your rules before pushing to notion.

5. set up notion

you need two databases in notion before the skill can write anything.

create the trendvane database with these properties:

property name type
trend title
date spotted date
platforms multi-select
category select (ai, product design, filmmaking, tech, how-to, lifestyle, business)
velocity select (rising, peaking, fading)
score number
time-to-stale select (< 3 days, 1 week, 2+ weeks)
status select (new, filming, posted, archived)
trending audio url
hook variants text
script text
shot list text
caption text
hashtags text
source urls text
reference clips text
my take text
posted url url
performance text

create the hook library database with these properties:

property name type
hook title
archetype select
niche select
used date date

connect the notion mcp to claude code. follow the notion mcp setup guide to get the integration token, then add it to your claude code mcp config. the skill uses the notion mcp tool (notion-create-pages) to write. it does not use the notion rest api directly.

fill in your notion config:

cp memory/notion_config.example.json memory/notion_config.json

edit memory/notion_config.json with your workspace details:

{
  "workspace_user": {
    "name": "your name",
    "email": "you@example.com",
    "user_id": "your-notion-user-id"
  },
  "parent_page": {
    "title": "trendvane",
    "url": "https://www.notion.so/your-parent-page-url",
    "id": "your-parent-page-id"
  },
  "databases": {
    "trend_radar": {
      "title": "trendvane",
      "url": "https://www.notion.so/your-trendvane-db-url",
      "data_source_id": "your-trendvane-data-source-id",
      "data_source_url": "collection://your-trendvane-data-source-id"
    },
    "hook_library": {
      "title": "hook library",
      "url": "https://www.notion.so/your-hook-library-db-url",
      "data_source_id": "your-hook-library-data-source-id",
      "data_source_url": "collection://your-hook-library-data-source-id"
    }
  }
}

to find your database's data_source_id, open the database in notion, click the three-dot menu, copy the link, and extract the uuid from the url.

notion_config.json is gitignored. it will not be committed.

6. add api keys (optional)

cp memory/secrets.example.json memory/secrets.json

edit memory/secrets.json:

{
  "YT_API_KEY": "AIza...",
  "PH_TOKEN": "your-product-hunt-token",
  "REDDIT_CLIENT_ID": "your-reddit-script-app-id",
  "REDDIT_CLIENT_SECRET": "your-reddit-script-app-secret"
}

secrets.json is gitignored.

without keys: hackernews works with zero auth. reddit now requires a free script-app oauth (reddit blocks unauthenticated .json access), and tiktok's creative center api is permission-gated, so the tiktok fetcher defers to the tier-2 browser fallback. you still get hackernews plus whatever keys you add, and tier 2 fills the gaps.

with keys:

you can also pass keys as environment variables. the skill checks os.environ before secrets.json.

7. install the skill in claude code

the easiest path is the skills cli, which copies the skill folder into place for you:

npx skills add codemathics/trendvane -g -a claude-code

or from a clone, python3 setup.py does the same and also installs python deps.

to install by hand, copy the skill folder into your claude code skills directory:

cp -r skills/trendvane ~/.claude/skills/trendvane

the skill is then available in claude code. run /trendvane - the first run finishes configuration (notion, niches, voice), and every run after that generates your daily briefs. you can also invoke it on a schedule (see below).


running the skill

daily scheduled run

the intended workflow is a 5:30am python fetch followed by a 6:00am claude brief.

step 1: schedule the python fetchers (cron or any scheduler):

# example cron entry, runs at 5:30am every day
# point it at the installed skill folder; the script resolves the data dir itself
30 5 * * * cd ~/.claude/skills/trendvane && python3 scripts/run_all.py

step 2: schedule the claude skill using claude code's /schedule command or the built-in scheduled tasks feature. set it to run at 6:00am and invoke the trendvane skill.

claude picks up the picks file from step 1, generates the briefs, and pushes to notion.

on-demand

you can ask for briefs at any time inside a claude code session:

"what's trending today?"

"find me a trend on ai agents"

"run trendvane for filmmaking only"

claude skips the schedule formatting, applies any topic constraint you give it, and still pushes to notion unless you tell it not to.

you can also re-run scoring without re-fetching (useful for testing niche config changes):

python3 scripts/run_all.py --score

understanding the output

after a successful run, claude posts a briefing in chat:

trendvane, thursday, may 29

#1  cursor's agent mode is shipping real code now (score: 84, rising)
    platforms: hackernews, reddit - category: ai - time-to-stale: < 3 days
    hook: "stop prompting. cursor's agent is coding for you now."
    full brief in notion

#2  ...

#3  ...

skipped 12 other trends (mostly fading tech / politics filtered).

the full brief for each pick is in notion as a page. the table view has all properties filled. the page body reads top to bottom: hook, script, shot list, captions, hashtags, context, sources.

local archive files are saved to briefings/YYYY-MM-DD.md whether or not the notion write succeeds.


scoring system

every trend candidate goes through this pipeline:

raw candidates
    - brand-safe filter (drop blocked topics)
    - cross-platform clustering (jaccard token similarity)
    - 5-dimension scoring
    - top 3 selection (with niche priority enforcement)

scoring formula:

final_score = (niche_fit      x 0.40)
            + (velocity       x 0.25)
            + (cross_platform x 0.15)
            + (recency        x 0.10)
            + (originality    x 0.10)

each dimension is 0-1 before weighting. the final score is multiplied by 100. only trends scoring >= 60 qualify as picks (configurable via min_score_for_pick, and the dimension weights above come from scoring_weights in your config).

niche fit is computed by counting keyword hits in the trend's title and raw text, then multiplying by the niche's weight. a single ai-niche match outscores multiple matches in an unweighted niche.

velocity is approximated without time-series data:

  • tiktok: rank movement in the creative center trending list
  • reddit/hackernews: percentile of mention count within today's source batch
  • youtube: percentile of view count within today's source batch

cross-platform gives a bonus for trends appearing on more than one source simultaneously. these tend to have broader longevity.

recency decays linearly over 7 days. content older than a week scores 0.

originality penalizes trends whose keywords overlap with anything you've already covered in the past 30 days (tracked in cache/seen_trends.json).

selection: the top trends_per_day qualifying clusters are chosen (3 by default). at least one slot is reserved for your priority_niche_id - or, if that's unset, your highest-weighted niche - when a qualifying trend exists in it. the remaining slots avoid duplicate categories unless there's no other option.


hook rotation

the skill tracks which hook archetypes were used each day in memory/used_hooks.json. the rules:

  • never use the same archetype 2 days in a row
  • never use the same archetype 3 times in a 7-day window
  • if a trend strongly fits one archetype (e.g., a breaking product launch fits bold claim), override rotation but log it

the 7 archetypes available, defined in templates/hook_patterns.md:

archetype best for
pattern interrupt product design, ai, tech
bold claim / hot take ai, tech, product design
question hook how-to, ai, filmmaking
pov / cold open lifestyle, filmmaking, how-to
stat shock business, ai, tech
direct address / callout product design, ai, how-to, filmmaking
demonstration / show-don't-tell filmmaking, ai, product design

every brief gets 3 variants from 3 different archetypes.


file structure

the repo splits into shipped skill code and (at runtime) the user's own data dir.

in the repo / installed skill folder (~/.claude/skills/trendvane/ after install):

trendvane/
├── README.md
├── setup.py                          # git-clone installer (deps + skills + data dir)
├── requirements.txt
├── .claude-plugin/
│   └── plugin.json                   # plugin manifest (skills + first-run hint)
└── skills/
    └── trendvane/                  # the skill (installed by the cli)
        ├── SKILL.md                  # daily workflow + first-run setup routing
        ├── requirements.txt          # deps travel with the skill
        ├── references/
        │   └── setup_guide.md        # the guided onboarding flow (first run only)
        ├── scripts/
        │   ├── common.py             # shared utils + path resolution
        │   ├── run_all.py            # orchestrator: fetch then score
        │   ├── score_trends.py       # scoring + clustering engine
        │   ├── validate_setup.py     # pre-flight config check
        │   ├── fetch_*.py            # one per source (hn, reddit, tiktok, ...)
        │   └── push_to_notion.py     # notion write helpers
        ├── templates/
        │   ├── brief_template.md
        │   ├── hook_patterns.md
        │   └── script_structures.md
        └── memory/                   # SHIPPED DEFAULTS (read-only, replaced on update)
            ├── my_niches.json        # default niche config
            ├── voice_examples.md     # voice profile template
            ├── notion_config.example.json
            ├── secrets.example.json
            └── used_hooks.json

user data dir (~/.claude/trendvane/, created on setup, never touched by updates):

~/.claude/trendvane/
├── memory/
│   ├── my_niches.json                # your niches, weights, keywords, filters
│   ├── voice_examples.md             # your voice profile
│   ├── notion_config.json            # your notion workspace ids (private)
│   ├── secrets.json                  # api keys (private)
│   └── used_hooks.json               # last 14 days of hook archetype history
├── cache/                            # written by the fetchers
│   ├── raw_<source>_YYYYMMDD.json
│   ├── picks_YYYYMMDD.json           # the day's top 3 with scores
│   └── seen_trends.json              # 30-day dedup history
└── briefings/
    └── YYYY-MM-DD.md                 # daily brief archive

when run from a clone (without installing into ~/.claude/skills/), the data dir collapses back into the repo folder so everything stays in one place for development. set TRENDVANE_DATA to override the data location explicitly.


customization reference

change your niche weights

in memory/my_niches.json, edit the weight field on any niche. a niche with weight 3.0 gets 3x the scoring bonus of a niche with weight 1.0. there is no enforced maximum, but weights above 4.0 will almost always force that niche into the top pick regardless of other signals.

add a new niche

add a new object to the niches array in memory/my_niches.json:

{
  "id": "gaming",
  "label": "gaming",
  "weight": 1.5,
  "keywords": ["gaming", "game dev", "unity", "unreal", "steam", "indie game"],
  "sources_priority": ["reddit_gaming", "youtube", "tiktok"],
  "subreddits": ["gamedev", "gaming", "indiegaming"]
}

the scoring engine picks it up on the next run with no code changes.

change the scoring weights

in memory/my_niches.json, edit scoring_weights. they must sum to 1.0:

"scoring_weights": {
  "niche_fit": 0.40,
  "velocity": 0.25,
  "cross_platform": 0.15,
  "recency": 0.10,
  "originality": 0.10
}

if velocity is most important to you (you only want fast-rising trends), bump it to 0.40 and trim niche_fit down.

change the minimum score threshold

in memory/my_niches.json, set min_score_for_pick (defaults to 60):

"min_score_for_pick": 60

lower it to get more picks even from weaker signal days. raise it to only publish when you have strong trending content. no code change needed - the constant in scripts/score_trends.py is just the fallback default.

change the dedup window

in scripts/score_trends.py:

SEEN_TRENDS_WINDOW_DAYS = 30

lower it to allow revisiting trends sooner.


adding a new data source

every fetcher in scripts/ follows the same contract. to add a new source:

  1. create scripts/fetch_myplatform.py
  2. export a fetch() function that returns a list of dicts (or TrendCandidate objects) matching the normalized shape:
from common import TrendCandidate, now_iso

def fetch() -> list[TrendCandidate]:
    items = []
    # your fetching logic goes here
    items.append(TrendCandidate(
        source="myplatform",
        platform="myplatform",
        title="trend title",
        url="https://...",
        raw_text="description or body text for keyword matching",
        mention_count=1234,     # views, upvotes, comments, anything comparable
        timestamp=now_iso(),
        extra={}                # any platform-specific fields
    ))
    return items
  1. add it to the fetchers list in scripts/run_all.py:
("myplatform", "fetch_myplatform"),

the scoring engine picks it up automatically. if your source needs an api key, read it with env("MY_KEY") from common.py. it checks os.environ then memory/secrets.json.


failure modes

the skill is designed to degrade gracefully. these are the expected failure states and what happens:

failure behavior
a fetcher is blocked or rate-limited logged as a warning, run continues with other sources
fewer than 3 trends score >= 60 claude delivers what it has, flags the count in the briefing
claude in chrome unavailable (tier 2 escalation) logged, skipped - tier 1 results are used
notion write fails brief saved to briefings/YYYY-MM-DD.md, flagged as [NOTION SYNC FAILED] in chat
voice_examples.md is empty claude falls back to script_structures.md defaults, flags it in the briefing
notion_config.json missing claude skips the notion write, saves locally, reports the issue

development

the scoring + clustering logic has a stdlib-only test suite (no extra deps):

python3 -m unittest discover -s skills/trendvane/tests -v

linting uses ruff (config in pyproject.toml):

pip install -r requirements-dev.txt
ruff check skills/trendvane/scripts skills/trendvane/tests
ruff check --fix skills/trendvane/scripts   # auto-fix what it can

both run in ci on every push and pull request (see .github/workflows/ci.yml). ci gates on the pyflakes (F) rules plus the test suite.


credits

built by @codemathics as a personal content workflow tool, open-sourced as a template for any creator who wants to automate their trend research and brief generation with claude code.

About

a claude code skill that runs every morning, fetches what' trending and drops 3 shootable video briefs into notion

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages