██████╗██████╗██████╗██████╗  ██████╗
      ██╔═══╝██╔═══╝██╔═══╝██╔══██╗██╔═══██╗
      █████╗ █████╗ █████╗ ██║  ██║██║   ██║
      ██╔══╝ ██╔══╝ ██╔══╝ ██║  ██║██║   ██║
      ██║    ██████╗██████╗██████╔╝╚██████╔╝
      ╚═╝    ╚═════╝╚═════╝╚═════╝  ╚═════╝ 
  

(◕ᴥ◕) Your terminal RSS companion

🌐 WebsiteInstallationFeaturesUsageConfigurationKeybindings

--- A **beautiful**, **fast**, and **modern** terminal RSS reader built with Rust. Think [Reeder](https://reederapp.com/) meets the command line.
## 📸 Screenshots ### Main View ![Feedo Main View](assets/screenshots/feedo-main.png) *Three-panel layout: feeds, articles, and content preview with Dracula theme* ### Search ![Feedo Search](assets/screenshots/feedo-search.png) *Real-time search across all your feeds* ### Add Feed ![Feedo Add Feed](assets/screenshots/feedo-add-feed.png) *Auto-discover RSS/Atom feeds from any URL*
## ✨ Features | Feature | Description | |---------|-------------| | 🎨 **Beautiful TUI** | Clean three-panel interface with rounded borders and smooth navigation | | 🔍 **Feed Discovery** | Auto-detect RSS/Atom feeds from any URL — just paste a website | | 📴 **Offline Mode** | Articles cached locally — read without internet, read states persist | | ☁️ **Cloud Sync** | Sync with FreshRSS, Miniflux, Inoreader via Google Reader API | | 📁 **Smart Folders** | Organize feeds into collapsible folders with custom emoji icons | | 🔎 **Instant Search** | Find articles across all feeds with real-time filtering | | 🎭 **15 Themes** | Dracula, Nord, Catppuccin, Gruvbox, Tokyo Night, Solarized, and more | | 📥 **OPML Support** | Import/export subscriptions for easy migration | | 📤 **Social Sharing** | Share articles to X, Mastodon, and Bluesky with one keypress | | ⚡ **Blazingly Fast** | Async feed fetching with Tokio — no UI blocking | | 🦀 **Memory Safe** | Written in 100% safe Rust with zero unsafe code | | 🌍 **Cross-Platform** | Linux, macOS, Windows — same config path everywhere | ## 🚀 Installation ### Homebrew (macOS/Linux) ```bash brew install ricardodantas/tap/feedo ``` ### Cargo (All Platforms) ```bash cargo install feedo ``` ### From Source ```bash # Clone the repository git clone https://github.com/ricardodantas/feedo.git cd feedo # Build with optimizations cargo build --release # Run it! ./target/release/feedo ``` ### Pre-built Binaries Download from [GitHub Releases](https://github.com/ricardodantas/feedo/releases) — available for Linux (x64, ARM64, musl), macOS (Intel, Apple Silicon), and Windows. ### Requirements - A terminal with Unicode support - That's it!
## 📖 Usage ### Basic Commands ```bash # Launch the TUI feedo # Import feeds from another reader feedo --import subscriptions.opml # Backup your feeds feedo --export backup.opml # Show help feedo --help ``` ### Sync Commands ```bash # Configure sync with your server feedo sync login # Check sync status feedo sync status # Run full sync (import feeds + sync read states) feedo sync ``` **Tip:** Once configured, press `S` in the TUI to sync without leaving the app! ### Adding Feeds Press `n` in the app to add a new feed. Just paste any URL — Feedo will auto-discover the RSS/Atom feed: ``` ┌─ ➕ Add Feed ──────────────────────────────────────────┐ │ 🔗 https://blog.rust-lang.org│ │ └───────────────────────────────────────────────────────┘ ``` Feedo tries: 1. The URL directly (if it's already a feed) 2. `` tags in HTML 3. Common paths like `/feed`, `/rss`, `/atom.xml` ### First Run On first launch, Feedo creates a default configuration with some starter feeds: - **Tech**: Hacker News, Lobsters - **News**: BBC World Feel free to modify `~/.config/feedo/config.json` to add your own!
## ⌨️ Keybindings ### Navigation | Key | Action | |-----|--------| | `j` / `↓` | Move down | | `k` / `↑` | Move up | | `l` / `→` / `Enter` | Select / Enter | | `h` / `←` | Go back | | `g` | Jump to top | | `G` | Jump to bottom | | `Tab` | Switch between panels | | `v` | Toggle content preview | ### Actions | Key | Action | |-----|--------| | `n` | Add new feed (with auto-discovery) | | `d` / `Delete` | Delete selected feed/folder | | `r` | Refresh all feeds | | `S` | Sync with server (if configured) | | `o` | Open article in browser | | `s` | Share article | | `Space` | Toggle read/unread | | `a` | Mark all as read (selected feed) | | `/` | Open search | | `t` | Open theme picker | | `?` / `F1` | Show keyboard shortcuts | | `A` | About Feedo | | `q` | Quit | ### Share Mode | Key | Action | |-----|--------| | `↑` / `↓` | Navigate platforms | | `Enter` | Share to selected platform | | `x` | Quick share to X (Twitter) | | `m` | Quick share to Mastodon | | `b` | Quick share to Bluesky | | `Esc` | Cancel | ### Add Feed Mode | Key | Action | |-----|--------| | `Enter` | Discover feeds / Confirm | | `↑` / `↓` | Select feed (if multiple found) | | `Esc` | Cancel / Go back | ### Search Mode | Key | Action | |-----|--------| | `Enter` | Go to selected result | | `↑` / `↓` | Navigate results | | `Esc` | Cancel search | ### Theme Picker | Key | Action | |-----|--------| | `↑` / `↓` | Browse themes (live preview) | | `Enter` | Apply and save theme | | `Esc` | Cancel |
## ⚙️ Configuration ### Config Location Feedo uses `~/.config/feedo/` on **all platforms** for consistency: | Platform | Path | |----------|------| | Linux | `~/.config/feedo/config.json` | | macOS | `~/.config/feedo/config.json` | | Windows | `%USERPROFILE%\.config\feedo\config.json` | ### Example Configuration ```json { "folders": [ { "name": "Tech", "icon": "💻", "expanded": true, "feeds": [ { "name": "Hacker News", "url": "https://hnrss.org/frontpage" }, { "name": "Lobsters", "url": "https://lobste.rs/rss" }, { "name": "This Week in Rust", "url": "https://this-week-in-rust.org/rss.xml" } ] }, { "name": "News", "icon": "📰", "expanded": false, "feeds": [ { "name": "BBC World", "url": "https://feeds.bbci.co.uk/news/world/rss.xml" } ] } ], "feeds": [ { "name": "xkcd", "url": "https://xkcd.com/rss.xml" } ], "theme": { "name": "dracula" }, "refresh_interval": 30 } ``` ### Offline Mode & Cache Feedo automatically caches all articles for offline reading: | File | Purpose | |------|---------| | `~/.config/feedo/data/cache.json` | Cached articles and read states | **How it works:** - Articles are cached after each successful fetch - Read/unread states persist between sessions - When offline, you can still browse all previously fetched articles - Cache is updated on every refresh and saved on exit **No configuration needed** — offline mode works automatically! ### ☁️ Cloud Sync Feedo supports syncing with RSS servers that implement the **Google Reader API**. #### ✅ Tested & Working | Service | Server URL | Notes | |---------|------------|-------| | **FreshRSS** | `https://your-server/api/greader.php` | Self-hosted, recommended | | **Miniflux** | `https://your-server/v1/` | Self-hosted, lightweight | | **The Old Reader** | `https://theoldreader.com` | Hosted, free tier | | **BazQux** | `https://bazqux.com` | Hosted, free trial | #### ⚠️ Not Currently Supported | Service | Reason | |---------|--------| | **Inoreader** | Requires OAuth 2.0 / App registration (not plain password login) | | **Feedly** | Uses proprietary API, not Google Reader compatible | #### Quick Start: FreshRSS (Docker) ```bash # 1. Spin up FreshRSS podman run -d --name freshrss -p 8080:80 freshrss/freshrss # Or: docker run -d --name freshrss -p 8080:80 freshrss/freshrss # 2. Visit http://localhost:8080 and complete the setup wizard # - Create your admin account # - Choose SQLite for simplicity # 3. Enable API access: # Settings → Authentication → ☑ Allow API access # 4. Set API password: # Settings → Profile → API password (can be different from login password) # 5. Connect Feedo feedo sync login http://localhost:8080/api/greader.php your_user your_api_password feedo sync status # Verify connection feedo sync # Run first sync ``` #### Quick Start: Miniflux (Docker) ```bash # 1. Spin up Miniflux with PostgreSQL podman run -d --name miniflux-db -e POSTGRES_USER=miniflux \ -e POSTGRES_PASSWORD=secret -e POSTGRES_DB=miniflux postgres:15 podman run -d --name miniflux -p 8080:8080 \ -e DATABASE_URL="postgres://miniflux:secret@miniflux-db/miniflux?sslmode=disable" \ -e RUN_MIGRATIONS=1 \ -e CREATE_ADMIN=1 \ -e ADMIN_USERNAME=admin \ -e ADMIN_PASSWORD=admin123 \ miniflux/miniflux:latest # Or with docker-compose (recommended for production) # 2. Visit http://localhost:8080 and login with admin/admin123 # 3. Enable Fever API (used for Google Reader compatibility): # Settings → Integrations → Fever → Enable & set password # 4. Connect Feedo (note: Miniflux uses /v1/ endpoint) feedo sync login http://localhost:8080/v1/ admin your_fever_password feedo sync status feedo sync ``` **Tip:** For production, see [FreshRSS Docker docs](https://github.com/FreshRSS/FreshRSS/tree/edge/Docker) or [Miniflux installation guide](https://miniflux.app/docs/installation.html). #### Setup ```bash # Configure your sync server feedo sync login https://freshrss.example.com/api/greader.php myuser mypassword # Verify connection feedo sync status ``` #### What syncs? | Direction | What | |-----------|------| | **Server → Local** | Subscriptions (feeds + folders) | | **Server → Local** | Read states | | **Local → Server** | Read states | #### Running Sync **From CLI:** ```bash feedo sync ``` **From TUI:** Press `S` (shift+s) — the status bar shows a ☁️ indicator when sync is configured. #### Config Example After running `feedo sync login`, your config will include: ```json { "sync": { "provider": "freshrss", "server": "https://freshrss.example.com/api/greader.php", "username": "myuser", "password": "mypassword" } } ``` **Note:** For security, consider using an API password or app-specific password if your service supports it. ### Theme Colors Feedo comes with **15 popular themes** from the terminal/editor world: | Theme | Description | |-------|-------------| | `dracula` | 🦇 Dark purple aesthetic (default) | | `one-dark-pro` | ⚛️ Atom's iconic dark theme | | `nord` | ❄️ Arctic, bluish color palette | | `catppuccin-mocha` | 🐱 Warm pastel dark theme | | `catppuccin-latte` | ☕ Warm pastel light theme | | `gruvbox-dark` | 🎸 Retro groove colors | | `gruvbox-light` | 🌻 Retro groove, light variant | | `tokyo-night` | 🌃 Futuristic dark blue | | `solarized-dark` | ☀️ Precision colors, dark | | `solarized-light` | 🌞 Precision colors, light | | `monokai-pro` | 🎨 Classic syntax highlighting | | `rose-pine` | 🌹 Soho vibes with natural pine | | `kanagawa` | 🌊 Inspired by Hokusai's art | | `everforest` | 🌲 Comfortable green forest | | `cyberpunk` | 💜 Neon-soaked futuristic | **Example config:** ```json { "theme": { "name": "catppuccin-mocha" } } ``` | `orange` | 🟠 Energetic | | `pink` | 🩷 Soft and playful |
## 🏗️ Architecture ``` src/ ├── main.rs # Entry point, CLI handling ├── lib.rs # Library root, public API │ ├── app/ # Application core │ └── mod.rs # App state, event loop, orchestration │ ├── config/ # Configuration management │ ├── mod.rs # Module exports │ └── data.rs # Config structs, load/save logic │ ├── feed/ # Feed management │ ├── mod.rs # Module exports │ ├── item.rs # FeedItem struct │ ├── manager.rs # FeedManager, Folder, async fetching │ └── parser.rs # RSS/Atom parsing with feed-rs │ ├── opml/ # OPML import/export │ └── mod.rs # Full OPML 2.0 support │ ├── theme/ # Theming system │ └── mod.rs # AccentColor, Theme configuration │ └── ui/ # Terminal UI ├── mod.rs # Module exports ├── state.rs # UI state machine ├── input.rs # Keyboard input handling ├── render.rs # Rendering logic, layouts └── widgets/ # Custom ratatui widgets ``` ### Design Principles - **Separation of Concerns** — Each module has a single responsibility - **Async by Default** — Network operations never block the UI - **Immutable State** — UI state is explicit and predictable - **Error Propagation** — Errors bubble up with context via `color-eyre` - **Zero Unsafe** — Memory safety guaranteed by the compiler
## 🗺️ Roadmap - [x] **Feed Discovery** — Auto-detect RSS from any URL ✅ - [x] **Offline Mode** — Cache articles for reading without internet ✅ - [x] **Cloud Sync** — Sync with FreshRSS, Miniflux via Google Reader API ✅ - [ ] **Custom Keybindings** — Full key remapping - [ ] **Notifications** — Desktop alerts for new articles
## 🤝 Contributing Contributions are welcome! Please feel free to submit a Pull Request. 1. Fork the repository 2. Create your feature branch (`git checkout -b feature/amazing`) 3. Commit your changes (`git commit -m 'Add amazing feature'`) 4. Push to the branch (`git push origin feature/amazing`) 5. Open a Pull Request
## 📄 License MIT © Ricardo Dantas ---

Made with ❤️ and 🦀

(◕ᴥ◕) Happy reading!