tanmay11k f7ccc153b4 feat: openclaw-style secrets (env.vars + \) and per-task model routing
- 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
2026-02-21 00:40:29 -05:00
2026-02-13 23:56:09 -05:00
2026-02-15 15:02:58 -05:00

Aetheel Logo

Aetheel

A personal AI assistant that lives in your chat — with persistent memory, dual runtimes, auto-failover, and zero cloud dependencies.

Quick StartFeaturesCommandsArchitectureConfigurationDocs


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 aetheel shell 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.jsonenv.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:

  1. You get notified in the channel
  2. Aetheel automatically switches to the other engine and retries
  3. 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 filesSOUL.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 .md files 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.md files
  • 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 claude not /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:
    • OpenCodecurl -fsSL https://opencode.ai/install | bash
    • Claude Codenpm install -g @anthropic-ai/claude-code

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

Description
No description provided
Readme 880 KiB
Languages
Python 85.3%
Shell 13.1%
HTML 1.6%