No description
  • TypeScript 99.9%
  • JavaScript 0.1%
Find a file
soma c0591c40ac
feat(posts): open a post's text in Google Translate
Port from social-app: no AT Protocol lexicon involved, just building a
translate.google.com URL and opening it in the browser (source
auto-detected, target guessed from the system locale). Bound to `T`
in Timeline/Thread/Profile/SearchView (posts tab).
2026-07-03 14:09:01 +09:00
.tangled/workflows ci: rename release.yaml to build.yml 2026-06-27 11:00:58 +09:00
public chore: scaffold Phase 0 (project skeleton, tooling, docs) 2026-06-24 18:10:11 +09:00
src feat(posts): open a post's text in Google Translate 2026-07-03 14:09:01 +09:00
.gitignore fix: remove accidentally committed worktree, add .gitignore 2026-06-27 10:23:16 +09:00
.prettierignore chore: scaffold Phase 0 (project skeleton, tooling, docs) 2026-06-24 18:10:11 +09:00
.prettierrc.json chore: scaffold Phase 0 (project skeleton, tooling, docs) 2026-06-24 18:10:11 +09:00
eslint.config.js feat: search, follows, copy, chat replies, profile social actions 2026-06-26 22:42:03 +09:00
LICENSE chore: scaffold Phase 0 (project skeleton, tooling, docs) 2026-06-24 18:10:11 +09:00
package.json feat(mouse): clickable action bar and sidebar navigation 2026-06-24 21:58:01 +09:00
pnpm-lock.yaml feat(mouse): clickable action bar and sidebar navigation 2026-06-24 21:58:01 +09:00
pnpm-workspace.yaml feat(auth): OAuth login vertical slice (Phase 1A) 2026-06-24 18:31:00 +09:00
README.md style: fix prettier formatting 2026-06-27 10:21:29 +09:00
tsconfig.json chore: scaffold Phase 0 (project skeleton, tooling, docs) 2026-06-24 18:10:11 +09:00
vitest.config.ts chore: scaffold Phase 0 (project skeleton, tooling, docs) 2026-06-24 18:10:11 +09:00

bsky-tui

A keyboard-driven terminal UI client for Bluesky / AT Protocol, inspired by Discordo.

Built with TypeScript + Ink (React-style TUI). Authenticates via AT Protocol OAuth — no App Passwords required.

Status: MVP complete. Daily-driver usable. Actively developed.


Features

  • Timeline — home feed, custom feeds, and lists via a unified feed picker
  • Threads — full reply tree with keyboard navigation
  • Compose — new posts, replies, and quote posts with multiline editor
  • Reactions — like and repost with optimistic updates
  • Notifications — mentions, likes, reposts, follows
  • Direct messages — 1:1 and group chat (AT Protocol DMs)
  • Search — posts and people; follow/unfollow from results
  • Profile — bio, post history, follow/mute/block actions
  • Follows — follower and following lists
  • Mouse support — click posts, buttons, and nav items throughout
  • Keyboard-first — vim-style navigation; full keybind reference via ?
  • OSC 8 hyperlinks — clickable URLs, mentions, and hashtags in supporting terminals

Installation

Requirements: Node.js ≥ 18, pnpm

git clone https://knot.soverth.blue/did:plc:mwgzrmy3nvvpd2qajuvvfiu6/bsky-tui
cd bsky-tui
pnpm install
pnpm build
node dist/index.js

Authentication

bsky-tui uses AT Protocol OAuth (PKCE + PAR + DPoP). It acts as a public native client — no client secret, no App Password.

Hosted mode (default)

The OAuth client_id is https://soverth.blue/bsky-tui/client-metadata.json. This file must be publicly reachable before OAuth will work. Once the metadata URL is live:

pnpm dev   # opens a browser tab for the OAuth flow

Loopback mode (local dev / no hosted metadata yet)

BSKY_TUI_OAUTH_MODE=loopback pnpm dev

Loopback mode starts a local HTTP server to complete the redirect without requiring a hosted client_id.


Keybindings

Key Action
j / k Move down / up
Enter Open thread
l / r Like / repost
c Compose new post
n Reply
q Quote post
p Open profile
Tab Feed picker
N Notifications
M Messages (DMs)
/ Search
F Follows
f Follow / unfollow
g / G Jump to top / bottom
? Help screen
Ctrl+q Quit

Press ? inside the app for the full reference.


Development

pnpm install
pnpm dev          # run with tsx (hot-ish reload via restart)
pnpm typecheck    # tsc --noEmit
pnpm lint         # eslint
pnpm format       # prettier --write
pnpm test         # vitest
pnpm build        # tsc → dist/

CI runs on Tangled Spindle (.tangled/workflows/ci.yaml): typecheck → lint → format check → test → build.

Architecture

The codebase follows a strict layered architecture:

src/
  core/        # models, ports (interfaces), use-cases, mappers — zero framework deps
  services/    # AT Protocol API, OAuth, storage — implements core ports
  state/       # useReducer + Context slices per feature
  ui/          # Ink components, views, hooks
  keybindings/ # key definitions
  shared/      # tiny utilities
  wiring.ts    # composition root

Business logic in core/ is framework-agnostic and unit-tested with Vitest. UI components use ink-testing-library.

Design documents

Doc Contents
docs/01-requirements.md Requirements
docs/02-features.md Feature list and screens
docs/03-architecture.md Architecture and data flow
docs/04-directory-structure.md Directory layout
docs/05-roadmap.md Phased roadmap

License

AGPL-3.0-or-later.