- Replace python-dotenv with config.json env.vars block + \ substitution - Add models section for per-task model routing (heartbeat, subagent, default) - Heartbeat/subagent tasks can use different models/providers than main chat - Remove python-dotenv from dependencies - Update all docs to reflect new config approach - Reorganize docs into project/ and research/ subdirectories
Aetheel
A personal AI assistant that lives in your chat — with persistent memory, dual runtimes, auto-failover, and zero cloud dependencies.
Quick Start • Features • Commands • Architecture • Configuration • Docs
Quick Start
One-line install
# 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
The interactive installer handles everything:
- Checks prerequisites (Python 3.12+, uv)
- Installs dependencies
- Detects or installs AI runtimes (OpenCode / Claude Code)
- Walks you through token setup for Slack, Discord, Telegram
- Installs the
aetheelshell command - Sets up a background service (launchd on macOS, systemd on Linux)
After install
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
aetheel help # All options
Manual install
git clone http://10.0.0.59:3051/tanmay/Aetheel.git
cd Aetheel
uv sync # or: pip install -r requirements.txt
uv run python main.py # start (edit ~/.aetheel/config.json for tokens)
Everything is config-driven — no flags required. See Configuration.
Features
💬 Multi-Channel
| Channel | Connection | Auth | Setup |
|---|---|---|---|
| Slack | Socket Mode (no public URL) | Bot + App tokens | docs/project/slack-setup.md |
| Discord | Gateway (no public URL) | Bot token | docs/project/discord-setup.md |
| Telegram | Bot API polling | Bot token | @BotFather |
| WebChat | HTTP + WebSocket on localhost | None (localhost only) | Config: webchat.enabled: true |
| Webhooks | HTTP POST endpoints | Bearer token | Config: webhooks.enabled: true |
All adapters are config-driven. Set a token in config.json → env.vars and the adapter auto-enables — no flags needed.
🤖 Dual AI Runtimes with Live Switching
| Runtime | Engine | Providers | Session Continuity |
|---|---|---|---|
| OpenCode | opencode |
Anthropic, OpenAI, Google, any | --continue --session |
| Claude Code | claude |
Anthropic | --continue --session-id |
Switch engines, models, and providers live from chat — no restart needed:
engine claude
model claude-sonnet-4-20250514
engine opencode
model openai/gpt-4o
provider openai
🔄 Auto-Failover & Usage Tracking
When a rate limit or quota error is detected:
- You get notified in the channel
- Aetheel automatically switches to the other engine and retries
- If failover succeeds, the response is delivered seamlessly
Claude Code returns per-request cost (cost_usd), which is tracked and viewable via the usage command. Rate limit hits and failover counts are also tracked.
🧠 Persistent Memory System
- Identity files —
SOUL.md(personality),USER.md(user profile),MEMORY.md(long-term notes) - Hybrid search — 0.7 vector + 0.3 BM25 keyword scoring
- Local embeddings — fastembed (ONNX, BAAI/bge-small-en-v1.5, 384-dim), zero API calls
- SQLite storage — FTS5 full-text search + JSON vector embeddings
- Session logs — Conversations auto-saved to
daily/YYYY-MM-DD.md - File watching — Auto re-indexes when
.mdfiles change
⏰ Scheduler & Action Tags
The AI can trigger actions by including tags in its response:
| Tag | Effect |
|---|---|
[ACTION:remind|5|Drink water!] |
One-shot reminder in 5 minutes |
[ACTION:cron|0 9 * * *|Good morning!] |
Recurring cron job |
[ACTION:spawn|Research Python 3.14] |
Background subagent task |
Jobs are persisted in SQLite and survive restarts.
🔧 More
- Skills — Teach the AI domain-specific behavior via
SKILL.mdfiles - Hooks — Event-driven lifecycle hooks (startup, shutdown, commands)
- Heartbeat — Periodic proactive tasks via
HEARTBEAT.md - Subagents — Background AI tasks with results sent back to the channel
- MCP Servers — Extend the agent with external tool servers
- WebChat — Browser-based chat UI at
http://localhost:8080 - Webhooks — HTTP endpoints for external systems to trigger the agent
🔒 Local-First
- Embeddings run locally (no API calls for memory)
- All data stored in
~/.aetheel/— your data stays on your machine - Only the AI runtime makes external API calls
Chat Commands
Type these as regular messages in any channel or DM. No / prefix needed.
In Slack channels, Slack intercepts
/as native slash commands. Use the prefix-free form (e.g.engine claudenot/engine claude). In DMs and other adapters, both forms work.
General
| Command | Description |
|---|---|
status |
Bot status, engine, model, sessions |
help |
All available commands |
time |
Server time |
sessions |
Active session count |
reload |
Reload config and skills |
subagents |
List active background tasks |
Runtime (live, no restart)
| Command | Description |
|---|---|
engine |
Show current engine |
engine opencode |
Switch to OpenCode |
engine claude |
Switch to Claude Code |
model |
Show current model |
model <name> |
Switch model |
provider |
Show current provider (OpenCode only) |
provider <name> |
Switch provider |
usage |
LLM usage stats, costs, rate limits |
Config
| Command | Description |
|---|---|
config |
Config summary |
config show |
Full config.json |
config set <key> <value> |
Edit config (e.g. config set runtime.timeout_seconds 300) |
Scheduler
| Command | Description |
|---|---|
cron list |
List scheduled jobs |
cron remove <id> |
Remove a job |
See docs/project/commands.md for the full reference including terminal commands.
Architecture
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Slack │ │ Discord │ │ Telegram │ │ WebChat │
│ (Socket) │ │ (Gateway) │ │ (Polling) │ │ (WebSocket) │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │ │
└────────────────┴────────────────┴────────────────┘
│
┌───────────┴───────────┐
│ main.py │
│ (ai_handler) │
│ │
│ • Command routing │
│ • Action tag parsing │
│ • Usage tracking │
│ • Auto-failover │
└───┬──────────┬────────┘
│ │
┌─────────┴──┐ ┌───┴──────────┐
│ Memory │ │ AI Runtime │
│ Manager │ │ │
│ │ │ OpenCode ◄──►│ Auto-failover
│ • SOUL.md │ │ Claude ◄──►│
│ • search │ │ │
│ • logs │ │ subprocess │
└────────────┘ └──────────────┘
│
┌─────┴──────┐
│ Scheduler │ Skills, Hooks, Heartbeat,
│ Subagents │ Webhooks, MCP Servers
└────────────┘
Project Structure
aetheel/
├── main.py # Entry point, command routing, failover
├── config.py # Config loading (config.json with env.vars + ${VAR})
├── cli.py # Click CLI (aetheel command)
├── install.sh # Interactive installer + setup wizard
├── adapters/
│ ├── base.py # BaseAdapter + IncomingMessage
│ ├── slack_adapter.py # Slack Socket Mode
│ ├── discord_adapter.py # Discord Gateway
│ ├── telegram_adapter.py # Telegram Bot API
│ └── webchat_adapter.py # Browser WebSocket chat
├── agent/
│ ├── opencode_runtime.py # OpenCode CLI/SDK + rate limit detection
│ ├── claude_runtime.py # Claude Code CLI + usage extraction
│ └── subagent.py # Background subagent manager
├── memory/
│ ├── manager.py # Sync, search, identity files, session logs
│ ├── embeddings.py # Local embeddings (fastembed)
│ ├── hybrid.py # Hybrid search (vector + BM25)
│ ├── schema.py # SQLite schema
│ ├── internal.py # Hashing, chunking, file discovery
│ └── types.py # Config and result types
├── scheduler/
│ ├── scheduler.py # APScheduler with SQLite persistence
│ └── store.py # Job store
├── skills/ # Skill discovery and context injection
├── hooks/ # Lifecycle hook system
├── heartbeat/ # Periodic proactive tasks
├── webhooks/ # HTTP webhook receiver
├── static/
│ └── chat.html # WebChat browser UI
├── docs/
│ ├── project/ # Aetheel documentation
│ │ ├── commands.md # Full command reference
│ │ ├── setup.md # Detailed setup guide
│ │ ├── configuration.md # Config deep dive
│ │ ├── features-guide.md # Feature walkthrough
│ │ ├── memory-system.md # Memory architecture
│ │ ├── security-audit.md # Security audit findings
│ │ ├── slack-setup.md # Slack app creation guide
│ │ └── discord-setup.md # Discord bot setup guide
│ └── research/ # External project research & comparisons
├── tests/ # Test suite
├── .env.example # Legacy secrets template (migration notes)
└── pyproject.toml # Dependencies
Configuration
All settings and secrets live in ~/.aetheel/config.json. Secrets go in the env.vars block and are referenced via ${VAR} syntax.
The install script writes the config file during setup. You can also edit from chat using config set.
Config File
{
"env": {
"vars": {
"SLACK_BOT_TOKEN": "xoxb-...",
"SLACK_APP_TOKEN": "xapp-...",
"DISCORD_BOT_TOKEN": "",
"TELEGRAM_BOT_TOKEN": "",
"ANTHROPIC_API_KEY": ""
}
},
"runtime": {
"engine": "opencode", // "opencode" or "claude"
"mode": "cli", // "cli" or "sdk"
"model": null, // e.g. "anthropic/claude-sonnet-4-20250514"
"provider": null, // e.g. "anthropic", "openai", "google"
"timeout_seconds": 120
},
"claude": {
"model": null, // e.g. "claude-sonnet-4-20250514"
"max_turns": 3,
"no_tools": false
},
"slack": { "enabled": true, "bot_token": "${SLACK_BOT_TOKEN}", "app_token": "${SLACK_APP_TOKEN}" },
"telegram": { "enabled": false, "bot_token": "${TELEGRAM_BOT_TOKEN}" },
"discord": { "enabled": false, "bot_token": "${DISCORD_BOT_TOKEN}", "listen_channels": [] },
"webchat": { "enabled": false, "port": 8080, "host": "127.0.0.1" },
"webhooks": { "enabled": false, "port": 8090, "token": "" },
"memory": { "workspace": "~/.aetheel/workspace", "db_path": "~/.aetheel/memory.db" },
"heartbeat": { "enabled": true, "default_channel": "slack" },
"models": { "heartbeat": null, "subagent": null, "default": null },
"hooks": { "enabled": true },
"mcp": { "servers": {} }
}
Adapters auto-enable when their token is set in env.vars, even without enabled: true.
Environment Variable Overrides
Process env vars override everything. Useful for CI, Docker, or systemd:
| Variable | Overrides |
|---|---|
AETHEEL_ENGINE |
runtime.engine |
OPENCODE_MODE |
runtime.mode |
OPENCODE_MODEL |
runtime.model |
OPENCODE_PROVIDER |
runtime.provider |
CLAUDE_MODEL |
claude.model |
CLAUDE_TIMEOUT |
claude.timeout_seconds |
CLAUDE_MAX_TURNS |
claude.max_turns |
LOG_LEVEL |
log_level |
Memory Files
Auto-created in ~/.aetheel/workspace/ (or personalized during setup):
| File | Purpose |
|---|---|
SOUL.md |
Personality, values, communication style |
USER.md |
User preferences, context, background |
MEMORY.md |
Long-term notes, facts, things to remember |
All agents share the same identity files — the main agent and any background subagents it spawns all read from the same SOUL.md, USER.md, and MEMORY.md. This is by design: subagents are workers for the same assistant, not separate personalities.
The installer lets you choose a personality preset (default, professional, casual, or custom) and fills in USER.md with your name, role, timezone, and preferences interactively.
Edit these files directly anytime — changes are picked up automatically via file watching.
Session logs: ~/.aetheel/workspace/daily/YYYY-MM-DD.md
Prerequisites
- Python 3.12+ (managed via uv)
- At least one chat platform token (Slack, Discord, Telegram, or WebChat)
- At least one AI runtime:
- OpenCode —
curl -fsSL https://opencode.ai/install | bash - Claude Code —
npm install -g @anthropic-ai/claude-code
- OpenCode —
The installer handles all of this interactively.
Development
# Run full test suite
uv run python test_all.py
# Run pytest
uv run python -m pytest tests/ -v
# Diagnostics
uv run python cli.py doctor
Docs
| Document | Description |
|---|---|
| commands.md | Full command reference (chat + terminal) |
| setup.md | Detailed setup guide |
| configuration.md | Config deep dive |
| security-audit.md | Security audit findings |
| memory-system.md | Memory architecture |
| features-guide.md | Feature walkthrough |
| slack-setup.md | Slack app creation |
| discord-setup.md | Discord bot setup |
Inspired By
Built with inspiration from OpenClaw — a TypeScript AI agent framework. Aetheel reimplements the core concepts (memory, hybrid search, session management) in Python with a local-first philosophy.
Made with ❤️ and a lot of Claude
