A modern terminal-based user interface for reading Khoros forum messages, BlueSky posts, and Mastodon posts using Textual. This application provides a rich, keyboard-driven experience for browsing and interacting with Khoros community content and social media posts from BlueSky and Mastodon directly from your terminal.
- π± Modern TUI Interface: Built with Textual for a responsive, modern terminal experience
- π Secure Authentication: Integrated with 1Password SDK (local authentication via desktop app) for secure credential management
- π¨ Message Browsing: Browse forum messages with subject, author, and timestamp information
- π¦ BlueSky Integration: Fetch and display BlueSky posts alongside Khoros messages
- π Mastodon Integration: Fetch and display Mastodon posts from any instance
- π Smart Filtering: Real-time message filtering and search capabilities
- π Message Viewer: Full message content display with HTML-to-text conversion
- π€ AI Summarization: Powered by Google Gemini API for intelligent message summaries
- β‘ Performance: Asynchronous message loading and efficient data handling
- π οΈ Debug Tools: Built-in debugging and connection testing utilities
- Python 3.10+ (required for 1Password SDK)
- 1Password subscription
- Latest beta release of the 1Password desktop app with desktop integrations enabled
- Access to a Khoros community
- BlueSky account with App Password (optional, for BlueSky integration)
- Mastodon account with Access Token (optional, for Mastodon integration)
- Google Gemini API key (optional, for AI summarization)
git clone <repository-url>
cd khoros_tui_reader
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install -r requirements.txtThe app now uses a TOML configuration file. Copy config.example.toml to config.toml and edit the values:
[onepassword]
# Optional: set if you have multiple 1Password accounts
account_name = "My Personal"
[khoros]
hostname = "your-community.khoros.com"
tapestry = "t5"
username = "op://vault/item/username"
password = "op://vault/item/password"
[bluesky]
handle = "op://vault/item/handle"
app_password = "op://vault/item/app-password"
[mastodon]
server = "op://vault/item/server"
access_token = "op://vault/item/access-token"
[gemini]
api_key = "op://vault/item/api-key"Notes:
- You can keep using
.env.templateif you prefer;config.tomltakes precedence. - 1Password references (
op://vault/item/field) are resolved automatically via the SDK.
-
Enable Desktop App Integration:
- Open and unlock the 1Password desktop app
- Select your account or collection at the top of the sidebar
- Navigate to Settings β Developer
- Under "Integrate with the 1Password SDKs", select Integrate with other apps
- (Optional) To use biometric authentication (e.g., Touch ID on Mac):
- Navigate to Settings β Security
- Turn on Touch ID (Mac) or Unlock using system authentication (Linux)
-
Set Account Name (if you have multiple 1Password accounts):
- Prefer setting it in
config.tomlunder[onepassword] account_name, or setONEPASSWORD_ACCOUNT_NAMEin your shell.
- Prefer setting it in
-
Store Credentials in 1Password:
- Store your Khoros credentials, BlueSky credentials, Mastodon credentials, and Gemini API key in 1Password
- Update the
.env.templatefile with the correct 1Password references (format:op://vault/item/field)
# Fetch 100 messages and start the TUI
./start.sh
# Or specify a custom message count
./start.sh 50# Test authentication (secrets loaded automatically via SDK)
python ./auth.py
# Fetch messages and save to file (secrets loaded automatically via SDK)
python ./fetch_posts.py --write-output --output-file ./current_data.json
# Start the TUI viewer
python ./app.pyNote: When you run the application, you may be prompted to authorize access through the 1Password desktop app. The authorization prompt will clearly show which account the integration will access.
- β/β: Navigate through message list
- Enter: Open selected message in browser
- q: Quit the application
- /: Enter filter mode to search messages
- ESC: Cancel filter mode or dismiss summary
- s: Generate AI summary of current message (requires Gemini API key)
- t: Test Gemini API connection
- d: Toggle debug window
- ESC: Dismiss dialogs and summaries
Control how many messages to fetch by modifying the start.sh script or passing arguments to fetch_posts.py:
python ./fetch_posts.py --write-output --output-file ./current_data.json --count 200To enable BlueSky posts alongside your Khoros messages:
- Log into your BlueSky account at bsky.app
- Go to Settings β Privacy and security β App passwords
- Click Add app password
- Enter a name for this application (e.g., "Khoros TUI Reader")
- Click Create app password
- Important: Copy the generated password immediately - you won't be able to see it again!
- Create a new item in 1Password for your BlueSky credentials
- Store your BlueSky handle (e.g.,
yourname.bsky.social) - Store the app password you just created
- Note the 1Password reference paths for both items
Add the BlueSky credentials to your .env.template file:
BLUESKY_HANDLE=op://path/to/1password/bluesky-handle
BLUESKY_APP_PASSWORD=op://path/to/1password/bluesky-app-passwordRun the application with ./start.sh and you should see:
- π’ Khoros messages (displayed in white text)
- π¦ BlueSky posts (displayed in cyan text)
- π Combined timeline sorted by date
Notes:
- BlueSky integration is optional - the app works fine with just Khoros messages
- The app searches for posts containing "1password" by default
- If BlueSky authentication fails, only Khoros messages will be displayed
- BlueSky posts are automatically cleaned of newlines for better list display
To enable Mastodon posts alongside your Khoros and BlueSky messages:
- Log into your Mastodon instance (e.g., mastodon.social, fosstodon.org, etc.)
- Go to Preferences β Development β Your applications
- Click New application
- Fill in the application details:
- Application name: "Khoros TUI Reader" (or any name you prefer)
- Application website: Leave blank or add your repository URL
- Scopes: Select read (you only need read access for searching posts)
- Click Submit
- Click on your newly created application
- Important: Copy the Access token - you won't be able to see it again!
- Create a new item in 1Password for your Mastodon credentials
- Store your Mastodon server URL (e.g.,
mastodon.social,fosstodon.org) - Store the access token you just created
- Note the 1Password reference paths for both items
Add the Mastodon credentials to your .env.template file:
MASTODON_SERVER=op://path/to/1password/mastodon-server
MASTODON_ACCESS_TOKEN=op://path/to/1password/mastodon-access-tokenRun the application with ./start.sh and you should see:
- π’ Khoros messages (displayed in white text)
- π¦ BlueSky posts (displayed in cyan text)
- π Mastodon posts (displayed in magenta text)
- π Combined timeline sorted by date
Notes:
- Mastodon integration is optional - the app works fine without it
- The app uses the Mastodon v2 search API for public post searching
- You can use any Mastodon instance - just update the server URL
- If Mastodon authentication fails, other message sources will still work
- HTML content is automatically cleaned for better display
To enable AI-powered message summarization:
- Get a Gemini API key from Google AI Studio
- Store it securely in 1Password
- Update your
.env.templatefile - Press
swhile viewing a message to generate summaries
Note: The Gemini API requires an internet connection and may have usage limits based on your Google Cloud account.
app.py: Main application entry point and UI orchestrationauth.py: Khoros authentication and session managementfetch_posts.py: GraphQL-based message retrieval from Khorosfetch_bluesky.py: BlueSky API integration and post retrievalfetch_mastodon.py: Mastodon API integration and post retrievalmessage_list.py: Reusable message list widget with filteringmessage_viewer.py: Message content display with HTML conversiongemini_summarizer.py: AI integration for message summarizationkeyboard_commands.py: Dynamic keyboard shortcut displayloading_screen.py: Asynchronous loading interfacedebug_widget.py: Development and debugging utilities
- Authentication: Secure credential retrieval via 1Password CLI (Khoros + BlueSky + Mastodon)
- Data Fetching: GraphQL queries to Khoros community API + REST API calls to BlueSky and Mastodon
- Processing: HTML-to-text conversion, data formatting, and message normalization
- Display: Rich TUI rendering with Textual framework and color-coded sources
- Interaction: Keyboard-driven navigation and AI features
khoros_tui_reader/
βββ app.py # Main application
βββ auth.py # Authentication module
βββ fetch_posts.py # Khoros data fetching
βββ fetch_bluesky.py # BlueSky data fetching
βββ fetch_mastodon.py # Mastodon data fetching
βββ message_list.py # Message list widget
βββ message_viewer.py # Message display widget
βββ gemini_summarizer.py # AI integration
βββ keyboard_commands.py # UI controls
βββ loading_screen.py # Loading interface
βββ debug_widget.py # Debug utilities
βββ summary_widget.py # AI summary display
βββ style.css # TUI styling
βββ start.sh # Convenience script
βββ requirements.txt # Python dependencies
βββ .env.template # Environment configuration
The modular architecture makes it easy to extend functionality:
- New Widgets: Create custom Textual widgets in separate modules
- API Integration: Add new data sources in dedicated modules
- UI Enhancements: Modify
style.cssfor visual improvements - Keyboard Shortcuts: Extend
keyboard_commands.pyfor new interactions
Authentication Errors
- Verify 1Password desktop app integration is enabled (Settings β Developer β Integrate with other apps)
- Ensure the 1Password desktop app is unlocked and running
- Check that credential references in
.env.templateuse the correct format:op://vault/item/field - If you have multiple accounts, set
ONEPASSWORD_ACCOUNT_NAMEenvironment variable - Ensure your Khoros community credentials are correct
- You may need to reauthorize after 10 minutes of inactivity or when the desktop app locks
No Messages Displayed
- Check if
current_data.jsonexists and contains data - Verify network connectivity to your Khoros community
- Check authentication token validity
Gemini API Issues
- Verify API key is correctly stored in 1Password
- Check internet connectivity
- Test connection with
tkey in the application
BlueSky Integration Issues
- Verify BlueSky handle and app password are correctly stored in 1Password
- Check that your BlueSky app password hasn't expired
- Ensure your BlueSky account is active and not suspended
- Test authentication by running:
python -c "from fetch_bluesky import create_bluesky_session; print('Token:', create_bluesky_session() is not None)" - If BlueSky fails, the app will continue with only Khoros messages
Mastodon Integration Issues
- Verify Mastodon server URL and access token are correctly stored in 1Password
- Check that your Mastodon access token hasn't been revoked
- Ensure your Mastodon server is accessible and not experiencing downtime
- Test authentication by running:
python -c "from fetch_mastodon import create_mastodon_session; server, token = create_mastodon_session(); print('Configured:', server is not None and token is not None)" - Verify your access token has 'read' scope permissions
- If Mastodon fails, the app will continue with other message sources
Performance Issues
- Reduce message count in
start.shor fetch command - Check network latency to Khoros community
- Monitor system resources during operation
Enable debug mode with the d key to see detailed application state and error information.
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
See LICENSE
For issues and questions:
- Check the troubleshooting section above
- Review the debug output (press
din the application) - Open an issue on the repository