> ## Documentation Index
> Fetch the complete documentation index at: https://anniemei.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Development Setup

> Get Annie Mei running locally for development

This guide walks you through setting up Annie Mei for local development.

<Note>
  This page focuses on the main bot service. If you want to test `/register` end to end, also set up the [Auth service](/self-hosting/auth-service).
</Note>

## Prerequisites

Ensure you have the following installed:

* **Rust 1.95 or later** - [Install via rustup](https://rustup.rs/)
* **PostgreSQL** - For database storage
* **Redis** - For caching API responses
* **SQLx CLI** (optional) - For auth service schema work

### Install SQLx CLI

```bash theme={}
cargo install sqlx-cli --no-default-features --features postgres
```

## Clone the Repository

<Steps>
  <Step title="Clone from GitHub">
    ```bash theme={}
    git clone https://github.com/annie-mei/annie-mei.git
    cd annie-mei
    ```
  </Step>

  <Step title="Install Dependencies">
    Rust dependencies are managed via `Cargo.toml`. Download and compile all dependencies:

    ```bash theme={}
    cargo build
    ```

    This will take a few minutes on first run as it compiles all dependencies.
  </Step>
</Steps>

## Configuration

### Environment Variables

Create a `.env` file in the project root with the following variables:

```bash theme={}
# Discord Bot Configuration
DISCORD_TOKEN=your_discord_bot_token

# Database
DATABASE_URL=postgresql://username:password@localhost/annie_mei

# Cache
REDIS_URL=redis://127.0.0.1:6379

# Error Tracking
SENTRY_DSN=your_sentry_dsn
SENTRY_TRACES_SAMPLE_RATE=0.1
ENV=development

# External APIs
SPOTIFY_CLIENT_ID=your_spotify_client_id
SPOTIFY_CLIENT_SECRET=your_spotify_client_secret
MAL_CLIENT_ID=your_mal_client_id

# Privacy
USERID_HASH_SALT=generate_a_random_secret_value

# OAuth linking
AUTH_SERVICE_BASE_URL=https://auth.your-domain.com
OAUTH_CONTEXT_SIGNING_SECRET=generate_a_random_secret_value
OAUTH_CONTEXT_TTL_SECONDS=300

# LLM (optional — enables /search natural-language queries)
# GEMINI_API_KEY=
# LLM_MODEL=gemini-3.1-flash-lite
# LLM_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai
```

<AccordionGroup>
  <Accordion title="Get a Discord Bot Token">
    1. Go to [Discord Developer Portal](https://discord.com/developers/applications)
    2. Create a new application
    3. Navigate to **Bot** section
    4. Click **Reset Token** and copy the token
    5. Copy the token into `DISCORD_TOKEN`
  </Accordion>

  <Accordion title="Get Spotify API Credentials">
    1. Go to [Spotify Developer Dashboard](https://developer.spotify.com/dashboard)
    2. Create a new app
    3. Copy the **Client ID** and **Client Secret**
  </Accordion>

  <Accordion title="Set up Sentry DSN">
    The current app startup expects `SENTRY_DSN` to be set. For local development, you can use a dummy DSN:

    ```bash theme={}
    SENTRY_DSN=https://example@sentry.io/123456
    ```

    For production, sign up at [sentry.io](https://sentry.io) and create a Rust project.
  </Accordion>

  <Accordion title="Set up AniList OAuth linking">
    1. Set up the [Auth service](/self-hosting/auth-service)
    2. Use the same value for `OAUTH_CONTEXT_SIGNING_SECRET` in both services
    3. Set `AUTH_SERVICE_BASE_URL` to the auth service origin, for example `https://auth.example.com`
    4. Start the bot after both services are configured and reachable
  </Accordion>
</AccordionGroup>

### Database Setup

<Steps>
  <Step title="Create PostgreSQL Database">
    ```bash theme={}
    createdb annie_mei
    ```

    Or using psql:

    ```sql theme={}
    CREATE DATABASE annie_mei;
    ```
  </Step>

  <Step title="Run Migrations">
    The bot runs its own SQLx migrations at startup for settings tables. If you are testing `/register`, run the auth service once to apply its OAuth SQLx migrations to the shared database.

    ```bash theme={}
    cd ../auth
    cargo run
    ```

    This step is optional for a bot-only local run. See the [Database](/development/database) guide for more details.
  </Step>

  <Step title="Verify Schema">
    Check that the expected tables exist:

    ```bash theme={}
    psql $DATABASE_URL -c "\dt"
    ```
  </Step>
</Steps>

### Redis Setup

Start a local Redis instance:

```bash theme={}
# Using Homebrew (macOS)
brew services start redis

# Using Docker
docker run -d -p 6379:6379 redis:latest

# Using apt (Ubuntu/Debian)
sudo systemctl start redis-server
```

Verify Redis is running:

```bash theme={}
redis-cli ping
# Should return: PONG
```

## Running Locally

### Development Mode

The repo includes a [`bacon.toml`](https://dystroy.org/bacon/) configuration. Install bacon once:

```bash theme={}
cargo install bacon
```

Then run the bot with auto-restart on code changes:

```bash theme={}
bacon
```

This runs the `dev` job by default, which executes `cargo run` and restarts the bot whenever a source file changes. Other useful jobs:

| Key | Job          | What it does                       |
| --- | ------------ | ---------------------------------- |
| `c` | `clippy-all` | Run Clippy on all targets          |
| `d` | `dev`        | Run and restart the bot on changes |
| `r` | `run-long`   | Same as dev, explicit alias        |
| `p` | `pedantic`   | Run Clippy in pedantic mode        |

You can also run a specific job directly:

```bash theme={}
bacon clippy-all
bacon test
bacon nextest   # requires cargo-nextest
```

To run the bot without bacon:

```bash theme={}
cargo run
```

To enable detailed tracing:

```bash theme={}
RUST_LOG=debug cargo run
```

Filter logs to specific modules:

```bash theme={}
RUST_LOG=annie_mei=debug,serenity=warn cargo run
```

### Fast Type Checking

For quick feedback without running the bot:

```bash theme={}
cargo check
```

This is much faster than `cargo build` and catches most errors.

### Production Build

Compile an optimized release binary:

```bash theme={}
cargo build --release
```

The binary will be at `target/release/annie-mei`.

## Invite Bot to Test Server

Generate an OAuth2 invite link:

1. Go to your app in [Discord Developer Portal](https://discord.com/developers/applications)
2. Navigate to **OAuth2** → **URL Generator**
3. Select scopes:
   * `bot`
   * `applications.commands`
4. Select bot permissions:
   * Send Messages
   * Embed Links
   * Read Message History
5. Copy the generated URL and open it in your browser
6. Select your test server and authorize

## Verify Installation

Once the bot is running and invited:

1. Open Discord
2. Type `/ping` in a channel
3. The bot should respond with a greeting

If you see the response, your development environment is ready!

## Troubleshooting

<AccordionGroup>
  <Accordion title="Bot doesn't show online">
    * Check that `DISCORD_TOKEN` is correct
    * Check logs for connection errors: `RUST_LOG=serenity=debug cargo run`
  </Accordion>

  <Accordion title="Slash commands not appearing">
    * Commands are registered globally and can take up to 1 hour to propagate
    * For faster development, use guild-specific commands (requires code changes)
    * Check logs for command registration errors
  </Accordion>

  <Accordion title="Database connection errors">
    * Verify PostgreSQL is running: `pg_isready`
    * Check `DATABASE_URL` format: `postgresql://user:password@host/database`
    * Ensure the database exists: `psql -l | grep annie_mei`
  </Accordion>

  <Accordion title="Redis connection errors">
    * Verify Redis is running: `redis-cli ping`
    * Check `REDIS_URL` format: `redis://127.0.0.1:6379`
    * For password-protected Redis: `redis://:password@host:port`
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Architecture" icon="sitemap" href="/development/architecture">
    Understand the project structure and technology stack
  </Card>

  <Card title="Adding Commands" icon="code" href="/development/adding-commands">
    Create your first slash command
  </Card>

  <Card title="Database" icon="database" href="/development/database">
    Learn database migration workflows
  </Card>

  <Card title="Testing" icon="flask" href="/development/testing">
    Run tests and ensure code quality
  </Card>
</CardGroup>
