Skip to main content
Glama
README.md
# Reading Buddy

Read an English book in your browser and discuss it with Claude Code or Codex CLI,
which always know **which sentence you are looking at**.

```
Chrome tab (any web page)
  └─ extension: visible paragraphs + selected text ──POST──▶ hub (127.0.0.1:8737)
                                                               └─ MCP /mcp ──▶ Claude Code / Codex CLI
                                                                                 reading_now, reading_section,
                                                                                 reading_note, reading_list
```

- **Pull-based, token-cheap.** The extension keeps the hub up to date; the AI fetches
  "what is on screen" only when you ask a question (one call, ~1–2k tokens).
- **Nothing leaves your machine.** The hub listens on localhost only. No API keys:
  the AI is whatever CLI you already use.
- **Works on any HTML page** — the extension reads the DOM directly, so paywalled or
  login-only pages work too. No fetching or HTML parsing on the server.
- **Several books at once.** The hub remembers the last position per URL; each session
  can pin itself to one book with the `book` filter.

## Setup

Requirements: macOS (launchd for the resident hub; the hub itself is plain Node), Node ≥ 20, Chrome.

```sh
git clone https://github.com/244t/reading-buddy && cd reading-buddy
npm install
npm run ext              # builds extension/dist
sh deploy/install.sh     # resident hub via launchd (or: npm run hub)
```

1. **Extension**: open `chrome://extensions`, enable *Developer mode*, *Load unpacked* → `extension/dist`.
   Reload any tab you were already reading (content scripts are not injected into existing tabs).
   The toolbar badge shows `on` once the hub receives data.
2. **Claude Code**:
   ```sh
   claude mcp add -s user --transport http reading-buddy http://127.0.0.1:8737/mcp
   cp -r skills/read ~/.claude/skills/     # adds the /read skill
   ```
3. **Codex CLI** (or any other MCP-capable agent):
   ```sh
   codex mcp add reading-buddy --url http://127.0.0.1:8737/mcp
   ```
   and add a few lines like these to your own `AGENTS.md` (global `~/.codex/AGENTS.md` or per project):
   ```markdown
   ## Reading partner
   The user reads books in Chrome. When they refer to what they are reading ("this sentence",
   "here", "this word"), call the MCP tool `reading_now` before answering; the selected text is
   what they mean. Use `reading_section` for questions beyond the screen, `reading_note` when
   they say "note this", and pass `book: "<url or title substring>"` if the session is about one book.
   ```

Check: select some text in the page, then `curl -s localhost:8737/state`.

## Usage

Open the book in Chrome, start `claude` anywhere, type `/read` (or `/read sre-book` to pin
a book). The assistant confirms which page you are on, then answer questions like
"what does *toil* mean in this sentence?" — it calls `reading_now` first and answers
with the selected text and surrounding paragraphs in context. Say "note this" to append
the conclusion to `~/.local/state/reading-buddy/notes/<page>.md`.

The `/read` skill answers in Japanese by default; edit `skills/read/SKILL.md` to change the
language or the discussion style.

## MCP tools

| tool | returns |
|---|---|
| `reading_now(book?, maxChars?)` | URL, title, heading path, selected text with neighbouring blocks, visible blocks |
| `reading_section(book?, heading?, maxChars?)` | all blocks under a heading (default: the section on screen) |
| `reading_note(book?, text)` | appends a note with URL + selection to the notes file |
| `reading_list()` | pages seen so far, most recent first, with progress |

`book` is a case-insensitive substring of the URL or title; omit it to use the tab you looked at last.

## Configuration

| env / file | default | meaning |
|---|---|---|
| `READING_BUDDY_PORT` | `8737` | hub port (also change `HUB` in `extension/src/background.ts`) |
| `READING_BUDDY_STATE_DIR` | `~/.local/state/reading-buddy` | `current.json` and `notes/` |
| `READING_BUDDY_LABEL` | `com.reading-buddy.hub` | launchd label used by `deploy/*.sh` |

Logs: `~/Library/Logs/reading-buddy-hub.log`. Restart after editing the hub:
`launchctl kickstart -k gui/$(id -u)/com.reading-buddy.hub`.

## Development

```sh
npm run hub:dev                    # hub with reload (stop the launchd one first)
npm run watch -w extension         # rebuild extension on change, then click "reload" in chrome://extensions
npm run typecheck -w hub && npm run typecheck -w extension
```

## License

MIT