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#
- User provides handle/email and app password via
thought login - Credentials stored in platform config directory (macOS:
~/Library/Application Support/com.thoughtstream.think/) - Session tokens (accessJwt/refreshJwt) cached separately in
session.json - Token refresh handled transparently by
create_authenticated_client()in main.rs:133 - 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#
- TUI spawns Jetstream listener in background task
- Listener connects to
wss://jetstream2.us-west.bsky.network/subscribewith collection filter - Incoming commits filtered for
stream.thought.blipcollection and "create" operations - DIDs resolved to handles via
app.bsky.actor.getProfile(with caching) - Messages sent through mpsc channel to TUI for rendering
- 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):
- Attempt operation with current access token
- On 401/ExpiredToken error, call
refresh_session() - Retry operation with new token
- 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.