> ## Documentation Index
> Fetch the complete documentation index at: https://docs.beta.b3os.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Hacker News

The io.b3os/hacker-news pack: 5 actions and 1 trigger with call snippets, fixture outputs, connection setup and error codes, generated from version 1.0.0.

`io.b3os/hacker-news` 1.0.0 · `news`, `developer-tools`, `social` · MIT

Read Hacker News: the current front page, full-text search over stories and comments (newest first or by relevance), single items with their comment ids, and user profiles. Uses the public Algolia HN Search API and the official Firebase API. Keyless and read-only; no connection needed.

Every call's result carries `upstream_status` and `timing`: `validate_ms`, `inject_ms`, `render_ms`, `upstream_ms`, `map_ms` and `total_ms`. `upstream` is the service's time; the others are B3OS's own ([call actions](/actions/call)). The snippets below show no timing values, because a fixture records none.

## Connection

No credential: a keyless public API. Calls name no connection.

Hosts it reaches: `hn.algolia.com`, `hacker-news.firebaseio.com`.

## Actions

| Action | Effect | MCP tool | Title |
|---|---|---|---|
| [`get-front-page`](/actions/catalog/hacker-news#hacker-news-get-front-page) | read | `hacker-news__get-front-page` | Get the front page |
| [`search`](/actions/catalog/hacker-news#hacker-news-search) | read | `hacker-news__search` | Search by relevance |
| [`search-recent`](/actions/catalog/hacker-news#hacker-news-search-recent) | read | `hacker-news__search-recent` | Search newest first |
| [`get-item`](/actions/catalog/hacker-news#hacker-news-get-item) | read | `hacker-news__get-item` | Get an item |
| [`get-user`](/actions/catalog/hacker-news#hacker-news-get-user) | read | `hacker-news__get-user` | Get a user |

get-front-page

**Get the front page.** The stories on the Hacker News front page right now, in Algolia's front-page order, with points, comment counts, links and discussion URLs. Use search-recent for what is new and search for a topic.

Ref `io.b3os/hacker-news/get-front-page@1.0.0` · effect `read` · no connection · MCP tool `hacker-news__get-front-page`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
          "ref": "io.b3os/hacker-news/get-front-page@1",
          "input": {"hits_per_page": 3}
        }'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({
      ref: "io.b3os/hacker-news/get-front-page@1",
      input: { hits_per_page: 3 },
    });
    console.log(result.output);
    ```
  **Python**

```python
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({
        "ref": "io.b3os/hacker-news/get-front-page@1",
        "input": {"hits_per_page": 3},
    })
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {
        "name": "hacker-news__get-front-page",
        "arguments": {"hits_per_page": 3}
      }
    }
    ```

    Expose the pack as tools with `--packs hacker-news` on the local server or `?packs=hacker-news` on the remote URL, and the agent calls `hacker-news__get-front-page` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: Get the front page (response recorded 2026-10-26). From the bundle's `fixtures/get-front-page.json`, not a live call.

```json
{
  "stories": [
    {
      "id": "50225695",
      "title": "We should be more ambitious with the software we build",
      "url": "https://danluu.com/ambitious/",
      "hn_url": "https://news.ycombinator.com/item?id=50225695",
      "author": "ltratt",
      "points": 782,
      "comments": 702,
      "created_at": "2026-10-24T21:47:31Z",
      "created_at_i": 1792878451,
      "text": null
    },
    {
      "id": "50233779",
      "title": "A 10-year-old CNN outperforms frontier LLMs for skin cancer diagnosis",
      "url": "https://lynchlab.net/llm-skin-cancer",
      "hn_url": "https://news.ycombinator.com/item?id=50233779",
      "author": "sungam",
      "points": 515,
      "comments": 229,
      "created_at": "2026-10-25T17:15:38Z",
      "created_at_i": 1792948538,
      "text": null
    },
    {
      "id": "50234474",
      "title": "Dolly Parton's Imagination Library",
      "url": "https://imaginationlibrary.com/",
      "hn_url": "https://news.ycombinator.com/item?id=50234474",
      "author": "jumploops",
      "points": 499,
      "comments": 88,
      "created_at": "2026-10-25T18:23:54Z",
      "created_at_i": 1792952634,
      "text": "With today&#x27;s news, I thought I&#x27;d share this great program:<p>“When I was growing up in the hills of East Tennessee, I knew my dreams would come true. I know there are children in your community with their own dreams. They dream of becoming a doctor or an inventor or a minister. Who knows, maybe there is a little girl whose dream is to be a writer and singer.<p>The seeds of these dreams are often found in books and the seeds you help plant in your community can grow across the world.”"
    }
  ],
  "total": 30,
```

The first 40 of 43 lines; the fixture file has the rest.

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `rate_limited` | 429 | yes | Algolia's HN Search rate limit reached (10,000 requests an hour per IP). |
| `invalid_request` | 400, 422 | no | built from the service's response |

search

**Search by relevance.** Full-text search over Hacker News ranked by relevance, then points and comment count. Filter by item type, minimum points and creation time; page through with page. Returns stories (or comments, when type is comment) with links and discussion URLs.

Ref `io.b3os/hacker-news/search@1.0.0` · effect `read` · no connection · MCP tool `hacker-news__search`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
          "ref": "io.b3os/hacker-news/search@1",
          "input": {
            "query": "firecracker microvm",
            "hits_per_page": 3,
            "min_points": 50
          }
        }'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({
      ref: "io.b3os/hacker-news/search@1",
      input: { query: "firecracker microvm", hits_per_page: 3, min_points: 50 },
    });
    console.log(result.output);
    ```
  **Python**

```python
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({
        "ref": "io.b3os/hacker-news/search@1",
        "input": {
            "query": "firecracker microvm",
            "hits_per_page": 3,
            "min_points": 50,
        },
    })
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {
        "name": "hacker-news__search",
        "arguments": {
          "query": "firecracker microvm",
          "hits_per_page": 3,
          "min_points": 50
        }
      }
    }
    ```

    Expose the pack as tools with `--packs hacker-news` on the local server or `?packs=hacker-news` on the remote URL, and the agent calls `hacker-news__search` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: Search by relevance (response recorded 2026-10-26). From the bundle's `fixtures/search.json`, not a live call.

```json
{
  "stories": [
    {
      "id": "49912444",
      "title": "5x faster Edge Functions: V8 isolates to Firecracker MicroVMs",
      "url": "https://www.netlify.com/blog/edge-functions-firecracker-microvms/",
      "hn_url": "https://news.ycombinator.com/item?id=49912444",
      "author": "jbott",
      "points": 230,
      "comments": 109,
      "created_at": "2026-09-30T18:17:45Z",
      "created_at_i": 1790792265,
      "text": null
    },
    {
      "id": "32767784",
      "title": "Attacking Firecracker: AWS' MicroVM Monitor Written in Rust",
      "url": "https://www.graplsecurity.com/post/attacking-firecracker",
      "hn_url": "https://news.ycombinator.com/item?id=32767784",
      "author": "pentestercrab",
      "points": 212,
      "comments": 29,
      "created_at": "2022-09-08T16:20:36Z",
      "created_at_i": 1662654036,
      "text": null
    },
    {
      "id": "28893884",
      "title": "Firecracker MicroVMs",
      "url": "https://firecracker-microvm.github.io/",
      "hn_url": "https://news.ycombinator.com/item?id=28893884",
      "author": "colinprince",
      "points": 176,
      "comments": 60,
      "created_at": "2021-10-17T04:11:41Z",
      "created_at_i": 1634443901,
      "text": null
    }
  ],
  "total": 14,
```

The first 40 of 43 lines; the fixture file has the rest.

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `rate_limited` | 429 | yes | Algolia's HN Search rate limit reached (10,000 requests an hour per IP). |
| `invalid_request` | 400, 422 | no | built from the service's response |

search-recent

**Search newest first.** The same search as search, sorted by creation time with the newest first. Use it to watch a topic or to list what was just posted (empty query with type story is the /newest page).

Ref `io.b3os/hacker-news/search-recent@1.0.0` · effect `read` · no connection · MCP tool `hacker-news__search-recent`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
          "ref": "io.b3os/hacker-news/search-recent@1",
          "input": {"query": "rust", "hits_per_page": 3}
        }'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({
      ref: "io.b3os/hacker-news/search-recent@1",
      input: { query: "rust", hits_per_page: 3 },
    });
    console.log(result.output);
    ```
  **Python**

```python
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({
        "ref": "io.b3os/hacker-news/search-recent@1",
        "input": {"query": "rust", "hits_per_page": 3},
    })
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {
        "name": "hacker-news__search-recent",
        "arguments": {"query": "rust", "hits_per_page": 3}
      }
    }
    ```

    Expose the pack as tools with `--packs hacker-news` on the local server or `?packs=hacker-news` on the remote URL, and the agent calls `hacker-news__search-recent` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: Search newest first (response recorded 2026-10-26). From the bundle's `fixtures/search-recent.json`, not a live call.

```json
{
  "stories": [
    {
      "id": "50240115",
      "title": "Ask HN: Did crates.io stop processing new crate publishes?",
      "url": null,
      "hn_url": "https://news.ycombinator.com/item?id=50240115",
      "author": "davvid",
      "points": 1,
      "comments": 0,
      "created_at": "2026-10-26T07:03:21Z",
      "created_at_i": 1792998201,
      "text": "For example https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;saphyr-parser&#x2F;0.3.2&#x2F;code was recently published (without any client-side errors) but crates.io says:<p><pre><code>    The source code for this version is not available yet.\n\n    Archives are built shortly after a version is published. This usually only takes a few seconds, so please try again in a couple of minutes.\n\n</code></pre>\nI&#x27;ve never seen this error before. The same can be seen by this just-published crate (12 minutes ago) says the same thing: https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;skia-bindings&#x2F;0.156.0&#x2F;code<p>Does anyone know what&#x27;s going on?"
    },
    {
      "id": "50239988",
      "title": "Show HN: Skill-spotter, auto detect agent prompts and commands to create skills",
      "url": "https://github.com/ykisana/skill-spotter",
      "hn_url": "https://news.ycombinator.com/item?id=50239988",
      "author": "ykisana",
      "points": 1,
      "comments": 0,
      "created_at": "2026-10-26T06:48:10Z",
      "created_at_i": 1792997290,
      "text": "Skill-spotter auto detects commands and prompts you type.\nIt detects variations such as &#x27;push these changes&#x27; and &#x27;get these changes pushed&#x27;. Using both word comparison and the actual actions you agent performs.<p>It also adds to your Claude.md if that&#x27;s more applicable than creating a skill.<p>Just saving lots of time if you do repeat prompts."
    },
    {
      "id": "50239884",
      "title": "France's Nuclear Forces Bring in Neighbors to Keep Russia in Check",
      "url": "https://www.wsj.com/world/europe/frances-nuclear-forces-bring-in-neighbors-to-keep-russia-in-check-58b0967d",
      "hn_url": "https://news.ycombinator.com/item?id=50239884",
      "author": "JumpCrisscross",
      "points": 2,
      "comments": 0,
      "created_at": "2026-10-26T06:33:35Z",
      "created_at_i": 1792996415,
      "text": null
    }
  ],
  "total": 71533,
```

The first 40 of 43 lines; the fixture file has the rest.

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `rate_limited` | 429 | yes | Algolia's HN Search rate limit reached (10,000 requests an hour per IP). |
| `invalid_request` | 400, 422 | no | built from the service's response |

get-item

**Get an item.** One story, comment, job or poll by id from the official API: title, link, text, author, score, time, and the ids of its direct replies (kids, in ranked order). Call it again with a kid id to walk a thread.

Ref `io.b3os/hacker-news/get-item@1.0.0` · effect `read` · no connection · MCP tool `hacker-news__get-item`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"ref": "io.b3os/hacker-news/get-item@1", "input": {"id": 8863}}'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({ ref: "io.b3os/hacker-news/get-item@1", input: { id: 8863 } });
    console.log(result.output);
    ```
  **Python**

```python
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({"ref": "io.b3os/hacker-news/get-item@1", "input": {"id": 8863}})
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {"name": "hacker-news__get-item", "arguments": {"id": 8863}}
    }
    ```

    Expose the pack as tools with `--packs hacker-news` on the local server or `?packs=hacker-news` on the remote URL, and the agent calls `hacker-news__get-item` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: Get an item (response recorded 2026-10-26). From the bundle's `fixtures/get-item.json`, not a live call.

```json
{
  "id": 8863,
  "type": "story",
  "by": "dhouston",
  "time": 1175714200,
  "title": "My YC app: Dropbox - Throw away your USB drive",
  "url": "http://www.getdropbox.com/u/2/screencast.html",
  "text": null,
  "score": 104,
  "descendants": 71,
  "parent": null,
  "kids": [9224, 8917, 8884, 8887],
  "dead": false,
  "deleted": false,
  "hn_url": "https://news.ycombinator.com/item?id=8863"
}
```

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `not_found` | 200 | no | No Hacker News item with this id. |

get-user

**Get a user.** A Hacker News user's public profile: karma, account creation time, the about text (HTML) and how many items they submitted. Ids are case-sensitive.

Ref `io.b3os/hacker-news/get-user@1.0.0` · effect `read` · no connection · MCP tool `hacker-news__get-user`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"ref": "io.b3os/hacker-news/get-user@1", "input": {"username": "pg"}}'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({ ref: "io.b3os/hacker-news/get-user@1", input: { username: "pg" } });
    console.log(result.output);
    ```
  **Python**

```python
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({
        "ref": "io.b3os/hacker-news/get-user@1",
        "input": {"username": "pg"},
    })
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {"name": "hacker-news__get-user", "arguments": {"username": "pg"}}
    }
    ```

    Expose the pack as tools with `--packs hacker-news` on the local server or `?packs=hacker-news` on the remote URL, and the agent calls `hacker-news__get-user` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: Get a user (response recorded 2026-10-26). From the bundle's `fixtures/get-user.json`, not a live call.

```json
{
  "id": "pg",
  "created": 1160418092,
  "karma": 157316,
  "about": "Bug fixer.",
  "submitted_count": 3
}
```

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `not_found` | 200 | no | No Hacker News user with this name. |

## Triggers

new-story (trigger)

**New story.** Fires once for each new Hacker News item matching a query, checked every minute by default. The first check records what exists and emits nothing; later checks emit only items not seen before.

Ref `io.b3os/hacker-news/new-story@1.0.0` · poll of `search-recent`, every 60 s by default (at least 30 s) · no connection

| `with` key | Required | Description |
|---|---|---|
| `query` | no | Words to match; empty matches every new item. Default `""`. |
| `type` | no | Item type. Default `"story"`. |
| `min_points` | no | Minimum points. Default `0`. |

In a routine:

```yaml
triggers:
  - type: action
    id: new_story
    uses: io.b3os/hacker-news/new-story@1
```

Event, labeled `fixture`: the first item of `search-recent`'s fixture fixtures/search-recent.json (Search newest first (response recorded 2026-10-26)) through the trigger's event mapping. A routine reads it as `trigger.data`; its fields are `id`, `title`, `url`, `hn_url`, `author`, `points`, `comments`, `created_at`, `created_at_i`, `text`.

```json
{
  "id": "50240115",
  "title": "Ask HN: Did crates.io stop processing new crate publishes?",
  "url": null,
  "hn_url": "https://news.ycombinator.com/item?id=50240115",
  "author": "davvid",
  "points": 1,
  "comments": 0,
  "created_at": "2026-10-26T07:03:21Z",
  "created_at_i": 1792998201,
  "text": "For example https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;saphyr-parser&#x2F;0.3.2&#x2F;code was recently published (without any client-side errors) but crates.io says:<p><pre><code>    The source code for this version is not available yet.\n\n    Archives are built shortly after a version is published. This usually only takes a few seconds, so please try again in a couple of minutes.\n\n</code></pre>\nI&#x27;ve never seen this error before. The same can be seen by this just-published crate (12 minutes ago) says the same thing: https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;skia-bindings&#x2F;0.156.0&#x2F;code<p>Does anyone know what&#x27;s going on?"
}
```