this repo has no description
3
fork

Configure Feed

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

Persist refreshed session tokens in TUI mode

When publish_blip() automatically refreshes expired tokens, the updated
session was only stored in memory. This caused subsequent publishes to
fail with the same expired token error. Now the session is persisted to
disk after each successful publish.

Also add CLAUDE.md documentation for codebase architecture.

+120
+113
CLAUDE.md
··· 1 + # CLAUDE.md 2 + 3 + This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. 4 + 5 + ## Project Overview 6 + 7 + "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. 8 + 9 + **Key Technology Stack:** 10 + - Rust with async/await (Tokio runtime) 11 + - ATProto API for authentication and posting 12 + - Jetstream WebSocket for real-time firehose 13 + - Ratatui for terminal UI 14 + - Custom record type: `stream.thought.blip` 15 + 16 + ## Building and Running 17 + 18 + ```bash 19 + # Build (development) 20 + cargo build 21 + 22 + # Build (release) 23 + cargo build --release 24 + 25 + # Run tests 26 + cargo test 27 + 28 + # Lint 29 + cargo clippy 30 + 31 + # Run the CLI 32 + ./target/release/thought 33 + 34 + # Login first-time use 35 + ./target/release/thought login 36 + 37 + # Main TUI mode (recommended) 38 + ./target/release/thought stream 39 + ``` 40 + 41 + ## Architecture 42 + 43 + ### Module Structure 44 + 45 + - **main.rs**: CLI entry point, command routing, and authentication setup 46 + - **client.rs**: ATProto HTTP client for authentication and posting blips 47 + - **credentials.rs**: Secure credential and session storage (platform-specific config directories) 48 + - **jetstream.rs**: WebSocket client for Jetstream firehose, DID resolution, and message filtering 49 + - **tui.rs**: Ratatui-based terminal UI with scrollable message feed 50 + - **interactive.rs**: Coordinator for TUI and simple REPL modes 51 + 52 + ### Authentication Flow 53 + 54 + 1. User provides handle/email and app password via `thought login` 55 + 2. Credentials stored in platform config directory (macOS: `~/Library/Application Support/com.thoughtstream.think/`) 56 + 3. Session tokens (accessJwt/refreshJwt) cached separately in `session.json` 57 + 4. Token refresh handled transparently by `create_authenticated_client()` in main.rs:133 58 + 5. Failed refresh triggers re-login with stored credentials 59 + 60 + **Important**: Session management uses both `credentials.json` (username/password/PDS URI) and `session.json` (JWT tokens). The client automatically refreshes tokens before operations. 61 + 62 + ### Real-time Message Flow 63 + 64 + 1. TUI spawns Jetstream listener in background task 65 + 2. Listener connects to `wss://jetstream2.us-west.bsky.network/subscribe` with collection filter 66 + 3. Incoming commits filtered for `stream.thought.blip` collection and "create" operations 67 + 4. DIDs resolved to handles via `app.bsky.actor.getProfile` (with caching) 68 + 5. Messages sent through mpsc channel to TUI for rendering 69 + 6. User's own messages filtered out using stored DID 70 + 71 + ### TUI Rendering 72 + 73 + - Messages displayed in **reverse chronological order** (newest first) 74 + - Scrollable with arrow keys/PageUp/PageDown 75 + - Auto-scrolls to bottom when at offset 0 76 + - User's own posts styled in bold green 77 + - Connection status tracked via channel activity 78 + - Maximum 1000 messages buffered 79 + 80 + ## Development Notes 81 + 82 + ### Credential Storage Paths 83 + - macOS: `~/Library/Application Support/com.thoughtstream.think/` 84 + - Linux: `~/.config/thoughtstream/think/` 85 + - Windows: `%APPDATA%\thoughtstream\think\` 86 + 87 + ### Token Refresh Logic 88 + The client implements automatic token refresh (client.rs:106-137): 89 + 1. Attempt operation with current access token 90 + 2. On 401/ExpiredToken error, call `refresh_session()` 91 + 3. Retry operation with new token 92 + 4. If refresh fails, clear session and prompt re-login 93 + 94 + ### Jetstream Connection 95 + - Attempts simple connection first, then falls back to collection-filtered URL 96 + - Reconnects with 5-second delay on failure 97 + - Uses User-Agent: `think-cli/0.1.0` 98 + - Filters messages on client side even with server-side collection filter 99 + 100 + ### Publishing Blips 101 + Records posted with structure: 102 + ```json 103 + { 104 + "$type": "stream.thought.blip", 105 + "content": "<message>", 106 + "createdAt": "<ISO8601 timestamp>" 107 + } 108 + ``` 109 + Posted to `com.atproto.repo.createRecord` with user's DID as repo. 110 + 111 + ## Note on Julia Dependencies 112 + 113 + 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`.
+7
src/tui.rs
··· 249 249 message, 250 250 true, 251 251 )); 252 + 253 + // Save updated session (in case token was refreshed) 254 + if let Ok(store) = crate::credentials::CredentialStore::new() { 255 + if let Some(session) = client.get_session() { 256 + let _ = store.store_session(session); 257 + } 258 + } 252 259 } 253 260 Err(e) => { 254 261 // Add error message