Files
Aetheel/docs/aetheel-vs-nanoclaw.md
tanmay11k 6d73f74e0b feat: config-driven architecture, install wizard, live runtime switching, usage tracking, auto-failover
Major changes:
- Config-driven adapters: all channels (Slack, Discord, Telegram, WebChat, Webhooks) controlled via config.json with enabled flags and token auto-detection, no CLI flags required
- Runtime engine field: runtime.engine selects opencode/claude from config
- Interactive install script: 8-phase setup wizard with AI runtime detection/installation, token setup, identity file personalization (personality presets), aetheel CLI command, background service (launchd/systemd)
- Live runtime switching: /engine, /model, /provider commands hot-swap the AI runtime from chat without restart, changes persisted to config.json
- Usage tracking: per-request cost extraction from Claude Code JSON output, cumulative stats via /usage command
- Auto-failover: rate limit detection on both runtimes, automatic switch to other engine on quota errors with user notification
- Chat commands work without / prefix (Slack intercepts / in channels), commands: engine, model, provider, config, usage, reload, cron, subagents, status, help
- /config set for editing config.json from chat with dotted key notation
- Security audit saved to docs/security-audit.md
- Full command reference in docs/commands.md
- Future changes doc with NanoClaw agent teams analysis
- Logo added to README and WebChat UI
- README fully rewritten with all features documented
2026-02-18 01:07:12 -05:00

7.8 KiB

Aetheel vs Nanoclaw: Feature Comparison & OpenCode Assessment

Aetheel is a solid reimplementation of the core nanoclaw concept in Python, but there are meaningful gaps. Here's what maps, what's missing, and where the opencode integration could be improved.


What Aetheel Has (Maps Well to Nanoclaw)

Feature Nanoclaw Aetheel Status
Multi-channel adapters WhatsApp (baileys) Slack + Telegram Good — cleaner abstraction via BaseAdapter
Session isolation Per-group sessions Per-thread sessions via SessionStore Good
Dual runtime support Claude Code SDK only OpenCode (CLI+SDK) + Claude Code CLI Good — more flexible
Scheduled tasks Cron + interval + once via MCP tool Cron + one-shot via APScheduler Good
Subagent spawning SDK Task/TeamCreate tools Background threads via SubagentManager Basic
Memory system CLAUDE.md files per group SOUL.md + USER.md + MEMORY.md + hybrid search Better — vector + BM25 search
Skills system .claude/skills/ with SKILL.md skills/<name>/SKILL.md with trigger matching Good
Action tags MCP tools (send_message, schedule_task) Regex-parsed [ACTION:remind|...] tags Different approach, works

What's Missing from Aetheel

1. Container Isolation

Nanoclaw's biggest architectural feature. Every agent runs in an isolated Apple Container (or Docker) with controlled volume mounts, secret injection via stdin, and per-group IPC namespaces. Aetheel runs everything in the same process. This means:

  • No sandboxing of agent tool use (bash, file writes)
  • No mount-based security boundaries between groups
  • Secrets are in the process environment, not isolated

2. MCP Server Integration

Nanoclaw runs a custom MCP server (ipc-mcp-stdio.ts) inside the container that gives the agent tools like send_message, schedule_task, register_group. Aetheel uses regex-parsed action tags instead, which is fragile — the AI has to format tags perfectly, and there's no validation or structured tool calling.

3. Multi-Group Support

Nanoclaw has per-group folders, per-group memory (CLAUDE.md), per-group IPC, and a global memory layer. Aetheel has a single workspace with shared memory files. No group isolation.

4. Persistent Conversation Sessions on Disk

Nanoclaw stores sessions as JSONL files in data/sessions/{group}/.claude/ and can resume at a specific assistant message UUID. Aetheel's SessionStore is in-memory only — sessions are lost on restart.

5. IPC Message Streaming

Nanoclaw's agent runner uses a MessageStream (AsyncIterable) to pipe follow-up messages into an active agent query. The host can send new messages to a running agent via IPC files. Aetheel's runtime is request-response only — one message in, one response out.

6. Transcript Archiving

Nanoclaw archives full conversation transcripts to markdown before context compaction via a PreCompact hook. Aetheel logs sessions to daily files but doesn't handle compaction.

7. Group Registration

Nanoclaw lets the main agent register new groups dynamically via an MCP tool. Aetheel has no equivalent.

8. Idle Timeout / Session Lifecycle

Nanoclaw has a 30-minute idle timeout that closes the container stdin, ending the session gracefully. Aetheel has session TTL cleanup but no active lifecycle management.


OpenCode Integration Assessment

The opencode runtime implementation in agent/opencode_runtime.py is well-structured. Here's what's correct and what needs attention.

What's Done Well

  • Dual mode (CLI + SDK) with graceful fallback from SDK to CLI
  • Binary auto-discovery across common install paths
  • JSONL event parsing for opencode run --format json output
  • Session ID extraction from event stream
  • System prompt injection via XML tags (correct workaround since opencode run doesn't have --system-prompt)
  • Config from environment variables

Issues / Improvements Needed

1. SDK Client API Mismatch

The code calls self._sdk_client.session.chat(session_id, **chat_kwargs) but the opencode Python SDK uses client.session.prompt() not .chat(). The correct call is:

response = self._sdk_client.session.prompt(
    path={"id": session_id},
    body={"parts": parts, "model": model_config}
)

2. SDK Client Initialization

The code uses from opencode_ai import Opencode but the actual SDK package is @opencode-ai/sdk (JS/TS) or opencode-sdk-python (Python). The Python SDK uses createOpencodeClient pattern. Verify the actual Python SDK import path — it may be from opencode import Client or similar depending on the package version.

3. No --continue Flag Validation

The CLI mode passes --continue and --session for session continuity, but opencode run may not support --continue the same way as the TUI. The opencode run command is designed for single-shot execution. For session continuity in CLI mode, you'd need to use the SDK mode with opencode serve.

4. Missing --system Flag

The code injects system prompts as XML in the message body. This works but is a workaround. The SDK mode's client.session.prompt() supports a system parameter in the body, which would be cleaner.

5. No Structured Output Support

Opencode's SDK supports format: { type: "json_schema", schema: {...} } for structured responses. This could replace the fragile [ACTION:...] regex parsing with proper tool calls.

6. No Plugin/Hook Integration

Opencode has a plugin system (tool.execute.before, tool.execute.after, experimental.session.compacting) that could replace the action tag parsing. You could create an opencode plugin that exposes send_message and schedule_task as custom tools, similar to nanoclaw's MCP approach.

7. Session Persistence

SessionStore is in-memory. Opencode's server persists sessions natively, so in SDK mode you could rely on the server's session storage and just map conversation_id → opencode_session_id in a SQLite table.


Architectural Gap Summary

The biggest architectural gap isn't about opencode specifically — it's that Aetheel runs the agent in-process without isolation, while nanoclaw's container model is what makes it safe to give the agent bash access and file write tools.

To close that gap, options include:

  • Containerize the opencode runtime — run opencode serve inside a Docker container with controlled mounts
  • Use opencode's permission system — configure all dangerous tools to "ask" or "deny" per agent
  • Add an MCP server — replace action tag regex parsing with proper MCP tools for send_message, schedule_task, etc.
  • Persist sessions to SQLite — survive restarts and enable resume-at-message functionality

Nanoclaw Features → Opencode Equivalents

Nanoclaw (Claude Code SDK) Opencode Equivalent Gap Level
query() async iterable HTTP server + SDK client.session.prompt() 🔴 Architecture change needed
resume + resumeSessionAt POST /session/:id/message 🟡 No resume-at-UUID equivalent
Streaming message types (system/init, assistant, result) SSE events via GET /event 🟡 Different event schema
PreCompact hook experimental.session.compacting plugin 🟢 Similar concept, different API
PreToolUse hook (bash sanitization) tool.execute.before plugin 🟢 Similar concept, different API
bypassPermissions Per-tool permission config set to "allow" 🟢 Direct mapping
isSingleUserTurn: false via AsyncIterable prompt_async endpoint 🟡 Needs verification
CLAUDE.md auto-loading via settingSources AGENTS.md convention 🟢 Rename files
Secrets via env param on query() shell.env plugin hook 🟡 Different isolation model
MCP servers in query() config opencode.json mcp config or POST /mcp 🟢 Direct mapping