Releases: thatsme/AlexClaw
v0.3.7 — Coder Skill, Knowledge Base, Authorization Layer
What's New
Autonomous Skill Generation (Coder)
/codercommand generates dynamic skills from natural language via local LLM- Runtime validation: compile, load, test, retry loop (configurable max retries)
- RAG-powered: queries knowledge base for Erlang/Elixir docs and skill patterns
- Targeted retrieval by kind (erlang_docs, elixir_source, skill_source)
Knowledge Base Reinforcement
- erlang_docs_scraper — fetches OTP docs from GitHub .erl source files with Elixir calling convention hints
- lyse_scraper — scrapes Learn You Some Erlang OTP chapters
- skill_source_indexer — indexes existing skill source code with checksum-based freshness tracking
- elixir_source_scraper — fetches Elixir stdlib source from GitHub
- Knowledge base grew from ~4400 to ~7200 embeddings
Agent Authorization Layer
Three-phase composable authorization system:
Phase 1 — Context-Aware Permission Checks
AuthContextstruct carries caller, type, permission, chain depth, workflow run IDPolicyEngineevaluates context with chain-depth enforcement (max 3)- Structured audit logging for all authorization denials
Phase 2 — Capability Tokens (Macaroon-style)
- HMAC-signed tokens with permission attenuation
- Workflow steps get scoped tokens; cross-skill invocation further restricts
SafeExecutorruns dynamic skills in isolated processes- Tampered tokens rejected via timing-safe comparison
Phase 3 — Policy Rules Engine
- Configurable policy rules stored in PostgreSQL (rate_limit, time_window, chain_restriction, permission_override)
- Per-skill rate limiting via ETS counters
- Audit log persistence with 30-day auto-prune
- Admin UI at
/policiesfor CRUD + audit log viewing
Other Changes
- Removed stale Feeds nav link
- Updated SECURITY.md with full authorization documentation and JSON config examples
v0.3.5 — Shell Skill, Inline Config Editing, Security Hardening
What's New
Shell Skill — Container Introspection
Run whitelisted OS commands (df, free, ps, uptime, git, etc.) inside the container via Telegram /shell or as workflow steps. Protected by 5 layers of defense-in-depth:
- Disabled by default (
shell.enabledin Admin > Config) - 2FA gate when TOTP is enabled
- Whitelist with word-boundary check (configurable via Admin UI)
- Blocklist for shell metacharacters (
|,;,&&,$(, etc.) - No shell interpretation —
System.cmd/3with args as list
Configurable timeout (default 30s) and output truncation (default 4000 chars). git included in runtime Docker image for repo cloning.
Admin Config UX Improvements
- Inline editing — edit settings in-place, no more scrolling to the top of the page
- Collapsed groups by default — all config categories start collapsed, expand what you need
Security Hardening
- Session management improvements (CSRF, body limits)
- Dual enabled-check for shell skill (dispatcher + skill module)
Workflow & Docs
- Container Health Check example workflow in seeds (memory + disk + uptime → LLM summary → Telegram)
- Shell skill scaffolds in workflow editor (Memory, Disk, Processes, Uptime, BEAM node, Git clone)
- Updated README, ALEXCLAW_ARCHITECTURE.md, and SECURITY.md with shell skill documentation
v0.3.4 — Discord Gateway & Health/Metrics
Discord Gateway (issue #1)
Full bidirectional Discord support — use Discord instead of (or alongside) Telegram for all commands and notifications.
- AlexClaw.Gateway.Discord via Nostrum — WebSocket for receiving, REST API for sending
- Configure entirely from Admin > Config — no
.envneeded. Setdiscord.enabled, paste bot token, restart - Auto-detects channel ID on first message (same pattern as Telegram)
- All commands work identically in Telegram and Discord
discord_notifycore skill — deliver workflow output to specific Discord channels viachannel_idconfig- Gateway behaviour abstraction — Router, Behaviour, facade pattern. Skills and Dispatcher are transport-agnostic
See INSTALLATION.md for Discord bot setup instructions.
Health & Metrics Endpoints
GET /health— unauthenticated liveness check (DB ping, version, status). Returns HTTP 503 when DB is unreachable.GET /metrics— authenticated JSON with system stats, LLM provider usage, workflow run counts, skill/circuit breaker states, log severity counts, knowledge/memory entry counts.
Other Changes
Memory.count/1,Workflows.run_stats_today/0query functionsConnCasetest helper for controller tests- SkillAPI: gateway-agnostic
send_message/3,:gateway_sendpermission - 565 tests passing
v0.3.3 — Knowledge Base RAG Pipeline
Knowledge Base RAG Pipeline
Add a documentation-aware RAG (Retrieval-Augmented Generation) pipeline that scrapes Elixir ecosystem documentation, stores it as vector embeddings, and injects relevant docs into chat responses.
New Features
-
Knowledge Base — New
knowledge_entriestable with pgvector 768-dim HNSW index, fully separate from news/conversation memory. Context module with hybrid search: keyword-first term extraction + vector cosine similarity, with keyword results prioritized for precise documentation retrieval. -
HexDocs Scraper Skill — Dynamic skill that discovers modules and guides via ExDoc sidebar JSON, chunks by section/function boundary, deduplicates by source URL, and embeds asynchronously. Currently scrapes 22 packages (4200+ chunks) including full Elixir stdlib and 53 official guides.
-
Chat RAG Integration — Knowledge search injected into chat prompt alongside Memory search. Context source selector in the UI: Docs + Memory / Docs only / Memory only / No context. Doc and memory hit counters displayed per query. System prompt instructs LLM to cite provided documentation over general knowledge.
-
SkillAPI Knowledge Permissions —
knowledge_readandknowledge_writepermissions withknowledge_store,knowledge_search,knowledge_exists?wrappers for dynamic skills.
Fixes
- LLM API Key Resolution —
resolve_api_key/1now falls back from provider record to config settings (llm.gemini_api_key,llm.anthropic_api_key). Providers work correctly when the API key is stored in the config table rather than the provider row.
Packages Scraped
phoenix, phoenix_live_view, phoenix_html, phoenix_pubsub, ecto, ecto_sql, plug, plug_crypto, jason, req, finch, mint, floki, sweet_xml, telemetry, telemetry_metrics, telemetry_poller, bandit, nimble_options, nimble_pool, gen_stage, elixir (stdlib + 53 guides)
Stats
- 13 files changed, 1067 insertions
- 452 tests, 0 failures
- 4243 knowledge chunks embedded with nomic-embed-text-v1.5 (768-dim)
v0.3.0 — Conditional Workflow Branching
What's New
Conditional Workflow Branching
- Skills declare branches — new
routes/0callback on the Skill behaviour. Each skill declares its possible outcomes (e.g.[:on_items, :on_empty, :on_error]) - Triple tuple returns — skills return
{:ok, result, :branch_name}indicating which outcome occurred. Legacy{:ok, result}treated as:on_success - Recursive graph executor — replaces linear
Enum.reduce_whilewith a recursive step walker that follows routes based on branches - Per-step route configuration — workflow editor shows route dropdowns for each branch the skill supports. Target any step or "End workflow"
- Backward compatible — existing workflows with no routes behave identically (linear fall-through, halt on error)
- Loop protection — visited set + max iterations guard prevents infinite cycles
- Default route — fallback route when no branch matches
Skill Routes (all 12 core skills)
| Skill | Branches |
|---|---|
rss_collector |
on_items, on_empty, on_error |
web_search |
on_results, on_no_results, on_timeout, on_error |
web_browse |
on_success, on_not_found, on_timeout, on_error |
api_request |
on_2xx, on_4xx, on_5xx, on_timeout, on_error |
telegram_notify |
on_delivered, on_error |
google_calendar |
on_events, on_empty, on_error |
google_tasks |
on_tasks, on_empty, on_error |
github_security_review |
on_clean, on_findings, on_error |
web_browse |
on_success, on_not_found, on_timeout, on_error |
web_automation |
on_success, on_timeout, on_error |
research |
on_results, on_error |
llm_transform, conversational |
on_success, on_error |
Dynamic Skills Parity
- Routes extracted from module on load, persisted in
dynamic_skillsDB table - Cleaned up on unload, reset on reload
- SkillRegistry ETS extended to 5-tuple:
{name, module, type, permissions, routes} SkillRegistry.get_routes/1returns branches for any skill (core or dynamic)
Circuit Breaker + Branching Integration
- Circuit breaker fires before skill (infrastructure guard)
- Skill branches fire after skill (business logic routing)
- Skip bypasses routes entirely — falls through to next position
- Error routes (
on_error → step N) prevent workflow halt when explicitly configured
UI Improvements
- Route dropdowns per step in workflow editor (edit + add forms)
- Purple route badges on collapsed step view (
on_items→2,on_error→5) - Branch taken shown in workflow run history (purple badge)
Migration
- New
routesJSONB column onworkflow_steps(default:[]) - New
routesarray column ondynamic_skills(default:[])
Example Workflow
Step 1: Fetch RSS feeds (rss_collector)
→ on_items: Step 2 (score and summarize)
→ on_empty: Step 4 (send "no news today")
→ on_error: Step 5 (notify failure)
Step 2: Score via LLM (llm_transform)
→ on_success: Step 3 (deliver to Telegram)
→ on_error: Step 5 (notify failure)
Step 3: Deliver (telegram_notify)
→ on_delivered: End workflow
Step 4: No news (telegram_notify)
→ on_delivered: End workflow
Step 5: Error alert (telegram_notify)
→ on_delivered: End workflow
Zero LLM tokens spent on routing. Pure OTP pattern matching.
v0.2.3 — OTP Circuit Breaker
What's New
OTP Circuit Breaker
- Per-skill circuit breaker — pure OTP implementation using GenServer + ETS, zero external dependencies
- State machine —
:closed(normal) →:open(failing, calls rejected instantly) →:half_open(testing with one probe call) - Auto-recovery — after 3 consecutive failures the circuit opens; after 5 minutes a half-open probe tests if the skill has recovered
- Telegram notifications — alerts on circuit open (with failure count and last error) and circuit closed (recovered)
- Transparent wrapper — skills have zero awareness of the breaker, no changes to
run/1signatures or args - Dynamic skill lifecycle — breakers are cleaned up on skill unload, reset on skill reload (fresh code = fresh circuit)
Workflow Resilience Controls
- Dead letter routing — per-step config for circuit open behavior: halt workflow, skip step (pass input through), or fallback to an alternative skill
- Missing skill handling — per-step config: halt or skip when a skill is not loaded (e.g. dynamic skill unloaded)
- Fallback skill — route to an alternative skill when the primary skill's circuit is open
- All controls are visible dropdowns in the workflow step editor — no JSON editing required
Circuit Breaker Observability
- Dedicated log severity —
:circuit_breakerevents classified by[CircuitBreaker]prefix in log messages - Logs page filter — new "Circuit Breaker" button with blue "CB" badge in the real-time log viewer
UI Improvements
- Tooltips on every field — all workflow and step editor fields now have
?tooltip balloons with contextual help - Extracted reusable
tipcomponent for consistent tooltip rendering across the UI
Testing
broken_skill.extest fixture — always-failing dynamic skill for circuit breaker verification- Unit tests for all state transitions (closed → open → half_open → closed/open)
v0.2.2 — Semantic Memory & Chat
What's New
Semantic Memory with pgvector Embeddings
- Hybrid search — vector cosine similarity + keyword matching, merged and deduplicated
- Async embedding pipeline — all skills auto-embed stored knowledge in the background via TaskSupervisor
- Multi-provider embeddings — Gemini
gemini-embedding-001, Ollamanomic-embed-text, or any OpenAI-compatible endpoint - 768-dimension vectors with HNSW index for fast similarity search
- Batch re-embed —
Memory.reembed_all/1for model switching
Chat Page (Admin UI)
- Interactive conversation with semantic memory context — queries are enriched with relevant memories (CVEs, news, research, past conversations)
- Provider selector — pick any configured LLM (cloud or local) directly from the dropdown
- Conversation history stored back to memory for continuity
- Memory hit counter showing how many memories matched each query
New Dynamic Skills
- NVD CVE Monitor — fetches vulnerabilities from NIST NVD 2.0 JSON API, filters by CVSS severity (HIGH/CRITICAL), stores with embeddings, notifies via Telegram
- RSS v2 enhanced — full article content fetching via Floki HTML parser, configurable timeouts,
dc:datefallback for RDF/RSS 1.0 feeds
Improvements
- Configurable RSS fetch timeout — global setting (
skills.rss.fetch_timeout) + per-step override. Default 15s, adjustable for slow feeds - Embedding config —
embedding.providerandembedding.modelsettings in admin UI - Updated seed feeds: CISA News, The Hacker News, BleepingComputer, Krebs on Security
Fixes
- Fixed Gemini embedding model (
text-embedding-004→gemini-embedding-001withoutputDimensionality: 768) - Fixed CISA RSS feed URLs (old paths returned 404)
- Fixed Ecto sandbox compatibility for async embedding tasks in tests
- Fixed nil guard in
embed_entrywhen memory is deleted before embedding completes
v0.2.0 — Dynamic Skill Hot-Loading
Dynamic Skill Hot-Loading
Load custom skills at runtime — no code changes, no Docker rebuild, no restart. Upload .ex files through the admin UI or Telegram, compile into the running VM immediately.
What's New
- SkillRegistry rewrite — GenServer + ETS replaces static module map. Backward-compatible API.
- SkillAPI — Sandboxed API for dynamic skills with 8 permissions (
llm,web_read,telegram_send,memory_read,memory_write,config_read,resources_read,skill_invoke) - Admin UI — Skills page with upload button, core/dynamic split view, reload and unload buttons, version badges, permission tags
- Telegram commands —
/skill load,/skill unload,/skill reload,/skill create,/skill list - Persistence — Dynamic skills survive container restarts (DB + Docker volume)
- Integrity — SHA256 checksum on load, verified on boot. Tampered files skipped with Telegram alert.
- Security — Namespace enforcement (
AlexClaw.Skills.Dynamic.*), path traversal protection, core skills cannot be unloaded - 5 example dynamic skills — rss_v2, research_v2, github_security_review_v2, web_search_v2, web_browse_v2
- Skill template — Fully documented template with complete SkillAPI reference
- 37 new tests — Full suite: 452 tests, 0 failures
Note: Dynamic skill loading is experimental. The API, permission model, and sandboxing may change in future releases.
Docker
Add to your docker-compose.yml under the alexclaw service:
environment:
SKILLS_DIR: /app/skills
volumes:
- skills_data:/app/skillsAnd add skills_data: to your volumes section.
v0.1.3 — Unified LLM Providers
What's new
- Unified LLM providers — all providers (cloud and local) stored in DB, no more hardcoded builtin/custom split
- Priority-based selection — providers within a tier are selected by priority (lower = preferred)
- Timezone support — all timestamps displayed in configured timezone (Settings > display.timezone)
- Update checker — dashboard shows green/yellow badge when a newer release exists on GitHub
- Dashboard improvements — scrollable Recent Memories, minimum height panels, date+time on all timestamps
Fixes
- LM Studio usage not showing on dashboard
- Disabled providers appearing in LLM Usage
- Crypto test flakiness (tampered ciphertext test)
- Missing SECRET_KEY_BASE in test config
v0.1.2 — Unified LLM Providers
What's new
- Unified LLM providers — all providers (cloud and local) now live in the database. No more hardcoded builtin/custom split.
- Timezone support — dashboard times displayed in configured timezone (default: Europe/Rome)
- Update checker — dashboard shows when a newer release is available on GitHub
- Encryption at rest — sensitive config values encrypted with AES-256-GCM (v0.1.1)
- Web automator added to default docker-compose
Breaking changes
- Workflow steps referencing old provider names (e.g.
lm_studio) need updating to new names (e.g.LM Studio)
