My agentic slop goes here. Not intended for anyone else!
README.md

Vicuna Bot#

A Zulip bot for user registration and management. Vicuna helps users register their email addresses and Zulip IDs, creating a persistent directory for easy @mentions and user tracking.

Features#

  • User Registration: Users can register themselves by sending a simple command
  • Custom Email Support: Register with your actual email address (not just the auto-generated Zulip email)
  • Persistent Storage: All registrations are stored on the server using Zulip's bot storage API
  • Bidirectional Lookup: Look up users by email address or Zulip ID
  • Message-based Configuration: All configuration happens via messages to the bot
  • User Directory: List all registered users

OAuth/SSO Email Issue & Solution#

Problem: Many Zulip instances that use OAuth, SSO, or other authentication methods assign auto-generated emails to users like user123@zulipchat.com instead of their actual email addresses.

Smart Solution: Vicuna automatically tries to find your real email address!

When you type register, the bot uses this priority:

  1. Custom email you provide: register alice@company.com (highest priority)
  2. delivery_email from your Zulip profile (the real email associated with your account)
  3. user.email from your Zulip profile API (may differ from message sender email)
  4. Zulip message email as a last resort (the internal user@zulipchat.com style)

This means most users can just type register and the bot will automatically use their real email address!

Manual Email Registration#

If needed, you can still manually specify your email:

register your-actual-email@example.com

The bot will:

  • Store your actual email for lookups
  • Still track your Zulip ID for @mentions
  • Show you both your registered email and your Zulip-internal email

This way, colleagues can find you by your real email address while the bot maintains the proper Zulip ID mapping.

Installation#

# Build the bot
cd vicuna
dune build

# Install (optional)
dune install

Configuration#

Create a ~/.zuliprc file with your bot credentials:

[api]
email=vicuna-bot@your-domain.zulipchat.com
key=your-bot-api-key
site=https://your-domain.zulipchat.com

Usage#

Running the Bot#

# Run with default configuration
vicuna

# Run with verbose logging
vicuna -v

# Run with debug logging
vicuna -vv

# Run with custom config file
vicuna -c /path/to/.zuliprc

Bot Commands#

Send these commands to the bot via direct message or by mentioning it in a channel:

register or register <your-email@example.com>#

Register your email and Zulip ID in the system.

Smart auto-detection (recommended - just type register):

> register
✅ Successfully registered!
• Email: `alice@mycompany.com`
• Zulip ID: `12345`
• Full Name: `Alice Smith`

💡 Your Zulip email is: `user123@zulipchat.com`
📧 Using your delivery email from your profile
You can now be @mentioned by your email or Zulip ID!

The bot automatically fetched alice@mycompany.com from your Zulip profile's delivery_email field!

Manual registration (if you want to override):

> register alice@different-email.com
✅ Successfully registered!
• Email: `alice@different-email.com`
• Zulip ID: `12345`
• Full Name: `Alice Smith`

💡 Your Zulip email is: `user123@zulipchat.com`
📝 Using the custom email you provided
You can now be @mentioned by your email or Zulip ID!

Note: The bot tries four sources in order:

  1. Custom email you provide (highest priority)
  2. delivery_email from your Zulip profile (auto-detected)
  3. user.email from your Zulip profile API (may be real email depending on permissions)
  4. Zulip message sender email (fallback)

whoami#

Check your registration status.

> whoami
📋 Your registration info:
• Email: `alice@example.com`
• Zulip ID: `12345`
• Full Name: `Alice Smith`
• Registered: 2025-01-15 10:30:45

whois <email|id>#

Look up a registered user by their email or Zulip ID.

> whois bob@example.com
👤 User found:
• Email: `bob@example.com`
• Zulip ID: `67890`
• Full Name: `Bob Jones`
• Registered: 2025-01-14 09:15:22

> whois 67890
👤 User found:
• Email: `bob@example.com`
• Zulip ID: `67890`
• Full Name: `Bob Jones`
• Registered: 2025-01-14 09:15:22

list#

List all registered users.

> list
📋 Registered users (3):
• **Alice Smith** (`alice@example.com`) - ID: 12345
• **Bob Jones** (`bob@example.com`) - ID: 67890
• **Carol White** (`carol@example.com`) - ID: 54321

help#

Show available commands and usage information.

> help
👋 Hi Alice! I'm **Vicuna**, your user registration assistant.

Available Commands:
• `register` - Register with your Zulip email
• `register <your-email@example.com>` - Register with a custom email
• `whoami` - Show your registration status
• `whois <email|id>` - Look up a registered user
• `list` - List all registered users
• `help` - Show this help message

Examples:
• `register` - Register with Zulip email (`user123@zulipchat.com`)
• `register alice@mycompany.com` - Register with your actual email
• `whois alice@example.com` - Look up Alice by email
• `whois 12345` - Look up user by Zulip ID

Note: Many Zulip instances use auto-generated emails like `user@zulipchat.com`.
You can provide your actual email address during registration!

Send me a direct message to get started!

Architecture#

Libraries Used#

  • zulip: OCaml bindings for the Zulip REST API
  • zulip_bot: Bot framework for building interactive Zulip bots
  • eio: Effects-based I/O for async operations
  • logs: Structured logging
  • cmdliner: Command-line interface

Storage#

Vicuna uses Zulip's bot storage API to persist user registrations. The storage format is:

  • User by email: user:email:<email><email>|<zulip_id>|<full_name>|<timestamp>
  • User by ID: user:id:<zulip_id><email>|<zulip_id>|<full_name>|<timestamp>
  • User list: users:all<email1>,<email2>,<email3>,...

This allows for efficient bidirectional lookups and maintains a master list of all registered users.

Development#

Project Structure#

vicuna/
├── dune-project          # Project definition
├── README.md             # This file
├── lib/                  # Bot library
│   ├── dune              # Library build config
│   ├── vicuna_bot.ml     # Bot implementation
│   └── vicuna_bot.mli    # Bot interface
└── bin/                  # Executable
    ├── dune              # Executable build config
    └── main.ml           # Main entry point

Building#

# Build the project
dune build

# Build with verbose output
dune build --verbose

# Clean build artifacts
dune clean

Testing#

You can test the bot by running it and sending messages to it in your Zulip instance:

  1. Create a bot account in your Zulip instance
  2. Download the bot's .zuliprc file
  3. Run vicuna -c path/to/.zuliprc -vv
  4. Send a direct message to the bot with help

License#

This project is part of the knot/slop/stack collection.

Dependencies#

  • OCaml 4.08+
  • Dune 3.0+
  • eio
  • zulip (from ../zulip)
  • zulip_bot (from ../zulip)
  • logs
  • cmdliner
  • mirage-crypto-rng-unix