Logging & Search

repartee includes a built-in logging system backed by SQLite with optional encryption and full-text search.

Configuration

[logging]
enabled = true
encrypt = false
retention_days = 0              # 0 = keep forever
event_retention_hours = 72      # auto-prune events after 72h (0 = keep forever)
exclude_types = []              # e.g. ["join", "part", "quit"]

Storage

Logs are stored in ~/.repartee/logs/messages.db using SQLite with WAL (Write-Ahead Logging) mode for concurrent read/write performance.

Database schema

Each message is stored with:

Column Type Description
msg_id TEXT Unique UUID
network TEXT Connection/network ID
buffer TEXT Channel or query name
timestamp INTEGER Unix timestamp
msg_type TEXT Message type (privmsg, join, etc.)
nick TEXT Sender nick
text TEXT Message content
highlight INTEGER 1 if message is a highlight
ref_id TEXT Reference to primary row (for fan-out dedup)

Fan-out deduplication

Events like QUIT and NICK affect multiple channels. repartee stores a single full row for the first channel and reference rows (with empty text and a ref_id pointing to the primary) for subsequent channels. This saves storage while preserving per-channel history.

Encryption

When encrypt = true, message text is encrypted with AES-256-GCM before storage. The encryption key is derived from a passphrase stored in ~/.repartee/.env:

# ~/.repartee/.env
REPARTEE_LOG_KEY=your-secret-passphrase

Encrypted logs can only be searched/read with the correct key.

Full-text search

repartee uses SQLite FTS5 for fast full-text search across all logs:

/log search <query>

Search supports standard FTS5 syntax including phrase matching ("exact phrase"), prefix matching (prefix*), and boolean operators (AND, OR, NOT).

Commands

/log status

Show logging status, database size, and message count.

/log search <query>

Search across all logged messages.

Read-only log browser

Start repartee in log browser mode to inspect history without connecting to IRC:

repartee l
repartee logs

This mode opens the log database read-only, disables IRC connections, web services, scripts, and autoconnect, then renders stored buffers with the normal TUI. Scroll up to page older messages, press Q or use /quit to exit, and use /search <query> for full-text search when logs are not encrypted.

Chat history backlog

When you open a channel, query, or DCC chat buffer, repartee automatically loads the most recent messages from the log database — so you immediately see recent context without scrolling.

/set display.backlog_lines 20    # default — load last 20 messages
/set display.backlog_lines 50    # load more history
/set display.backlog_lines 0     # disable backlog

Backlog messages appear at the top of the buffer, followed by a separator:

─── End of backlog (20 lines) ───

Date separator lines are automatically inserted between messages from different days for easier history reading. Day-changed markers also appear at midnight in all active chat buffers. Both the date_separator and backlog_end formats are customizable via the theming system.

Backlog messages do not trigger highlights or notifications, and are not re-logged to the database (they already exist). This works for autoconnect channels, manual /join, queries opened via incoming messages, and DCC chat reconnections.

Event retention

Event messages (join, part, quit, nick, kick, mode changes) are high-volume noise that accumulates over time. The event_retention_hours setting automatically prunes old event messages while keeping actual chat history intact.

/set logging.event_retention_hours 72    # default — keep 3 days of events
/set logging.event_retention_hours 24    # aggressive — only 1 day
/set logging.event_retention_hours 0     # disable — keep events forever

Pruning runs on startup and every hour in the background. It only deletes rows with type = 'event' — chat messages, actions, notices, and CTCPs are never touched regardless of their age.

This complements retention_days which controls the maximum age for all message types. When both are set, event messages are pruned at whichever threshold is reached first.

Batched writes

Messages are written to the database in batches (50 rows or every 1 second) using an async writer task connected via a tokio mpsc channel. This minimizes SQLite lock contention and ensures the UI never blocks on disk I/O.