* feat: Add benchmarking harness for agent evaluation Introduces ironclaw-bench, a Rust-native benchmarking crate that drives the real agent loop headlessly. Supports standard benchmarks (GAIA, Tau-bench, SWE-bench Pro) and custom JSONL task sets with parallel execution, resume support, and incremental JSONL output. Key components: - BenchChannel: headless Channel impl with auto-approval and response capture - InstrumentedLlm: LlmProvider wrapper recording per-call token/cost metrics - BenchRunner: task orchestration with parallel execution and JSONL resume - Scoring utilities: exact match, contains, regex (all with normalization) - CLI: run, results, compare, list subcommands via clap - Four suite adapters: custom, gaia, tau_bench, swe_bench Also fixes a pre-existing missing SseEvent::ToolResult match arm in the web gateway and adds FinishReason to the LLM module's public re-exports. Co-Authored-By: Claude Opus 4.6 <[email protected]> * feat: Add spot benchmark suite for end-to-end agent verification Adds a "spot" suite with 13 scenarios across 4 categories (smoke, tool use, multi-tool chaining, robustness) using multi-criterion assertions instead of simple text matching. Also adds an `error` field to TaskSubmission so suites can hard-fail on agent errors. Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: address audit findings in benchmarks crate - Fix O(n²) scoring loop by indexing tasks in a HashMap (was re-parsing JSONL per result) - Add UTF-8-safe truncation to prevent panic on multi-byte chars in channel capture - Wire setup_task/teardown_task into both sequential and parallel runner paths - Convert BenchRunner.suite from Box to Arc for parallel task setup/teardown - Add tracing::warn for placeholder scores in custom, swe_bench, tau_bench adapters - Add spot suite to CLI help text - Add doc comment clarifying tools_used HashSet behavior in SpotAssertions - Reorder match arms in create_suite to match KNOWN_SUITES alphabetical order Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: rewrite tasks.jsonl with scored results after scoring The JSONL file was only written during execution (pre-scoring), so the `results` command showed "pending" scores even after scoring completed. Now the runner rewrites the JSONL with final scored results, keeping task-level and aggregate data consistent. Co-Authored-By: Claude Opus 4.6 <[email protected]> * feat: prefix benchmark runs with model name and commit hash Run logs and results table now show the base model and short git commit hash, making it easy to correlate results with code versions. The commit hash is also persisted in run.json for historical tracking. Co-Authored-By: Claude Opus 4.6 <[email protected]> * feat: add 8 memory benchmark scenarios to spot suite Tests save-and-recall workflows using file tools: - daily tasks, reminders, meeting notes, append logs - detail extraction, todo priorities, multi-file ops - context updates (write-read-rewrite-verify) Total spot scenarios: 13 -> 21 Co-Authored-By: Claude Opus 4.6 <[email protected]> * chore: fmt channel.rs and gitignore bench-results Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: address critical and high findings from PR review - Fix race condition: parallel mode now writes JSONL after all tasks complete instead of concurrent unsynchronized appends - Fix UTF-8 panic: use .chars().take(25) instead of byte slicing on task_id which could panic on multi-byte characters - Remove dead code: max_iterations (parsed but never used), tool_whitelist() (declared but never called), MatrixEntry.tools (declared but never applied) - Eliminate double load_tasks(): cache task list on first load and reuse the index for scoring instead of re-reading from disk Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: relax smoke-greeting assertion to not demand parrot greeting The LLM often introduces itself without echoing "hello" back. Use a regex that accepts any reasonable self-introduction (hello, hi, hey, assistant, agent, help) instead of demanding a specific word. Co-Authored-By: Claude Opus 4.6 <[email protected]> * feat: 100% spot baseline (GPT-5.2 @ 2c43b83, 21/21 pass) Relax two brittle assertions: - smoke-greeting: use regex for any reasonable self-intro instead of demanding the model parrot "hello" - memory-update-context: drop response_not_contains PST since the model correctly says "not PST" which triggers the literal check - memory-multifile: lower min_tool_calls from 4 to 3, the model can batch two writes in one LLM turn Baseline results committed to benchmarks/baselines/ for regression tracking. Local runs stay in bench-results/ (gitignored). Results: 100.0% pass, 1.000 avg, $0.31 cost, 111s wall time Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: address remaining PR review comments - Replace .expect("semaphore closed") with proper error handling - Derive PartialEq on BenchScore for cleaner test assertions - Use ToPrimitive::to_f64() instead of string roundtrip in estimated_cost() - Validate SWE-bench inputs: task_id (path traversal), repo (owner/repo format), base_commit (valid git ref) with 5 new tests - Skip "pending" (unscored) entries during resume so they get re-executed - Use run.json mtime for find_latest_run (falls back to tasks.jsonl, then dir) - Move additional_tools() outside parallel loop to share Arc<[Tool]> across tasks - Add doc comments documenting known limitations (single-turn, resources, conversation) Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: reject absolute paths in SWE-bench and validate matrix config - is_safe_path_component now rejects paths starting with '/' - BenchConfig::from_file validates matrix is non-empty - Added tests for both validations Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: fail tasks on setup_task error and compute git hash once - setup_task failure now records an error TaskResult instead of continuing to run the task (both sequential and parallel paths) - git_short_hash() computed once per run instead of twice Co-Authored-By: Claude Opus 4.6 <[email protected]> --------- Co-authored-by: Claude Opus 4.6 <[email protected]>
IronClaw
Your secure personal AI assistant, always on your side
Philosophy • Features • Installation • Configuration • Security • Architecture
Philosophy
IronClaw is built on a simple principle: your AI assistant should work for you, not against you.
In a world where AI systems are increasingly opaque about data handling and aligned with corporate interests, IronClaw takes a different approach:
- Your data stays yours - All information is stored locally, encrypted, and never leaves your control
- Transparency by design - Open source, auditable, no hidden telemetry or data harvesting
- Self-expanding capabilities - Build new tools on the fly without waiting for vendor updates
- Defense in depth - Multiple security layers protect against prompt injection and data exfiltration
IronClaw is the AI assistant you can actually trust with your personal and professional life.
Features
Security First
- WASM Sandbox - Untrusted tools run in isolated WebAssembly containers with capability-based permissions
- Credential Protection - Secrets are never exposed to tools; injected at the host boundary with leak detection
- Prompt Injection Defense - Pattern detection, content sanitization, and policy enforcement
- Endpoint Allowlisting - HTTP requests only to explicitly approved hosts and paths
Always Available
- Multi-channel - REPL, HTTP webhooks, WASM channels (Telegram, Slack), and web gateway
- Docker Sandbox - Isolated container execution with per-job tokens and orchestrator/worker pattern
- Web Gateway - Browser UI with real-time SSE/WebSocket streaming
- Routines - Cron schedules, event triggers, webhook handlers for background automation
- Heartbeat System - Proactive background execution for monitoring and maintenance tasks
- Parallel Jobs - Handle multiple requests concurrently with isolated contexts
- Self-repair - Automatic detection and recovery of stuck operations
Self-Expanding
- Dynamic Tool Building - Describe what you need, and IronClaw builds it as a WASM tool
- MCP Protocol - Connect to Model Context Protocol servers for additional capabilities
- Plugin Architecture - Drop in new WASM tools and channels without restarting
Persistent Memory
- Hybrid Search - Full-text + vector search using Reciprocal Rank Fusion
- Workspace Filesystem - Flexible path-based storage for notes, logs, and context
- Identity Files - Maintain consistent personality and preferences across sessions
Installation
Prerequisites
- Rust 1.85+
- PostgreSQL 15+ with pgvector extension
- NEAR AI account (authentication handled via setup wizard)
Download or Build
Visit Releases page to see the latest updates.
Install via Windows Installer (Windows)
Download the Windows Installer and run it.
Install via powershell script (Windows)
irm https://github.com/nearai/ironclaw/releases/latest/download/ironclaw-installer.ps1 | iex
Install via shell script (macOS, Linux, Windows/WSL)
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/nearai/ironclaw/releases/latest/download/ironclaw-installer.sh | sh
Compile the source code (Cargo on Windows, Linux, macOS)
Install it with cargo, just make sure you have Rust installed on your computer.
# Clone the repository
git clone https://github.com/nearai/ironclaw.git
cd ironclaw
# Build
cargo build --release
# Run tests
cargo test
For full release (after modifying channel sources), run ./scripts/build-all.sh to rebuild channels first.
Database Setup
# Create database
createdb ironclaw
# Enable pgvector
psql ironclaw -c "CREATE EXTENSION IF NOT EXISTS vector;"
Configuration
Run the setup wizard to configure IronClaw:
ironclaw onboard
The wizard handles database connection, NEAR AI authentication (via browser OAuth),
and secrets encryption (using your system keychain). All settings are saved to
~/.ironclaw/settings.toml.
Security
IronClaw implements defense in depth to protect your data and prevent misuse.
WASM Sandbox
All untrusted tools run in isolated WebAssembly containers:
- Capability-based permissions - Explicit opt-in for HTTP, secrets, tool invocation
- Endpoint allowlisting - HTTP requests only to approved hosts/paths
- Credential injection - Secrets injected at host boundary, never exposed to WASM code
- Leak detection - Scans requests and responses for secret exfiltration attempts
- Rate limiting - Per-tool request limits to prevent abuse
- Resource limits - Memory, CPU, and execution time constraints
WASM ──► Allowlist ──► Leak Scan ──► Credential ──► Execute ──► Leak Scan ──► WASM
Validator (request) Injector Request (response)
Prompt Injection Defense
External content passes through multiple security layers:
- Pattern-based detection of injection attempts
- Content sanitization and escaping
- Policy rules with severity levels (Block/Warn/Review/Sanitize)
- Tool output wrapping for safe LLM context injection
Data Protection
- All data stored locally in your PostgreSQL database
- Secrets encrypted with AES-256-GCM
- No telemetry, analytics, or data sharing
- Full audit log of all tool executions
Architecture
┌────────────────────────────────────────────────────────────────┐
│ Channels │
│ ┌──────┐ ┌──────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ REPL │ │ HTTP │ │WASM Channels│ │ Web Gateway │ │
│ └──┬───┘ └──┬───┘ └──────┬──────┘ │ (SSE + WS) │ │
│ │ │ │ └──────┬──────┘ │
│ └─────────┴──────────────┴────────────────┘ │
│ │ │
│ ┌─────────▼─────────┐ │
│ │ Agent Loop │ Intent routing │
│ └────┬──────────┬───┘ │
│ │ │ │
│ ┌──────────▼────┐ ┌──▼───────────────┐ │
│ │ Scheduler │ │ Routines Engine │ │
│ │(parallel jobs)│ │(cron, event, wh) │ │
│ └──────┬────────┘ └────────┬─────────┘ │
│ │ │ │
│ ┌─────────────┼────────────────────┘ │
│ │ │ │
│ ┌───▼─────┐ ┌────▼────────────────┐ │
│ │ Local │ │ Orchestrator │ │
│ │Workers │ │ ┌───────────────┐ │ │
│ │(in-proc)│ │ │ Docker Sandbox│ │ │
│ └───┬─────┘ │ │ Containers │ │ │
│ │ │ │ ┌───────────┐ │ │ │
│ │ │ │ │Worker / CC│ │ │ │
│ │ │ │ └───────────┘ │ │ │
│ │ │ └───────────────┘ │ │
│ │ └─────────┬───────────┘ │
│ └──────────────────┤ │
│ │ │
│ ┌───────────▼──────────┐ │
│ │ Tool Registry │ │
│ │ Built-in, MCP, WASM │ │
│ └──────────────────────┘ │
└────────────────────────────────────────────────────────────────┘
Core Components
| Component | Purpose |
|---|---|
| Agent Loop | Main message handling and job coordination |
| Router | Classifies user intent (command, query, task) |
| Scheduler | Manages parallel job execution with priorities |
| Worker | Executes jobs with LLM reasoning and tool calls |
| Orchestrator | Container lifecycle, LLM proxying, per-job auth |
| Web Gateway | Browser UI with chat, memory, jobs, logs, extensions, routines |
| Routines Engine | Scheduled (cron) and reactive (event, webhook) background tasks |
| Workspace | Persistent memory with hybrid search |
| Safety Layer | Prompt injection defense and content sanitization |
Usage
# First-time setup (configures database, auth, etc.)
ironclaw onboard
# Start interactive REPL
cargo run
# With debug logging
RUST_LOG=ironclaw=debug cargo run
Development
# Format code
cargo fmt
# Lint
cargo clippy --all --benches --tests --examples --all-features
# Run tests
createdb ironclaw_test
cargo test
# Run specific test
cargo test test_name
- Telegram channel: See docs/TELEGRAM_SETUP.md for setup and DM pairing.
- Changing channel sources: Run
./channels-src/telegram/build.shbeforecargo buildso the updated WASM is bundled.
OpenClaw Heritage
IronClaw is a Rust reimplementation inspired by OpenClaw. See FEATURE_PARITY.md for the complete tracking matrix.
Key differences:
- Rust vs TypeScript - Native performance, memory safety, single binary
- WASM sandbox vs Docker - Lightweight, capability-based security
- PostgreSQL vs SQLite - Production-ready persistence
- Security-first design - Multiple defense layers, credential protection
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
