250 lines
8.4 KiB
Markdown
250 lines
8.4 KiB
Markdown
<p align="center">
|
|
<h1 align="center">⚔️ Aetheel</h1>
|
|
<p align="center">
|
|
<strong>A personal AI assistant that lives in Slack — with persistent memory, dual runtimes, and zero cloud dependencies.</strong>
|
|
</p>
|
|
<p align="center">
|
|
<a href="#quick-start">Quick Start</a> •
|
|
<a href="#features">Features</a> •
|
|
<a href="#architecture">Architecture</a> •
|
|
<a href="#configuration">Configuration</a>
|
|
</p>
|
|
</p>
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
### One-line install
|
|
|
|
```bash
|
|
curl -fsSL http://10.0.0.59:3051/tanmay/Aetheel/raw/branch/main/install.sh | sh
|
|
```
|
|
|
|
This will clone the repo, set up a Python virtual environment, install dependencies, and walk you through configuration.
|
|
|
|
### Manual install
|
|
|
|
```bash
|
|
git clone http://10.0.0.59:3051/tanmay/Aetheel.git
|
|
cd Aetheel
|
|
uv sync # or: pip install -r requirements.txt
|
|
cp .env.example .env
|
|
# Edit .env with your Slack tokens
|
|
```
|
|
|
|
### Run
|
|
|
|
```bash
|
|
# Default — OpenCode runtime
|
|
uv run python main.py
|
|
|
|
# Claude Code runtime
|
|
uv run python main.py --claude
|
|
|
|
# Test mode (echo handler, no AI)
|
|
uv run python main.py --test
|
|
|
|
# Custom model
|
|
uv run python main.py --model anthropic/claude-sonnet-4-20250514
|
|
|
|
# Debug logging
|
|
uv run python main.py --log DEBUG
|
|
```
|
|
|
|
---
|
|
|
|
## Features
|
|
|
|
### 🧠 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 over all memory files
|
|
- **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** — Memory re-indexes when you edit `.md` files
|
|
|
|
### 🤖 Dual AI Runtimes
|
|
| Runtime | Flag | System Prompt | Session Continuity |
|
|
|---------|------|---------------|--------------------|
|
|
| **OpenCode** (default) | `--cli` / `--sdk` | XML-injected into message | `--continue --session <id>` |
|
|
| **Claude Code** | `--claude` | Native `--system-prompt` flag | `--continue --session-id <id>` |
|
|
|
|
Both return the same `AgentResponse` — zero code changes needed to switch.
|
|
|
|
### 💬 Slack Integration
|
|
- **Socket Mode** — no public URL or webhook needed
|
|
- **DMs + @mentions** — responds in both
|
|
- **Thread isolation** — each thread gets its own AI session
|
|
- **Chunked replies** — auto-splits long responses at Slack's 4000-char limit
|
|
|
|
### ⏰ Action Tags
|
|
The AI can perform actions by including tags in its response:
|
|
|
|
```
|
|
[ACTION:remind|2|Time to drink water! 💧]
|
|
```
|
|
|
|
The system strips the tag from the visible response and schedules the action.
|
|
|
|
### 🔒 Local-First
|
|
- Embeddings run locally (no OpenAI/Gemini API for memory)
|
|
- Memory stored in `~/.aetheel/` — your data stays on your machine
|
|
- Only the AI runtime (OpenCode/Claude) makes external API calls
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌──────────────┐
|
|
│ Slack │ Socket Mode (no public URL)
|
|
│ Workspace │
|
|
└──────┬───────┘
|
|
│ Events (DM, @mention)
|
|
▼
|
|
┌──────────────┐ ┌──────────────────┐
|
|
│ Slack │────▶│ main.py │
|
|
│ Adapter │ │ (ai_handler) │
|
|
└──────────────┘ └────────┬─────────┘
|
|
│
|
|
┌─────────┴─────────┐
|
|
▼ ▼
|
|
┌──────────────┐ ┌──────────────┐
|
|
│ Memory │ │ AI Runtime │
|
|
│ Manager │ │ (OpenCode │
|
|
│ │ │ or Claude) │
|
|
│ • SOUL.md │ │ │
|
|
│ • USER.md │ │ subprocess │
|
|
│ • MEMORY.md │ │ execution │
|
|
│ • search │ └──────────────┘
|
|
│ • session │
|
|
│ logs │
|
|
└──────────────┘
|
|
```
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
aetheel/
|
|
├── main.py # Entry point — handler, memory init, action tags
|
|
├── adapters/
|
|
│ └── slack_adapter.py # Slack Socket Mode adapter
|
|
├── agent/
|
|
│ ├── opencode_runtime.py # OpenCode CLI/SDK runtime
|
|
│ └── claude_runtime.py # Claude Code CLI runtime
|
|
├── memory/
|
|
│ ├── manager.py # MemoryManager — sync, search, identity files
|
|
│ ├── embeddings.py # Local embeddings via fastembed
|
|
│ ├── hybrid.py # Hybrid search (vector + BM25)
|
|
│ ├── schema.py # SQLite schema (files, chunks, FTS5)
|
|
│ ├── internal.py # Hashing, chunking, file discovery
|
|
│ └── types.py # Config, result types
|
|
├── docs/
|
|
│ ├── memory-system.md # Memory architecture docs
|
|
│ ├── opencode-setup.md # OpenCode install & config guide
|
|
│ ├── slack-setup.md # Slack app setup guide
|
|
│ └── opencode-integration-summary.md
|
|
├── .env.example # Template for secrets
|
|
├── pyproject.toml # Dependencies (uv/pip)
|
|
└── install.sh # One-click installer
|
|
```
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
### Required: Slack Tokens
|
|
|
|
| Variable | Where to get it |
|
|
|----------|----------------|
|
|
| `SLACK_BOT_TOKEN` | [api.slack.com/apps](https://api.slack.com/apps) → OAuth & Permissions → Bot Token (`xoxb-...`) |
|
|
| `SLACK_APP_TOKEN` | [api.slack.com/apps](https://api.slack.com/apps) → Basic Info → App-Level Tokens (`xapp-...`) |
|
|
|
|
See [`docs/slack-setup.md`](docs/slack-setup.md) for full Slack app creation instructions.
|
|
|
|
### AI Runtime
|
|
|
|
#### OpenCode (default)
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `OPENCODE_MODE` | `cli` | `cli` (subprocess) or `sdk` (server API) |
|
|
| `OPENCODE_MODEL` | auto | Model, e.g. `anthropic/claude-sonnet-4-20250514` |
|
|
| `OPENCODE_TIMEOUT` | `120` | CLI timeout in seconds |
|
|
| `OPENCODE_SERVER_URL` | `http://localhost:4096` | SDK mode server URL |
|
|
| `OPENCODE_WORKSPACE` | `.` | Working directory for OpenCode |
|
|
|
|
#### Claude Code (`--claude`)
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `CLAUDE_MODEL` | auto | Model, e.g. `claude-sonnet-4-20250514` |
|
|
| `CLAUDE_TIMEOUT` | `120` | CLI timeout in seconds |
|
|
| `CLAUDE_MAX_TURNS` | `3` | Max agentic tool-use turns |
|
|
| `CLAUDE_NO_TOOLS` | `true` | Disable tools for pure chat |
|
|
|
|
### Memory System
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `AETHEEL_WORKSPACE` | `~/.aetheel/workspace` | Path to memory files (SOUL.md, etc.) |
|
|
| `AETHEEL_MEMORY_DB` | `~/.aetheel/memory.db` | SQLite database path |
|
|
|
|
### General
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `LOG_LEVEL` | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR` |
|
|
|
|
---
|
|
|
|
## Memory Files
|
|
|
|
Aetheel auto-creates three identity files in `~/.aetheel/workspace/`:
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `SOUL.md` | Personality, values, communication style |
|
|
| `USER.md` | User preferences, context, background |
|
|
| `MEMORY.md` | Long-term notes, facts, things to remember |
|
|
|
|
Edit these files directly — changes are picked up automatically via file watching.
|
|
|
|
Session logs are saved to `~/.aetheel/workspace/daily/YYYY-MM-DD.md` and indexed for search.
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
- **Python 3.14+** (managed via [uv](https://docs.astral.sh/uv/))
|
|
- **Slack workspace** with bot + app tokens
|
|
- **One of:**
|
|
- [OpenCode](https://opencode.ai) CLI — `curl -fsSL https://opencode.ai/install | bash`
|
|
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) — `npm install -g @anthropic-ai/claude-code`
|
|
|
|
---
|
|
|
|
## Development
|
|
|
|
```bash
|
|
# Run tests
|
|
uv run python test_memory.py # Memory system smoke test
|
|
uv run python test_slack.py # Slack adapter unit tests
|
|
|
|
# Check help
|
|
uv run python main.py --help
|
|
```
|
|
|
|
---
|
|
|
|
## Inspired By
|
|
|
|
Built with inspiration from [OpenClaw](https://github.com/nichochar/openclaw) — a TypeScript AI agent framework. Aetheel reimplements the core concepts (memory, hybrid search, session management) in Python with a local-first philosophy.
|
|
|
|
---
|
|
|
|
<p align="center">
|
|
<sub>Made with ❤️ and a lot of Claude</sub>
|
|
</p>
|