
Fs Street
- 58 installs
- 26 repo stars
- Updated February 8, 2026
- geekjourneyx/mind-skills
Fetch articles from the Farnam Street RSS feed by relative date, absolute date, or available-date range for topics like mental models and decision-making.
About
Pulls Farnam Street blog articles via RSS, supporting relative dates, absolute dates, and listing which dates are available. A developer uses it to retrieve Farnam Street writing on mental models, decision-making, learning, or leadership.
- Query by relative date, absolute YYYY-MM-DD date, or available date range
- Focused on Farnam Street mental-models and decision-making content
Fs Street by the numbers
- 58 all-time installs (skills.sh)
- Ranked #1,009 of 2,715 Automation & Workflows skills by installs in the Skillselion catalog
- Data as of Jul 24, 2026 (Skillselion catalog sync)
npx skills add https://github.com/geekjourneyx/mind-skills --skill fs-streetAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 58 |
|---|---|
| repo stars | ★ 26 |
| Last updated | February 8, 2026 |
| Repository | geekjourneyx/mind-skills ↗ |
What it does
Fetch articles from the Farnam Street RSS feed by relative date, absolute date, or available-date range for topics like mental models and decision-making.
Files
Farnam Street
Fetches articles from Farnam Street blog, covering topics like mental models, decision-making, leadership, and learning.
Quick Start
# Basic queries
昨天的文章
今天的FS文章
2024-06-13的文章
# Search
有哪些可用的日期Query Types
| Type | Examples | Description |
|---|---|---|
| Relative date | 昨天的文章 今天的文章 前天 | Yesterday, today, day before |
| Absolute date | 2024-06-13的文章 | YYYY-MM-DD format |
| Date range | 有哪些日期 可用的日期 | Show available dates |
| Topic search | 关于决策的文章 思维模型 | Search by keyword |
Workflow
- [ ] Step 1: Parse date from user request
- [ ] Step 2: Fetch RSS data
- [ ] Check content availability
- [ ] Format and display results---
Step 1: Parse Date
| User Input | Target Date | Calculation |
|---|---|---|
昨天 | Yesterday | today - 1 day |
前天 | Day before | today - 2 days |
今天 | Today | Current date |
2024-06-13 | 2024-06-13 | Direct parse |
Format: Always use YYYY-MM-DD
---
Step 2: Fetch RSS
python skills/fs-street/scripts/fetch_blog.py --date YYYY-MM-DDAvailable commands:
# Get specific date
python skills/fs-street/scripts/fetch_blog.py --date 2024-06-13
# Get date range
python skills/fs-street/scripts/fetch_blog.py --date-range
# Relative dates
python skills/fs-street/scripts/fetch_blog.py --relative yesterdayRequirements: pip install feedparser requests
---
Step 3: Check Content
When NOT Found
Sorry, no article available for 2024-06-14
Available date range: 2023-04-19 ~ 2024-06-13
Suggestions:
- View 2024-06-13 article
- View 2024-06-12 articleMembers Only Content
Some articles are marked [FS Members] - these are premium content and may only show a teaser.
---
Step 4: Format Results
Example Output:
# Farnam Street · 2024年6月13日
> Experts vs. Imitators: How to tell the difference between real expertise and imitation
## Content
If you want the highest quality information, you have to speak to the best people. The problem is many people claim to be experts, who really aren't.
**Key Insights**:
- Imitators can't answer questions at a deeper level
- Experts can tell you all the ways they've failed
- Imitators don't know the limits of their expertise
---
Source: Farnam Street
URL: https://fs.blog/experts-vs-imitators/---
Configuration
| Variable | Description | Default |
|---|---|---|
| RSS_URL | RSS feed URL | https://fs.blog/feed/ |
No API keys required.
---
Troubleshooting
| Issue | Solution |
|---|---|
| RSS fetch fails | Check network connectivity |
| Invalid date | Use YYYY-MM-DD format |
| No content | Check available date range |
| Members only | Some articles are premium content |
---
CLI Reference
# Get specific date
python skills/fs-street/scripts/fetch_blog.py --date 2024-06-13
# Get date range
python skills/fs-street/scripts/fetch_blog.py --date-range
# Relative dates
python skills/fs-street/scripts/fetch_blog.py --relative yesterdayOutput Format Reference
Markdown Template
# Farnam Street · {date}
> {article_title}
## Content
{article_content}
---
Source: Farnam Street
URL: {article_url}Fields
| Field | Description |
|---|---|
| title | Article title |
| link | Article URL |
| pubDate | Publication date |
| content | Article content (HTML) |
| is_members_only | Whether this is premium content |
#!/usr/bin/env python3
"""
Farnam Street Blog Fetcher
Fetches articles from Farnam Street RSS and returns structured data.
"""
import sys
import json
import argparse
from datetime import datetime, timezone, timedelta
from pathlib import Path
try:
import feedparser
import requests
except ImportError:
print("Error: Required packages not installed.")
print("Run: pip install feedparser requests")
sys.exit(1)
# RSS URL
RSS_URL = "https://fs.blog/feed/"
REQUEST_TIMEOUT = 30
def fetch_rss():
"""Download and parse RSS from Farnam Street"""
try:
response = requests.get(RSS_URL, timeout=REQUEST_TIMEOUT)
response.raise_for_status()
return feedparser.parse(response.content)
except requests.RequestException as e:
print(json.dumps({"error": f"Failed to fetch RSS: {e}"}))
sys.exit(1)
def get_date_range(feed):
"""Get available date range from RSS entries
Returns:
tuple: (min_date, max_date) in YYYY-MM-DD format, or (None, None)
"""
dates = []
for entry in feed.entries:
# Parse from pubDate
if hasattr(entry, 'published_parsed') and entry.published_parsed:
dt = datetime(*entry.published_parsed[:6], tzinfo=timezone.utc)
dates.append(dt.strftime("%Y-%m-%d"))
if not dates:
return None, None
return min(dates), max(dates)
def extract_date_from_link(link):
"""Extract date from URL (FS Blog doesn't use dates in links)
Args:
link: URL string
Returns:
None (FS Blog doesn't encode dates in URLs)
"""
# FS Blog doesn't encode dates in article URLs
return None
def get_content_by_date(feed, target_date):
"""Extract content for a specific date
Args:
feed: Feedparser parsed feed
target_date: Date string in YYYY-MM-DD format
Returns:
dict with keys: title, link, content, pubDate, or None if not found
"""
target_dt = datetime.strptime(target_date, "%Y-%m-%d")
for entry in feed.entries:
# Check by pubDate
if hasattr(entry, 'published_parsed') and entry.published_parsed:
dt = datetime(*entry.published_parsed[:6], tzinfo=timezone.utc)
entry_date = dt.strftime("%Y-%m-%d")
if entry_date == target_date:
return extract_entry_content(entry)
return None
def extract_entry_content(entry):
"""Extract content from an RSS entry
Returns:
dict with keys: title, link, content, pubDate, is_members_only
"""
# Check if members only
title = entry.get("title", "")
is_members_only = "[FS Members]" in title
# Get full content
if hasattr(entry, 'content') and entry.content:
content = entry.content[0].get('value', '')
elif hasattr(entry, 'summary'):
content = entry.summary
else:
content = title
# Check for members only in content
if "Members Only content" in content or "Not a member? Join Us" in content:
is_members_only = True
return {
"title": title,
"link": entry.get("link", ""),
"pubDate": entry.get("published"),
"content": content,
"is_members_only": is_members_only
}
def search_by_keyword(feed, keyword):
"""Search articles by keyword in title
Args:
feed: Feedparser parsed feed
keyword: Search keyword
Returns:
List of matching articles
"""
results = []
keyword_lower = keyword.lower()
for entry in feed.entries:
title = entry.get("title", "")
if keyword_lower in title.lower():
results.append({
"title": title,
"link": entry.get("link", ""),
"pubDate": entry.get("published"),
"summary": entry.get("summary", "")
})
return results
def main():
parser = argparse.ArgumentParser(description='Fetch Farnam Street articles')
parser.add_argument('--date-range', action='store_true', help='Show available date range')
parser.add_argument('--date', type=str, help='Get content for specific date (YYYY-MM-DD)')
parser.add_argument('--relative', type=str, choices=['yesterday', 'today', 'day-before'],
help='Relative date: yesterday, today, day-before')
parser.add_argument('--search', type=str, help='Search articles by keyword')
args = parser.parse_args()
# Fetch RSS
feed = fetch_rss()
# Date range mode
if args.date_range:
min_date, max_date = get_date_range(feed)
print(json.dumps({
"min_date": min_date,
"max_date": max_date,
"total_entries": len(feed.entries)
}, indent=2))
return
# Search mode
if args.search:
results = search_by_keyword(feed, args.search)
print(json.dumps({
"keyword": args.search,
"count": len(results),
"results": results[:10] # Limit to 10 results
}, indent=2, ensure_ascii=False))
return
# Calculate target date
if args.relative:
if args.relative == 'yesterday':
target_date = (datetime.now(timezone.utc) - timedelta(days=1)).strftime("%Y-%m-%d")
elif args.relative == 'day-before':
target_date = (datetime.now(timezone.utc) - timedelta(days=2)).strftime("%Y-%m-%d")
else: # today
target_date = datetime.now(timezone.utc).strftime("%Y-%m-%d")
date_arg = target_date
elif args.date:
target_date = args.date
date_arg = target_date
else:
# Default: yesterday
target_date = (datetime.now(timezone.utc) - timedelta(days=1)).strftime("%Y-%m-%d")
date_arg = target_date
# Get content
content = get_content_by_date(feed, target_date)
if content:
# Clean HTML entities
content["content"] = content["content"].replace('<', '<').replace('>', '>').replace('&', '&')
print(json.dumps(content, indent=2, ensure_ascii=False))
else:
# Return empty result with available range
min_date, max_date = get_date_range(feed)
print(json.dumps({
"error": "not_found",
"message": f"No content found for {target_date}",
"target_date": target_date,
"available_range": {
"min": min_date,
"max": max_date
}
}, indent=2))
if __name__ == "__main__":
main()
# Farnam Street Skill