| name | freshrss |
| description | Access and manage my FreshRSS instance. Use for RSS reading, search, recommendations, subscriptions, auto-categorization, uncategorized-feed cleanup, or subscribing to an email newsletter through Kill the Newsletter. |
| allowed-tools | Bash, WebFetch, AskUserQuestion |
FreshRSS
My self-hosted RSS reader. Use this skill for anything RSS-related: browsing
articles, searching content, managing feeds, finding recommendations, answering
questions about what I read.
Environment
Variables from sops-nix secrets:
FRESHRSS_URL - Base URL of FreshRSS instance
FRESHRSS_API_USER - API username
FRESHRSS_API_PASSWORD - API password
Authentication
Required before all API calls:
AUTH_TOKEN=$(curl -s -X POST "$FRESHRSS_URL/api/greader.php/accounts/ClientLogin" \
-d "Email=$FRESHRSS_API_USER" \
-d "Passwd=$FRESHRSS_API_PASSWORD" | grep -oP 'Auth=\K.*')
Reading & Searching Articles
Get recent items (all feeds)
curl -s "$FRESHRSS_URL/api/greader.php/reader/api/0/stream/contents/reading-list?output=json&n=20" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" | jq '.items[] | {title, published: .published, origin: .origin.title, summary: .summary.content[:200], href: .alternate[0].href}'
Get unread items
curl -s "$FRESHRSS_URL/api/greader.php/reader/api/0/stream/contents/reading-list?output=json&n=50&xt=user/-/state/com.google/read" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" | jq '.items[] | {title, origin: .origin.title, href: .alternate[0].href}'
Get items from a specific feed
curl -s "$FRESHRSS_URL/api/greader.php/reader/api/0/stream/contents/feed%2fFEED_URL?output=json&n=20" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" | jq '.items[] | {title, published: .published, summary: .summary.content[:200]}'
Get items from a category
curl -s "$FRESHRSS_URL/api/greader.php/reader/api/0/stream/contents/user%2f-%2flabel%2fCATEGORY_NAME?output=json&n=20" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" | jq '.items[] | {title, origin: .origin.title, href: .alternate[0].href}'
Get starred items
curl -s "$FRESHRSS_URL/api/greader.php/reader/api/0/stream/contents/user%2f-%2fstate%2fcom.google%2fstarred?output=json&n=50" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" | jq '.items[] | {title, origin: .origin.title, href: .alternate[0].href}'
Search articles by keyword
FreshRSS GReader API does not have a native search endpoint. To search, fetch a
large batch of items and filter client-side with jq:
curl -s "$FRESHRSS_URL/api/greader.php/reader/api/0/stream/contents/reading-list?output=json&n=200" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" | jq '[.items[] | select(.title | test("KEYWORD"; "i")) | {title, origin: .origin.title, href: .alternate[0].href}]'
For deeper search, also check summary content:
curl -s "$FRESHRSS_URL/api/greader.php/reader/api/0/stream/contents/reading-list?output=json&n=500" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" | jq '[.items[] | select((.title // "" | test("KEYWORD"; "i")) or (.summary.content // "" | test("KEYWORD"; "i"))) | {title, origin: .origin.title, href: .alternate[0].href}]'
Use &c=TIMESTAMP (unix epoch) to paginate through older items.
Get item stream IDs (lightweight, for pagination)
curl -s "$FRESHRSS_URL/api/greader.php/reader/api/0/stream/items/ids?output=json&n=100&s=reading-list" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" | jq '.itemRefs[].id'
Feed Management
List all feeds
curl -s "$FRESHRSS_URL/api/greader.php/reader/api/0/subscription/list?output=json" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" | jq '.subscriptions[] | {title, id, url: .url, categories: [.categories[].label]}'
List categories
curl -s "$FRESHRSS_URL/api/greader.php/reader/api/0/tag/list?output=json" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" | jq '.tags[].id' | grep label
Unread count (per feed)
curl -s "$FRESHRSS_URL/api/greader.php/reader/api/0/unread-count?output=json" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" | jq '.unreadcounts[] | {id, count}'
Add a feed
RESULT=$(curl -s -X POST "$FRESHRSS_URL/api/greader.php/reader/api/0/subscription/quickadd" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" \
-d "quickadd=https://example.com/feed.xml")
FEED_ID=$(echo "$RESULT" | jq -r '.streamId')
curl -s -X POST "$FRESHRSS_URL/api/greader.php/reader/api/0/subscription/edit" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" \
-d "ac=edit" \
-d "s=$FEED_ID" \
-d "a=user/-/label/CATEGORY_NAME"
Move feed between categories
curl -s -X POST "$FRESHRSS_URL/api/greader.php/reader/api/0/subscription/edit" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" \
-d "ac=edit" \
-d "s=feed/ID" \
-d "a=user/-/label/NewCategory" \
-d "r=user/-/label/OldCategory"
Remove a feed
curl -s -X POST "$FRESHRSS_URL/api/greader.php/reader/api/0/subscription/edit" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" \
-d "ac=unsubscribe" \
-d "s=feed/FEED_ID"
Mark as read / star
curl -s -X POST "$FRESHRSS_URL/api/greader.php/reader/api/0/edit-tag" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" \
-d "i=ITEM_ID" \
-d "a=user/-/state/com.google/read"
curl -s -X POST "$FRESHRSS_URL/api/greader.php/reader/api/0/edit-tag" \
-H "Authorization: GoogleLogin auth=$AUTH_TOKEN" \
-d "i=ITEM_ID" \
-d "a=user/-/state/com.google/starred"
Recommendations
When asked for feed recommendations:
- List all current subscriptions with categories
- Identify themes and interests from the feed titles and categories
- Use WebSearch to find feeds in similar topic areas that the user does not
already subscribe to
- Present recommendations grouped by interest area, with feed URL and a brief
description of what the feed covers
Workflow: add and categorize a feed
- Authenticate and fetch the existing categories.
- Fetch the feed URL and sample its title, description, and recent posts.
- Prefer the best-fitting existing category. Propose a short category matching
the current naming style only when none fits.
- Confirm the category unless the match is obvious.
- Add the feed using
subscription/quickadd, then assign the category using
subscription/edit.
- Verify the resulting subscription and report its title, URL, and category.
Workflow: subscribe to an email newsletter
-
Fetch the newsletter's site to understand its subject and choose a title.
-
Create a Kill the Newsletter inbox:
FEED_SLUG=$(curl -s -X POST https://kill-the-newsletter.com/feeds \
-H "CSRF-Protection: true" \
-d "title=NEWSLETTER_TITLE" \
-D - -o /dev/null | grep -oP 'location:.*feeds/\K[^\s]+')
-
Add https://kill-the-newsletter.com/feeds/${FEED_SLUG}.xml using the feed
workflow above.
-
Report ${FEED_SLUG}@kill-the-newsletter.com, the private Atom feed URL,
its FreshRSS category, and that the email address must be entered on the
newsletter signup page. Confirmation messages will appear in FreshRSS.
-
Never share the Kill the Newsletter feed URL publicly.
Workflow: organize uncategorized feeds
- Fetch existing categories and subscriptions with no category or only the
Uncategorized category.
- Sample each feed's site or RSS URL. Infer an existing category where
possible; skip feeds with insufficient evidence rather than guessing.
- Present one batch table containing each feed, proposed category, and brief
rationale. Let the user approve, reject, or override the proposals.
- For approved feeds, add the selected category with
subscription/edit and
remove user/-/label/Uncategorized.
- Report categorized, skipped, and still-uncategorized feeds, including any
newly created categories.
Notes
- Token is session-based, get a fresh one each invocation
- Feed IDs use format
feed/https://example.com/rss
- The Fever API (
/api/fever.php) is read-only, use GReader API for mutations
- URL-encode slashes in stream IDs when used in URL paths (
%2f)
n= controls batch size, c= is a continuation token (unix timestamp) for pagination
- To read full article content, use WebFetch on the article's
href