
Geeknews Search
Fetch and parse the GeekNews RSS feed so your coding agent can surface Korean tech-community headlines during early research.
Overview
geeknews-search is an agent skill for the Idea phase that fetches and structures GeekNews RSS items for discovery research.
Install
npx skills add https://github.com/nomadamas/k-skill --skill geeknews-searchWhat is this skill?
- Pulls the GeekNews FeedBurner RSS URL and normalizes feed metadata plus item list
- Parses item fields: id, title, link, published, author, summary, and content HTML
- Includes a small HTML-to-text helper for stripping tags from summaries and content
- Python CLI-oriented script suitable for agent-invoked research runs
- Outputs structured dicts via dataclasses for JSON-friendly agent consumption
Adoption & trust: 1.8k installs on skills.sh; 5.4k GitHub stars; 2/3 security scanners passed (skills.sh audits).
What problem does it solve?
You want GeekNews headlines inside your agent workflow but do not have a small, repeatable feed parser wired for automation.
Who is it for?
Solo builders doing Korean tech-news discovery who already run Python-capable agents and want RSS structured as JSON-like records.
Skip if: Teams that need full-text search, paywalled archives, or English-only global news without extending the script themselves.
When should I use this skill?
When you need GeekNews feed items parsed into structured records during idea discovery or research.
What do I get? / Deliverables
You get a normalized list of GeekNews posts with titles, links, dates, and text summaries ready for summarization or idea backlog notes.
- Structured GeekNews feed metadata and item records
- Plain-text summaries extracted from HTML content fields
Recommended Skills
Journey fit
Discovery workflows start in Idea when you scan what builders are talking about before picking a product direction. discover is the shelf for feed ingestion and headline surfacing, not full competitive teardown.
How it compares
Use as a focused RSS integration instead of asking the agent to scrape GeekNews pages ad hoc each session.
Common Questions / FAQ
Who is geeknews-search for?
Indie and solo developers who research product ideas from Korean developer-community news and want that feed inside Claude Code, Cursor, or similar agents.
When should I use geeknews-search?
Use it in Idea during discover or research when you need fresh GeekNews links before validate; it is not meant for ship, launch, or production monitoring.
Is geeknews-search safe to install?
Review the Security Audits panel on this Prism page and treat any skill that performs outbound HTTP as something you should run in a trusted environment with normal feed URL verification.
SKILL.md
READMESKILL.md - Geeknews Search
#!/usr/bin/env python3 from __future__ import annotations import argparse import json import re import urllib.request from dataclasses import asdict, dataclass from html import unescape from html.parser import HTMLParser from pathlib import Path GEEKNEWS_FEED_URL = "https://feeds.feedburner.com/geeknews-feed" class _TextExtractor(HTMLParser): def __init__(self) -> None: super().__init__() self.parts: list[str] = [] def handle_data(self, data: str) -> None: self.parts.append(data) def text(self) -> str: return " ".join(part.strip() for part in self.parts if part.strip()) @dataclass(frozen=True) class GeekNewsItem: id: str title: str link: str published: str | None updated: str | None author_name: str | None author_url: str | None summary: str content_html: str def to_dict(self) -> dict[str, object]: return asdict(self) @dataclass(frozen=True) class GeekNewsFeed: title: str source_id: str | None updated: str | None home_url: str | None feed_url: str | None category: str | None items: list[GeekNewsItem] def source_dict(self) -> dict[str, object]: return { "title": self.title, "id": self.source_id, "updated": self.updated, "home_url": self.home_url, "feed_url": self.feed_url, "category": self.category, } def _strip_cdata(value: str | None) -> str: if not value: return "" stripped = value.strip() if stripped.startswith("<![CDATA[") and stripped.endswith("]]>"): return stripped[9:-3] return stripped def _collapse_whitespace(value: str) -> str: return re.sub(r"\s+", " ", value).strip() def _clean_xml_text(value: str | None) -> str: return _collapse_whitespace(unescape(_strip_cdata(value))) def _html_to_text(html: str) -> str: parser = _TextExtractor() parser.feed(html) parser.close() return _collapse_whitespace(unescape(parser.text())) def _first_tag(block: str, tag: str) -> str | None: match = re.search(rf"<{tag}\b[^>]*>(.*?)</{tag}>", block, re.DOTALL) if not match: return None return _clean_xml_text(match.group(1)) def _first_raw_tag(block: str, tag: str) -> str | None: match = re.search(rf"<{tag}\b[^>]*>(.*?)</{tag}>", block, re.DOTALL) if not match: return None return _strip_cdata(match.group(1)).strip() def _first_link_href(block: str) -> str | None: patterns = ( r"<link\b[^>]*rel=['\"]alternate['\"][^>]*href=['\"]([^'\"]+)['\"]", r"<link\b[^>]*href=['\"]([^'\"]+)['\"]", ) for pattern in patterns: match = re.search(pattern, block) if match: return unescape(match.group(1).strip()) return None def _link_href(block: str, *, rel: str | None = None) -> str | None: if rel: match = re.search( rf"<link\b[^>]*(?:rel|ref)=['\"]{re.escape(rel)}['\"][^>]*href=['\"]([^'\"]+)['\"]", block, ) if match: return unescape(match.group(1).strip()) return _first_link_href(block) def _feed_prefix(xml_text: str) -> str: if "<entry" not in xml_text: return xml_text return xml_text.split("<entry", 1)[0] def _entry_blocks(xml_text: str) -> list[str]: return re.findall(r"<entry\b[^>]*>(.*?)</entry>", xml_text, re.DOTALL) def _validate_limit(limit: int) -> int: if limit <= 0: raise ValueError("limit must be positive") return limit def load_feed(xml_text: str) -> GeekNewsFeed: prefix = _feed_prefix(xml_text) items = [] for entry in _entry_blocks(xml_text): author_block_match = re.search(r"<author\b[^>]*>(.*?)</author>", entry, re.DOTALL) author_block = author_block_match.group(1) if author_block_match else "" content_html = (_first_raw_tag(entry, "content") or "").strip() items.append( GeekNewsItem(