16 KiB
Aetheel Server Setup Guide
Step-by-step guide to deploy Aetheel on a Linux or macOS machine.
Quick Start (Recommended)
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
aetheelcommand - 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
- Prerequisites
- Install System Dependencies
- Install uv (Python Package Manager)
- Install an AI Runtime
- Clone the Repository
- Install Python Dependencies
- Configure Secrets (.env)
- Configure Settings (config.json)
- Set Up Messaging Channels
- Run the Test Suite
- Start Aetheel
- Run as a systemd Service
- Verify Everything Works
- Optional: Enable WebChat
- Optional: Enable Webhooks
- Optional: Configure Hooks
- Optional: Configure Heartbeat
- Optional: Add MCP Servers
- Optional: Create Skills
- Updating
- 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:
- OpenCode CLI
- Claude Code CLI
- An API key for the LLM provider (Anthropic, OpenAI, etc.)
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):
Option A: OpenCode (recommended)
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)
- Create a Slack app at https://api.slack.com/apps
- Add bot scopes:
app_mentions:read,chat:write,im:history,im:read,im:write,channels:history,users:read - Enable Socket Mode, generate an app-level token (
xapp-...) - Install to workspace, copy bot token (
xoxb-...) - Invite bot to channels:
/invite @Aetheel
Discord (see docs/discord-setup.md)
- Create app at https://discord.com/developers/applications
- Create bot, copy token
- Enable Message Content Intent
- Invite with
botscope + Send Messages + Read Message History
Telegram
- Message @BotFather on Telegram
/newbot→ follow prompts → copy token- Set
TELEGRAM_BOT_TOKENin.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
- Send
status→ should show runtime info - Send
help→ should show command list - Send any question → should get an AI response
- 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_TOKENTELEGRAM_BOT_TOKEN(with--telegramflag)DISCORD_BOT_TOKEN(with--discordflag)--webchatflag (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
WorkingDirectorypath - Wrong
User .envfile not found (checkEnvironmentFilepath)- 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.