Skip to main content
skill CX Codex

hackernews · imoonkey — Claude Code skill: what it does, how to install

Connects your coding agent to Hacker News to search stories, inspect nested comment trees, and post upvotes or replies.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add imoonkey/openweb --skill hackernews -a claude-code
Open on GitHub

What hackernews does

The skill separates read and write flows into two distinct transports. Browsing top stories, filtering by domain, and fetching discussion trees go directly through the Algolia Search API and Firebase. No browser runs during reads. Note that raw text fields like comment_text return HTML fragments.

Write actions run through a browser page session. Upvoting stories or posting replies requires an active login state. Deleting comments works as well, but only within the two-hour window enforced by Hacker News.

What it helps with

  • Search top, newest, or domain-specific stories on Hacker News
  • Fetch nested comment threads for any story ID
  • Look up user karma, creation date, and post history
  • Upvote stories and post replies using a browser session

Example prompts for the agent

  • Fetch the top stories from Hacker News right now and summarize the main topics
  • Get the comments for Hacker News item 42407357 and summarize the main points
  • Check recent stories submitted from domain github.com on Hacker News

How to install hackernews

1Skills CLI (Vercel)

npx skills add imoonkey/openweb --skill hackernews -a claude-code

2Manually: put the files in place

~/.claude/skills/hackernews/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/hackernews/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about hackernews

How to install hackernews in Claude Code?

Run npx skills add imoonkey/openweb --skill hackernews -a claude-code in your terminal.

What does the hackernews skill do?

It lets your agent read Hacker News feeds, search comments, view profiles, and submit upvotes or replies directly from the CLI.

Does reading Hacker News require a browser session?

No, all read actions use the Algolia Search and Firebase APIs directly. A browser context with login is only required when upvoting or commenting.

Source text

SKILL.md · MIT
# Hacker News

## Overview
Tech news aggregator by Y Combinator. Reads via Algolia Search API and Firebase API (node-direct). Writes via browser page context.

## Workflows

### Browse and read a story
1. `getTopStories` → pick story → note `objectID`
2. `getStoryDetail(id)` → title, url, points, author, nested comment tree

### Upvote a story
1. `getTopStories` → pick story → `objectID`
2. `upvoteStory(id=objectID)` → `{ok, id}` (requires login)
3. `unvoteStory(id=${prev.upvoteStory.id})` → `{ok, id}` — reverses the upvote (only valid while upvoted)

### Comment on a story
1. `getStoryDetail(id)` → `item.id`
2. `addComment(parent=item.id, text)` → `{ok, parent, id}` — `id` is the new comment's id (requires login)
3. `deleteComment(id=${prev.addComment.id})` → `{ok, id}` — must be within HN's ~2-hour delete window

### Reply to a comment
1. `getStoryDetail(id)` → `children[]` → pick comment → `comment.id`
2. `addComment(parent=comment.id, text)` → `{ok, parent, id}` — posts reply (requires login)

### Explore a user
1. `getUserProfile(id)` → karma, created, about
2. `getUserSubmissions(id)` → stories they posted
3. `getUserComments(id)` → their comment history

### Find stories from a domain
1. `getStoriesByDomain(query)` → all stories linking to that domain

### Read latest activity
1. `getNewComments` → newest comments across all stories

## Operations

| Operation | Intent | Key Input | Key Output | Transport |
|-----------|--------|-----------|------------|-----------|
| getTopStories | browse top stories | — | objectID, title, url, author, points, num_comments | L1 node (Algolia) |
| getNewestStories | browse newest | — | same as above | L1 node (Algolia) |
| getBestStories | all-time highest-voted | — | same as above | L1 node (Algolia) |
| getAskStories | recent Ask HN | — | same as above | L1 node (Algolia) |
| getShowStories | recent Show HN | — | same as above | L1 node (Algolia) |
| getJobPostings | browse jobs | — | objectID, title, url, created_at | L1 node (Algolia) |
| getFrontPageStories | time-based front page | — | same as feeds | L1 node (Algolia) |
| getStoryDetail | story + comment tree | id (item ID) | id, title, url, points, children[] | L1 node (Algolia) |
| getUserProfile | user profile | id (username) | id, karma, created, about | L1 node (Firebase) |
| getNewComments | newest comments | — | objectID, author, comment_text, story_title | L1 node (Algolia) |
| getStoryComments | comment thread | id, limit? | storyId, commentCount, comments[] | adapter (Algolia) |
| getStoriesByDomain | recent domain stories | query (domain) | objectID, title, url, author, points | L1 node (Algolia) |
| getUserSubmissions | user's stories | id (username) | objectID, title, url, author, points | adapter (Algolia) |
| getUserComments | user's comments | id (username) | objectID, author, comment_text | adapter (Algolia) |
| upvoteStory | upvote item | id <- feeds/getStoryDetail | ok, id | adapter (page) |
| unvoteStory | reverse upvote | id <- upvoteStory | ok, id | adapter (page) |
| addComment | post comment | parent <- getStoryDetail, text | ok, parent, id | adapter (page) |
| deleteComment | delete own comment | id <- addComment | ok, id | adapter (page); ~2-hour window |

## Raw Algolia wire shape

Read operations hit `https://hn.algolia.com/api/v1/search` over the node transport. The raw Algolia response is:

```json
{
  "hits": [ /* ... */ ],
  "nbHits": 1234,
  "hitsPerPage": 20,
  "page": 0,
  "nbPages": 50,
  "processingTimeMS": 3,
  "query": "",
  "params": "tags=story"
}
```

The spec declares `unwrap: hits`, so adapters/agents receive just the `hits` array — the envelope (`nbHits`, `page`, etc.) is stripped by the runtime.

Each hit carries Algolia-indexed fields:

- `objectID` — story/comment id as a **string** (cast if you need a number)
- `title`, `url`, `author`, `points`, `num_comments`
- `story_text`, `comment_text` — HTML strings (see note below)
- `created_at` (ISO), `created_at_i` (unix seconds)
- `_tags` — e.g. `["story", "author_pg", "story_12345"]`
- `story_id`, `parent_id` — for comments

### Templated reads

Some reads template the `id` param into an Algolia filter/tag expression:

- `getStoryComments` → `numericFilters=story_id={id}`
- `getUserSubmissions` → `tags=story,author_{id}`
- `getUserComments` → `tags=comment,author_{id}`

Because `id` is used as a template source, the runtime does **not** emit it as a bare query key — only the interpolated filter/tag appears on the wire.

### HTML in text fields

`comment_text` and `story_text` are HTML fragments (typically wrapped in `<p>` or `<pre>`). When rendering, strip those tags (and decode entities) rather than displaying raw markup.

## Quick Start

```bash
# Browse top stories (node-direct, no browser needed)
openweb hackernews exec getTopStories '{}'

# Get story detail with full comment tree
openweb hackernews exec getStoryDetail '{"id": 42407357}'

# Get comments for a story (with limit)
openweb hackernews exec getStoryComments '{"id": 42407357, "limit": 10}'

# Look up a user (Firebase API)
openweb hackernews exec getUserProfile '{"id": "pg"}'

# User's submitted stories
openweb hackernews exec getUserSubmissions '{"id": "pg"}'

# Stories from a domain
openweb hackernews exec getStoriesByDomain '{"query": "github.com"}'

# Latest comments site-wide
openweb hackernews exec getNewComments '{}'

# Upvote a story (requires browser + login)
openweb hackernews exec upvoteStory '{"id": 42407357}'

# Reverse the upvote (only valid while currently upvoted)
openweb hackernews exec unvoteStory '{"id": 42407357}'

# Comment on a story (requires browser + login)
openweb hackernews exec addComment '{"parent": 42407357, "text": "Great article!"}'

# Delete your own comment (HN ~2-hour delete window)
openweb hackernews exec deleteComment '{"id": 47830121}'
```

© imoonkey · MIT · imoonkey/openweb

Similar skills

All skills for Browser and scraping →

hackernews by other authors comes first.

From the same set12

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor