Metadata-Version: 2.4
Name: tldw_chatbook
Version: 0.2.2
Summary: A Textual TUI for chatting with LLMs, and interacting with the tldw server.
Author-email: Robert Musser <contact@rmusser.net>
License-Expression: AGPL-3.0-or-later
Project-URL: Homepage, https://github.com/rmusser01/tldw_chatbook
Project-URL: Bug Tracker, https://github.com/rmusser01/tldw_chatbook/issues
Project-URL: Documentation, https://github.com/rmusser01/tldw_chatbook#readme
Project-URL: Source Code, https://github.com/rmusser01/tldw_chatbook
Project-URL: Changelog, https://github.com/rmusser01/tldw_chatbook/blob/main/CHANGELOG.md
Keywords: tui,cli,llm,textual,ai,chat,rag,embeddings,terminal
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Utilities
Classifier: Topic :: Terminals
Classifier: Topic :: Communications :: Chat
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Environment :: Console
Classifier: Operating System :: OS Independent
Classifier: Natural Language :: English
Classifier: Typing :: Typed
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: chardet<6,>=3.0.2
Requires-Dist: httpx
Requires-Dist: loguru
Requires-Dist: textual==8.2.8
Requires-Dist: textual-diff-view==0.1.5
Requires-Dist: requests
Requires-Dist: rich
Requires-Dist: pyte==0.8.2
Requires-Dist: regex==2026.4.4
Requires-Dist: wcwidth<1,>=0.2.14
Requires-Dist: rich-pixels>=3.0.0
Requires-Dist: pillow>=10.4
Requires-Dist: PyYAML
Requires-Dist: pydantic<3,>=2.4
Requires-Dist: rfc8785==0.1.4
Requires-Dist: cryptography
Requires-Dist: portalocker==3.2.0
Requires-Dist: psutil
Requires-Dist: toml
Requires-Dist: tomli; python_version < "3.11"
Requires-Dist: pyperclip
Requires-Dist: emoji
Requires-Dist: jinja2
Requires-Dist: pycryptodomex
Requires-Dist: keyring
Requires-Dist: markdownify
Requires-Dist: aiofiles
Requires-Dist: croniter>=1.4.0
Requires-Dist: textual-image
Requires-Dist: tiktoken==0.14.0
Requires-Dist: defusedxml
Requires-Dist: html5lib<2,>=1.1
Requires-Dist: tinycss2<2,>=1.4
Requires-Dist: aiohttp<4,>=3.9
Requires-Dist: sherpa-onnx<2,>=1.13
Requires-Dist: numpy
Provides-Extra: coding-map
Requires-Dist: grep_ast; extra == "coding-map"
Requires-Dist: pygments; extra == "coding-map"
Requires-Dist: tqdm; extra == "coding-map"
Provides-Extra: chunker
Requires-Dist: langdetect; extra == "chunker"
Requires-Dist: nltk; extra == "chunker"
Requires-Dist: scikit-learn; extra == "chunker"
Requires-Dist: fugashi; extra == "chunker"
Requires-Dist: transformers; extra == "chunker"
Requires-Dist: tqdm; extra == "chunker"
Requires-Dist: jieba; extra == "chunker"
Provides-Extra: embeddings-rag
Requires-Dist: torch; extra == "embeddings-rag"
Requires-Dist: numpy; extra == "embeddings-rag"
Requires-Dist: pydantic; extra == "embeddings-rag"
Requires-Dist: transformers; extra == "embeddings-rag"
Requires-Dist: chromadb>=0.4.0; extra == "embeddings-rag"
Requires-Dist: sentence-transformers; extra == "embeddings-rag"
Requires-Dist: opentelemetry-api; extra == "embeddings-rag"
Requires-Dist: opentelemetry-sdk; extra == "embeddings-rag"
Provides-Extra: websearch
Requires-Dist: lxml; extra == "websearch"
Requires-Dist: beautifulsoup4; extra == "websearch"
Requires-Dist: pandas; extra == "websearch"
Requires-Dist: playwright; extra == "websearch"
Requires-Dist: trafilatura; extra == "websearch"
Requires-Dist: langdetect; extra == "websearch"
Requires-Dist: nltk; extra == "websearch"
Requires-Dist: scikit-learn; extra == "websearch"
Requires-Dist: aiohttp; extra == "websearch"
Requires-Dist: defusedxml; extra == "websearch"
Requires-Dist: tqdm; extra == "websearch"
Provides-Extra: local-vllm
Requires-Dist: vllm; extra == "local-vllm"
Provides-Extra: local-mlx
Requires-Dist: mlx-lm; extra == "local-mlx"
Provides-Extra: transcription-faster-whisper
Requires-Dist: faster-whisper; extra == "transcription-faster-whisper"
Provides-Extra: transcription-parakeet-onnx
Requires-Dist: onnx-asr[cpu]==0.12.0; extra == "transcription-parakeet-onnx"
Provides-Extra: transcription-transcribe-cpp
Requires-Dist: transcribe-cpp==0.1.3; extra == "transcription-transcribe-cpp"
Provides-Extra: transcription-lightning-whisper
Requires-Dist: lightning-whisper-mlx; sys_platform == "darwin" and extra == "transcription-lightning-whisper"
Provides-Extra: transcription-parakeet
Requires-Dist: onnx-asr[cpu]==0.12.0; extra == "transcription-parakeet"
Provides-Extra: mlx-whisper
Requires-Dist: lightning-whisper-mlx; sys_platform == "darwin" and extra == "mlx-whisper"
Requires-Dist: parakeet-mlx; sys_platform == "darwin" and extra == "mlx-whisper"
Provides-Extra: local-transformers
Requires-Dist: transformers; extra == "local-transformers"
Provides-Extra: mcp
Requires-Dist: mcp-unified==0.2.1; extra == "mcp"
Provides-Extra: image-generation
Requires-Dist: aiohttp; extra == "image-generation"
Provides-Extra: video-playback
Requires-Dist: av; extra == "video-playback"
Requires-Dist: textual-canvas; extra == "video-playback"
Provides-Extra: svg
Requires-Dist: cairosvg; extra == "svg"
Provides-Extra: frontmatter
Requires-Dist: mdit-py-plugins; extra == "frontmatter"
Provides-Extra: pdf
Requires-Dist: pymupdf; extra == "pdf"
Requires-Dist: pymupdf4llm; extra == "pdf"
Requires-Dist: docling; extra == "pdf"
Provides-Extra: ebook
Requires-Dist: ebooklib; extra == "ebook"
Requires-Dist: beautifulsoup4; extra == "ebook"
Requires-Dist: lxml; extra == "ebook"
Requires-Dist: html2text; extra == "ebook"
Requires-Dist: markdownify; extra == "ebook"
Requires-Dist: defusedxml; extra == "ebook"
Provides-Extra: audio
Requires-Dist: soundfile; extra == "audio"
Requires-Dist: scipy; extra == "audio"
Requires-Dist: yt-dlp; extra == "audio"
Requires-Dist: numpy; extra == "audio"
Requires-Dist: pydub; extra == "audio"
Requires-Dist: audioop-lts; python_version >= "3.13" and extra == "audio"
Requires-Dist: parakeet-mlx; sys_platform == "darwin" and extra == "audio"
Requires-Dist: onnx-asr[cpu]==0.12.0; extra == "audio"
Requires-Dist: faster-whisper; extra == "audio"
Provides-Extra: video
Requires-Dist: soundfile; extra == "video"
Requires-Dist: scipy; extra == "video"
Requires-Dist: yt-dlp; extra == "video"
Requires-Dist: numpy; extra == "video"
Requires-Dist: parakeet-mlx; sys_platform == "darwin" and extra == "video"
Requires-Dist: onnx-asr[cpu]==0.12.0; extra == "video"
Requires-Dist: faster-whisper; extra == "video"
Provides-Extra: media-processing
Requires-Dist: soundfile; extra == "media-processing"
Requires-Dist: scipy; extra == "media-processing"
Requires-Dist: yt-dlp; extra == "media-processing"
Requires-Dist: numpy; extra == "media-processing"
Requires-Dist: faster-whisper; extra == "media-processing"
Requires-Dist: onnx-asr[cpu]==0.12.0; extra == "media-processing"
Provides-Extra: chatterbox
Requires-Dist: chatterbox-tts>=0.1.7; extra == "chatterbox"
Requires-Dist: setuptools<82; extra == "chatterbox"
Requires-Dist: torchaudio; extra == "chatterbox"
Requires-Dist: torch; extra == "chatterbox"
Requires-Dist: faster-whisper; extra == "chatterbox"
Provides-Extra: local-tts
Requires-Dist: kokoro-onnx; extra == "local-tts"
Requires-Dist: kokoro<0.10,>=0.9.4; python_version < "3.13" and extra == "local-tts"
Requires-Dist: scipy; extra == "local-tts"
Requires-Dist: numpy; extra == "local-tts"
Requires-Dist: nltk; extra == "local-tts"
Requires-Dist: pyaudio; extra == "local-tts"
Requires-Dist: pydub; extra == "local-tts"
Requires-Dist: audioop-lts; python_version >= "3.13" and extra == "local-tts"
Requires-Dist: transformers; extra == "local-tts"
Requires-Dist: torch; extra == "local-tts"
Requires-Dist: onnxruntime; extra == "local-tts"
Requires-Dist: av; extra == "local-tts"
Provides-Extra: higgs-tts
Requires-Dist: torch; extra == "higgs-tts"
Requires-Dist: torchaudio; extra == "higgs-tts"
Requires-Dist: numpy; extra == "higgs-tts"
Requires-Dist: scipy; extra == "higgs-tts"
Requires-Dist: librosa; extra == "higgs-tts"
Requires-Dist: soundfile; extra == "higgs-tts"
Requires-Dist: transformers; extra == "higgs-tts"
Provides-Extra: nemo
Requires-Dist: nemo-toolkit[asr]>=1.20.0; extra == "nemo"
Requires-Dist: torch; extra == "nemo"
Requires-Dist: torchaudio; extra == "nemo"
Provides-Extra: speech-recording
Requires-Dist: pyaudio>=0.2.14; extra == "speech-recording"
Requires-Dist: sounddevice>=0.4.6; extra == "speech-recording"
Requires-Dist: webrtcvad-wheels>=2.0.14; extra == "speech-recording"
Provides-Extra: realtime
Requires-Dist: websockets>=14.0; extra == "realtime"
Requires-Dist: sounddevice>=0.4.6; extra == "realtime"
Requires-Dist: numpy; extra == "realtime"
Provides-Extra: ocr-docext
Requires-Dist: docext; extra == "ocr-docext"
Requires-Dist: gradio_client; extra == "ocr-docext"
Requires-Dist: transformers>=4.30.0; extra == "ocr-docext"
Requires-Dist: torch; extra == "ocr-docext"
Requires-Dist: openai; extra == "ocr-docext"
Requires-Dist: Pillow; extra == "ocr-docext"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-timeout; extra == "dev"
Requires-Dist: pytest-xdist; extra == "dev"
Requires-Dist: pytest-mock; extra == "dev"
Requires-Dist: jsonschema; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: textual-dev; extra == "dev"
Requires-Dist: hypothesis; extra == "dev"
Requires-Dist: pytest-asyncio; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: uv<1,>=0.8.0; extra == "dev"
Requires-Dist: twine; extra == "dev"
Requires-Dist: wheel; extra == "dev"
Requires-Dist: prometheus_client; extra == "dev"
Provides-Extra: debugging
Requires-Dist: prometheus_client; extra == "debugging"
Requires-Dist: opentelemetry-api; extra == "debugging"
Requires-Dist: opentelemetry-sdk; extra == "debugging"
Requires-Dist: opentelemetry-exporter-prometheus; extra == "debugging"
Requires-Dist: opentelemetry-instrumentation-system-metrics; extra == "debugging"
Provides-Extra: diarization
Requires-Dist: torch; extra == "diarization"
Requires-Dist: torchaudio; extra == "diarization"
Requires-Dist: speechbrain; extra == "diarization"
Requires-Dist: scikit-learn; extra == "diarization"
Requires-Dist: numpy; extra == "diarization"
Provides-Extra: subscriptions
Requires-Dist: beautifulsoup4; extra == "subscriptions"
Requires-Dist: cryptography; extra == "subscriptions"
Requires-Dist: defusedxml; extra == "subscriptions"
Requires-Dist: tqdm; extra == "subscriptions"
Provides-Extra: web
Requires-Dist: textual-serve; extra == "web"
Provides-Extra: all-tools
Requires-Dist: grep_ast; extra == "all-tools"
Requires-Dist: pygments; extra == "all-tools"
Requires-Dist: tqdm; extra == "all-tools"
Requires-Dist: langdetect; extra == "all-tools"
Requires-Dist: nltk; extra == "all-tools"
Requires-Dist: scikit-learn; extra == "all-tools"
Requires-Dist: fugashi; extra == "all-tools"
Requires-Dist: jieba; extra == "all-tools"
Requires-Dist: chromadb>=0.4.0; extra == "all-tools"
Requires-Dist: torch; extra == "all-tools"
Requires-Dist: numpy; extra == "all-tools"
Requires-Dist: transformers; extra == "all-tools"
Requires-Dist: sentence-transformers; extra == "all-tools"
Requires-Dist: opentelemetry-api; extra == "all-tools"
Requires-Dist: opentelemetry-sdk; extra == "all-tools"
Requires-Dist: vllm; extra == "all-tools"
Requires-Dist: mlx-lm; extra == "all-tools"
Requires-Dist: lxml; extra == "all-tools"
Requires-Dist: beautifulsoup4; extra == "all-tools"
Requires-Dist: pandas; extra == "all-tools"
Requires-Dist: playwright; extra == "all-tools"
Requires-Dist: trafilatura; extra == "all-tools"
Requires-Dist: aiohttp; extra == "all-tools"
Requires-Dist: defusedxml; extra == "all-tools"
Requires-Dist: faster-whisper; extra == "all-tools"
Requires-Dist: onnx-asr[cpu]==0.12.0; extra == "all-tools"
Requires-Dist: lightning-whisper-mlx; sys_platform == "darwin" and extra == "all-tools"
Requires-Dist: parakeet-mlx; sys_platform == "darwin" and extra == "all-tools"
Requires-Dist: soundfile; extra == "all-tools"
Requires-Dist: scipy; extra == "all-tools"
Requires-Dist: yt-dlp; extra == "all-tools"
Requires-Dist: pydub; extra == "all-tools"
Requires-Dist: audioop-lts; python_version >= "3.13" and extra == "all-tools"
Requires-Dist: pyaudio>=0.2.14; extra == "all-tools"
Requires-Dist: sounddevice>=0.4.6; extra == "all-tools"
Requires-Dist: webrtcvad-wheels>=2.0.14; extra == "all-tools"
Requires-Dist: librosa; extra == "all-tools"
Requires-Dist: chatterbox-tts>=0.1.7; extra == "all-tools"
Requires-Dist: setuptools<82; extra == "all-tools"
Requires-Dist: torchaudio; extra == "all-tools"
Requires-Dist: kokoro-onnx; extra == "all-tools"
Requires-Dist: kokoro<0.10,>=0.9.4; python_version < "3.13" and extra == "all-tools"
Requires-Dist: onnxruntime; extra == "all-tools"
Requires-Dist: av; extra == "all-tools"
Requires-Dist: speechbrain; extra == "all-tools"
Requires-Dist: nemo-toolkit[asr]>=1.20.0; extra == "all-tools"
Requires-Dist: pymupdf; extra == "all-tools"
Requires-Dist: pymupdf4llm; extra == "all-tools"
Requires-Dist: docling; extra == "all-tools"
Requires-Dist: ebooklib; extra == "all-tools"
Requires-Dist: html2text; extra == "all-tools"
Requires-Dist: markdownify; extra == "all-tools"
Requires-Dist: docext; extra == "all-tools"
Requires-Dist: gradio_client; extra == "all-tools"
Requires-Dist: openai; extra == "all-tools"
Requires-Dist: Pillow; extra == "all-tools"
Requires-Dist: mcp-unified==0.2.1; extra == "all-tools"
Requires-Dist: markdown; extra == "all-tools"
Requires-Dist: schedule; extra == "all-tools"
Requires-Dist: feedparser; extra == "all-tools"
Requires-Dist: cryptography; extra == "all-tools"
Requires-Dist: pytest; extra == "all-tools"
Requires-Dist: pytest-timeout; extra == "all-tools"
Requires-Dist: textual-dev; extra == "all-tools"
Requires-Dist: hypothesis; extra == "all-tools"
Requires-Dist: pytest-asyncio; extra == "all-tools"
Requires-Dist: build; extra == "all-tools"
Requires-Dist: twine; extra == "all-tools"
Requires-Dist: wheel; extra == "all-tools"
Requires-Dist: prometheus_client; extra == "all-tools"
Requires-Dist: opentelemetry-exporter-prometheus; extra == "all-tools"
Requires-Dist: opentelemetry-instrumentation-system-metrics; extra == "all-tools"
Requires-Dist: textual-serve; extra == "all-tools"
Dynamic: license-file

# tldw_chatbook

[![Status: Alpha](https://img.shields.io/badge/status-alpha-orange)](#alpha-status)
[![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue)](https://www.python.org/)
[![License: AGPL-3.0-or-later](https://img.shields.io/badge/license-AGPL--3.0--or--later-green)](LICENSE)

tldw_chatbook is a local-first terminal application for chatting with large
language models, working with personal knowledge, and supervising tools and
agent workflows. It connects to hosted model APIs or a local model server while
keeping conversations, notes, prompts, and other core application data on your
machine by default.

![tldw_chatbook Console showing a grounded conversation with sources and tool activity](Docs/static/tldw-chatbook-console.png)

> **New here?** Follow the [five-minute quick start](#quick-start), then use
> [Your first conversation](#your-first-conversation). The
> [User Guide](Docs/User_Guide/index.md) covers every major screen and workflow.

## Alpha status

tldw_chatbook is **Alpha** software. The current package version is `0.2.2`.
The core application is usable, but the project is moving quickly: interfaces
can change, advanced integrations vary in maturity, and older data may
occasionally need migration or recovery.

- **Available now:** the Textual application shell, hosted and local-server
  model connections, streaming conversations, local conversations and notes,
  Library search and ingestion, Roleplay, Artifacts and Chatbooks, Settings,
  and the source installation described below.
- **Still evolving:** ACP runtime integration, some agent and tool workflows,
  write synchronization, deeper server-backed features, and optional
  capabilities that depend on large models, native libraries, or external
  services.
- **Goal:** a modular terminal environment where LLM conversations, local
  knowledge, media, and explicitly controlled tools can work together without
  forcing every integration into the core install.

“Local-first” describes storage and ownership, not necessarily inference.
Hosted providers receive the prompts you send to them. Local models normally run
in a separate server such as Ollama, llama.cpp, vLLM, MLX-LM, or another
OpenAI-compatible endpoint.

## Why tldw_chatbook?

- **Use your choice of model.** Switch between hosted providers and local model
  servers without changing applications.
- **Keep useful context close.** Store and search conversations, notes, prompts,
  media, collections, and imported source material locally.
- **Work with more than text.** Ingest documents, web pages, audio, video, and
  e-books with the optional capability groups you choose.
- **Build grounded conversations.** Search the Library with SQLite FTS5 or add
  embeddings for semantic and hybrid RAG.
- **Create different kinds of conversations.** Use ordinary assistant chats,
  characters, personas, lorebooks, and chat dictionaries.
- **Stay in control of automation.** Review tool calls, permissions, agent runs,
  schedules, workflows, and recovery states in the UI.
- **Install only what you need.** The core package stays smaller while RAG,
  media, speech, local inference, MCP, and browser serving remain optional.

<a id="installation"></a>
## Quick start

### Requirements

- Python `>=3.12`
- Windows, macOS, or Linux
- A terminal with Unicode support
- Either an API key for a hosted provider or a separately running local model
  server

### 1. Clone the repository

```bash
git clone https://github.com/rmusser01/tldw_chatbook.git
cd tldw_chatbook
```

### 2. Create and activate a virtual environment

macOS or Linux:

```bash
python3 --version
python3 -m venv .venv
source .venv/bin/activate
```

Windows PowerShell:

```powershell
py -3 --version
py -3 -m venv .venv
.venv\Scripts\Activate.ps1
```

Windows Command Prompt:

```bat
py -3 -m venv .venv
.venv\Scripts\activate.bat
```

Use an executable that reports Python 3.12 or newer. A versioned executable such
as `python3.12` or `py -3.12` is fine.

### 3. Install the core application

```bash
python -m pip install --upgrade pip
python -m pip install -e .
```

### 4. Launch it

```bash
tldw-cli
```

The first-run wizard opens on a new profile. Choose **Quick setup** to connect a
provider, select a model, and keep the remaining features at their recommended
defaults. The full setup track also covers RAG, tools, notes sync, appearance,
speech, and key protection.

### 5. Send a message

Finish the wizard, open **Console** with **Ctrl+2**, type in the composer, and
send. Press **F1** for screen-specific shortcuts or **Ctrl+P** for the command
palette.

If setup was skipped or interrupted, open
**Settings › Diagnostics › Run setup wizard**. Provider, endpoint, key, and
model settings can also be repaired directly under
**Settings › Providers & Models**.

## Your first conversation

### Option A: Connect a hosted model API

1. Choose a hosted provider in the first-run wizard.
2. Enter its API key and select one of its available models.
3. Finish setup and open **Console**.
4. Send a message.

Prompts and responses cross the selected provider’s service boundary and are
handled under that provider’s terms. Keys can be saved through the guided setup
or supplied through supported environment variables.

### Option B: Connect a local model server

1. Start the local server separately.
2. Choose the matching local or OpenAI-compatible provider in the wizard.
3. Confirm its endpoint and select a model exposed by that server.
4. Finish setup, open **Console**, and send a message.

Local servers on localhost may be detected by the wizard. tldw_chatbook does not
claim an embedded model runtime: the external server owns model loading and
inference; the app owns the conversation and workflow interface.

See [First-Run Setup](Docs/User_Guide/First_Run_Setup.md) and
[Console basics](Docs/User_Guide/console/chat-basics.md) for a detailed
walkthrough.

## Installation options

The editable source install is the primary path while the project is Alpha:

```bash
python -m pip install -e .
```

A published package can be installed with:

```bash
python -m pip install tldw_chatbook
```

The examples below use editable source installs. For a published package, add
the same optional-dependency group to the package name.

### Common combinations

```bash
# Development and tests
python -m pip install -e ".[dev]"

# Semantic and hybrid RAG
python -m pip install -e ".[embeddings_rag,chunker]"

# Audio/video ingestion and document extraction
python -m pip install -e ".[audio,video,pdf,ebook]"

# Web search plus browser-served TUI
python -m pip install -e ".[websearch,web]"

# MCP integration
python -m pip install -e ".[mcp]"

# Local model integrations
python -m pip install -e ".[local_vllm,local_transformers]"
```

Optional groups can install large ML dependencies, download model assets, or
require native libraries. Add only the groups you plan to use.

## Optional capabilities

| Group | Adds |
| --- | --- |
| `embeddings_rag` | Embeddings, vector storage, semantic search, and hybrid RAG |
| `chunker` | Language-aware and advanced text chunking |
| `websearch` | Web retrieval, extraction, and search dependencies |
| `coding_map` | Code parsing, syntax highlighting, and repository mapping helpers |
| `local_vllm` | vLLM local-inference integration |
| `local_mlx` | MLX-LM support on compatible Apple Silicon systems |
| `local_transformers` | Hugging Face Transformers local-model support |
| `mcp` | Model Context Protocol client/server dependencies |
| `audio` | Audio ingestion, processing, and transcription |
| `video` | Video ingestion and transcription |
| `media_processing` | Shared audio/video processing stack |
| `pdf` | PDF extraction with PyMuPDF and Docling |
| `ebook` | EPUB and e-book extraction |
| `image_generation` | Image-generation HTTP adapter support |
| `video_playback` | In-app video decoding and playback widgets |
| `svg` | SVG rasterization; the Cairo system library may also be required |
| `frontmatter` | YAML front matter support in Markdown notes and previews |
| `speech_recording` | Microphone recording support |
| `realtime` | Realtime audio/model dependencies |
| `local_tts` | Kokoro ONNX and official Kokoro PyTorch (Python 3.12) |
| `chatterbox` | Chatterbox TTS support |
| `higgs_tts` | Supporting packages for Higgs Audio; manual Higgs installation is also required |
| `transcription_faster_whisper` | CPU/CUDA-optimized Whisper |
| `transcription_parakeet_onnx` | Cross-platform Parakeet ONNX runtime |
| `transcription_transcribe_cpp` | Direct local GGUF transcription runtime |
| `transcription_lightning_whisper` | Apple Silicon Lightning Whisper |
| `transcription_parakeet` | Compatibility alias for Parakeet ONNX |
| `mlx_whisper` | Legacy Apple Silicon transcription bundle |
| `nemo` | NVIDIA NeMo speech models |
| `diarization` | Speaker diarization dependencies |
| `ocr_docext` | OCR and document-extraction integrations |
| `subscriptions` | Feed and subscription parsing helpers |
| `debugging` | Prometheus and OpenTelemetry development instrumentation |
| `web` | Browser serving through `textual-serve` |
| `dev` | Test, packaging, and development tools |

The list in `pyproject.toml` is authoritative. For recovery commands and
ownership, see
[Release Recovery and Setup](Docs/Development/release-recovery-setup.md).

### Speech and transcription choices

The `audio`, `video`, and `media_processing` groups include practical
cross-platform transcription defaults. Additional engines can be installed
alongside them:

```bash
# Cross-platform audio ingestion
python -m pip install -e ".[audio]"

# Add Apple Silicon-optimized Whisper
python -m pip install -e ".[audio,transcription_lightning_whisper]"

# Direct local GGUF transcription
python -m pip install -e ".[audio,transcription_transcribe_cpp]"
```

Some speech engines have hardware, model-download, or system-library
requirements. See the
[Speech Services Guide](Docs/Features/Speech-Services-Guide.md) before choosing
a large local stack.

Higgs Audio requires manual installation of its upstream package before the
`higgs_tts` extra can be used. Follow the
[Higgs Audio guide](Docs/Development/TTS/Higgs-Audio-TTS-Guide.md) rather than
guessing compatible versions.

## What you can do

The application is organized around workflows. You do not need every
destination or optional dependency to use the core chat experience.

### Conversations and live work

Use **Console** to:

- stream responses from hosted or local providers;
- create, save, search, branch, edit, regenerate, and resume conversations;
- attach images and other supported context;
- stage Library sources for grounded answers;
- review tool calls, results, approvals, and agent-run activity;
- switch sessions, models, context policy, and workspace bindings;
- open separately armed, user-only persistent Terminal sessions on supported
  POSIX hosts;
- inspect failures and follow explicit recovery actions.

The conversation transcript is the primary work surface. Home, Library,
Research, Roleplay, and other destinations can hand context or work back to the
active Console session.

Read the [Console guide](Docs/User_Guide/console.md) for chat basics, context
and RAG, attachments, tools, sessions, branching, and rewind.

Persistent Terminal is deliberately different from both one-shot raw commands
and model tools. It runs a normal interactive shell with the full authority of
your OS account, retains its current directory/environment/screen in memory,
and is not confined to a Workspace. It requires the saved raw-CLI unlock plus
its own per-launch arm. Terminal content is never sent to a model, persisted,
exported, or reconnected after restart. Up to four sessions are retained.
Current builds support admitted PTYs on macOS/Linux; Windows refuses Terminal
launches because no qualified ConPTY dependency ships.

### Local knowledge, search, and RAG

Use **Library** to work with:

- conversations, notes, prompts, media, skills, and collections;
- local files and imported source material;
- full-text search with SQLite FTS5 and BM25 ranking;
- semantic and hybrid retrieval with `embeddings_rag`;
- source selection and handoff into Console;
- document, web, audio, video, PDF, and e-book ingestion;
- study workflows such as flashcards and quizzes.

Basic full-text search does not require the embeddings stack. Semantic/vector
retrieval, some re-ranking, and model-backed indexing do.

Library access in Console is intentionally split into explicit controls:
manual Library search, automatic retrieval policy, assistant tool permission,
and direct/RAG retrieval mode. New conversations do not silently grant every
tool or source.

See the [Library guide](Docs/User_Guide/library.md) and
[Search and RAG](Docs/User_Guide/library/search-and-rag.md).

### Notes and file sync

Library Notes support Markdown content, folders, templates, import/export,
search, links, and a reviewed lasting-sync relationship between a managed
Library folder and a chosen folder on disk. Folder Files (File Notes) is a
separate, disk-authoritative workspace: it edits files in the selected folder
directly and does not mirror them into the Library database.

See [Library Notes](Docs/User_Guide/library/notes.md) and
[File Notes](Docs/User_Guide/library/file-notes.md).

### Media and speech

With the appropriate extras, tldw_chatbook can:

- import local files and supported URLs;
- extract text and structure from documents, PDFs, and e-books;
- transcribe audio and video with local or configured remote engines;
- attach images to supported vision models;
- record voice input;
- synthesize and play spoken responses;
- generate images or videos through configured adapters;
- preview supported media inside the application.

These workflows can be resource-intensive. Local engines may download large
models; remote engines send selected media or text to their service.

See [Media and Conversations](Docs/User_Guide/library/media-and-conversations.md),
[Console attachments, images, and voice](Docs/User_Guide/console/attachments-images-voice.md),
and [Console video](Docs/User_Guide/console/video.md).

### Roleplay, characters, and lore

Use **Roleplay** to manage:

- character cards and character conversations;
- user personas and profile context;
- chat dictionaries;
- lorebooks and world information;
- import/export of supported character formats.

See the
[Roleplay and Chat Dictionaries guide](Docs/User_Guide/roleplay-chat-dictionaries.md).

### Artifacts and Chatbooks

**Artifacts** collects outputs that should live beyond one message: reports,
datasets, generated files, and Chatbooks. Chatbooks provide a portable bundle
for selected conversation and source material.

See [Artifacts](Docs/User_Guide/artifacts.md).

### Home, Research, Watchlists, Schedules, and Workflows

- **Home** shows attention items, running work, recent activity, and useful next
  actions.
- **Research** provides grounded workspaces and durable research-run
  observation.
- **Watchlists** monitors configured sources and exposes runs, alerts, and
  recovery.
- **Schedules** owns timing and triggers for supported recurring work.
- **Workflows** defines reusable procedures, dry runs, and outputs.

Some live service, runtime, and write-sync paths remain intentionally explicit
or blocked until their required backend is configured. An unavailable state
should tell you what is missing rather than pretending the workflow ran.

Guides:
[Home](Docs/User_Guide/home.md) ·
[Research](Docs/User_Guide/research_workspace.md) ·
[Watchlists](Docs/User_Guide/watchlists.md) ·
[Schedules](Docs/User_Guide/schedules.md) ·
[Workflows](Docs/User_Guide/workflows.md)

### Tools, MCP, and ACP

The built-in tool system includes simple local tools and a catalog that can
incorporate local, skill, and MCP providers. Console renders calls, results,
permissions, and failures inline.

**MCP** manages Model Context Protocol servers, discovered tools, permissions,
authentication, and audit information. Install `mcp` when its optional
dependencies are needed:

```bash
python -m pip install -e ".[mcp]"
```

The standalone stdio server can then be launched with:

```bash
python -m tldw_chatbook.MCP
```

**ACP** manages compatible agent runtimes, sessions, diffs, and terminals. ACP
does not include a runtime by itself; configure a compatible runtime in the ACP
destination before attempting to launch a session.

See [MCP](Docs/User_Guide/mcp.md),
[ACP](Docs/User_Guide/acp.md), and
[Agent runs and tools](Docs/User_Guide/console/agent-runs-and-tools.md).

### Models, evaluation, and Lab

**Lab** groups model management, speech, and evaluation workflows. Evaluation
support includes configurable tasks, metrics, result storage, and comparisons.
Optional model and media stacks add hardware-specific capabilities without
making them core requirements.

See [Lab](Docs/User_Guide/lab.md).

## Application destinations

| Shortcut | Destination | Purpose |
| --- | --- | --- |
| **Ctrl+1** | Home | Status, attention items, running work, and next actions |
| **Ctrl+2** | Console | Conversations, context, tools, approvals, and runs |
| **Ctrl+3** | Library | Notes, media, prompts, conversations, skills, search, RAG, and ingestion |
| **F10** | Research | Grounded workspaces and research-run observation |
| **Ctrl+4** | Artifacts | Generated outputs, reports, datasets, and Chatbooks |
| **Ctrl+5** | Roleplay | Characters, personas, dictionaries, and lore |
| **Ctrl+6** | Watchlists | Monitored sources, runs, alerts, and recovery |
| **Ctrl+7** | Schedules | Timing and triggers |
| **Ctrl+8** | Workflows | Reusable procedures and outputs |
| **Ctrl+9** | MCP | MCP servers, tools, permissions, and auth |
| **Ctrl+0** | ACP | Compatible agent runtimes and sessions |
| **F7** | Lab | Models, speech, and evaluations |
| **F8** | Logs | Application logs and diagnostics |
| **F9** | Settings | Providers, storage, appearance, privacy, and application behavior |

Legacy route names may still resolve during migration, but they are not the
primary navigation model.

## Model connections

Provider integrations include major hosted APIs and OpenAI-compatible services.
The exact provider and model catalog evolves faster than this README; use the
first-run wizard or **Settings › Providers & Models** for the current list.

Local and compatible endpoints can include:

- Ollama
- llama.cpp
- KoboldCpp
- vLLM
- Aphrodite
- MLX-LM
- any compatible endpoint that exposes the expected API and model identifiers

Capabilities such as images, tool calling, structured output, reasoning, and
streaming depend on both the selected model and provider adapter. The UI reports
readiness and recovery information rather than assuming support from a model
name alone.

## Configuration and data

### Preferred setup path

Use the first-run wizard and **Settings** for ordinary configuration. Hand-edit
TOML only when a setting has no UI owner or you need a reproducible advanced
profile.

The main config file is:

```text
~/.config/tldw_cli/config.toml
```

Run the wizard again from **Settings › Diagnostics › Run setup wizard**.
Provider and model repair belongs under **Settings › Providers & Models**.

Configuration precedence is generally:

1. supported environment variables;
2. `config.toml`;
3. built-in defaults.

Provider-specific details can vary, so prefer the current Settings UI and
maintained guides over copied configuration blocks.

### API keys and secrets

API keys can be entered in the wizard or Settings, or supplied with the
provider’s supported environment variable. Common examples include
`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `DASHSCOPE_API_KEY`,
`MOONSHOT_API_KEY`, and `ZAI_API_KEY`.

Do not commit keys to the repository. Config encryption and keyring-backed
storage are available for supported paths; the wizard’s **Protect keys** step
explains the active choice.

### Local data

The default base data directory on a typical Unix-like system is:

```text
~/.local/share/tldw_cli/
```

On a fresh POSIX install, if existing `.local` or `share` permissions prevent
private storage, Chatbook automatically uses `~/.tldw_cli-data/<user>/` instead.
This location remains selected on later launches, including after those
permissions change. Shared ancestor permissions are left untouched; application
directories remain owner-only. Settings shows the selected storage location.
Existing data and explicit `[paths] data_dir` settings are never silently
bypassed. If both default roots exist, select the intended base explicitly with
`[paths] data_dir` before restarting. An unsafe home directory still requires a
safe storage location; Chatbook does not weaken its private-file checks.

Profiles live below it:

```text
~/.local/share/tldw_cli/<profile>/
```

A fresh install normally uses `default_user`. Profile directories can contain
SQLite databases, logs, caches, generated media, exports, model artifacts, and
tool/workspace state. Exact paths vary by platform and configuration.

For that default profile, the usual Unix-like path is:

```text
~/.local/share/tldw_cli/default_user/
```

Before deleting, moving, or sharing this directory:

1. inspect the active paths in **Settings › Storage**;
2. close other running instances;
3. back up the profile data you care about;
4. remember that generated files and optional model caches may be large.

Local storage does not prevent a configured feature from sending selected
content elsewhere. Hosted models, web search, MCP servers, agent runtimes, and
server-backed workflows each introduce a separate trust boundary.

### Advanced profiles

`TLDW_CONFIG_PATH` can select a different config file. A config override does
not automatically relocate every data path; set `[paths].data_dir` inside that
profile when true isolation is required.

## Browser access

Install the `web` group to serve the Textual application in a browser:

```bash
python -m pip install -e ".[web]"
tldw-serve
```

Common options:

```bash
tldw-serve --host localhost --port 8080 --title "tldw chatbook"
```

The default bind address is localhost. Binding to `0.0.0.0` makes the service
reachable through network interfaces; do that only with appropriate firewall,
authentication, and network controls. Browser access does not make private
Library content safe to expose publicly.

## Troubleshooting

### `tldw-cli` is not found

Activate the virtual environment and reinstall through its interpreter:

```bash
python -m pip install -e .
```

Then confirm the environment’s scripts directory is on `PATH`.

### The Console says the provider or model is blocked

Open **Settings › Providers & Models** and check:

- provider selection;
- API key or local endpoint;
- default model;
- connection/readiness result.

Run the setup wizard again if several fields are missing.

### A local model does not respond

Confirm the separate model server is running, the configured endpoint is
reachable, and the model identifier exactly matches one exposed by that server.

### An advanced feature is unavailable

Read the recovery message, install the named optional group, and restart the
application. Missing an optional group should not make the core install
unusable.

### RAG has no sources

Import or select content in Library, choose a source or search result, and stage
it into Console. Semantic/vector search additionally requires the
`embeddings_rag` group and an available embedding model.

### Startup or migration fails

Open **Logs** with **F8** and inspect the error before deleting data. Back up the
active profile, then use the
[Release Recovery and Setup guide](Docs/Development/release-recovery-setup.md).

### The UI looks wrong in the terminal

Use a Unicode-capable terminal, try a larger window, and press **F1** to inspect
screen controls. Some media rendering depends on terminal image support.

## Project structure

<details>
<summary>Major directories</summary>

```text
tldw_chatbook/
├── Agents/                 Agent orchestration and tool catalogs
├── Artifacts/              Artifact contracts and storage
├── Character_Chat/         Characters, cards, lore, and roleplay logic
├── Chat/                   Conversation and transcript behavior
├── Chatbooks/              Portable Chatbook creation and import
├── DB/                     SQLite databases, schemas, and migrations
├── Evals/                  Evaluation runners and metrics
├── Event_Handlers/         Textual message and worker coordination
├── Image_Generation/       Image-generation adapters
├── LLM_Calls/              Hosted and local provider integrations
├── Local_Ingestion/        File and media ingestion
├── MCP/                    MCP client/server and permission handling
├── Notes/                  Notes and file-sync logic
├── RAG_Search/             Search, indexing, chunking, and retrieval
├── TTS/                    Text-to-speech providers and playback
├── Tools/                  Built-in and local tool implementations
├── UI/                     Screens, views, wizards, and navigation
├── Video_Generation/       Video-generation adapters and stores
├── Widgets/                Reusable Textual widgets
├── Workspaces/             Workspace bindings and lifecycle
├── app.py                  Main Textual application
├── cli.py                  Lightweight installed command entry point
├── config.py               Configuration and path resolution
└── Constants.py            Shared application constants
```

</details>

## Development

Install development dependencies:

```bash
python -m pip install -e ".[dev]"
```

Run the application from the installed entry point:

```bash
tldw-cli
```

Run focused tests while developing:

```bash
python -m pytest Tests/Chat/
python -m pytest Tests/UI/test_legacy_entrypoints_retired.py
```

Run the full suite before a release or merge when the complete environment is
available:

```bash
python -m pytest
```

Coverage:

```bash
python -m pytest --cov=tldw_chatbook
```

See [Testing](Docs/Testing.md) and [Contributing](CONTRIBUTING.md) before making
large changes. Public APIs should use type hints; database queries must be
parameterized; file paths and external inputs must be validated at their
boundaries.

## Documentation

- [User Guide](Docs/User_Guide/index.md) — task-oriented application guidance
- [First-Run Setup](Docs/User_Guide/First_Run_Setup.md) — wizard tracks and recovery
- [Console](Docs/User_Guide/console.md) — conversations, context, tools, and runs
- [Library](Docs/User_Guide/library.md) — local content, ingestion, search, and RAG
- [Settings](Docs/User_Guide/settings.md) — providers, models, storage, and behavior
- [Release Recovery and Setup](Docs/Development/release-recovery-setup.md) — blocked states and optional dependencies
- [Changelog](CHANGELOG.md) — release history
- [Contributing](CONTRIBUTING.md) — development and pull-request guidance

The User Guide tracks the `dev` branch. If a label differs in an older
checkout, compare the installed version and the guide’s verification note.

## Inspiration

- [Elia](https://github.com/darrenburns/elia)
- [ParLlama](https://github.com/paulrobello/parllama)

## Contributing

Contributions are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md), keep pull
requests focused, and include verification appropriate to the behavior being
changed. Development work targets the `dev` branch before reaching `main`.

Use the [issue tracker](https://github.com/rmusser01/tldw_chatbook/issues) for
reproducible bugs, feature discussion, and documentation gaps.

## License

tldw_chatbook is licensed under the
[GNU Affero General Public License v3.0 or later](LICENSE).

## Contact

For project questions and feature requests, open a
[GitHub issue](https://github.com/rmusser01/tldw_chatbook/issues). For security
issues, do not publish sensitive details in a public issue; contact the
maintainer privately at [contact@rmusser.net](mailto:contact@rmusser.net).
