Files
Aetheel/docs/setup.md

16 KiB

Aetheel Server Setup Guide

Step-by-step guide to deploy Aetheel on a Linux or macOS machine.


The interactive installer handles everything automatically:

# If repo is public:
curl -fsSL http://10.0.0.59:3051/tanmay/Aetheel/raw/branch/main/install.sh | bash

# If repo is private (clone first):
git clone http://10.0.0.59:3051/tanmay/Aetheel.git && cd Aetheel && bash install.sh

Or if you already have the repo cloned:

./install.sh

The installer will:

  • Check prerequisites (Python 3.12+, uv)
  • Install dependencies
  • Detect or install AI runtimes (OpenCode / Claude Code)
  • Walk you through token configuration
  • Install the aetheel command
  • Optionally set up a background service (launchd/systemd)

After install, use the aetheel command:

aetheel start      # Start the bot
aetheel stop       # Stop the background service
aetheel restart    # Restart the service
aetheel status     # Check status
aetheel logs       # Tail live logs
aetheel setup      # Re-run setup wizard
aetheel update     # Pull latest + update deps
aetheel doctor     # Run diagnostics
aetheel config     # Edit config.json

For flags and options: aetheel help


Manual Setup

If you prefer to set things up manually, follow the steps below.


Table of Contents

  1. Prerequisites
  2. Install System Dependencies
  3. Install uv (Python Package Manager)
  4. Install an AI Runtime
  5. Clone the Repository
  6. Install Python Dependencies
  7. Configure Secrets (.env)
  8. Configure Settings (config.json)
  9. Set Up Messaging Channels
  10. Run the Test Suite
  11. Start Aetheel
  12. Run as a systemd Service
  13. Verify Everything Works
  14. Optional: Enable WebChat
  15. Optional: Enable Webhooks
  16. Optional: Configure Hooks
  17. Optional: Configure Heartbeat
  18. Optional: Add MCP Servers
  19. Optional: Create Skills
  20. Updating
  21. Troubleshooting

1. Prerequisites

Requirement Minimum Recommended
OS Ubuntu 20.04 / Debian 11 Ubuntu 22.04+ / Debian 12+
Python 3.12 3.13
RAM 512 MB 1 GB+ (fastembed uses ~300 MB for embeddings)
Disk 500 MB 1 GB+
Network Outbound HTTPS Outbound HTTPS

You also need at least one of:

  • Slack workspace with admin access (for Slack adapter)
  • Telegram bot token (for Telegram adapter)
  • Discord bot token (for Discord adapter)
  • Nothing (for WebChat-only mode)

And at least one AI runtime:


2. Install System Dependencies

# Update packages
sudo apt update && sudo apt upgrade -y

# Install essentials
sudo apt install -y git curl build-essential

# Verify
git --version
curl --version

3. Install uv

uv is the recommended Python package manager. It handles Python versions, virtual environments, and dependencies.

# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh

# Add to PATH (restart shell or source profile)
source ~/.bashrc  # or ~/.zshrc

# Verify
uv --version

uv will automatically install the correct Python version (3.13) when you run uv sync.


4. Install an AI Runtime

You need at least one AI runtime. Pick one (or both):

curl -fsSL https://opencode.ai/install | bash

# Verify
opencode --version

# Configure a provider
opencode auth login

Option B: Claude Code

# Requires Node.js
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

# Install Claude Code
npm install -g @anthropic-ai/claude-code

# Verify
claude --version

Set your API key

Whichever runtime you use, you need an API key for the LLM provider:

# For Anthropic (used by both OpenCode and Claude Code)
export ANTHROPIC_API_KEY="sk-ant-..."

# For OpenAI
export OPENAI_API_KEY="sk-..."

Add these to your .env file later (step 7).


5. Clone the Repository

# Clone
cd ~
git clone http://10.0.0.59:3051/tanmay/Aetheel.git
cd Aetheel

# Verify
ls pyproject.toml  # Should exist

6. Install Python Dependencies

# Install project + test dependencies
uv sync --extra test

# Verify Python version
uv run python --version  # Should be 3.13.x

# Verify key packages
uv run python -c "import click; import aiohttp; import apscheduler; print('All packages OK')"

7. Configure Secrets

Secrets (tokens, API keys) go in the .env file. This file is gitignored.

# Create from template
cp .env.example .env

# Edit with your tokens
nano .env

Fill in the tokens you need:

# Required for Slack
SLACK_BOT_TOKEN=xoxb-your-bot-token
SLACK_APP_TOKEN=xapp-your-app-token

# Required for Telegram (if using --telegram)
TELEGRAM_BOT_TOKEN=your-telegram-token

# Required for Discord (if using --discord)
DISCORD_BOT_TOKEN=your-discord-token

# AI provider API key
ANTHROPIC_API_KEY=sk-ant-your-key

# Optional overrides
# OPENCODE_MODEL=anthropic/claude-sonnet-4-20250514
# LOG_LEVEL=DEBUG

See docs/slack-setup.md and docs/discord-setup.md for how to get these tokens.


8. Configure Settings

Non-secret settings go in ~/.aetheel/config.json. A default is created on first run, but you can create it now:

# Create the config directory
mkdir -p ~/.aetheel/workspace

# Generate default config
uv run python -c "from config import save_default_config; save_default_config()"

# View it
cat ~/.aetheel/config.json

Edit if needed:

nano ~/.aetheel/config.json

Key settings to review:

{
  "runtime": {
    "mode": "cli",
    "model": null
  },
  "claude": {
    "no_tools": false,
    "allowed_tools": ["Bash", "Read", "Write", "..."]
  },
  "heartbeat": {
    "enabled": true,
    "default_channel": "slack",
    "default_channel_id": ""
  },
  "webchat": {
    "enabled": false,
    "port": 8080
  },
  "webhooks": {
    "enabled": false,
    "port": 8090,
    "token": ""
  }
}

9. Set Up Messaging Channels

Slack (see docs/slack-setup.md)

  1. Create a Slack app at https://api.slack.com/apps
  2. Add bot scopes: app_mentions:read, chat:write, im:history, im:read, im:write, channels:history, users:read
  3. Enable Socket Mode, generate an app-level token (xapp-...)
  4. Install to workspace, copy bot token (xoxb-...)
  5. Invite bot to channels: /invite @Aetheel

Discord (see docs/discord-setup.md)

  1. Create app at https://discord.com/developers/applications
  2. Create bot, copy token
  3. Enable Message Content Intent
  4. Invite with bot scope + Send Messages + Read Message History

Telegram

  1. Message @BotFather on Telegram
  2. /newbot → follow prompts → copy token
  3. Set TELEGRAM_BOT_TOKEN in .env

10. Run the Test Suite

Before starting, verify everything works:

cd ~/Aetheel

# Run the full test + smoke check script
uv run python test_all.py

You should see all checks pass:

━━━ RESULTS ━━━
Total: 45 checks
  Passed:  45
  Failed:  0
  Skipped: 0
All checks passed! 🎉

If anything fails, fix it before proceeding. Common issues:

  • Missing packages → uv sync --extra test
  • Wrong directory → cd ~/Aetheel

You can also run just the pytest suite:

uv run python -m pytest tests/ -v --ignore=tests/test_scheduler.py

11. Start Aetheel

Basic start (Slack only)

uv run python main.py

With additional adapters

# Slack + Discord
uv run python main.py --discord

# Slack + Telegram
uv run python main.py --telegram

# Slack + Discord + WebChat
uv run python main.py --discord --webchat

# All adapters
uv run python main.py --discord --telegram --webchat

With Claude Code runtime

uv run python main.py --claude

Test mode (no AI, echo handler)

uv run python main.py --test

Using the CLI

# Same as above but via the click CLI
uv run python cli.py start --discord --webchat

# One-shot chat (no adapters needed)
uv run python cli.py chat "What is Python?"

# Diagnostics
uv run python cli.py doctor

12. Run as a systemd Service

To keep Aetheel running after you disconnect from SSH:

Create the service file

sudo nano /etc/systemd/system/aetheel.service

Paste (adjust paths to match your setup):

[Unit]
Description=Aetheel AI Assistant
After=network.target

[Service]
Type=simple
User=your-username
WorkingDirectory=/home/your-username/Aetheel
ExecStart=/home/your-username/.local/bin/uv run python main.py
Restart=on-failure
RestartSec=10
Environment=PATH=/home/your-username/.local/bin:/usr/local/bin:/usr/bin:/bin

# Load .env file
EnvironmentFile=/home/your-username/Aetheel/.env

# Optional: add more adapters
# ExecStart=/home/your-username/.local/bin/uv run python main.py --discord --webchat

[Install]
WantedBy=multi-user.target

Enable and start

# Reload systemd
sudo systemctl daemon-reload

# Enable on boot
sudo systemctl enable aetheel

# Start now
sudo systemctl start aetheel

# Check status
sudo systemctl status aetheel

# View logs
sudo journalctl -u aetheel -f

Manage the service

sudo systemctl stop aetheel      # Stop
sudo systemctl restart aetheel   # Restart
sudo systemctl disable aetheel   # Disable on boot

13. Verify Everything Works

Check the startup log

sudo journalctl -u aetheel --no-pager | tail -20

You should see:

============================================================
  Aetheel Starting
============================================================
  Config:     /home/user/.aetheel/config.json
  Runtime:    opencode/cli, model=default
  Channels:   slack
  Skills:     0
  Scheduler:  ✅
  Heartbeat:  ✅ 3 tasks
  Subagents:  ✅
  Hooks:      ✅ 0 hooks
  Webhooks:   ❌
============================================================

Test from Slack/Discord/Telegram

  1. Send status → should show runtime info
  2. Send help → should show command list
  3. Send any question → should get an AI response
  4. Send /reload → should confirm reload

Test from CLI

uv run python cli.py doctor
uv run python cli.py status

14. Optional: Enable WebChat

Browser-based chat at http://your-server:8080.

Via config

Edit ~/.aetheel/config.json:

{
  "webchat": {
    "enabled": true,
    "port": 8080,
    "host": "0.0.0.0"
  }
}

Set host to 0.0.0.0 to accept connections from other machines (not just localhost).

Via CLI flag

uv run python main.py --webchat

Firewall

If using ufw:

sudo ufw allow 8080/tcp

Then open http://your-server-ip:8080 in a browser.


15. Optional: Enable Webhooks

HTTP endpoints for external systems to trigger the agent.

Configure

Edit ~/.aetheel/config.json:

{
  "webhooks": {
    "enabled": true,
    "port": 8090,
    "host": "0.0.0.0",
    "token": "your-secret-webhook-token"
  }
}

Generate a random token:

python3 -c "import secrets; print(secrets.token_urlsafe(32))"

Firewall

sudo ufw allow 8090/tcp

Test

# Health check (no auth)
curl http://localhost:8090/hooks/health

# Wake the agent
curl -X POST http://localhost:8090/hooks/wake \
  -H "Authorization: Bearer your-secret-webhook-token" \
  -H "Content-Type: application/json" \
  -d '{"text": "What time is it?"}'

# Send to a specific channel
curl -X POST http://localhost:8090/hooks/agent \
  -H "Authorization: Bearer your-secret-webhook-token" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "New alert from monitoring",
    "channel": "slack",
    "channel_id": "C123456"
  }'

16. Optional: Configure Hooks

Lifecycle hooks run custom code on gateway events.

Create a hook

mkdir -p ~/.aetheel/workspace/hooks/startup-logger

Create ~/.aetheel/workspace/hooks/startup-logger/HOOK.md:

---
name: startup-logger
description: Log when the gateway starts
events: [gateway:startup]
enabled: true
---
# Startup Logger
Logs a message when Aetheel starts.

Create ~/.aetheel/workspace/hooks/startup-logger/handler.py:

import logging

logger = logging.getLogger("aetheel.hooks.startup-logger")

def handle(event):
    logger.info("Gateway started — startup hook fired!")

Hooks are discovered automatically on startup.


17. Optional: Configure Heartbeat

The heartbeat system runs periodic tasks automatically.

Edit HEARTBEAT.md

nano ~/.aetheel/workspace/HEARTBEAT.md

Example:

# Heartbeat Tasks

## Every 30 minutes
- Check if any scheduled reminders need attention

## Every morning (9:00 AM)
- Summarize yesterday's conversations
- Check for any pending follow-ups

## Every evening (6:00 PM)
- Update MEMORY.md with today's key learnings

Configure where heartbeat responses go

Edit ~/.aetheel/config.json:

{
  "heartbeat": {
    "enabled": true,
    "default_channel": "slack",
    "default_channel_id": "C123456"
  }
}

Set default_channel_id to the Slack channel ID where heartbeat responses should be sent.


18. Optional: Add MCP Servers

External tool servers that extend the agent's capabilities.

Edit ~/.aetheel/config.json:

{
  "mcp": {
    "servers": {
      "brave-search": {
        "command": "uvx",
        "args": ["brave-search-mcp@latest"],
        "env": {
          "BRAVE_API_KEY": "your-key"
        }
      }
    }
  }
}

Aetheel writes the appropriate config file (.mcp.json or opencode.json) to the workspace before launching the runtime.


19. Optional: Create Skills

Skills teach the agent how to handle specific types of requests.

mkdir -p ~/.aetheel/workspace/skills/weather

Create ~/.aetheel/workspace/skills/weather/SKILL.md:

---
name: weather
description: Check weather for any city
triggers: [weather, forecast, temperature, rain]
---

# Weather Skill

When the user asks about weather:
1. Use web search to find current conditions
2. Include temperature, conditions, and forecast
3. Format the response with emoji

Skills are loaded at startup and can be reloaded with /reload.


20. Updating

cd ~/Aetheel

# Pull latest
git pull

# Update dependencies
uv sync --extra test

# Run tests
uv run python test_all.py

# Restart service
sudo systemctl restart aetheel

21. Troubleshooting

"No channel adapters initialized!"

No messaging tokens are set. Check your .env file has at least one of:

  • SLACK_BOT_TOKEN + SLACK_APP_TOKEN
  • TELEGRAM_BOT_TOKEN (with --telegram flag)
  • DISCORD_BOT_TOKEN (with --discord flag)
  • --webchat flag (no tokens needed)

"AI runtime not initialized"

The AI CLI (opencode or claude) isn't installed or isn't in PATH.

# Check
which opencode
which claude

# Install OpenCode
curl -fsSL https://opencode.ai/install | bash

"Request timed out"

The AI took too long. Increase timeout in config:

{
  "runtime": { "timeout_seconds": 300 },
  "claude": { "timeout_seconds": 300 }
}

Memory system init failed

Usually means fastembed can't download the embedding model on first run. Check internet access and disk space.

# Test manually
uv run python -c "from fastembed import TextEmbedding; e = TextEmbedding(); print('OK')"

Port already in use (WebChat/Webhooks)

Another process is using the port. Change it in config or find the process:

sudo lsof -i :8080  # Find what's using port 8080

systemd service won't start

Check logs:

sudo journalctl -u aetheel -n 50 --no-pager

Common issues:

  • Wrong WorkingDirectory path
  • Wrong User
  • .env file not found (check EnvironmentFile path)
  • uv not in PATH (check Environment=PATH=...)

Run diagnostics

uv run python cli.py doctor

This checks config validity, workspace, runtime CLIs, tokens, and memory DB.