A modern Python CLI application that stores and retrieves categorized facts with both command-line and text-based user interfaces. Built with security-first architecture featuring encrypted credential storage, Argon2 password hashing, and persistent authentication.
- Dual Interface: Choose between a simple CLI (Typer) or an interactive TUI (Textual)
- Categorized Facts: Organize facts into happy and sad categories
- User Authentication: Secure signup/login with Argon2 password hashing
- Persistent Sessions: Encrypted session storage using keyring
- Database Flexibility: SQLite for development, PostgreSQL for production
- LLM Integration: AI-powered fact generation and management using LangChain and LangGraph
- Database Migrations: Alembic-powered schema versioning
- Python 3.13+: Modern Python with latest language features
- Typer: CLI framework with automatic help generation and type hints
- Textual: Modern TUI framework for building terminal applications
- Rich: Beautiful terminal formatting and output
- SQLAlchemy 2.0: Modern Python ORM with full typing support
- Alembic: Database migration management
- PostgreSQL: Production database (via psycopg2-binary)
- SQLite: Development database (built-in)
- Passlib: Password hashing library with Argon2 support
- Keyring: Encrypted credential storage
- CryptFile: File-based encrypted keyring backend
- Argon2: Memory-hard password hashing algorithm
- LangChain: LLM application framework
- LangGraph: State machine for AI workflows
- OpenAI Integration: LLM-powered features
- UV: Fast Python package installer and resolver
- Pydantic: Data validation using Python type hints
- python-dotenv: Environment variable management
- Python 3.13 or higher
- UV package manager (recommended) or pip
- PostgreSQL (optional, for production use)
-
Clone the repository
git clone <repository-url> cd Facts
-
Install UV (if not already installed)
# Windows powershell -c "irm https://astral.sh/uv/install.ps1 | iex" # macOS/Linux curl -LsSf https://astral.sh/uv/install.sh | sh
-
Install dependencies
uv sync
-
Configure environment variables
# Copy the example environment file cp .env.example .env # Edit .env and set your values # Required: # - KEYRING_PASSWORD: Master password for encrypted credential storage # - LLM: LLM name # - LLM_API_KEY: API key for your LLM provider # Optional: # - FACTCLI_DATABASE_URL: Database connection string (defaults to SQLite) # - LLM_BASE_URL: Custom base URL for LLM API (if using local/custom endpoint)
-
Initialize the database
# Run migrations (creates tables) alembic upgrade head # Or simply run the app (auto-creates tables) uv run python main.py
Create a .env file in the project root with the following variables:
# Required: Master password for encrypted keyring storage
KEYRING_PASSWORD=your-secure-password-here
# Required: LLM configuration
LLM=llama3.2:latest
LLM_API_KEY=your-llm-api-key-here
# Optional: Database connection string
# Defaults to SQLite at ./database.sqlite3
FACTCLI_DATABASE_URL=sqlite:///database.sqlite3
# For PostgreSQL:
# FACTCLI_DATABASE_URL=postgresql+psycopg2://user:password@localhost:5432/facts
# Optional: Custom LLM endpoint (for local models or custom deployments)
LLM_BASE_URL=http://localhost:11434 # Example for Ollama# Show help and available commands
uv run python main.py --help
# Get a random fact by category
uv run python main.py happy # Get a happy fact
uv run python main.py sad # Get a sad fact
# Add a new fact
uv run python main.py add happy "Your fact text here"
uv run python main.py add sad "Another fact"
# User management
uv run python main.py whoami # Show logged-in user
uv run python main.py signout # Sign out current user
# Launch the TUI
uv run python main.py ui
# Launch the sgell
uv run python main.py shellLaunch the interactive terminal UI:
uv run python main.py uiNavigation:
- Login or signup when first launched
- Use Tab/Shift+Tab to navigate between fields
- Press Enter to submit forms
- Navigate through menu options using arrow keys or buttons
- Press Ctrl+C or use quit button to exit
Facts/
├── app/ # Core application logic
│ ├── agent.py # LLM agent integration
│ ├── auth.py # Authentication and password hashing
│ ├── cli.py # CLI command handlers
│ ├── fact_handler.py # Fact management logic
│ ├── facts.py # Core facts business logic
│ ├── schema.py # Pydantic schemas
│ └── session_store.py # Session restoration
├── conf/ # Configuration modules
│ ├── database.py # Database setup and connection
│ └── env.py # Environment variable handling
├── models/ # SQLAlchemy data models
│ ├── fact.py # Fact model
│ ├── session_token.py # SessionToken model
│ ├── user.py # User model
│ └── user_fact.py # UserFact relationship model
├── screens/ # Textual TUI screens
│ ├── add_fact.py # Add fact screen
│ ├── login.py # Login screen
│ ├── menu.py # Main menu screen
│ ├── show_fact.py # Display fact screen
│ └── signup.py # User registration screen
├── styles/ # TUI styling
│ └── app.tcss # Textual CSS
├── migrations/ # Alembic database migrations
├── main.py # Application entry point
├── tui.py # TUI application setup
└── .env # Environment configuration (not in git)
- User: Stores username and Argon2-hashed password
- Fact: Stores category (happy/sad/fun) and fact text
- UserFact: Many-to-many relationship between users and facts
- SessionToken: UUID-based session tokens for persistent authentication
Password Security:
- Argon2 hashing with memory-hard parameters (100MB memory cost)
- Time cost: 2, Parallelism: 8
- Passwords never stored in plain text
Session Management:
- UUID-based session tokens stored in database
- Local tokens encrypted using CryptFile keyring
- Keyring protected by
KEYRING_PASSWORDenvironment variable - Automatic session restoration on app launch
# Create a new migration after model changes
alembic revision --autogenerate -m "description of changes"
# Apply all pending migrations
alembic upgrade head
# Rollback one migration
alembic downgrade -1
# Show migration history
alembic history
# Show current revision
alembic currentThe app supports both SQLite (default) and PostgreSQL:
SQLite (Development):
FACTCLI_DATABASE_URL=sqlite:///database.sqlite3PostgreSQL (Production):
FACTCLI_DATABASE_URL=postgresql://username:password@localhost:5432/factcli# Run with auto-reload (if configured)
uv run python main.py ui
# Run CLI commands directly
uv run python main.py <command>- Models: Add new SQLAlchemy models in models/
- Migrations: Generate migration with
alembic revision --autogenerate - Business Logic: Add logic to app/ modules
- CLI Commands: Add commands in app/cli.py
- TUI Screens: Create new screens in screens/
- Styling: Update styles/app.tcss

