Files
optimclaw/FEATURE_PARITY.md
T
d144484b06 feat: WASM channel attachments with LLM pipeline integration (#596)
* feat: add inbound attachment support to WASM channel system

Add attachment record to WIT interface and implement inbound media
parsing across all four channel implementations (Telegram, Slack,
WhatsApp, Discord). Attachments flow from WASM channels through
EmittedMessage to IncomingMessage with validation (size limits,
MIME allowlist, count caps) at the host boundary.

- Add `attachment` record to `emitted-message` in wit/channel.wit
- Add `IncomingAttachment` struct to channel.rs and re-export
- Add host-side validation (20MB total, 10 max, MIME allowlist)
- Telegram: parse photo, document, audio, video, voice, sticker
- Slack: parse file attachments with url_private
- WhatsApp: parse image, audio, video, document with captions
- Discord: backward-compatible empty attachments
- Update FEATURE_PARITY.md section 7
- Add fixture-based tests per channel and host integration tests

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* feat: integrate outbound attachment support and reconcile WIT types (#409)

Reconcile PR #409's outbound attachment work with our inbound attachment
support into a unified design:

WIT type split:
- `inbound-attachment` in channel-host: metadata-only (id, mime_type,
  filename, size_bytes, source_url, storage_key, extracted_text)
- `attachment` in channel: raw bytes (filename, mime_type, data) on
  agent-response for outbound sending

Outbound features (from PR #409):
- `on-broadcast` WIT export for proactive messages without prior inbound
- Telegram: multipart sendPhoto/sendDocument with auto photo→document
  fallback for files >10MB
- wrapper.rs: `call_on_broadcast`, `read_attachments` from disk,
  attachment params threaded through `call_on_respond`
- HTTP tool: `save_to` param for binary downloads to /tmp/ (50MB limit,
  path traversal protection, SSRF-safe redirect following)
- Message tool: allow /tmp/ paths for attachments alongside base_dir
- Credential env var fallback in inject_channel_credentials

Channel updates:
- All 4 channels implement on_broadcast (Telegram full, others stub)
- Telegram: polling_enabled config, adjusted poll timeout
- Inbound attachment types renamed to InboundAttachment in all channels

Tests: 1965 passing (9 new), 0 clippy warnings

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* feat: add audio transcription pipeline and extensible WIT attachment design

Add host-side transcription middleware (OpenAI Whisper) that detects audio
attachments with inline data on incoming messages and transcribes them
automatically. Refactor WIT inbound-attachment to use extras-json and a
store-attachment-data host function instead of typed fields, so future
attachment properties (dimensions, codec, etc.) don't require WIT changes
that invalidate all channel plugins.

- Add src/transcription/ module: TranscriptionProvider trait,
  TranscriptionMiddleware, AudioFormat enum, OpenAI Whisper provider
- Add src/config/transcription.rs: TRANSCRIPTION_ENABLED/MODEL/BASE_URL
- Wire middleware into agent message loop via AgentDeps
- WIT: replace data + duration-secs with extras-json + store-attachment-data
- Host: parse extras-json for well-known keys, merge stored binary data
- Telegram: download voice files via store-attachment-data, add duration
  to extras-json, add /file/bot to HTTP allowlist, voice-only placeholder
- Add reqwest multipart feature for Whisper API uploads
- 5 regression tests for transcription middleware

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* feat: wire attachment processing into LLM pipeline with multimodal image support

Attachments on incoming messages are now augmented into user text via XML tags
before entering the turn system, and images with data are passed as multimodal
content parts (base64 data URIs) to LLM providers. This enables audio transcripts,
document text, and image content to reach the LLM without changes to ChatMessage
serialization or provider interfaces.

- Add src/agent/attachments.rs with augment_with_attachments() and 9 unit tests
- Add ContentPart/ImageUrl types to llm::provider with OpenAI-compatible serde
- Carry image_content_parts transiently on Turn (skipped in serialization)
- Update nearai_chat and rig_adapter to serialize multimodal content
- Add 3 e2e tests verifying attachments flow through the full agent loop

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: CI failures — formatting, version bumps, and Telegram voice test

- Fix cargo fmt formatting in attachments.rs, nearai_chat.rs, rig_adapter.rs,
  e2e_attachments.rs
- Bump channel registry versions 0.1.0 → 0.2.0 (discord, slack, telegram,
  whatsapp) to satisfy version-bump CI check
- Fix Telegram test_extract_attachments_voice: add missing required `duration`
  field to voice fixture JSON

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: bump WIT channel version to 0.3.0, fix Telegram voice test, add pre-commit hook

- Bump wit/channel.wit package version 0.2.0 → 0.3.0 (interface changed with
  store-attachment-data)
- Update WIT_CHANNEL_VERSION constant and registry wit_version fields to match
- Fix Telegram test_extract_attachments_voice: gate voice download behind
  #[cfg(target_arch = "wasm32")] so host functions aren't called in native tests,
  update assertions for generated filename and extras_json duration
- Add @0.3.0 linker stubs in wit_compat.rs
- Add .githooks/pre-commit hook that runs scripts/check-version-bumps.sh when
  WIT or extension sources are staged
- Symlink commit-msg regression hook into .githooks/

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* refactor: extract voice download from extract_attachments into handle_message

Move download_voice_file + store_attachment_data calls out of
extract_attachments into a separate download_and_store_voice function
called from handle_message. This keeps extract_attachments as a pure
data-mapping function with no host calls, making it fully testable
in native unit tests without #[cfg(target_arch)] gates.

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: address PR review comments — security, correctness, and code quality

Security fixes:
- Add path validation to read_attachments (restrict to /tmp/) preventing
  arbitrary file reads from compromised tools
- Escape XML special characters in attachment filenames, MIME types, and
  extracted text to prevent prompt injection via tag spoofing
- Percent-encode file_id in Telegram getFile URL to prevent query injection
- Clone SecretString directly instead of expose_secret().to_string()

Correctness fixes:
- Fix store_attachment_data overwrite accounting: subtract old entry size
  before adding new to prevent inflated totals and false rejections
- Use max(reported, stored_size) for attachment size accounting to prevent
  WASM channels from under-reporting size_bytes to bypass limits
- Add application/octet-stream to MIME allowlist (channels default unknown
  types to this)

Code quality:
- Extract send_response helper in Telegram, deduplicating on_respond and
  on_broadcast
- Rename misleading Discord test to test_parse_slash_command_interaction
- Fix .githooks/commit-msg to use relative symlink (portable across machines)

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* feat: add tool_upgrade command + fix TOCTOU in save_to path validation

Add `tool_upgrade` — a new extension management tool that automatically
detects and reinstalls WASM extensions with outdated WIT versions.
Preserves authentication secrets during upgrade. Supports upgrading a
single extension by name or all installed WASM tools/channels at once.

Fix TOCTOU in `validate_save_to_path`: validate the path *before*
creating parent directories, so traversal paths like `/tmp/../../etc/`
cannot cause filesystem mutations outside /tmp before being rejected.

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: unify WIT package version to 0.3.0 across tool.wit and all capabilities

tool.wit and channel.wit share the `near:agent` package namespace, so they
must declare the same version. Bumps tool.wit from 0.2.0 to 0.3.0 and
updates all capabilities files and registry entries to match.

Fixes `cargo component build` failure: "package identifier near:[email protected]
does not match previous package name of near:[email protected]"

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: move WIT file comments after package declaration

WIT treats `//` comments before `package` as doc comments. When both
tool.wit and channel.wit had header comments, the parser rejected them
as "doc comments on multiple 'package' items". Move comments after the
package declaration in both files.

Also bumps tool registry versions to 0.2.0 to match the WIT 0.3.0 bump.

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* feat: display extension versions in gateway Extensions tab

Add version field to InstalledExtension and RegistryEntry types, pipe
through the web API (ExtensionInfo, RegistryEntryInfo), and render as
a badge in the gateway UI for both installed and available extensions.

For installed WASM extensions, version is read from the capabilities
file with a fallback to the registry entry when the local file has no
version (old installations). Bump all extension Cargo.toml and registry
JSON versions from 0.1.0 to 0.2.0 to keep them in sync.

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* feat: add document text extraction middleware for PDF, Office, and text files

Extract text from document attachments (PDF, DOCX, PPTX, XLSX, RTF, plain text,
code files) so the LLM can reason about uploaded documents. Uses pdf-extract for
PDFs, zip+XML parsing for Office XML formats, and UTF-8 decode for text files.
Wired into the agent loop after transcription middleware.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: download document files in Telegram channel for text extraction

The DocumentExtractionMiddleware needs file bytes in the attachment `data`
field, but only voice files were being downloaded. Document attachments
(PDFs, DOCX, etc.) had empty `data` and a source_url with a credential
placeholder that only works inside the WASM host's http_request.

Add `download_and_store_documents()` that downloads non-voice, non-image,
non-audio attachments via the existing two-step getFile→download flow and
stores bytes via `store_attachment_data` for host-side extraction.

Also rename `download_voice_file` → `download_telegram_file` since it's
generic for any file_id.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: allow Office MIME types and increase file download limit for Telegram

Two issues preventing document extraction from Telegram:

1. PPTX/DOCX/XLSX MIME types (application/vnd.*) were dropped by the
   WASM host attachment allowlist — add application/vnd., application/msword,
   and application/rtf prefixes.

2. Telegram file downloads over 10 MB failed with "Response body too large" —
   set max_response_bytes to 20 MB in Telegram capabilities.

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: report document extraction errors back to user instead of silently skipping

- Bump max_response_bytes to 50 MB for Telegram file downloads
- When document extraction fails (too large, download error, parse error),
  set extracted_text to a user-friendly error message instead of leaving it
  None. This ensures the LLM tells the user what went wrong.
- On Telegram download failure, set extracted_text with the error so the
  user sees feedback even when the file never reaches the extraction middleware.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* feat: store extracted document text in workspace memory for search/recall

After document extraction succeeds, write the extracted text to workspace
memory at `documents/{date}/{filename}`. This enables:
- Full-text and semantic search over past uploaded documents
- Cross-conversation recall ("what did that PDF say?")
- Automatic chunking and embedding via the workspace pipeline

Documents are stored with metadata header (uploader, channel, date, MIME type).
Error messages (extraction failures) are not stored — only successful extractions.

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: CI failures — formatting, unused assignment warning

- Run cargo fmt on document_extraction and agent_loop modules
- Suppress unused_assignments warning on trace_llm_ref (used only
  behind #[cfg(feature = "libsql")])

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: address PR review comments — security, correctness, and code quality

Security fixes:
- Remove SSRF-prone download() from DocumentExtractionMiddleware (#13)
- Sanitize filenames in workspace path to prevent directory traversal (#11)
- Pre-check file size before reading in WASM wrapper to prevent OOM (#2)
- Percent-encode file_id in Telegram source URLs (#7)

Correctness fixes:
- Clear image_content_parts on turn end to prevent memory leak (#1)
- Find first *successful* transcription instead of first overall (#3)
- Enforce data.len() size limit in document extraction (#10)
- Use UTF-8 safe truncation with char_indices() (#12)

Robustness & code quality:
- Add 120s timeout to OpenAI Whisper HTTP client (#5)
- Trim trailing slash from Whisper base_url (#6)
- Allow ~/.ironclaw/ paths in WASM wrapper (#8)
- Return error from on_broadcast in Slack/Discord/WhatsApp (#9)
- Fix doc comment in HTTP tool (#4)

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: formatting — cargo fmt

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: address latest PR review — doc comments, error messages, version bumps

- Fix DocumentExtractionMiddleware doc comment (no longer downloads from source_url)
- Fix error message: "no inline data" instead of "no download URL"
- Log error + fallback instead of silent unwrap_or_default on Whisper HTTP client
- Bump all capabilities.json versions from 0.1.0 to 0.2.0 to match Cargo.toml

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: remove unsupported profile: minimal from CI workflows [skip-regression-check]

dtolnay/rust-toolchain@stable does not accept the 'profile' input
(it was a parameter for the deprecated actions-rs/toolchain action).

Co-Authored-By: Claude Opus 4.6 <[email protected]>

* fix: merge with latest main — resolve compilation errors and PR review nits

- Add version: None to RegistryEntry/InstalledExtension test constructors
- Fix MessageContent type mismatches in nearai_chat tests (String → MessageContent::Text)
- Fix .contains() calls on MessageContent — use .as_text().unwrap()
- Remove redundant trace_llm_ref = None assignment in test_rig
- Check data size before clone in document extraction to avoid unnecessary allocation

[skip-regression-check]

Co-Authored-By: Claude Opus 4.6 <[email protected]>

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
2026-03-07 18:01:40 +00:00

28 KiB
Raw Blame History

IronClaw ↔ OpenClaw Feature Parity Matrix

This document tracks feature parity between IronClaw (Rust implementation) and OpenClaw (TypeScript reference implementation). Use this to coordinate work across developers.

Legend:

  • Implemented
  • 🚧 Partial (in progress or incomplete)
  • Not implemented
  • 🔮 Planned (in scope but not started)
  • 🚫 Out of scope (intentionally skipped)
  • N/A (not applicable to Rust implementation)

1. Architecture

Feature OpenClaw IronClaw Notes
Hub-and-spoke architecture Web gateway as central hub
WebSocket control plane Gateway with WebSocket + SSE
Single-user system
Multi-agent routing Workspace isolation per-agent
Session-based messaging Per-sender sessions
Loopback-first networking HTTP binds to 0.0.0.0 but can be configured

Owner: Unassigned


2. Gateway System

Feature OpenClaw IronClaw Notes
Gateway control plane Web gateway with 40+ API endpoints
HTTP endpoints for Control UI Web dashboard with chat, memory, jobs, logs, extensions
Channel connection lifecycle ChannelManager + WebSocket tracker
Session management/routing SessionManager exists
Configuration hot-reload
Network modes (loopback/LAN/remote) 🚧 HTTP only
OpenAI-compatible HTTP API /v1/chat/completions, per-request model override
Canvas hosting Agent-driven UI
Gateway lock (PID-based)
launchd/systemd integration
Bonjour/mDNS discovery
Tailscale integration
Health check endpoints /api/health + /api/gateway/status
doctor diagnostics
Agent event broadcast 🚧 SSE broadcast manager exists (SseManager) but tool/job-state events not fully wired
Channel health monitor Auto-restart with configurable interval
Presence system Beacons on connect, system presence for agents
Trusted-proxy auth mode Header-based auth for reverse proxies
APNs push pipeline Wake disconnected iOS nodes via push
Oversized payload guard 🚧 HTTP webhook has 64KB body limit + Content-Length check; no chat.history cap
Pre-prompt context diagnostics Context size logging before prompt

Owner: Unassigned


3. Messaging Channels

Channel OpenClaw IronClaw Priority Notes
CLI/TUI - Ratatui-based TUI
HTTP webhook - axum with secret validation
REPL (simple) - For testing
WASM channels - IronClaw innovation
WhatsApp P1 Baileys (Web), same-phone mode with echo detection
Telegram - WASM channel(MTProto), DM pairing, caption, /start, bot_username
Discord P2 discord.js, thread parent binding inheritance
Signal P2 signal-cli daemonPC, SSE listener HTTP/JSON-R, user/group allowlists, DM pairing
Slack - WASM tool
iMessage P3 BlueBubbles or Linq recommended
Linq P3 Real iMessage via API, no Mac required
Feishu/Lark P3 Bitable create app/field tools
LINE P3
WebChat - Web gateway chat
Matrix P3 E2EE support
Mattermost P3 Emoji reactions
Google Chat P3
MS Teams P3
Twitch P3
Voice Call P3 Twilio/Telnyx, stale call reaper, pre-cached greeting
Nostr P3

Telegram-Specific Features (since Feb 2025)

Feature OpenClaw IronClaw Notes
Forum topic creation Create topics in forum groups
channel_post support Bot-to-bot communication
User message reactions Surface inbound reactions
sendPoll Poll creation via agent
Cron/heartbeat topic targeting Messages land in correct topic

Discord-Specific Features (since Feb 2025)

Feature OpenClaw IronClaw Notes
Forwarded attachment downloads Fetch media from forwarded messages
Faster reaction state machine Watchdog + debounce
Thread parent binding inheritance Threads inherit parent routing

Slack-Specific Features (since Feb 2025)

Feature OpenClaw IronClaw Notes
Streaming draft replies Partial replies via draft message updates
Configurable stream modes Per-channel stream behavior
Thread ownership Thread-level ownership tracking

Channel Features

Feature OpenClaw IronClaw Notes
DM pairing codes ironclaw pairing list/approve, host APIs
Allowlist/blocklist 🚧 allow_from + pairing store
Self-message bypass Own messages skip pairing
Mention-based activation bot_username + respond_to_all_group_messages
Per-group tool policies Allow/deny specific tools
Thread isolation Separate sessions per thread
Per-channel media limits Attachment type in WIT; max 10 per msg, 20MB total, MIME allowlist
Typing indicators 🚧 TUI + Telegram typing/actionable status prompts; richer parity pending
Per-channel ackReaction config Customizable acknowledgement reactions
Group session priming Member roster injected for context
Sender_id in trusted metadata Exposed in system metadata

Owner: Unassigned


4. CLI Commands

Command OpenClaw IronClaw Priority Notes
run (agent) - Default command
tool install/list/remove - WASM tools
gateway start/stop P2
onboard (wizard) - Interactive setup
tui - Ratatui TUI
config - Read/write config
channels P2 Channel management
models 🚧 - Model selector in TUI
status - System status (enriched session details)
agents P3 Multi-agent management
sessions P3 Session listing (shows subagent models)
memory - Memory search CLI
skills - Skills tools + web API endpoints (install, list, activate)
pairing - list/approve, account selector
nodes P3 Device management, remove/clear flows
plugins P3 Plugin management
hooks P2 Lifecycle hooks
cron P2 Scheduled jobs (model/thinking fields in edit)
webhooks P3 Webhook config
message send P2 Send to channels
browser P3 Browser automation
sandbox - WASM sandbox
doctor P2 Diagnostics
logs P3 Query logs
update P3 Self-update
completion - Shell completion
/subagents spawn P3 Spawn subagents from chat
/export-session P3 Export current session transcript

Owner: Unassigned


5. Agent System

Feature OpenClaw IronClaw Notes
Pi agent runtime IronClaw uses custom runtime
RPC-based execution Orchestrator/worker pattern
Multi-provider failover FailoverProvider tries providers sequentially on retryable errors
Per-sender sessions
Global sessions Optional shared context
Session pruning Auto cleanup old sessions
Context compaction Auto summarization
Post-compaction read audit Layer 3: workspace rules appended to summaries
Post-compaction context injection Workspace context as system event
Custom system prompts Template variables, safety guardrails
Skills (modular capabilities) Prompt-based skills with trust gating, attenuation, activation criteria, catalog, selector
Skill routing blocks 🚧 ActivationCriteria (keywords, patterns, tags) but no "Use when / Don't use when" blocks
Skill path compaction ~ prefix to reduce prompt tokens
Thinking modes (low/med/high) Configurable reasoning depth
Per-model thinkingDefault override Override thinking level per model
Block-level streaming
Tool-level streaming
Z.AI tool_stream Real-time tool call streaming
Plugin tools WASM tools
Tool policies (allow/deny)
Exec approvals (/approve) TUI approval overlay
Elevated mode Privileged execution
Subagent support Task framework
/subagents spawn command Spawn from chat
Auth profiles Multiple auth strategies
Generic API key rotation Rotate keys across providers
Stuck loop detection Exponential backoff on stuck agent loops
llms.txt discovery Auto-discover site metadata
Multiple images per tool call Single tool call, multiple images
URL allowlist (web_search/fetch) Restrict web tool targets
suppressToolErrors config Hide tool errors from user
Intent-first tool display Details and exec summaries
Transcript file size in status Show size in session status

Owner: Unassigned


6. Model & Provider Support

Provider OpenClaw IronClaw Priority Notes
NEAR AI - Primary provider
Anthropic (Claude) 🚧 - Via NEAR AI proxy; Opus 4.5, Sonnet 4, Sonnet 4.6
OpenAI 🚧 - Via NEAR AI proxy
AWS Bedrock P3
Google Gemini P3
NVIDIA API P3 New provider
OpenRouter - Via OpenAI-compatible provider (RigAdapter)
Tinfoil - Private inference provider (IronClaw-only)
OpenAI-compatible - Generic OpenAI-compatible endpoint (RigAdapter)
Ollama (local) - via rig::providers::ollama (full support)
Perplexity P3 Freshness parameter for web_search
MiniMax P3 Regional endpoint selection
GLM-5 P3
node-llama-cpp - N/A for Rust
llama.cpp (native) 🔮 P3 Rust bindings

Model Features

Feature OpenClaw IronClaw Notes
Auto-discovery
Failover chains FailoverProvider with configurable fallback_model
Cooldown management Lock-free per-provider cooldown in FailoverProvider
Per-session model override Model selector in TUI
Model selection UI TUI keyboard shortcut
Per-model thinkingDefault Override thinking level per model in config
1M context beta header Anthropic extended context support

Owner: Unassigned


7. Media Handling

Feature OpenClaw IronClaw Priority Notes
WIT inbound-attachment type N/A P1 inbound-attachment record in channel-host (id, mime_type, filename, size_bytes, source_url, storage_key, extracted_text)
WIT outbound attachment type N/A P1 attachment record in channel (filename, mime_type, data) on agent-response
WIT on-broadcast export N/A P1 Proactive message sending without prior incoming message
IncomingMessage attachments N/A P1 IncomingAttachment struct on IncomingMessage, populated from WASM channels
OutgoingResponse attachments N/A P1 File paths on OutgoingResponse, read from disk and sent as WIT attachments
Attachment security (size/MIME) N/A P1 Inbound: max 10, 20MB total, MIME allowlist. Outbound: 50MB total
Telegram media parsing P1 Photo, document, audio, video, voice, sticker parsed and emitted as attachments
Telegram media sending P1 sendPhoto/sendDocument multipart upload, auto photo→document fallback >10MB
Slack file parsing P1 files array from Events API parsed into attachments
WhatsApp media parsing P1 Image, audio, video, document parsed with caption as extracted_text
Discord attachment parsing P2 Discord interaction payloads don't include file attachments (needs message events)
HTTP tool save_to N/A P1 Download binary files to /tmp/ for attachment sending (50MB limit, path traversal protection)
Credential env var fallback N/A P2 Channels can use env vars (e.g., TELEGRAM_BOT_TOKEN) when secrets store not configured
Image processing (Sharp) P2 Resize, format convert
Configurable image resize dims P2 Per-agent dimension config
Multiple images per tool call P2 Single tool invocation, multiple images
Audio transcription P2
Video support P3
PDF parsing P2 pdfjs-dist
MIME detection P2 MIME allowlist in host validates attachment types
Media caching P3
Vision model integration P2 Image understanding
TTS (Edge TTS) P3 Text-to-speech
TTS (OpenAI) P3
Incremental TTS playback P3 iOS progressive playback
Sticker-to-image P3 Telegram stickers emitted as image/webp attachments

Owner: Unassigned


8. Plugin & Extension System

Feature OpenClaw IronClaw Notes
Dynamic loading WASM modules
Manifest validation WASM metadata
HTTP path registration Plugin routes
Workspace-relative install ~/.ironclaw/tools/
Channel plugins WASM channels
Auth plugins
Memory plugins Custom backends
Tool plugins WASM tools
Hook plugins Declarative hooks from extension capabilities
Provider plugins
Plugin CLI (install, list) tool subcommand
ClawHub registry Discovery
before_agent_start hook modelOverride/providerOverride support
before_message_write hook Pre-write message interception
llm_input/llm_output hooks LLM payload inspection

Owner: Unassigned


9. Configuration System

Feature OpenClaw IronClaw Notes
Primary config file ~/.openclaw/openclaw.json .env Different formats
JSON5 support Comments, trailing commas
YAML alternative
Environment variable interpolation ${VAR}
Config validation/schema Type-safe Config struct
Hot-reload
Legacy migration
State directory ~/.openclaw-state/ ~/.ironclaw/
Credentials directory Session files
Full model compat fields in schema pi-ai model compat exposed in config

Owner: Unassigned


10. Memory & Knowledge System

Feature OpenClaw IronClaw Notes
Vector memory pgvector
Session-based memory
Hybrid search (BM25 + vector) RRF algorithm
Temporal decay (hybrid search) Opt-in time-based scoring factor
MMR re-ranking Maximal marginal relevance for result diversity
LLM-based query expansion Expand FTS queries via LLM
OpenAI embeddings
Gemini embeddings
Local embeddings
SQLite-vec backend IronClaw uses PostgreSQL
LanceDB backend Configurable auto-capture max length
QMD backend
Atomic reindexing
Embeddings batching embed_batch on EmbeddingProvider trait
Citation support
Memory CLI commands memory search/read/write/tree/status CLI subcommands
Flexible path structure Filesystem-like API
Identity files (AGENTS.md, etc.)
Daily logs
Heartbeat checklist HEARTBEAT.md

Owner: Unassigned


11. Mobile Apps

Feature OpenClaw IronClaw Priority Notes
iOS app (SwiftUI) 🚫 - Out of scope initially
Android app (Kotlin) 🚫 - Out of scope initially
Apple Watch companion 🚫 - Send/receive messages MVP
Gateway WebSocket client 🚫 -
Camera/photo access 🚫 -
Voice input 🚫 -
Push-to-talk 🚫 -
Location sharing 🚫 -
Node pairing 🚫 -
APNs push notifications 🚫 - Wake disconnected nodes before invoke
Share to OpenClaw (iOS) 🚫 - iOS share sheet integration
Background listening toggle 🚫 - iOS background audio

Owner: Unassigned (if ever prioritized)


12. macOS App

Feature OpenClaw IronClaw Priority Notes
SwiftUI native app 🚫 - Out of scope
Menu bar presence 🚫 - Animated menubar icon
Bundled gateway 🚫 -
Canvas hosting 🚫 - Agent-controlled panel with placement/resizing
Voice wake 🚫 - Overlay, mic picker, language selection, live meter
Voice wake overlay 🚫 - Partial transcripts, adaptive delays, dismiss animations
Push-to-talk hotkey 🚫 - System-wide hotkey
Exec approval dialogs - TUI overlay
iMessage integration 🚫 -
Instances tab 🚫 - Presence beacons across instances
Agent events debug window 🚫 - Real-time event inspector
Sparkle auto-updates 🚫 - Appcast distribution

Owner: Unassigned (if ever prioritized)


13. Web Interface

Feature OpenClaw IronClaw Priority Notes
Control UI Dashboard - Web gateway with chat, memory, jobs, logs, extensions
Channel status view 🚧 P2 Gateway status widget, full channel view pending
Agent management P3
Model selection - TUI only
Config editing P3
Debug/logs viewer - Real-time log streaming with level/target filters
WebChat interface - Web gateway chat with SSE/WebSocket
Canvas system (A2UI) P3 Agent-driven UI, improved asset resolution
Control UI i18n P3 English, Chinese, Portuguese
WebChat theme sync P3 Sync with system dark/light mode
Partial output on abort P2 Preserve partial output when aborting

Owner: Unassigned


14. Automation

Feature OpenClaw IronClaw Priority Notes
Cron jobs - Routines with cron trigger
Cron stagger controls P3 Default stagger for scheduled jobs
Cron finished-run webhook P3 Webhook on job completion
Timezone support - Via cron expressions
One-shot/recurring jobs - Manual + cron triggers
Channel health monitor P2 Auto-restart with configurable interval
beforeInbound hook P2
beforeOutbound hook P2
beforeToolCall hook P2
before_agent_start hook P2 Model/provider override
before_message_write hook P2 Pre-write interception
onMessage hook - Routines with event trigger
onSessionStart hook P2
onSessionEnd hook P2
transcribeAudio hook P3
transformResponse hook P2
llm_input/llm_output hooks P3 LLM payload inspection
Bundled hooks P2 Audit + declarative rule/webhook hooks
Plugin hooks P3 Registered from WASM capabilities.json
Workspace hooks P2 hooks/hooks.json and hooks/*.hook.json
Outbound webhooks P2 Fire-and-forget lifecycle event delivery
Heartbeat system - Periodic execution
Gmail pub/sub P3

Owner: Unassigned


15. Security Features

Feature OpenClaw IronClaw Notes
Gateway token auth Bearer token auth on web gateway
Device pairing
Tailscale identity
Trusted-proxy auth Header-based reverse proxy auth
OAuth flows 🚧 NEAR AI OAuth
DM pairing verification ironclaw pairing approve, host APIs
Allowlist/blocklist 🚧 allow_from + pairing store
Per-group tool policies
Exec approvals TUI overlay
TLS 1.3 minimum reqwest rustls
SSRF protection WASM allowlist
SSRF IPv6 transition bypass block Block IPv4-mapped IPv6 bypasses
Cron webhook SSRF guard SSRF checks on webhook delivery
Loopback-first 🚧 HTTP binds 0.0.0.0
Docker sandbox Orchestrator/worker containers
Podman support Alternative to Docker
WASM sandbox IronClaw innovation
Sandbox env sanitization 🚧 Shell tool scrubs env vars (secret detection); docker container env sanitization partial
Tool policies
Elevated mode
Safe bins allowlist Hardened path trust
LD*/DYLD* validation
Path traversal prevention Including config includes (OC-06)
Credential theft via env injection 🚧 Shell env scrubbing + command injection detection; no full OC-09 defense
Session file permissions (0o600) Session token file set to 0o600 in llm/session.rs
Skill download path restriction Prevent arbitrary write targets
Webhook signature verification
Media URL validation
Prompt injection defense Pattern detection, sanitization
Leak detection Secret exfiltration
Dangerous tool re-enable warning Warn when gateway.tools.allow re-enables HTTP tools

Owner: Unassigned


16. Development & Build System

Feature OpenClaw IronClaw Notes
Primary language TypeScript Rust Different ecosystems
Build tool tsdown cargo
Type checking TypeScript/tsgo rustc
Linting Oxlint clippy
Formatting Oxfmt rustfmt
Package manager pnpm cargo
Test framework Vitest built-in
Coverage V8 tarpaulin/llvm-cov
CI/CD GitHub Actions GitHub Actions
Pre-commit hooks prek - Consider adding
Docker: Chromium + Xvfb Optional browser in container
Docker: init scripts /openclaw-init.d/ support
Browser: extraArgs config Custom Chrome launch arguments

Owner: Unassigned


Implementation Priorities

P0 - Core (Already Done)

  • TUI channel with approval overlays
  • HTTP webhook channel
  • DM pairing (ironclaw pairing list/approve, host APIs)
  • WASM tool sandbox
  • Workspace/memory with hybrid search + embeddings batching
  • Prompt injection defense
  • Heartbeat system
  • Session management
  • Context compaction
  • Model selection
  • Gateway control plane + WebSocket
  • Web Control UI (chat, memory, jobs, logs, extensions, routines)
  • WebChat channel (web gateway)
  • Slack channel (WASM tool)
  • Telegram channel (WASM tool, MTProto)
  • Docker sandbox (orchestrator/worker)
  • Cron job scheduling (routines)
  • CLI subcommands (onboard, config, status, memory)
  • Gateway token auth
  • Skills system (prompt-based with trust gating, attenuation, activation criteria)
  • Session file permissions (0o600)
  • Memory CLI commands (search, read, write, tree, status)
  • Shell env scrubbing + command injection detection
  • Tinfoil private inference provider
  • OpenAI-compatible / OpenRouter provider support

P1 - High Priority

  • Slack channel (real implementation)
  • Telegram channel (WASM, DM pairing, caption, /start)
  • WhatsApp channel
  • Multi-provider failover (FailoverProvider with retryable error classification)
  • Hooks system (core lifecycle hooks + bundled/plugin/workspace hooks + outbound webhooks)

P2 - Medium Priority

  • Media handling (images, PDFs)
  • Ollama/local model support (via rig::providers::ollama)
  • Configuration hot-reload
  • Webhook trigger endpoint in web gateway
  • Channel health monitor with auto-restart
  • Partial output preservation on abort

P3 - Lower Priority

  • Discord channel
  • Matrix channel
  • Other messaging platforms
  • TTS/audio features
  • Video support
  • 🚧 Skills routing blocks (activation criteria exist, but no "Use when / Don't use when")
  • Plugin registry
  • Streaming (block/tool/Z.AI tool_stream)
  • Memory: temporal decay, MMR re-ranking, query expansion
  • Control UI i18n
  • Stuck loop detection

How to Contribute

  1. Claim a section: Edit this file and add your name/handle to the "Owner" field
  2. Create a tracking issue: Link to GitHub issue for the feature area
  3. Update status: Change to 🚧 when starting, when complete
  4. Add notes: Document any design decisions or deviations

Coordination

  • Each major section should have one owner to avoid conflicts
  • Owners can delegate sub-features to others
  • Update this file as part of your PR

Deviations from OpenClaw

IronClaw intentionally differs from OpenClaw in these ways:

  1. Rust vs TypeScript: Native performance, memory safety, single binary distribution
  2. WASM sandbox vs Docker: Lighter weight, faster startup, capability-based security
  3. PostgreSQL + libSQL vs SQLite: Dual-backend (production PG + embedded libSQL for zero-dep local mode)
  4. NEAR AI focus: Primary provider with session-based auth
  5. No mobile/desktop apps: Focus on server-side and CLI initially
  6. WASM channels: Novel extension mechanism not in OpenClaw
  7. Tinfoil private inference: IronClaw-only provider for private/encrypted inference
  8. GitHub WASM tool: Native GitHub integration as WASM tool
  9. Prompt-based skills: Different approach than OpenClaw capability bundles (trust gating, attenuation)

These are intentional architectural choices, not gaps to be filled.