์ ๋ฌธ | 15๋ถ | ํ๋ซํผ ๊ฐ ์ ๋ณด ์์ง ๋ง์คํฐ, ์กฐ์ฌ ํจ์จ ๋ฐฐ๊ฐ
TIP
last30days-Skill์ ํ์ฌ ClawHub์์ ๊ฐ์ฅ ํฌ๊ด์ ์ธ AI ์กฐ์ฌ์ฉ Skill๋ก, 10๊ฐ ์ด์์ ์ ํธ์์ ๋ณ๋ ฌ๋ก ๊ฒ์ํ๊ณ ์ค๋ณต ์ ๊ฑฐ ๋ฐ ์ ์ ์ฐ์ ์ ์๋ํํ๋ฉฐ ์ธ์ฉ๊ตฌ๊ฐ ํฌํจ๋ ์ฌ์ค ๊ธฐ๋ฐ ๋ณด๊ณ ์๋ฅผ ์์ฑํฉ๋๋ค.
GitHub: mvanhorn/last30days-skill
๋์ ๋ ์ ํ๋กํ
- 1~5๋ ์ฐจ ๊ฐ๋ฐ์
- ์ผ์์ ์ผ๋ก AI ๋๊ตฌ ์ ์ , ๊ฒฝ์์ฌ ์กฐ์ฌ, ๊ธฐ์ ํธ๋ ๋ ์ถ์ ์ด ํ์ํ ๋ถ
- ๊ธฐ๋ณธ์ ์ธ ์ปค๋งจ๋ ๋ผ์ธ ์ง์์ด ์๊ณ Claude Code ๋๋ Codex CLI์ ์ต์ํ ๋ถ
- Reddit/HN์ ์ผ์ผ์ด ํ์ผ๋ฉฐ ์ ๋ณด๋ฅผ ์ฐพ๋ ํํธํ๋ ๊ณผ์ ์์ ๋ฒ์ด๋๊ณ ์ถ์ ๋ถ
ํต์ฌ ์์กด์ฑ ๋ฐ ํ๊ฒฝ
| ์์กด์ฑ | ์ค๋ช | ํ์ ์ฌ๋ถ |
|---|---|---|
| Node.js 18+ | Skill ์คํ ํ๊ฒฝ | ์ |
| Python 3.10+ | ๊ธฐ๋ณธ ์คํฌ๋ฆฝํธ ์ธ์ด | ์ |
| ScrapeCreators API Key | Reddit/TikTok/Instagram ํตํฉ ํค | ์ |
| Claude Code ๋๋ Codex CLI | Skill ์คํ ๋งค๊ฐ์ฒด | ์ |
| X AUTH_TOKEN / CT0 | X ๊ฒ์ ์ธ์ฆ (์ ํ ์ฌํญ) | ์๋์ |
| Bluesky App Password | Bluesky ๊ฒ์ (์ ํ ์ฌํญ) | ์๋์ |
| Polymarket Gamma API | ์์ธก ์์ฅ ๋ฐ์ดํฐ (๋ฌด๋ฃ) | ์๋์ |
์ ์ฒด ํ๋ก์ ํธ ๊ตฌ์กฐ ํธ๋ฆฌ
last30days-skill/
โโโ SKILL.md # Skill ์ ์ ํ์ผ (~/.claude/skills/ ์ ๋ฐฐํฌ)
โโโ SPEC.md # ์ ์ฒด ๊ธฐ์ ์ฌ์ ๋ฌธ์
โโโ CLAUDE.md # Claude Code ๊ฐ๋ฐ ๊ฐ์ด๋
โโโ scripts/
โ โโโ last30days.py # Python ๋ฉ์ธ ์ํธ๋ฆฌ (๋ฆฌ์์น ์์ง)
โ โโโ sync.sh # ๋ฐฐํฌ ๋๊ธฐํ ์คํฌ๋ฆฝํธ
โ โโโ lib/
โ โโโ __init__.py # ํจํค์ง ์ํธ๋ฆฌ (Eager import ๊ธ์ง)
โ โโโ env.py # ํ๊ฒฝ ๋ณ์ ๋ก๋
โ โโโ dates.py # ๋ ์ง ๋ฒ์ ๋ฐ ์ ๋ขฐ๋ ๊ณ์ฐ
โ โโโ cache.py # 24h TTL ์บ์
โ โโโ http.py # ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ HTTP ํด๋ผ์ด์ธํธ
โ โโโ models.py # OpenAI/xAI ๋ชจ๋ธ ์๋ ์ ํ
โ โโโ openai_reddit.py # Reddit ๊ฒ์ (OpenAI Responses API)
โ โโโ xai_x.py # X ๊ฒ์ (xAI Responses API)
โ โโโ reddit_enrich.py # Reddit ํฌ์คํธ ์ฌ์ธต ์งํ ์ถ์ถ
โ โโโ hackernews.py # Hacker News (Algolia ๋ฌด๋ฃ API)
โ โโโ polymarket.py # Polymarket ์์ธก ์์ฅ (Gamma API)
โ โโโ bluesky.py # Bluesky/AT Protocol ๊ฒ์
โ โโโ truthsocial.py # Truth Social ๊ฒ์
โ โโโ normalize.py # ์์ ์๋ต โ ๊ท๊ฒฉํ๋ Schema
โ โโโ score.py # ๋ค์ค ์ ํธ ์ ์ ๋ชจ๋ธ
โ โโโ dedupe.py # ์ ์ฌ ์ค๋ณต ํ์ง
โ โโโ render.py # Markdown / JSON ๋ณด๊ณ ์ ๋ ๋๋ง
โ โโโ schema.py # ํ์
์ ์ ๋ฐ ๊ฒ์ฆ
โโโ skills/last30days/
โ โโโ last30days.sh # Shell ๋ํผ (Claude Code Skill ์ํธ๋ฆฌ)
โโโ fixtures/ # ํ
์คํธ์ฉ ํผ์ค์ฒ ๋ฐ์ดํฐ
Step 1 ์ค์น ๋ฐ ์ธ์ฆ ์ค์
1.1 Claude Code ํ๋ฌ๊ทธ์ธ ๋ฐฉ์ ์ค์น (๊ถ์ฅ)
์ด๋ฏธ Claude Code๋ฅผ ์ฌ์ฉ ์ค์ด๋ผ๋ฉด ํ๋ฌ๊ทธ์ธ ๋ช ๋ น์ด๋ก ์ง์ ์ค์นํ์ธ์:
/plugin marketplace add mvanhorn/last30days-skill
/plugin install last30days@last30days-skill
๋๋ ๊ณต์ ๋๊ตฌ์ธ ClawHub๋ฅผ ์ฌ์ฉํ์ฌ ์ค์นํฉ๋๋ค:
clawhub install last30days-official
WARNING
ํ๋ฌ๊ทธ์ธ ์ค์น ๋ฐฉ์์ ์ฌ์ฉ ์ค์ธ Claude Code ๋ฒ์ ์ด /plugin ๋ช
๋ น์ด๋ฅผ ์ง์ํด์ผ ํฉ๋๋ค. ๋จผ์ claude --version >= 1.0 ์ธ์ง ํ์ธํ์ธ์.
1.2 ์๋ Git Clone ์ค์น
ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ๊ณ ์ถ์ง ์๋ค๋ฉด ๋ก์ปฌ๋ก ์ง์ ํด๋ก ํ์ธ์:
# Claude Code skills ๋๋ ํ ๋ฆฌ๋ก ํด๋ก
git clone https://github.com/mvanhorn/last30days-skill.git \
~/.claude/skills/last30days
# ๋๋ ํ ๋ฆฌ ์ด๋ ํ ํ์ผ ํ์ธ
cd ~/.claude/skills/last30days
ls -la scripts/
1.3 ScrapeCreators API Key ์ค์ (ํ์)
Reddit/TikTok/Instagram ์ธ ํ๋ซํผ์ ์ํ ํตํฉ ์ํธ๋ฆฌํฌ์ธํธ๋ก, ํ๋์ ํค๋ก ๋ชจ๋ ํด๊ฒฐ๋ฉ๋๋ค:
- scrapecreators.com์ ์ ์ํ์ฌ ๊ฐ์ ํ API Key๋ฅผ ๋ฐ๊ธ๋ฐ์ต๋๋ค.
- ์ค์ ํ์ผ์ ์์ฑํฉ๋๋ค:
mkdir -p ~/.config/last30days
cat > ~/.config/last30days/.env << 'EOF'
# ํ์: Reddit + TikTok + Instagram ํตํฉ Key
SCRAPECREATORS_API_KEY=sc_xxxxxxxxxxxxxxxxxxxx
# ์ ํ: OpenAI API (Codex ๋ก๊ทธ์ธ ํ์๋ ์๋ต ๊ฐ๋ฅ)
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxx
EOF
chmod 600 ~/.config/last30days/.env # ๋ฏผ๊ฐํ ํ์ผ ๋ณดํธ
1.4 X / Bluesky ์ ํ์ ์ธ์ฆ ์ค์
X ๊ฒ์ (๊ถ์ฅ ๋ฐฉ์):
# 1. x.com์ ๋ก๊ทธ์ธํ๊ณ ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ๋๊ตฌ(F12)๋ฅผ ์ฝ๋๋ค.
# 2. Application โ Cookies โ auth_token ๋ฐ ct0 ๊ฐ์ ๋ณต์ฌํฉ๋๋ค.
# 3. .env ํ์ผ์ ์์ฑํฉ๋๋ค.
cat >> ~/.config/last30days/.env << 'EOF'
# X ๊ฒ์ ์ธ์ฆ (cookie ๋ฐฉ์)
AUTH_TOKEN=xxxxxxxxxxxxxxxxxxxx
CT0=xxxxxxxxxxxxxxxxxxxx
# X ๋์: xAI API (cookie ๋ถํ์)
XAI_API_KEY=xai-xxxxxxxxxxxxxxxxxxxx
EOF
Bluesky ๊ฒ์:
# 1. bsky.app/settings/app-passwords์์ ์ฑ ๋น๋ฐ๋ฒํธ๋ฅผ ์์ฑํฉ๋๋ค.
# 2. .env ํ์ผ์ ์์ฑํฉ๋๋ค.
cat >> ~/.config/last30days/.env << 'EOF'
# Bluesky/AT Protocol
BSKY_HANDLE=yourhandle.bsky.social
BSKY_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx
EOF
TIP
X cookie์ Bluesky ๋น๋ฐ๋ฒํธ๋ ์ ํ ์ฌํญ์ ๋๋ค. ๋ณต์กํ ์ค์ ์ด ์ซ๋ค๋ฉด ๋ฌด๋ฃ์ธ Polymarket, Hacker News, Reddit๋ง์ผ๋ก๋ ๋๋ถ๋ถ์ ์๋๋ฆฌ์ค๋ฅผ ์ปค๋ฒํ ์ ์์ต๋๋ค.
1.5 ์ค์น ์ฑ๊ณต ํ์ธ
# ๊ฐ๋จํ ํ
์คํธ ์คํ (--mock์ ๋ก์ปฌ ํ
์คํธ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ API ํ ๋น๋์ ์ฌ์ฉํ์ง ์์)
python3 ~/.claude/skills/last30days/scripts/last30days.py "Claude Code tips" --mock --emit=compact
๋ค์๊ณผ ๊ฐ์ ์ถ๋ ฅ์ด ๋ณด์ด๋ฉด ๋ชจ๋ ๊ฒ์ด ์ ์์ ๋๋ค:
=== last30days Report: Claude Code tips ===
Sources: reddit, hackernews | Time: 2026-03-25 | Mode: mock
[results...]
Step 2 ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
2.1 /last30days ์ปค๋งจ๋ ๋ผ์ธ
Claude Code์์ ์ง์ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํ์ธ์:
/last30days best Claude Code prompts
Codex CLI ๋ฐฉ์:
python3 ~/.claude/skills/last30days/scripts/last30days.py "best Claude Code prompts" --emit=compact
TIP
๊ธฐ๋ณธ์ ์ผ๋ก ์ต๊ทผ 30์ผ๊ฐ์ ์ธ๊ธฐ ์ฝํ ์ธ ๋ฅผ ๊ฒ์ํ๋ฉฐ, Reddit, X, YouTube, TikTok, Instagram, Hacker News, Polymarket, Bluesky ๋ฑ 10๊ฐ ์ด์์ ์ ํธ์์ ํฌํจํฉ๋๋ค. ๊ฒ์ ํ ๋ฒ์ ๋ณดํต 2~8๋ถ์ด ์์๋๋ฉฐ, ๋์น(Niche)ํ ์ฃผ์ ๋ ๋ ์ค๋ ๊ฑธ๋ฆด ์ ์์ต๋๋ค.
2.2 ๋ณด๊ณ ์ ๊ตฌ์กฐ ํด์
์คํ์ด ์๋ฃ๋๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์กฐํ๋ ๋ณด๊ณ ์๋ฅผ ๋ฐ๊ฒ ๋ฉ๋๋ค:
# last30days Report: best Claude Code prompts
## Sources Searched (6 active)
reddit | x | hackernews | polymarket | youtube | reddit_threads
## Top Findings
...
## Best Practices (์ปค๋ฎค๋ํฐ ๊ฒ์ฆ ๋ฐฉ๋ฒ)
...
## Prompt Pack (๋ณต์ฌ ๊ฐ๋ฅ)
...
## Recent Developments
...
## References (์ถ์ฒ ๋งํฌ ํฌํจ)
...
๋ณด๊ณ ์๋ ์๋์ผ๋ก ๋ค์ ์์ ์ ์ํํฉ๋๋ค:
- ์๋ ด ํ์ง: ์ฌ๋ฌ ํ๋ซํผ์์ ๋์์ ์ธ๊ธ๋ ์ฝํ ์ธ ์ ๋ ๋์ ๊ฐ์ค์น ๋ถ์ฌ
- ์ค๋ณต ์ฒ๋ฆฌ: ์๋ฏธ์ ์ ์ฌํ ํฌ์คํธ ์ค ๊ฐ์ฅ ์ฐ์ํ ํ๋๋ง ์ ์ง
- ์ํจ์ฑ ๊ฐ์: ์ต์ ์ฝํ ์ธ ์ผ์๋ก ์๋จ์ ๋ฐฐ์น
- ์ธ์ฉ ํ๊ธฐ: ๋ชจ๋ ๊ฒฐ๋ก ์ ์๋ณธ ๋งํฌ ์ฒจ๋ถ
2.3 --quick ๋น ๋ฅธ ๋ชจ๋
์๊ฐ์ด ์๋ค๋ฉด --quick์ ์ถ๊ฐํ์ฌ ์ผ๋ถ ์ฌ์ธต ๊ฒ์์ ๊ฑด๋๋ฐ์ธ์:
python3 ~/.claude/skills/last30days/scripts/last30days.py \
"Cursor AI vs Windsurf" \
--quick \
--emit=compact
2.4 --days=N ์ฌ์ฉ์ ์ ์ ์๊ฐ ๋ฒ์
30์ผ๋ฟ๋ง ์๋๋ผ ๊ธฐ๊ฐ์ ์ง์ ์ง์ ํ ์ ์์ต๋๋ค:
python3 ~/.claude/skills/last30days/scripts/last30days.py \
"OpenClaw latest news" \
--days=7 \
--emit=compact
2.5 --refresh ์บ์ ๊ฐ์ ์๋ก๊ณ ์นจ
๊ธฐ๋ณธ์ ์ผ๋ก ๊ฒฐ๊ณผ๋ 24์๊ฐ ๋์ ์บ์ฑ๋ฉ๋๋ค. ๋ค์ ๊ฒ์ํ๊ณ ์ถ๋ค๋ฉด:
python3 ~/.claude/skills/last30days/scripts/last30days.py \
"AI code editors comparison" \
--refresh \
--emit=compact
Step 3 ๋ค์ค ์์ค ๋ณ๋ ฌ ๊ฒ์ ๋ฉ์ปค๋์ฆ
3.1 Reddit ๊ฒ์ ์๋ฆฌ
Reddit์ ๊ฐ์ฅ ์ค์ํ ์ ํธ์์ ๋๋ค. Skill์ ๋ ๋จ๊ณ๋ก ์๋ํฉ๋๋ค:
# scripts/lib/openai_reddit.py (๊ฐ๋ต๋ณธ)
def search_reddit(query: str, days: int = 30) -> list[dict]:
# 1๋จ๊ณ: OpenAI Responses API + web_search๋ฅผ ์ฌ์ฉํ์ฌ ๊ธฐ์ด ๋ฐ๊ฒฌ
response = openai.responses.create(
model="gpt-4o",
input=f"Find active Reddit discussions about: {query}",
tools=[{"type": "web_search"}],
max_tokens=2000
)
# 2๋จ๊ณ: ์์ ํฌ์คํธ JSON์ ๊ฐ์ ธ์ ์ค์ ์ถ์ฒ/๋๊ธ ์ ํ๋
enriched = reddit_enrich.fetch_threads(response.urls, days)
return enriched
TIP
v2.9 ์ดํ Reddit์ ๊ธฐ๋ณธ์ ์ผ๋ก ScrapeCreators๋ฅผ ์ฌ์ฉํฉ๋๋ค. ํ๋์ ํค๋ก Reddit + TikTok + Instagram์ ๋ชจ๋ ์ปค๋ฒํ๋ฏ๋ก ์ด์ ์ ๋ ๋ฆฝํ ๋ฐฉ์๋ณด๋ค ํจ์ฌ ์์ ์ ์ ๋๋ค.
3.2 Hacker News ํตํฉ
๋ณ๋์ API Key ์์ด ๋ฌด๋ฃ๋ก ์ฐ๋๋ฉ๋๋ค:
# scripts/lib/hackernews.py
def search_hackernews(query: str, days: int = 30) -> list[dict]:
# HN Algolia API๋ ๋ฌด๋ฃ ๊ฐ๋ฐฉ๋์ด ์์ต๋๋ค.
url = "https://hn.algolia.com/api/v1/search"
params = {
"query": query,
"tags": "story",
"numericFilters": f"created_at_i>{cutoff_timestamp(days)}"
}
resp = requests.get(url, params=params)
items = resp.json()["hits"]
# points + num_comments๋ฅผ ํฉ์ฐํ์ฌ ์ ๋ ฌ
return sorted(items, key=lambda x: x["points"] + x["num_comments"] * 2, reverse=True)
3.3 Polymarket ์์ธก ์์ฅ ๋ฐ์ดํฐ
์ด๊ฒ์ last30days๊ฐ ๋ค๋ฅธ ์กฐ์ฌ ๋๊ตฌ์ ์ฐจ๋ณํ๋๋ ํต์ฌ ํ์ด๋ผ์ดํธ์ ๋๋ค. ๋จ์ํ "์ฌ๋๋ค์ด ๋ฌด์์ ๋งํ๋๊ฐ"๋ฟ๋ง ์๋๋ผ "์ฌ๋๋ค์ด ๋์ ์ด๋์ ๊ฑฐ๋๊ฐ"๋ฅผ ํ์ธํฉ๋๋ค:
# scripts/lib/polymarket.py
def search_polymarket(query: str) -> list[dict]:
# Gamma API ๋ฌด๋ฃ ์ ์
url = "https://gamma-api.polymarket.com/markets"
resp = requests.get(url, params={"topic": query, "limit": 20})
markets = resp.json()
# 5์์ ์ ์ ๋ชจ๋ธ
for m in markets:
m["composite_score"] = (
m["text_relevance"] * 0.30 +
m["volume_24h"] * 0.30 +
m["liquidity"] * 0.15 +
m["price_velocity"] * 0.15 +
m["outcome_competitiveness"] * 0.10
)
return sorted(markets, key=lambda x: x["composite_score"], reverse=True)
์ค์ ํจ๊ณผ: "OpenClaw"๋ฅผ ๊ฒ์ํ๋ฉด Reddit ํฌ์คํธ๋ฟ๋ง ์๋๋ผ, Polymarket์์ "OpenClaw ์๊ฐ ํ์ฑ ์ฌ์ฉ์ ์"์ ๋ํ ์์ธก ๋ฐ์ดํฐ๋ ๋ณผ ์ ์์ต๋๋ค. ์ค์ ์๋ณธ์ด ํฌ์ ๋ ๋ฐฐ๋น๋ฅ ์ ๊ทธ ์ด๋ค ํฌ์คํธ๋ณด๋ค ์ค๋๋ ฅ์ด ์์ต๋๋ค.
3.4 ๋ค์ค ์ ํธ ์ ์ ๋ชจ๋ธ ๋ถ์
๋ชจ๋ ์์ค์ ๊ฒฐ๊ณผ๋ ํตํฉ ์ ์ ํ์ดํ๋ผ์ธ์ผ๋ก ๋ชจ์ ๋๋ค:
# scripts/lib/score.py
def compute_composite_score(item: dict, query: str, days: int) -> float:
# 1. ํ
์คํธ ๊ด๋ จ์ฑ (์๋ฐฉํฅ ์ ์ฌ๋ + ์ ์์ด ํ์ฅ)
text_score = bidirectional_similarity(item["text"], query)
# 2. ์ํธ์์ฉ ์ด๊ธฐ ์ ๊ทํ
engagement_score = normalize_velocity(item["engagement"])
# 3. ์์ค ๊ถ์ ๊ฐ์ค์น (HN > Reddit > X > TikTok)
authority_score = SOURCE_WEIGHTS[item["source"]]
# 4. ํ๋ซํผ ๊ฐ ์๋ ด ๋ณด๋์ค (๋ค์ ํ๋ซํผ ๋์ ์ธ๊ธ ์ ๊ฐ์ค์น ๋ถ์ฌ)
convergence_score = detect_convergence(item, all_results)
# 5. ์ํจ์ฑ ๊ฐ์ (๋งค์ผ 0.98์ ์ง์ ๊ฐ์ ์ ์ฉ)
recency_score = 0.98 ** days_since_post(item["timestamp"])
return (
text_score * 0.35 +
engagement_score * 0.25 +
authority_score * 0.20 +
convergence_score * 0.10 +
recency_score * 0.10
)
v2.5์ ๋ธ๋ผ์ธ๋ ํ ์คํธ ์ ์๋ v1์ 3.73/5.0์์ 4.38/5.0์ผ๋ก ์ฝ 17% ํฅ์๋์์ต๋๋ค.
Step 4 ๋น๊ต ๋ชจ๋ (X vs Y)
4.1 "Cursor vs Windsurf" ์ฌ๋ก
last30days์ ๊ฐ์ฅ ๋ฉ์ง ๊ธฐ๋ฅ ์ค ํ๋๋ก, ๋ ๋๊ตฌ๋ฅผ ์ง์ ๋น๊ตํฉ๋๋ค:
/last30days cursor vs windsurf
๋๋ ์ปค๋งจ๋ ๋ผ์ธ์์:
python3 ~/.claude/skills/last30days/scripts/last30days.py \
"cursor vs windsurf" \
--emit=compact
4.2 ๋ณ๋ ฌ 3๋ก ์กฐ์ฌ ๋ฉ์ปค๋์ฆ
๋น๊ต ๋ชจ๋๋ ์ธ ๋ฒ์ ๋ ๋ฆฝ์ ์ธ ์กฐ์ฌ๋ฅผ ํธ๋ฆฌ๊ฑฐํฉ๋๋ค:
# scripts/lib/score.py (๋น๊ต ๋ชจ๋ ๋ธ๋์น)
def run_comparative_mode(query_a: str, query_b: str, base_query: str):
# 3๋ก ๋ณ๋ ฌ ๊ฒ์
results_a = run_research(query_a) # 1: Cursor๋ง ๊ฒ์
results_b = run_research(query_b) # 2: Windsurf๋ง ๊ฒ์
results_base = run_research(base_query) # 3: ๋ ํญ๋ชฉ์ ๋น๊ต ํ ๋ก ๊ฒ์
# ๋ณ๋ ฌ ๋น๊ต ๋ณด๊ณ ์ ์์ฑ
return render_comparison(results_a, results_b, results_base)
4.3 ๋น๊ต ๋ณด๊ณ ์ ํด์
์ถ๋ ฅ๋๋ ๋ณด๊ณ ์ ํ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
## Comparative Analysis: Cursor vs Windsurf
### Strengths
| Dimension | Cursor | Windsurf |
|---|---|---|
| ์ฝ๋ ์์ฑ ์๋ | โญโญโญโญโญ | โญโญโญ |
| ์ปจํ
์คํธ ์ดํด | โญโญโญโญ | โญโญโญโญโญ |
| ๋ค์ค ํ์ผ ํธ์ง | โญโญโญโญ | โญโญโญ |
| ์ปค๋ฎค๋ํฐ ์ํ๊ณ | โญโญโญโญโญ | โญโญโญ |
### Weaknesses
| Dimension | Cursor | Windsurf |
|---|---|---|
| ๋ฉ๋ชจ๋ฆฌ ์ ์ ์จ | ๋์ | ์ค๊ฐ |
| ์คํ๋ผ์ธ ์ง์ | ๋ฏธํก | ์ํธ |
### Community Sentiment (30-day)
- Cursor: 78% positive (1,240 discussions)
- Windsurf: 65% positive (890 discussions)
### Data-Driven Verdict
Cursor๋ ์ปค๋ฎค๋ํฐ ์ฐธ์ฌ๋์ ์ฝ๋ ์์ฑ ํ์ง ๋ฉด์์ ์์ ์์ต๋๋ค.
Windsurf๋ ๋ณต์กํ ๋ฆฌํฉํฐ๋ง์ ์ํ ์ปจํ
์คํธ ์ดํด ๋ฅ๋ ฅ์ด ํ์ํฉ๋๋ค.
**Recommendation**: ์ผ์์ ์ธ ์ฝ๋ฉ์๋ Cursor๋ฅผ, ์ํคํ
์ฒ ์ค๊ณ์๋ Windsurf๋ฅผ ์ฌ์ฉํ์ธ์.
Step 5 ๋ค๋ฅธ Skill / CI ํ์ดํ๋ผ์ธ์ ์๋ฒ ๋ฉ
5.1 ์ปจํ ์คํธ ์ฃผ์ ์ผ๋ก ์ฌ์ฉ
๋ค๋ฅธ Skill์์ last30days์ ์ฐ๊ตฌ ๊ฒฐ๊ณผ๋ฅผ ์ง์ ์ฐธ์กฐํ ์ ์์ต๋๋ค:
## Recent Research Context
!python3 ~/.claude/skills/last30days/scripts/last30days.py \
"your research topic" \
--emit=context
5.2 ํ์ผ์์ ์ปจํ ์คํธ ์ฝ๊ธฐ
## Research Context
!cat ~/.local/share/last30days/out/last30days.context.md
5.3 CI/CD์ JSON ์ถ๋ ฅ ํตํฉ
์กฐ์ฌ ๊ฒฐ๊ณผ๋ฅผ ์๋ํ ํ์ดํ๋ผ์ธ์ ์ฃผ์ ํฉ๋๋ค:
# ํ๋ก๊ทธ๋จ์ฉ JSON ํ์ ์ถ๋ ฅ
python3 ~/.claude/skills/last30days/scripts/last30days.py \
"best LLM for code review 2026" \
--emit=json > research.json
# ์ถ์ฒ Top 3 ๋ชจ๋ธ ํ์ธ
python3 -c "
import json
data = json.load(open('research.json'))
for r in data['top_results'][:3]:
print(f\"- {r['title']} (score: {r['score']:.2f})\")
"
5.4 ํ๋ก์ ํธ ๋ ๋ฒจ .env ๋ฎ์ด์ฐ๊ธฐ
์ ์ญ ์ค์ ์ ์ํ์ง ์๋์? ํ๋ก์ ํธ ๋ฃจํธ์ .claude/last30days.env๋ฅผ ๋๋ฉด ์ ์ญ ์ค์ ์ ๋ฎ์ด์๋๋ค:
mkdir -p .claude
cat > .claude/last30days.env << 'EOF'
# ์ด ํ๋ก์ ํธ์๋ง ์ ์ฉ๋๋ API Key
SCRAPECREATORS_API_KEY=sc_project_specific_key
OPENAI_API_KEY=sk-project-specific-key
EOF
TIP
ํ ํ์ ์ ํนํ ์ ์ฉํฉ๋๋ค. ๊ฐ์ ์์ ์ ํค๋ฅผ ์ฌ์ฉํ๋ฉด์๋ Skill์ ๋์์ ๋์ผํ๊ฒ ์ ์งํ ์ ์์ต๋๋ค.
5.5 ์ธ์ ์์ ์ ์๋ ๊ฒ์ฆ
v2.9.5์ ์ถ๊ฐ๋ ๊ธฐ๋ฅ์ผ๋ก, Claude Code๊ฐ ์์๋ ๋๋ง๋ค .env ์ค์ ์ ์๊ฒฐ์ฑ์ ์๋์ผ๋ก ํ์ธํฉ๋๋ค:
# ์๋ ๊ฒ์ฆ ์คํ
python3 ~/.claude/skills/last30days/scripts/last30days.py \
--validate-config
ํ์ ํค๊ฐ ๋๋ฝ๋ ๊ฒฝ์ฐ ๋ช ํํ๊ฒ ์๋ดํฉ๋๋ค:
โ SCRAPECREATORS_API_KEY is missing (required)
โ
OPENAI_API_KEY found
โ ๏ธ BSKY_HANDLE is missing (optional)
์์ฃผ ๋ฌป๋ ์ง๋ฌธ(FAQ) ๋ฐ ํธ๋ฌ๋ธ์ํ
Q1: SCRAPECREATORS_API_KEY ๋๋ฝ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
์์ธ: ํ๊ฒฝ ๋ณ์๊ฐ ์ ๋๋ก ๋ก๋๋์ง ์์์ต๋๋ค.
ํด๊ฒฐ:
# ํค ์กด์ฌ ์ฌ๋ถ ํ์ธ
cat ~/.config/last30days/.env | grep SCRAPECREATORS_API_KEY
# ํ๋ฌ๊ทธ์ธ์ผ๋ก ์ค์นํ๋ค๋ฉด ์๋ ๋๊ธฐํ ์๋
bash ~/.claude/skills/last30days/scripts/sync.sh
Q2: X ๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ๊ณ์ ๋น์ด ์์ต๋๋ค.
์์ธ: AUTH_TOKEN / CT0 ์ฟ ํค๊ฐ ๋ง๋ฃ๋์๊ฑฐ๋ ์ ํจํ์ง ์์ต๋๋ค.
ํด๊ฒฐ:
# 1. x.com์ ๋ค์ ๋ก๊ทธ์ธ
# 2. ์ต์ auth_token๊ณผ ct0๋ฅผ ๋ค์ ๋ณต์ฌ
# 3. .env ์
๋ฐ์ดํธ
# ๋๋ xAI API ๋์ ์ฌ์ฉ (์ฟ ํค ๋ถํ์)
echo "XAI_API_KEY=xai-your_key" >> ~/.config/last30days/.env
Q3: ๊ฒ์ ์๋๊ฐ ๋๋ฌด ๋๋ฆฝ๋๋ค (10๋ถ ์ด์).
์์ธ: ๊ธฐ๋ณธ์ ์ผ๋ก ์ต๋ 10๊ฐ์ ์์ค๋ฅผ ๋ณ๋ ฌ ๊ฒ์ํ๋ฉฐ, ๋์นํ ์ฃผ์ ์ ๊ฒฝ์ฐ API ์ฌ์๋๊ฐ ๋ง์์ง ์ ์์ต๋๋ค.
ํด๊ฒฐ:
# 1. --quick์ ์ฌ์ฉํ์ฌ ์ฌ์ธต ๊ฒ์ ๊ฑด๋๋ฐ๊ธฐ
python3 ~/.claude/skills/last30days/scripts/last30days.py \
"niche topic" \
--quick
# 2. ํน์ ์์ค์์ ํ์์์์ด ๋ฐ์ํ๋์ง ํ์ธ
python3 ~/.claude/skills/last30days/scripts/last30days.py \
"topic" \
--sources=reddit # Reddit๋ง ๊ฒ์ํ์ฌ ๋๋ฒ๊น
๊ฐ์ํ
Q4: Polymarket์์ ๊ด๋ จ ์๋ ์์ฅ ์ ๋ณด๊ฐ ๋ฐํ๋ฉ๋๋ค.
์์ธ: ์ฃผ์ ๋งค์นญ์ด ํค์๋ ๊ธฐ๋ฐ์ด์ด์ ์ผ๋ถ ์ฃผ์ ์๋ ํ์ฑ ์์ฅ์ด ์์ ์ ์์ต๋๋ค.
ํด๊ฒฐ:
# ์๋ ํค์๋ ํ์ฅ ์ง์
python3 ~/.claude/skills/last30days/scripts/last30days.py \
"AI coding assistant" \
--polymarket-tags="artificial intelligence,llm,gpt" \
--emit=compact
Q5: Claude Code์์ ์คํฌ๋ฆฝํธ์ ๋ํด Permission denied ์ค๋ฅ๊ฐ ๋น๋๋ค.
์์ธ: ์ ์คํฌ๋ฆฝํธ์ ์คํ ๊ถํ์ด ์์ต๋๋ค.
ํด๊ฒฐ:
chmod +x ~/.claude/skills/last30days/skills/last30days.sh
chmod +x ~/.claude/skills/last30days/scripts/last30days.py
Q6: Reddit์ ํ ๋ก ์ด ๋ง์๋ฐ ๋ณด๊ณ ์์๋ ํฌ์คํธ๊ฐ ์ ๊ฒ ๋์ต๋๋ค.
์์ธ: v2.9 ์ดํ ๊ธฐ๋ณธ์ ์ผ๋ก ScrapeCreators๋ฅผ ์ฌ์ฉํ๋๋ฐ, Key๊ฐ ์ค์ ๋์์ด๋ ํ์์ด ์๋ชป๋์์ ์ ์์ต๋๋ค.
ํด๊ฒฐ:
# ScrapeCreators Key ์ ํจ์ฑ ํ์ธ
curl -H "x-api-key: sc_your_key" \
https://api.scrapecreators.com/v1/reddit/search?q=test
# Key๊ฐ ์ ํจํ๋ฐ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด OpenAI ๋์์ผ๋ก ์๋ํ๋์ง ํ์ธ
# .env์ ScrapeCreators ๊ฐ์ ์ฌ์ฉ ์ค์ ์ถ๊ฐ
echo "FORCE_SCRAPECREATORS=1" >> ~/.config/last30days/.env
์ถ๊ฐ ์ฝ์๊ฑฐ๋ฆฌ / ์ฌํ ํ์ต
1. ์ ์ ๋ชจ๋ธ ์์ธ ํ๋
scripts/lib/score.py์ ๊ฐ์ค์น๋ ํ๋์ฝ๋ฉ๋์ด ์์ต๋๋ค. ํน์ ์์ค๋ฅผ ์ ํธํ๋ค๋ฉด ํฌํฌ(fork) ํ ์์ ํ ์ ์์ต๋๋ค:
# Hacker News์ ๊ถ์ ๊ฐ์ค์น๋ฅผ 0.20์์ 0.35๋ก ์ํฅ
SOURCE_WEIGHTS = {
"hackernews": 0.35, # โ 0.20์์ ๋ณ๊ฒฝ
"reddit": 0.25,
"x": 0.15,
"polymarket": 0.15,
"youtube": 0.10,
}
2. ์ฌ์ฉ์ ์ ์ ์์ค ์ถ๊ฐ
GitHub Issues๋ LinkedIn์ ์ถ๊ฐํ๊ณ ์ถ๋์? hackernews.py์ ์ธํฐํ์ด์ค ๊ท๊ฒฉ์ ์ฐธ๊ณ ํ์ฌ scripts/lib/์ ์ ๋ชจ๋์ ๋ง๋ค๊ณ last30days.py์ ๋ฑ๋กํ์ธ์. SPEC.md์ ์์ธํ ์ธํฐํ์ด์ค ์ ์๊ฐ ์์ต๋๋ค.
3. ์ ๊ธฐ ์กฐ์ฌ ์๋ํ
cron์ ์ฌ์ฉํ์ฌ ์ ๊ธฐ์ ์ผ๋ก ์กฐ์ฌ๋ฅผ ์ํํ๊ณ ๋ฆฌ์์น ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ๋ฐ์ดํธํ์ธ์:
# ๋งค์ผ ์ค์ 8์์ "AI tools weekly" ์กฐ์ฌ ์คํ
0 8 * * * python3 ~/.claude/skills/last30days/scripts/last30days.py \
"AI developer tools weekly" \
--days=7 \
--emit=md \
--output ~/Documents/Last30Days/ai-tools-weekly-$(date +\%Y-\%m-\%d).md
4. ์ง์ ๋ฒ ์ด์ค(KB) ์ฐ๋
์กฐ์ฌ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ธ ์ง์ ๋ฒ ์ด์ค(RAG ํ์ดํ๋ผ์ธ)์ ์ง์ ์ฃผ์ ํ์ธ์:
# ์ธ์ฉ๊ตฌ๊ฐ ํฌํจ๋ context๋ฅผ ์์ฑํ์ฌ ๋ค๋ฅธ Skill์ ์ ๋ฌ
python3 ~/.claude/skills/last30days/scripts/last30days.py \
"Claude Code advanced techniques" \
--emit=context > ~/.knowledge/last30_context.md
๊ด๋ จ ๋ฆฌ์์ค
- GitHub: mvanhorn/last30days-skill
- ClawHub: last30days-official
- ScrapeCreators API: scrapecreators.com
- OpenClaw ๊ณต์ ์ฌ์ดํธ: openclaw.ai
- Hacker News Algolia API: hn.algolia.com/api
- Polymarket Gamma API: gamma-api.polymarket.com