Skip to content

Commit a4c90c7

Browse files
program247365claude
andcommitted
feat(comments): add threaded comments view, help bar, and version 0.3.0
- Threaded comments view with 'c' key: fetch and display HN comments inline with indentation, j/k navigation, line-based scrolling - Open comments in browser with 'o', reply with 'r', refresh with 'R' - Comment counts shown on each story in the list - Context-aware help bar at the bottom of every screen - Bump version to 0.3.0, update README, CHANGELOG, and CLAUDE.md - Remove stray escape sequence file Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 18752c4 commit a4c90c7

10 files changed

Lines changed: 609 additions & 153 deletions

File tree

[38

Whitespace-only changes.

CHANGELOG.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
11
# Changelog
22
All notable changes to this project will be documented in this file. See [conventional commits](https://www.conventionalcommits.org/) for commit guidelines.
33

4+
- - -
5+
## 0.3.0 - 2026-04-10
6+
#### Features
7+
- Threaded comments view with `c` key — fetches and displays HN comments inline with indentation
8+
- Comment counts displayed for each story in the list
9+
- Open individual comments in browser with `o` / `Enter` from comments view
10+
- Reply to comments with `r` — opens HN reply page in browser
11+
- Refresh comments with `R` from comments view
12+
- Context-aware help bar at the bottom of every screen showing relevant keyboard shortcuts
13+
#### Refactoring
14+
- Split main.rs into types.rs, hn_api.rs, and ui.rs modules matching documented architecture
15+
- Added `make format` and `make verify` (format + lint + build + test) targets
16+
#### Miscellaneous Chores
17+
- Updated all dependencies to latest versions (ratatui 0.30, crossterm 0.29, reqwest 0.13, open 5.3, rand 0.9, tokio 1.51)
18+
- Removed unused serde_json dependency
19+
- Fixed all clippy warnings
20+
- Updated README with Features section, current project structure, and keyboard controls
21+
- Added CLAUDE.md for AI-assisted development context
22+
423
- - -
524
## 0.2.0 - 2025-07-30
625
#### Documentation
@@ -42,4 +61,4 @@ All notable changes to this project will be documented in this file. See [conven
4261

4362
- - -
4463

45-
Changelog generated by [cocogitto](https://github.com/cocogitto/cocogitto).
64+
Changelog generated by [cocogitto](https://github.com/cocogitto/cocogitto).

CLAUDE.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,18 @@ make bump # cog bump --auto (cocogitto versioning)
2424

2525
The `src/` directory is split by concern:
2626

27-
- **`types.rs`** — Data types: `Story`, `Section`, `Mode`, `ClaudeRequest`, `Message`. No dependencies on other local modules.
28-
- **`hn_api.rs`** — HTTP layer: `fetch_stories` (HN Firebase API) and `get_claude_summary` (Anthropic API). Depends on `types`.
29-
- **`ui.rs`** — All rendering: `draw_ui`, `draw_menu`, `draw_summary`, `draw_command_palette`, `centered_rect`. Depends on `types` and `app`.
27+
- **`types.rs`** — Data types: `Story`, `Comment`, `FlatComment`, `Section`, `Mode`, `ClaudeRequest`, `Message`. No dependencies on other local modules.
28+
- **`hn_api.rs`** — HTTP layer: `fetch_stories`, `fetch_comments` (HN Firebase API), `get_claude_summary` (Anthropic API). Depends on `types`.
29+
- **`ui.rs`** — All rendering: `draw_ui`, `draw_comments`, `draw_help_bar`, `draw_menu`, `draw_summary`, `draw_command_palette`, `centered_rect`, `strip_html`. Depends on `types` and `app`.
3030
- **`loading_screen.rs`**`MatrixRain` struct for the Matrix-style loading animation.
3131
- **`main.rs`**`App` struct (all application state), `Command`/`CommandPalette`, terminal setup/teardown, and the main event loop. `App` is exposed via `pub mod app` so `ui.rs` can reference it.
3232

33-
The app uses a single-threaded tokio runtime. Story fetching spawns tokio tasks per section that run concurrently. The `App` struct holds all state: stories, UI mode, cached stories per section, command palette state, and search state.
33+
The app uses a single-threaded tokio runtime. Story fetching spawns tokio tasks per section that run concurrently. The `App` struct holds all state: stories, UI mode, cached stories per section, command palette state, comments state, and search state.
3434

3535
## Key Details
3636

3737
- HN API: Firebase REST API at `hacker-news.firebaseio.com/v0/`. Fetches up to 100 stories per section.
3838
- Claude API: Requires `CLAUDE_API_KEY` env var. Currently hardcoded to `claude-3-opus-20240229` model.
3939
- Versioning: Uses cocogitto (`cog.toml`) with conventional commits. Changelog at `CHANGELOG.md`.
4040
- CI: GitHub Actions runs `cargo build` and `cargo test` on push/PR to main.
41-
- Cargo.toml lists edition 2021; version is `0.1.0` (behind the `0.2.0` tag from cog).
41+
- Cargo.toml lists edition 2021; version is `0.3.0`.

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "hackertuah"
3-
version = "0.1.0"
3+
version = "0.3.0"
44
edition = "2021"
55

66
[dependencies]

README.md

Lines changed: 80 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ A terminal-based user interface for browsing Hacker News with Vim-style navigati
1010

1111
Install Rust by going here and following the instructions: [https://www.rust-lang.org/tools/install](https://www.rust-lang.org/tools/install)
1212

13-
### Install Hackertauh
13+
### Install Hackertuah
1414

1515
Install and run immediately with Cargo:
1616

@@ -34,56 +34,71 @@ hackertuah
3434

3535
## Features
3636

37-
- 🚀 **Browse** top Hacker News stories in your terminal
38-
- ⌨️ **Vim-style navigation** (j/k, arrows, etc.)
39-
- 🤖 **Claude AI integration** for story summarization
40-
- 🌐 **Open stories** directly in your default browser
41-
- 💚 **Classic green-on-black** terminal aesthetic
42-
- 🎯 **Minimalist, distraction-free interface**
43-
- 🔍 **Instant search/filter**: Press `/` or use the command palette to filter stories as you type
44-
- 🧑‍💻 **Command Palette**: Press `Ctrl+K` to access all commands, including search, section switching, and more
45-
- 📝 **Options menu** for each story (summarize, open, close)
46-
- 🏷️ **Section switching**: Top, Ask, Show, Jobs
47-
- 🛠️ **Easy install & run** with Cargo
48-
49-
## Command Palette 🧑‍💻
50-
51-
Press `Ctrl+K` to open the command palette:
52-
53-
- 🔎 **Search for commands** as you type
54-
-**Quickly switch sections** (Top, Ask, Show, Jobs)
55-
- 🔄 **Refresh** current or all sections
56-
- 🔍 **Activate search mode** (type 'search' and press Enter)
57-
- 🌐 **Open in browser**, 💬 **Open comments**, 🤖 **Summarize**
58-
-**Quit** the app
59-
- ⬆️⬇️ Navigate with Up/Down arrows, `Esc` to close
60-
61-
## Search 🔍
62-
63-
- Press `/` to start searching, or open the command palette and type 'search'
64-
- Type to filter stories by title in real-time
65-
- Use Up/Down arrows to navigate filtered results
66-
- Press Enter to open the selected story, or Esc to cancel
67-
- Works across all sections (Top, Ask, Show, Jobs)
37+
- **Browse** top Hacker News stories in your terminal across Top, Ask, Show, and Jobs sections
38+
- **Vim-style navigation** (j/k, h/l, arrows) throughout the app
39+
- **Threaded comments view** — press `c` to read comments inline with indentation mirroring HN's thread structure, scroll through them with j/k, and reply directly
40+
- **Comment counts** displayed for each story in the list
41+
- **Claude AI integration** for story summarization via the options menu
42+
- **Command Palette** (`Ctrl+K`) for quick access to all commands with fuzzy search
43+
- **Instant search/filter** — press `/` to filter stories by title as you type
44+
- **Open in browser** — open stories, comments, or reply pages directly in your default browser
45+
- **Section switching** — navigate between Top, Ask, Show, and Jobs with `h/l` or hotkeys
46+
- **Context-aware help bar** — keyboard shortcuts displayed at the bottom of every screen, updating per context
47+
- **Matrix-style loading screen** while fetching data
48+
- **Classic green-on-black** terminal aesthetic
6849

6950
## Keyboard Controls
7051

71-
- `j` or ``: Move down
72-
- `k` or ``: Move up
73-
- `Enter`: Open selected story in default browser
74-
- `C`: Open comments for selected story
75-
- `o`: Open options menu
76-
- `q`: Quit application
77-
- `Esc`: Close menus/summaries
78-
- `T`: Switch to Top stories
79-
- `A`: Switch to Ask HN
80-
- `S`: Switch to Show HN
81-
- `J`: Switch to Jobs
82-
- `h`/`l`: Navigate between sections
83-
- `r`: Refresh current section
84-
- `R`: Refresh all sections
85-
- `Ctrl+K`: Open command palette (search and execute commands)
86-
- `/`: Start search (type to filter stories)
52+
### Stories (Normal Mode)
53+
54+
| Key | Action |
55+
|-----|--------|
56+
| `j` / `` | Move down |
57+
| `k` / `` | Move up |
58+
| `Enter` | Open story in browser |
59+
| `c` | View comments inline |
60+
| `C` | Open comments in browser |
61+
| `o` | Open options menu |
62+
| `h` / `l` | Previous / next section |
63+
| `T` / `A` / `S` / `J` | Jump to Top / Ask / Show / Jobs |
64+
| `r` | Refresh current section |
65+
| `R` | Refresh all sections |
66+
| `/` | Search / filter stories |
67+
| `Ctrl+K` | Open command palette |
68+
| `q` / `Ctrl+C` | Quit |
69+
70+
### Comments View
71+
72+
| Key | Action |
73+
|-----|--------|
74+
| `j` / `` | Move down |
75+
| `k` / `` | Move up |
76+
| `o` / `Enter` | Open selected comment in browser |
77+
| `r` | Reply to selected comment (opens HN reply page) |
78+
| `R` | Refresh comments |
79+
| `Esc` / `q` | Back to stories |
80+
81+
### Search Mode
82+
83+
| Key | Action |
84+
|-----|--------|
85+
| `` / `` | Navigate filtered results |
86+
| `Enter` | Open selected story |
87+
| `Esc` | Cancel search |
88+
89+
### Command Palette
90+
91+
Press `Ctrl+K` to open the command palette, which provides:
92+
- Searchable list of all available commands
93+
- Real-time filtering as you type
94+
- Navigate with Up/Down arrows, execute with Enter, close with Esc
95+
96+
### Options Menu
97+
98+
Press `o` to open the options menu:
99+
1. Summarize this post (uses Claude AI)
100+
2. Open in browser
101+
3. Close menu
87102

88103
## Installation
89104

@@ -96,14 +111,14 @@ cargo install --git https://github.com/program247365/hackertuah
96111
### Prerequisites
97112

98113
- Rust and Cargo (Latest stable version)
99-
- A Claude API key from Anthropic
114+
- A Claude API key from Anthropic (for summarization feature)
100115

101116
### Setup
102117

103118
1. Clone the repository:
104119
```bash
105120
git clone https://github.com/program247365/hackertuah
106-
cd hackernews-tui
121+
cd hackertuah
107122
```
108123

109124
2. Add your Claude API key to your environment:
@@ -117,102 +132,30 @@ cargo build --release
117132
cargo run
118133
```
119134

120-
## Usage
121-
122-
### Keyboard Controls
123-
124-
- `j` or ``: Move down
125-
- `k` or ``: Move up
126-
- `Enter`: Open selected story in default browser
127-
- `C`: Open comments for selected story
128-
- `o`: Open options menu
129-
- `q`: Quit application
130-
- `Esc`: Close menus/summaries
131-
- `T`: Switch to Top stories
132-
- `A`: Switch to Ask HN
133-
- `S`: Switch to Show HN
134-
- `J`: Switch to Jobs
135-
- `h`/`l`: Navigate between sections
136-
- `r`: Refresh current section
137-
- `R`: Refresh all sections
138-
- `Ctrl+K`: Open command palette (search and execute commands)
139-
- `/`: Start search (type to filter stories)
140-
141-
### Command Palette
142-
143-
Press `Ctrl+K` to open the command palette, which provides:
144-
- Searchable list of all available commands
145-
- Real-time filtering as you type
146-
- Command descriptions
147-
- Execute commands with Enter
148-
- Navigate with Up/Down arrows
149-
- Close with Esc
150-
151-
Available commands now include:
152-
- Open in Browser
153-
- Open Comments
154-
- Summarize
155-
- Search (activate search/filter mode)
156-
- Switch to Top/Ask/Show/Jobs
157-
- Refresh/Refresh All
158-
- Quit
159-
160-
### Options Menu
161-
162-
Press `o` to open the options menu, which provides:
163-
1. Summarize this post (uses Claude AI)
164-
2. Open in browser
165-
3. Close menu
166-
167-
### Story Information
135+
## Project Structure
168136

169-
Each story displays:
170-
- Title
171-
- Score
172-
- Author
173-
- Direct link to article or discussion
137+
```
138+
src/
139+
├── main.rs # App state, event loop, terminal setup
140+
├── types.rs # Data types (Story, Comment, Section, Mode)
141+
├── hn_api.rs # Hacker News & Claude API integration
142+
├── ui.rs # UI rendering and layout
143+
└── loading_screen.rs # Matrix-style loading animation
144+
```
174145

175146
## Dependencies
176147

177148
```toml
178149
[dependencies]
179-
ratatui = "0.21.0"
180-
crossterm = "0.26.0"
181-
tokio = { version = "1.0", features = ["full"] }
182-
reqwest = { version = "0.11", features = ["json"] }
150+
ratatui = "0.30.0"
151+
crossterm = "0.29.0"
152+
tokio = { version = "1.51", features = ["full"] }
153+
reqwest = { version = "0.13", features = ["json"] }
183154
serde = { version = "1.0", features = ["derive"] }
184-
serde_json = "1.0"
185-
open = "3.2"
155+
open = "5.3"
156+
rand = "0.9"
186157
```
187158

188-
## Project Structure
189-
190-
```
191-
src/
192-
├── main.rs # Main application logic
193-
├── types.rs # Data structures and type definitions
194-
├── ui.rs # UI rendering and layout
195-
└── hn_api.rs # Hacker News API integration
196-
```
197-
198-
## Features in Detail
199-
200-
### Hacker News Integration
201-
- Fetches top 30 stories from Hacker News API
202-
- Real-time score and comment updates
203-
- Direct access to article URLs and discussion pages
204-
205-
### Claude AI Integration
206-
- Summarizes long articles and discussions
207-
- Provides concise, intelligent summaries of complex topics
208-
- Accessible through the options menu with `o`
209-
210-
### Terminal UI
211-
- Built with ratatui for smooth rendering
212-
- Classic green-on-black color scheme
213-
- Efficient memory usage and fast rendering
214-
- Responsive layout that adapts to terminal size
215-
216159
## Contributing
217160

218161
1. Fork the repository

src/hn_api.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::error::Error;
22

3-
use crate::types::{ClaudeRequest, Message, Section, Story};
3+
use crate::types::{ClaudeRequest, Comment, FlatComment, Message, Section, Story};
44

55
pub async fn fetch_stories(section: Section) -> Result<Vec<Story>, Box<dyn Error + Send + Sync>> {
66
let client = reqwest::Client::new();
@@ -29,6 +29,48 @@ pub async fn fetch_stories(section: Section) -> Result<Vec<Story>, Box<dyn Error
2929
Ok(stories)
3030
}
3131

32+
pub async fn fetch_comments(
33+
story: &Story,
34+
) -> Result<Vec<FlatComment>, Box<dyn Error + Send + Sync>> {
35+
let client = reqwest::Client::new();
36+
let mut flat_comments = Vec::new();
37+
fetch_comment_tree(&client, &story.kids, 0, &mut flat_comments, 4).await?;
38+
Ok(flat_comments)
39+
}
40+
41+
async fn fetch_comment_tree(
42+
client: &reqwest::Client,
43+
kid_ids: &[u32],
44+
depth: usize,
45+
out: &mut Vec<FlatComment>,
46+
max_depth: usize,
47+
) -> Result<(), Box<dyn Error + Send + Sync>> {
48+
for &id in kid_ids {
49+
let url = format!("https://hacker-news.firebaseio.com/v0/item/{}.json", id);
50+
let resp = client.get(&url).send().await?;
51+
let comment: Comment = match resp.json().await {
52+
Ok(c) => c,
53+
Err(_) => continue,
54+
};
55+
if comment.deleted || comment.dead {
56+
continue;
57+
}
58+
let child_ids = comment.kids.clone();
59+
out.push(FlatComment { comment, depth });
60+
if depth < max_depth {
61+
Box::pin(fetch_comment_tree(
62+
client,
63+
&child_ids,
64+
depth + 1,
65+
out,
66+
max_depth,
67+
))
68+
.await?;
69+
}
70+
}
71+
Ok(())
72+
}
73+
3274
pub async fn get_claude_summary(text: &str) -> Result<String, Box<dyn Error + Send + Sync>> {
3375
let client = reqwest::Client::new();
3476

0 commit comments

Comments
 (0)