個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Hacker News in your terminal: interactive TUI, scriptable CLI, and agent-friendly JSON for macOS and Linux. Rust.
翻譯準備中
正在載入完整 README。
檢視完整 README ↗hn is a single static binary on Linux and a universal binary on macOS.
Native packages install hn, its man page, license, and README. The only runtime dependency is ca-certificates.
VERSION=0.4.2
curl -LO "https://github.com/kaushalvivek/hn-cli/releases/download/v${VERSION}/hn_${VERSION}_amd64.deb"
sudo apt install "./hn_${VERSION}_amd64.deb"
Use arm64 instead of amd64 on ARM servers.
VERSION=0.4.2
curl -LO "https://github.com/kaushalvivek/hn-cli/releases/download/v${VERSION}/hn-${VERSION}-1.x86_64.rpm"
sudo dnf install "./hn-${VERSION}-1.x86_64.rpm"
# openSUSE: sudo zypper install "./hn-${VERSION}-1.x86_64.rpm"
Use aarch64 instead of x86_64 on ARM servers.
VERSION=0.4.2
curl -LO "https://github.com/kaushalvivek/hn-cli/releases/download/v${VERSION}/hn-${VERSION}-1-x86_64.pkg.tar.zst"
sudo pacman -U "./hn-${VERSION}-1-x86_64.pkg.tar.zst"
Use aarch64 instead of x86_64 on ARM servers.
VERSION=0.4.2
curl -LO "https://github.com/kaushalvivek/hn-cli/releases/download/v${VERSION}/hn_${VERSION}_x86_64.apk"
sudo apk add --allow-untrusted "./hn_${VERSION}_x86_64.apk"
Use aarch64 instead of x86_64 on ARM servers.
curl -fsSL https://raw.githubusercontent.com/kaushalvivek/hn-cli/main/install.sh | sh
Detects x86_64 or aarch64 and installs to ~/.local/bin. Override with HN_INSTALL_DIR and pin a release with HN_VERSION:
HN_VERSION=0.4.2 HN_INSTALL_DIR="$HOME/bin" sh install.sh
All Linux release binaries are statically linked against musl and run across distributions. They need CA certificates for HTTPS; install ca-certificates on minimal systems.
Homebrew is the simplest option:
brew install kaushalvivek/tap/hn
Homebrew 7 may ask you to trust a third-party tap on first use. If prompted, run
brew trust kaushalvivek/tap.
Or use the same install script as Linux:
curl -fsSL https://raw.githubusercontent.com/kaushalvivek/hn-cli/main/install.sh | sh
| Platform | Archive | Native packages |
|---|---|---|
| macOS Apple Silicon + Intel | hn-macos-universal.tar.gz | — |
| Linux x86_64 | hn-linux-x86_64.tar.gz | .deb, .rpm, .pkg.tar.zst, .apk |
| Linux aarch64 | hn-linux-aarch64.tar.gz | .deb, .rpm, .pkg.tar.zst, .apk |
VERSION=0.4.2
ASSET=hn-linux-x86_64.tar.gz # or hn-macos-universal.tar.gz
curl -LO "https://github.com/kaushalvivek/hn-cli/releases/download/v${VERSION}/${ASSET}"
curl -LO "https://github.com/kaushalvivek/hn-cli/releases/download/v${VERSION}/checksums.txt"
# Linux:
sha256sum -c checksums.txt --ignore-missing
# macOS:
# grep " ${ASSET}$" checksums.txt | shasum -a 256 -c -
tar -xzf "$ASSET"
mkdir -p ~/.local/bin
install -m 755 hn ~/.local/bin/hn
cargo install --locked --git https://github.com/kaushalvivek/hn-cli
Requires Rust 1.88+.
git clone https://github.com/kaushalvivek/hn-cli.git
cd hn-cli
make install
make install builds with Cargo and installs to /usr/local/bin by default. Use PREFIX=~/.local make install for a user-local install.
brew upgrade hn.sudo apt remove hn # Debian / Ubuntu
sudo dnf remove hn # Fedora / RHEL
sudo pacman -Rns hn # Arch
sudo apk del hn # Alpine
rm -f ~/.local/bin/hn # install-script installs
brew uninstall hn # Homebrew
rm -rf ~/.config/hn # optional: remove session and drafts
hn # open the interactive browser
hn browse --feed new # start on a specific feed
hn front --limit 10 # line-oriented output
hn thread 8863 # story + comment tree
hn search "rust async" --sort date
hn login # authenticated actions
hn whoami
Run hn --help or hn <command> --help for the full surface.
Every read command supports --json (or HN_JSON=1). The CLI is designed to be discovered without reading the source:
hn capabilities # machine-readable command map, schemas, env vars
hn front --limit 5 --json # structured feed
hn item 8863 --json
hn thread 8863 --json
hn search "sqlite" --type story --limit 10 --json
hn user pg --json
hn front --limit 10 --json \
| jq -r '.entries[] | "\(.score)\t\(.title)\t\(.id)"'
Errors are JSON on stderr with --json:
{"ok": false, "error": {"code": "rate_limited", "message": "Hacker News rate-limited the request"}}
Exit code is 0 on success and 1 on error. Read commands make no writes and need no account. Authenticated writes are never implicit.
Agent guides: AGENTS.md and llms.txt.
hn opens a full-screen terminal app with a feed sidebar, story list, detail pane, and threaded comments.
| Key | Action |
|---|---|
j / k, ↑ / ↓ | Move |
g / G | Top / bottom |
Enter / l | Open |
Tab | Next pane |
Esc / h | Back / close |
Space | Expand or collapse replies |
/ | Search |
: or Ctrl-P | Command palette |
r | Refresh |
o / y | Open in browser / copy URL |
v / V / u | Upvote / downvote / unvote |
f / F | Favorite / unfavorite |
H / U | Hide / unhide |
! | Flag |
c / e / d | Comment / edit / delete |
s | Submit a story (title, link, text) |
L | Log in |
? | Keyboard help |
q / Ctrl-C | Quit |
Drafts are saved to ~/.config/hn/drafts.json on Esc, on Ctrl-C, and on failed posts. Reopening the same composer restores them.
The line-oriented commands are designed for pipes, scripts, and quick one-off reads.
| Command | Description |
|---|---|
hn front, hn new, hn best | Core feeds |
hn ask, hn show, hn jobs | Ask HN, Show HN, and jobs |
hn active, hn comments | Active threads and latest comments |
hn noob-stories, hn noob-comments | New low-karma submissions and comments |
hn past [YYYY-MM-DD] | Past front page |
hn from <domain> | Submissions from one site |
hn item <id> | One item |
hn thread <id> | Story or comment tree |
hn context <comment-id> | Comment plus its ancestor chain |
hn user <username> | Profile and activity |
hn search <query> | Search stories and comments |
hn leaders, hn updates | Leaders and recent changes |
hn upvoted, hn hidden | Your upvoted and hidden items |
Pagination is --limit N --page N on feed and activity commands.
hn login
hn vote 8863
hn submit
hn submit --title "..." --url https://example.com
hn submit --title "..." --text "A text post"
hn comment 8863 --text "..."
hn comment 8863 # context + $EDITOR, saved as a draft on failure
hn comment 8863 --use-draft # resume a saved draft
hn edit 8863 --text "..."
hn delete 8863 --yes
hn favorite 8863
hn hide 8863
hn flag 8863 --reason spam
hn unflag 8863
hn logout
In the browser, press s to open a real submission form:
example.com/post is normalized to https://example.com/post.Tab / Shift-Tab move between fields, Ctrl-S submits, and Esc saves the whole form as a draft. Failed submissions are kept as drafts too.
From the CLI, hn submit walks you through the same fields: it prompts for a title and link, and opens $VISUAL/$EDITOR when you leave the link empty. Non-interactive use is explicit:
hn submit --title "..." --url https://example.com
hn submit --title "..." --text "A text post"
hn submit --use-draft # resume a saved submission
When hn comment runs in a terminal without --text, it fetches the parent, prints the author and a quoted excerpt, opens $VISUAL/$EDITOR, and saves the text as a draft if posting fails. hn drafts lists drafts; hn drafts --clear removes them.
Hacker News has no official write API. Authenticated actions use the site's HTML forms, session cookie, and per-page tokens. The session file is stored at ~/.config/hn/session.json with 0600 permissions; passwords are never persisted. Because these interfaces are unofficial, write actions can break if HN changes its markup.
| Variable | Purpose |
|---|---|
HN_CONFIG_DIR | Directory for session and drafts (default ~/.config/hn) |
HN_PASSWORD | Password for non-interactive hn login (prefer --password-stdin) |
HN_JSON | Same as --json. 1 and true enable JSON; 0 and false disable it; an empty value is unset |
NO_COLOR | Disable color in line-oriented output when set to any non-empty value. An empty value is unset |
VISUAL / EDITOR | Editor for interactive comment and edit |
HN_SITE_URL | Override the HN HTML base URL (testing/self-hosting) |
HN_FIREBASE_URL | Override the Firebase base URL (testing) |
HN_ALGOLIA_URL | Override the Algolia base URL (testing) |
hn is a Rust crate with a pure domain model and narrow transport adapters:
| Module | Responsibility |
|---|---|
src/domain.rs | Domain entities, value objects, feeds, threads, and operations. No networking. |
src/http.rs | HttpTransport abstraction and the reqwest implementation. |
src/firebase.rs | Firebase items, users, feeds, and updates. |
src/algolia.rs | Search and item-tree fast path. |
src/site.rs | news.ycombinator.com HTML, session, login, and write actions. |
src/client.rs | Composed client and thread fallback. |
src/cli.rs | clap command surface, human output, and JSON output. |
src/tui.rs | ratatui interactive browser. |
src/drafts.rs | Shared on-disk drafts for the CLI and TUI. |
The domain model is documented in docs/DomainModel.md. Release instructions live in docs/RELEASING.md.
cargo test
cargo run -- --limit 5
cargo run -- browse
cargo build --release
The test suite covers the domain model, Firebase and Algolia decoding, HN HTML parsing, session handling, drafts, and CLI behaviour. Tests never use a real account: authenticated flows are exercised against a local fake HN server.
Contributions are welcome. Start with CONTRIBUTING.md. For security issues, use SECURITY.md.
Questions, ideas, or feedback: vivekkaushal.com/talk
MIT © 2026 Vivek Kaushal
hn is not affiliated with Y Combinator or Hacker News. Thanks to Hacker News for the site and APIs, Algolia for search, and the Rust open-source ecosystem.