Metadata-Version: 2.3
Name: wyrd-tui
Version: 1.3.0
Summary: A TUI for personal knowledge management — feeds, saved articles, deep research, optional Obsidian export
Keywords: tui,textual,rss,research,terminal
Author: Blake Rhodes
License: MIT
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
Classifier: Topic :: Office/Business :: News/Diary
Classifier: Topic :: Terminals
Requires-Dist: feedparser>=6.0.12
Requires-Dist: httpx>=0.28.1
Requires-Dist: platformdirs>=4.9.6
Requires-Dist: pypdf>=6.11.0
Requires-Dist: pyte>=0.8.2
Requires-Dist: textual>=8.2.5
Requires-Dist: trafilatura>=2.0.0
Requires-Python: >=3.12
Project-URL: Homepage, https://codeberg.org/brhodes/wyrd
Project-URL: Repository, https://codeberg.org/brhodes/wyrd.git
Project-URL: Issues, https://codeberg.org/brhodes/wyrd/issues
Project-URL: Changelog, https://codeberg.org/brhodes/wyrd/src/branch/main/CHANGELOG.md
Description-Content-Type: text/markdown

# wyrd

A small Linux RSS reader with AI-assisted discovery, for people tired of the feed.

The modern web is mostly other people's machines deciding what you should care
about — engagement-tuned timelines, SEO-mulched listicles, ad auctions deciding
which article you even *see*. wyrd is a terminal app built on the opposite
premise: you pick the sources, you pick the keywords that matter, articles
arrive as plain Markdown stripped of every banner and pop-up, and the only
ranking is a transparent keyword score you control. No accounts, no
recommendations from a stranger's model, no telemetry from the app itself. The
name is Anglo-Saxon for the woven thread of personal fate — your reading list
is yours to weave.

The reader is RSS-only on purpose. Every publisher worth following exposes a
feed (Hacker News, Reddit, Substack, blogs, news sites); the ones that don't
are usually the ones you wouldn't miss. **And when you want to find pieces that
don't have a feed at all, `Ctrl+D` asks Claude — using web search and fetch
under the hood — for articles you'd like based on what you've already saved.**
Discovered items land in the same feed table; like or dismiss them like
anything else. A deep-research helper on `3` turns Claude loose on the
peer-reviewed literature when you want to actually understand something. An
embedded terminal and optional Obsidian export round out the rest.

**Requirements:** Linux (x86_64 or arm64) with Python 3.12+. wyrd uses
Linux-specific behavior in the embedded terminal (`pyte`-backed PTY via
`os.forkpty`). **There are no plans to support macOS or Windows** — Linux is
the only target I'm interested in maintaining. If you want wyrd on another
platform, a PR is welcome and I'll review it on its merits, but I won't be
writing it myself and I won't gate Linux changes on cross-platform
compatibility. See [`PLAN.md`](PLAN.md) for the design and roadmap.

## What it does

**Feeds.** RSS / Atom URLs you configure flow through one scheduler. Audio /
video items are filtered out — it's a reader. Manual refresh with `Ctrl+R`;
auto-refresh runs quietly on a configurable interval (default hourly) and only
notifies when something new arrives or a source errors. `F3` opens an
**Activity** modal showing recent refresh runs with per-source status and any
errors. The default `config.toml` ships with commented-out HN-via-RSS and
long-form-journalism examples to get you started.

**Read in-app.** Highlighting a feed item fetches the page and renders it as
Markdown right in the TUI (httpx → trafilatura → in-house XML→Markdown
converter that keeps code-block indentation and turns HTML tables into real
GitHub pipe tables). Each article shows a "*N min read · ~W words*" line plus
a 2–3 sentence Claude-generated brief at the top — what the piece is actually
about, not the publisher's SEO description. Results are cached. `o` falls back
to opening the URL in a real browser; `y` copies the URL to your clipboard
(via OSC 52 — works over SSH); `Ctrl+Shift+Y` copies the whole article + URL
as Markdown; `Enter` or `F4` toggles reader-focus mode that hides the left
panel.

**Like → save → loop back.** `l` in the Feed snapshots an item into the
**Saved** pane (`d` dismisses it). Saved items get editable **Tags** and
**Notes** alongside the article, autosaved as you navigate. FTS5-backed search
(`/`) covers title / summary / article body / notes / tags with bm25 ranking.
And — the loop — wyrd auto-detects RSS feeds from articles you've read
(`<link rel="alternate">` in the page head) and surfaces them as "Suggested
feeds" in the setup wizard. One-click subscribe.

**AI-assisted discovery (`Ctrl+D`).** Press `Ctrl+D` from any tab. Claude
gathers ~40 candidate articles based on your recent saved items and the
active *taste profile* (built-ins: `default`, `engineer`, `academic`, `essays`
— or define your own under `[discover.profiles.<name>]`). Each URL is
HEAD-verified before insertion; a second Claude pass re-ranks and drops weak
ones. The survivors land in the Feed table with `source_kind = "discover"`.
Press `m` on a saved item to find more articles like that one specifically.
First press shows a one-time consent modal explaining exactly what data goes
to Claude. Every run is logged locally so you can see which profile produces
the highest like-rate over time.

**Deep research (`3`).** Type a topic, hit Enter, and a Claude-driven agent
reads the peer-reviewed literature on it. Each run produces a structured
review paper plus a per-source note with the agent's summary and, where an
open-access copy exists, the full text (PDF or HTML, extracted to Markdown).
Files land in a per-run folder; the left column is a tree of past runs with
live progress while the agent works.

**Embedded terminal (`4`).** A `pyte`-backed PTY running your `$SHELL`.
`F12` detaches; `F10` (anywhere) suspends the TUI entirely and drops into a
real shell — the always-works escape hatch.

**Obsidian export.** Set `[obsidian] vault` (in `config.toml` or via the
setup wizard) and every liked article lands as Markdown under
`<vault>/<folder>/saved/` while every finished research run lands under
`<vault>/<folder>/research/`. Direct file writes — no Obsidian CLI or
desktop app required. Articles get YAML frontmatter (url, source, author,
published, saved, tags including `wyrd/saved`). A like before extraction
finishes defers the write until the worker lands. The wizard has an "Export
saved items to vault" button to migrate everything you'd liked before
configuring Obsidian.

**Customizable.** Theme picker in the setup wizard with live preview;
`Ctrl+T` cycles themes anywhere. Every app-level key is overridable via
`[keys]` in `config.toml`, applied live on save — no restart needed.

## Install

```bash
uv tool install wyrd-tui    # from PyPI (binary is `wyrd`)
uv tool install .           # or from a git clone
```

This puts a `wyrd` binary on your `PATH` (under `~/.local/bin` by default).

## Develop

```bash
uv sync            # create the venv, install deps
uv run wyrd        # launch the TUI
uv run pytest      # run the tests (parallel via pytest-xdist; ~30s)
```

Config lives at `~/.config/wyrd/config.toml`, data (the SQLite db) at
`~/.local/share/wyrd/wyrd.db`. Set `WYRD_HOME=/some/dir` to relocate both (used by tests).

First run pops the setup wizard — add some RSS feeds (or let Claude suggest
them with verified-before-shown URLs), then `Ctrl+R` to fetch.

### Keys

All shortcuts are configurable — `F2` opens the wizard with a "Keybindings" section, or edit `[keys]` in `config.toml` directly. Defaults:

- `1` / `2` / `3` / `4` — Feed / Saved / Research / Terminal tabs
- `F12` — detach from the embedded terminal (it captures every other key while focused)
- `F10` — suspend the TUI and drop into a real `$SHELL` (escape hatch for anything the embedded emulator mangles)
- `F2` — open the setup / preferences wizard
- `F3` — open the **Activity** modal (recent refresh runs; Esc to close)
- `F4` — toggle reader focus mode: hides the left panel so the article fills the screen; works in Feed, Saved, and Research
- `ctrl+r` — fetch new content from all configured feeds
- `ctrl+d` — run AI-assisted content discovery (anywhere; switches to the Feed pane)
- `ctrl+t` — cycle through Textual themes (persisted to config)
- In the Feed pane: `↑`/`↓` browse (the highlighted item's article is fetched and shown as Markdown on the right); `Enter` enters reader focus mode (article fills the pane — `Enter` or `F4` exits); `l` like/save, `d` dismiss, `o` open in a browser if the in-app reader can't parse the page; `y` copy the article's URL to the clipboard (via OSC 52 — works over SSH); `Ctrl+Shift+Y` copy the whole article + URL as Markdown; `f5` cycles the view between all / interesting only (★) / ranked by keyword score; `/` focuses the search box (FTS5-backed)
- In the Saved pane: `↑`/`↓` browse, `Enter` enters reader focus mode (`Enter` or `F4` exits), edit Tags/Notes (autosaved on navigate-away), `Ctrl+S` save now, `y` copy URL, `Ctrl+Shift+Y` copy article + URL as Markdown, `m` find more articles like this one, `/` focus search
- `ctrl+q` — quit (only when the terminal doesn't have focus — detach with `F12` first)
