Skip to content

Latest commit

 

History

History
458 lines (330 loc) · 10.8 KB

File metadata and controls

458 lines (330 loc) · 10.8 KB

Getting Started with Traul

Traul is a personal intelligence engine that syncs messages from Slack, Telegram, Discord, Linear, Gmail, WhatsApp, Claude Code sessions, and local Markdown files into a single searchable SQLite database.

For AI agents: If you are an AI assistant setting up Traul for a user, follow this doc step by step. Present the list of available connectors (Section 4), let the user choose which ones they want, then walk through each selected connector one at a time. After setup, start the daemon and verify with a search query.

1. Install Prerequisites

Bun (required)

Traul uses Bun as its runtime and package manager.

curl -fsSL https://bun.sh/install | bash

Restart your terminal, then verify:

bun --version   # should be 1.0+

Homebrew SQLite (required on macOS)

Apple's bundled SQLite does not support loadable extensions. Traul needs Homebrew's build for the sqlite-vec vector extension.

brew install sqlite

Traul automatically loads the library from /opt/homebrew/opt/sqlite/lib/libsqlite3.dylib — no PATH changes needed.

Ollama (optional — enables vector search)

Ollama runs embedding models locally. Without it, you can still use keyword search (--fts).

brew install ollama
ollama pull snowflake-arctic-embed2
ollama serve

Keep ollama serve running in a background terminal or configure it as a launch agent.

Python 3 + Telethon (optional — for Telegram sync)

Only needed if you want to sync Telegram messages.

python3 --version          # macOS ships with Python 3
pip3 install telethon

You will also need a Telegram API app — see the Telegram section below.

2. Install Traul

git clone <repo-url> && cd traul
bun install
bun link

bun link registers traul as a global CLI command. Verify:

traul --help

3. Create Config File

Create ~/.config/traul/config.json with your desired settings. You can start with an empty object and add connector config as you go:

{}

All connector credentials can be set via environment variables (shown in each section below) or in this config file. Environment variables take precedence over config file values.

4. Set Up Connectors

Each connector syncs independently. Pick the ones you want and set them up one at a time.

Connector Difficulty What you need
Claude Code Zero config Nothing — reads ~/.claude/projects/
Markdown Minimal List of directories in config
Linear Easy API key
Discord Easy Bot token
Slack Moderate Token (bot or user)
Telegram Moderate API ID/hash + one-time auth
Gmail Moderate OAuth2 credentials
WhatsApp Advanced WAHA server + QR auth

Claude Code (zero config)

Reads session files from ~/.claude/projects/ — nothing to configure.

traul sync claudecode

Markdown

Add a list of directories to your config file:

{
  "markdown": {
    "dirs": ["~/notes", "~/docs"]
  }
}
traul sync markdown

Linear

Get an API key from Linear Settings > API.

export LINEAR_API_KEY="lin_api_..."

For multiple workspaces, use suffixed variables:

export LINEAR_API_KEY_WORK="lin_api_..."
export LINEAR_API_KEY_PERSONAL="lin_api_..."
traul sync linear

Discord

Create a Discord bot at discord.com/developers/applications:

  1. Create a New Application
  2. Go to Bot > Reset Token — copy the token
  3. Under Privileged Gateway Intents, enable Message Content Intent
  4. Go to OAuth2 > URL Generator, select bot scope with Read Message History permission
  5. Open the generated URL to invite the bot to your server
export DISCORD_TOKEN="your-bot-token"

Optional — filter by server or channel in config:

{
  "discord": {
    "servers": {
      "allowlist": ["server_id_1"]
    },
    "channels": {
      "stoplist": ["channel_id_to_skip"]
    }
  }
}
traul sync discord

Slack

You need a Slack token. Two approaches:

Bot token (xoxb) — create a Slack app at api.slack.com/apps, add OAuth scopes (channels:history, channels:read, users:read), install to workspace, copy the Bot User OAuth Token.

User token (xoxc) — extract from your browser's Slack session. Open Slack in a browser, find the xoxc- token and d= cookie value in DevTools (Application > Cookies and Network requests). This gives access to all channels you can see.

export SLACK_TOKEN="xoxb-..."
# or for xoxc tokens:
export SLACK_TOKEN="xoxc-..."
export SLACK_COOKIE="xoxd=..."

For multiple workspaces, use suffixed variables:

export SLACK_TOKEN_MYTEAM="xoxb-..."
export SLACK_TOKEN_WORK="xoxc-..."
export SLACK_COOKIE_WORK="xoxd=..."
traul sync slack

Telegram

  1. Go to my.telegram.org, log in, and create an app under "API development tools". Note the api_id and api_hash.

  2. Set environment variables:

export TELEGRAM_API_ID="12345678"
export TELEGRAM_API_HASH="abc123..."
  1. Run the one-time interactive auth (enters your phone number, sends a code):
python3 scripts/tg_sync.py setup

This creates a session file at ~/.config/telegram-telethon/session. You only need to do this once.

  1. Sync:
traul sync telegram

Gmail

Gmail requires OAuth2 credentials. You need a Google Cloud project with the Gmail API enabled.

  1. Go to Google Cloud Console
  2. Create a project (or use an existing one)
  3. Enable the Gmail API under APIs & Services > Library
  4. Create OAuth2 credentials under APIs & Services > Credentials > Create Credentials > OAuth client ID
  5. Set application type to "Desktop app"
  6. Note the client_id and client_secret
  7. Obtain a refresh token by completing the OAuth2 flow (use the Google OAuth Playground or a local script)
export GMAIL_CLIENT_ID="your-client-id"
export GMAIL_CLIENT_SECRET="your-client-secret"
export GMAIL_REFRESH_TOKEN="your-refresh-token"

Or as a single JSON variable:

export GMAIL_CREDS_JSON='{"client_id":"...","client_secret":"...","refresh_token":"..."}'

For multiple accounts, use config:

{
  "gmail": {
    "accounts": [
      {
        "name": "personal",
        "client_id": "...",
        "client_secret": "...",
        "refresh_token": "...",
        "labels": ["INBOX"]
      }
    ]
  }
}
traul sync gmail

WhatsApp

WhatsApp sync uses WAHA (WhatsApp HTTP API), a self-hosted service that bridges WhatsApp Web.

  1. Start a WAHA instance:
docker compose -f docker-compose.waha.yml up -d
  1. Add the instance to your config:
{
  "whatsapp": {
    "instances": [
      {
        "name": "personal",
        "url": "http://localhost:3000",
        "api_key": "your-waha-api-key",
        "session": "default"
      }
    ]
  }
}
  1. Authenticate by scanning a QR code:
traul whatsapp auth personal

This displays a QR code in your terminal. Scan it with WhatsApp on your phone within 2 minutes.

  1. Optional — filter to specific chats:
{
  "whatsapp": {
    "instances": [
      {
        "name": "personal",
        "url": "http://localhost:3000",
        "api_key": "your-waha-api-key",
        "session": "default",
        "chats": ["chat_id_1", "chat_id_2"]
      }
    ]
  }
}
traul sync whatsapp

5. Start the Daemon

Instead of running traul sync manually, start the daemon for continuous background sync:

traul daemon start --detach

This runs the daemon in the background, syncing all configured connectors at regular intervals and generating embeddings automatically. Logs are written to ~/.local/share/traul/daemon.log.

Check daemon status:

traul daemon status

Stop the daemon:

traul daemon stop

Auto-start on boot (optional, macOS)

To start the daemon automatically when you log in, create a launchd plist:

cat > ~/Library/LaunchAgents/com.traul.daemon.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.traul.daemon</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/YOUR_USERNAME/.bun/bin/traul</string>
        <string>daemon</string>
        <string>start</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/Users/YOUR_USERNAME/.local/share/traul/daemon-launchd.log</string>
    <key>StandardErrorPath</key>
    <string>/Users/YOUR_USERNAME/.local/share/traul/daemon-launchd.log</string>
</dict>
</plist>
EOF

Replace YOUR_USERNAME with your macOS username, then load it:

launchctl load ~/Library/LaunchAgents/com.traul.daemon.plist

To disable auto-start:

launchctl unload ~/Library/LaunchAgents/com.traul.daemon.plist

6. Verify It Works

After your first sync, verify everything is working:

traul stats

This shows the number of messages synced per source.

Run a search to confirm:

traul search "hello" --fts

If you have Ollama running and have generated embeddings (traul embed), you can use hybrid search:

traul search "recent discussions about deployments"

Browse your synced channels:

traul channels
traul messages general --limit 20

7. Database Location

Traul stores everything in a single SQLite file:

~/.local/share/traul/traul.db

Override with TRAUL_DB_PATH:

export TRAUL_DB_PATH="~/my-data/traul.db"

8. Troubleshooting

"unable to load extension" or SQLite errors Homebrew SQLite is not installed. Run brew install sqlite and try again.

"connect ECONNREFUSED" on search Ollama is not running. Start it with ollama serve, or use --fts for keyword-only search.

Telegram "session expired" or auth errors Re-run python3 scripts/tg_sync.py setup to create a fresh session.

Slack "not_authed" or 403 Your token has expired. For xoxc tokens, re-extract the token and cookie from your browser — they rotate periodically.

"model not found" on embed/search Pull the model first: ollama pull snowflake-arctic-embed2. If you use a different model, set TRAUL_EMBED_MODEL.

No search results with hybrid mode Embeddings may not be generated yet. Run traul embed first, or use --fts for keyword search.

Daemon won't start or port conflict Check if another daemon is running: traul daemon status. The default port is 3847 — change it in config under daemon.port if needed.

WhatsApp QR code expired Run traul whatsapp auth <account> again — you have 2 minutes to scan before it expires.