this repo has no description
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

CLAUDE.md#

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview#

"Thought" is a Rust CLI application for real-time streaming and posting to the ATProto network using stream.thought.blip records. It functions like an IRC client for Bluesky, featuring a terminal UI (TUI) for live message streaming.

Key Technology Stack:

  • Rust with async/await (Tokio runtime)
  • ATProto API for authentication and posting
  • Jetstream WebSocket for real-time firehose
  • Ratatui for terminal UI
  • Custom record type: stream.thought.blip

Building and Running#

# Build (development)
cargo build

# Build (release)
cargo build --release

# Run tests
cargo test

# Lint
cargo clippy

# Run the CLI
./target/release/thought

# Login first-time use
./target/release/thought login

# Main TUI mode (recommended)
./target/release/thought stream

Architecture#

Module Structure#

  • main.rs: CLI entry point, command routing, and authentication setup
  • client.rs: ATProto HTTP client for authentication and posting blips
  • credentials.rs: Secure credential and session storage (platform-specific config directories)
  • jetstream.rs: WebSocket client for Jetstream firehose, DID resolution, and message filtering
  • tui.rs: Ratatui-based terminal UI with scrollable message feed
  • interactive.rs: Coordinator for TUI and simple REPL modes

Authentication Flow#

  1. User provides handle/email and app password via thought login
  2. Credentials stored in platform config directory (macOS: ~/Library/Application Support/com.thoughtstream.think/)
  3. Session tokens (accessJwt/refreshJwt) cached separately in session.json
  4. Token refresh handled transparently by create_authenticated_client() in main.rs:133
  5. Failed refresh triggers re-login with stored credentials

Important: Session management uses both credentials.json (username/password/PDS URI) and session.json (JWT tokens). The client automatically refreshes tokens before operations.

Real-time Message Flow#

  1. TUI spawns Jetstream listener in background task
  2. Listener connects to wss://jetstream2.us-west.bsky.network/subscribe with collection filter
  3. Incoming commits filtered for stream.thought.blip collection and "create" operations
  4. DIDs resolved to handles via app.bsky.actor.getProfile (with caching)
  5. Messages sent through mpsc channel to TUI for rendering
  6. User's own messages filtered out using stored DID

TUI Rendering#

  • Messages displayed in reverse chronological order (newest first)
  • Scrollable with arrow keys/PageUp/PageDown
  • Auto-scrolls to bottom when at offset 0
  • User's own posts styled in bold green
  • Connection status tracked via channel activity
  • Maximum 1000 messages buffered

Development Notes#

Credential Storage Paths#

  • macOS: ~/Library/Application Support/com.thoughtstream.think/
  • Linux: ~/.config/thoughtstream/think/
  • Windows: %APPDATA%\thoughtstream\think\

Token Refresh Logic#

The client implements automatic token refresh (client.rs:106-137):

  1. Attempt operation with current access token
  2. On 401/ExpiredToken error, call refresh_session()
  3. Retry operation with new token
  4. If refresh fails, clear session and prompt re-login

Jetstream Connection#

  • Attempts simple connection first, then falls back to collection-filtered URL
  • Reconnects with 5-second delay on failure
  • Uses User-Agent: think-cli/0.1.0
  • Filters messages on client side even with server-side collection filter

Publishing Blips#

Records posted with structure:

{
  "$type": "stream.thought.blip",
  "content": "<message>",
  "createdAt": "<ISO8601 timestamp>"
}

Posted to com.atproto.repo.createRecord with user's DID as repo.

Note on Julia Dependencies#

The Project.toml and Manifest.toml files are unrelated to the Rust project—likely leftover artifacts or separate experiments (Franklin static site generator). The actual Rust dependencies are in Cargo.toml.