{"id":48639892,"url":"https://github.com/ginkida/rustyhand","last_synced_at":"2026-05-14T19:01:58.220Z","repository":{"id":348884391,"uuid":"1200228169","full_name":"ginkida/rustyhand","owner":"ginkida","description":"Agent OS in Rust — one binary, 37 agents, 26 LLM providers, 37 channels (Telegram/Discord/Slack...), MCP server, A2A protocol, 120+ API endpoints, web dashboard","archived":false,"fork":false,"pushed_at":"2026-05-14T16:12:43.000Z","size":4762,"stargazers_count":17,"open_issues_count":0,"forks_count":5,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-14T16:31:15.607Z","etag":null,"topics":["agent-framework","agent-os","ai","ai-agents","anthropic","autonomous-agents","chatbot","cli","discord-bot","llm","mcp","mcp-server","multi-agent","ollama","open-source","openai","rust","self-hosted","slack-bot","telegram-bot"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ginkida.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE-MIT","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":"ginkida"}},"created_at":"2026-04-03T07:06:57.000Z","updated_at":"2026-05-14T16:12:45.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ginkida/rustyhand","commit_stats":null,"previous_names":["ginkida/rustyhand"],"tags_count":63,"template":false,"template_full_name":null,"purl":"pkg:github/ginkida/rustyhand","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ginkida%2Frustyhand","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ginkida%2Frustyhand/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ginkida%2Frustyhand/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ginkida%2Frustyhand/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ginkida","download_url":"https://codeload.github.com/ginkida/rustyhand/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ginkida%2Frustyhand/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33039250,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-13T13:14:54.681Z","status":"online","status_checked_at":"2026-05-14T02:00:06.663Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-framework","agent-os","ai","ai-agents","anthropic","autonomous-agents","chatbot","cli","discord-bot","llm","mcp","mcp-server","multi-agent","ollama","open-source","openai","rust","self-hosted","slack-bot","telegram-bot"],"created_at":"2026-04-09T17:14:05.254Z","updated_at":"2026-05-14T19:01:58.211Z","avatar_url":"https://github.com/ginkida.png","language":"Rust","funding_links":["https://github.com/sponsors/ginkida"],"categories":["⚙️ Implementations \u0026 Libraries"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"crates/rusty-hand-api/static/logo.png\" width=\"500\" alt=\"RustyHand Logo\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eRustyHand\u003c/h1\u003e\n\u003ch3 align=\"center\"\u003eThe Agent Operating System\u003c/h3\u003e\n\n\u003cp align=\"center\"\u003e\n  Open-source Agent OS built in Rust. 124K LOC. 10 crates. 1,577 tests. Zero clippy warnings.\u003cbr/\u003e\n  \u003cstrong\u003eOne binary. Autonomous Telegram agent. Agents that actually work for you.\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/ginkida/rustyhand#quick-start\"\u003eQuick Start\u003c/a\u003e \u0026bull;\n  \u003ca href=\"https://github.com/ginkida/rustyhand#cli-reference\"\u003eCLI Reference\u003c/a\u003e \u0026bull;\n  \u003ca href=\"https://github.com/ginkida/rustyhand#api-endpoints\"\u003eAPI Docs\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/language-Rust-orange?style=flat-square\" alt=\"Rust\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/license-MIT-blue?style=flat-square\" alt=\"MIT\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/version-0.7.41-green?style=flat-square\" alt=\"v0.7.41\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/tests-1,577%20passing-brightgreen?style=flat-square\" alt=\"Tests\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/clippy-0%20warnings-brightgreen?style=flat-square\" alt=\"Clippy\" /\u003e\n\u003c/p\u003e\n\n---\n\n\u003e **v0.7.33–v0.7.41 — Demo Mode + persistence + product polish (May 2026)**\n\u003e\n\u003e Clone → `cargo run --release start` → open the dashboard → talk to an agent.\n\u003e **No API key required.** When no provider key is found in the environment,\n\u003e RustyHand falls back to a deterministic mock driver and seeds four sample\n\u003e resources so every major dashboard page is interactive on first visit:\n\u003e\n\u003e - **`rusty`** welcome agent (chat-ready)\n\u003e - **`demo-pipeline`** workflow (2-step sample, click to run)\n\u003e - sample agent-spawn trigger\n\u003e - **`demo-daily-ping`** cron job (registered, disabled by default)\n\u003e\n\u003e A welcome modal on first visit lists all four with one-click navigation.\n\u003e The CLI startup banner and Docker entrypoint both announce demo mode\n\u003e as a feature instead of a missing-key warning. Set `ANTHROPIC_API_KEY`\n\u003e (or any of 26 other supported providers' env vars) and restart for real\n\u003e LLM responses, or `RUSTYHAND_DISABLE_DEMO_MODE=1` to force a hard fail.\n\u003e\n\u003e Also new since v0.7.27:\n\u003e - **Audit log persists** — Merkle hash chain at `~/.rustyhand/data/audit.jsonl`,\n\u003e   replayed and validated on boot.\n\u003e - **Triggers and workflows persist** — webhook triggers and pipeline\n\u003e   definitions survive daemon restart, including subtle state like\n\u003e   `max_fires` auto-disable and trigger fire-counts.\n\u003e - **31 API response-shape contract tests** — every endpoint the dashboard\n\u003e   or CLI reads is pinned to its JSON shape, so a server-side rename fails\n\u003e   CI loudly instead of producing a silently-empty widget.\n\u003e - **6 mock-driver e2e tests** — full HTTP → kernel → driver → result\n\u003e   pipeline runs in CI without burning real LLM credits, covering agent\n\u003e   message round-trip, workflow run, all three CronAction variants, and\n\u003e   the demo-mode auto-spawn flow.\n\u003e - **wasmtime 42 → 44** for [RUSTSEC-2026-0114](https://rustsec.org/advisories/RUSTSEC-2026-0114).\n\n---\n\n## Origin\n\nThis project is based on [OpenFang](https://github.com/RightNow-AI/openfang) by RightNow-AI, modified and extended for custom use cases.\n\n## Table of Contents\n\n- [What is RustyHand?](#what-is-rustyhand)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Telegram Setup](#telegram-setup)\n- [Configuration](#configuration)\n- [CLI Reference](#cli-reference)\n- [Autonomous Templates](#autonomous-templates)\n- [40 Pre-built Agent Templates](#40-pre-built-agent-templates)\n- [Channel Adapters](#channel-adapters)\n- [7 LLM Providers](#7-llm-providers)\n- [Architecture](#architecture)\n- [API Endpoints](#api-endpoints)\n- [Dashboard](#dashboard)\n- [Security](#security)\n- [Deployment](#deployment)\n- [Docker Environment Variables](#docker-environment-variables)\n- [Development](#development)\n- [Benchmarks](#benchmarks)\n- [MCP Integration (for AI Agents)](#mcp-integration-for-ai-agents)\n- [How It Works — Data Flow](#how-it-works--data-flow)\n- [License](#license)\n\n---\n\n## What is RustyHand?\n\nRustyHand is an **open-source Agent Operating System** — not a chatbot framework, not a Python wrapper around an LLM. It is a full operating system for autonomous agents, built from scratch in Rust.\n\nTraditional agent frameworks wait for you to type something. RustyHand runs **autonomous agents that work for you** — on schedules, 24/7, building knowledge graphs, monitoring targets, generating leads, managing social media, and reporting results directly to your **Telegram chat**.\n\n### Telegram-First Autonomous Agent\n\nTelegram is the primary interface for RustyHand agents. Your agent can:\n\n| Capability | How it works |\n|------------|-------------|\n| **See photos** | Auto-describes images via vision API |\n| **Hear voice** | Auto-transcribes voice messages via Whisper |\n| **Receive files** | Downloads documents, forwards to agent |\n| **Send files/photos/voice** | Sends generated content back to chat |\n| **Ask permission** | Inline keyboard buttons (Approve/Reject) pushed automatically |\n| **Show progress** | Real-time tool-use updates: \"⚙️ web_search...\" → \"✅ Done\" |\n| **Report autonomously** | Background tasks push results to your chat without prompting |\n| **61 built-in tools** | Shell, web/news search, browser (wait, JS exec, scroll, download), RAG, knowledge graph |\n| **Markdown formatting** | Bold, italic, code blocks render natively in Telegram |\n| **Reply threading** | Responses reply to the user's message for clean conversation flow |\n| **Sticker/GIF/Location** | Agent understands stickers, animations, and shared locations |\n\nThe entire system compiles to a **single ~32MB binary**. One install, one command, your agents are live.\n\n---\n\n## Installation\n\n### One-liner (Linux / macOS / WSL)\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/ginkida/rustyhand/main/scripts/install.sh | sh\n```\n\nEnvironment variables:\n- `RUSTY_HAND_INSTALL_DIR` — custom install path (default: `~/.rustyhand/bin`)\n- `RUSTY_HAND_VERSION` — pin a specific version tag\n\n### Windows (PowerShell)\n\n```powershell\nirm https://raw.githubusercontent.com/ginkida/rustyhand/main/scripts/install.ps1 | iex\n```\n\n### From source\n\n```bash\ngit clone https://github.com/ginkida/rustyhand.git\ncd rustyhand\ncargo build --release -p rusty-hand-cli\n# Binary: target/release/rustyhand (or rustyhand.exe on Windows)\n```\n\nRequires Rust 1.75+ (stable). The `rust-toolchain.toml` in the repo will auto-select the right toolchain.\n\n### Docker\n\n```bash\ndocker compose up --build\n# Dashboard at http://localhost:4200\n```\n\nOr run directly with env vars (no config.toml needed):\n\n```bash\ndocker run -p 4200:4200 \\\n  -e ANTHROPIC_API_KEY=your-key \\\n  -e RUSTYHAND_API_KEY=my-secret-bearer-token \\\n  -v rustyhand-data:/data \\\n  ghcr.io/ginkida/rustyhand:latest\n```\n\nAll configuration can be set via `RUSTYHAND_*` environment variables — see [Docker Environment Variables](#docker-environment-variables).\n\n---\n\n## Quick Start\n\n### Option Zero: Try it in 30 seconds, no API key\n\nThe fastest possible first run, no credentials, no configuration:\n\n```bash\ngit clone https://github.com/ginkida/rustyhand\ncd rustyhand\ncargo run --release -- start\n# In another tab: open http://localhost:4200\n```\n\nThe dashboard banner will read **\"DEMO MODE — running on the deterministic\nmock driver.\"** Spawn an agent, send a message, watch the agent loop run,\nsession grow, audit log fill up. Every reply is `[mock] \u003cyour message\u003e` —\nunmistakably demo, but the full pipeline (sessions, persistence, workflows,\ncron jobs) is real. Set `ANTHROPIC_API_KEY` (or any of 26 other supported\nproviders' env vars) and restart for real LLM responses.\n\n### Option A: Docker (fastest)\n\n```bash\ndocker run -d --name rustyhand \\\n  -p 4200:4200 \\\n  -e ANTHROPIC_API_KEY=your-key \\\n  -v rustyhand-data:/data \\\n  ghcr.io/ginkida/rustyhand:latest\n\n# Dashboard: http://localhost:4200\n# API:       http://localhost:4200/api/health\n```\n\nTo secure the API with a bearer token:\n\n```bash\ndocker run -d --name rustyhand \\\n  -p 4200:4200 \\\n  -e ANTHROPIC_API_KEY=your-key \\\n  -e RUSTYHAND_API_KEY=my-secret-token \\\n  -v rustyhand-data:/data \\\n  ghcr.io/ginkida/rustyhand:latest\n\n# Now all API calls require: -H \"Authorization: Bearer my-secret-token\"\n```\n\nSee [Docker Environment Variables](#docker-environment-variables) for all options.\n\n### Option B: From binary\n\n```bash\n# 1. Initialize — creates ~/.rustyhand/ and walks you through provider setup\nrustyhand init\n\n# 2. Start the daemon (API + kernel)\nrustyhand start\n# Dashboard is live at http://localhost:4200\n\n# 3. Chat with the default agent\nrustyhand chat\n\n# 4. Spawn a pre-built agent\nrustyhand agent new coder\n\n# 5. Send a one-shot message\nrustyhand message researcher \"What are the emerging trends in AI agent frameworks?\"\n\n# 6. Launch the interactive TUI dashboard\nrustyhand tui\n\n# 7. Run diagnostics\nrustyhand doctor\n```\n\n---\n\n## Telegram Setup\n\nTelegram is the **primary channel** for interacting with RustyHand agents. Setup takes 2 minutes:\n\n### 1. Create a Telegram Bot\n\n1. Message [@BotFather](https://t.me/BotFather) on Telegram\n2. Send `/newbot`, follow prompts, get your bot token\n3. Set the token: `export TELEGRAM_BOT_TOKEN=123456:ABC-DEF...`\n\n### 2. Configure RustyHand\n\n```toml\n# ~/.rustyhand/config.toml\n[channels.telegram]\nbot_token_env = \"TELEGRAM_BOT_TOKEN\"\nallowed_users = []    # Empty = allow anyone. Set [123456] for specific user IDs.\n```\n\n### 3. Start and chat\n\n```bash\nrustyhand start\n# Open Telegram, message your bot\n# /agents — list agents\n# /agent assistant — select an agent\n# Send text, photos, voice messages — the agent handles all of them\n```\n\n### What your agent can do in Telegram\n\n```\nYou:     [send a voice message]\nAgent:   [auto-transcribes via Whisper, processes your request]\n\nYou:     [send a photo]\nAgent:   [auto-describes the image, responds based on what it sees]\n\nYou:     \"Search for Rust 2024 edition changes\"\nAgent:   ⚙️ web_search...\n         ✅ web_search\n         Here are the key changes in Rust 2024...\n\nAgent:   ⚠️ Agent \"coder\" wants to execute:\n         `shell_exec: rm -rf /tmp/cache`\n         [✅ Approve] [❌ Reject]    ⏱️ 60s\n\nYou:     [click ✅ Approve]\nAgent:   Done! Cache cleared.\n```\n\n### Autonomous mode\n\nAgents with `schedule_mode = \"continuous\"` or `\"periodic\"` run in the background and **push results to your Telegram chat automatically** — no prompting needed.\n\n```toml\n# agent.toml\n[schedule]\nmode = \"periodic\"\ncron = \"0 9 * * *\"    # Every day at 9 AM\n```\n\nThe agent wakes up, performs its task, and sends the result to the last Telegram chat it was used in.\n\n---\n\n## Configuration\n\nRustyHand can be configured in two ways:\n- **Config file** (`~/.rustyhand/config.toml`) — for binary installs\n- **Environment variables** (`RUSTYHAND_*`) — for Docker, see [Docker Environment Variables](#docker-environment-variables)\n\n### API Authentication\n\nWhen `api_key` is set, all endpoints (except `/api/health`) require a Bearer token:\n\n```bash\n# In config.toml:\napi_key = \"my-secret-token\"\n\n# Or via env var (Docker):\nRUSTYHAND_API_KEY=my-secret-token\n\n# Clients must include the header:\ncurl -H \"Authorization: Bearer my-secret-token\" http://localhost:4200/api/agents\n```\n\nWithout `api_key`, the API is open (fine for local development).\n\n### Config file\n\nLocation: `~/.rustyhand/config.toml`\n\n```toml\n# API server settings\napi_key = \"your-bearer-token\"          # Recommended for non-localhost access\napi_listen = \"127.0.0.1:4200\"          # HTTP bind address\n\n[default_model]\nprovider = \"anthropic\"                 # anthropic, kimi, deepseek, zhipu, minimax, openrouter, ollama\nmodel = \"claude-sonnet-4-20250514\"     # Model identifier\napi_key_env = \"ANTHROPIC_API_KEY\"      # Env var holding the API key\n# base_url = \"https://api.anthropic.com\"  # Optional: override endpoint\n\n[memory]\ndecay_rate = 0.05                      # Memory confidence decay\n# sqlite_path = \"~/.rustyhand/data/rustyhand.db\"\n\n[network]\nlisten_addr = \"127.0.0.1:4200\"        # RHP P2P listen address\n# shared_secret = \"\"                  # Required for P2P authentication\n\n# Session compaction (LLM-based context management)\n[compaction]\nthreshold = 80                         # Compact when messages exceed this count\nkeep_recent = 20                       # Keep this many recent messages\nmax_summary_tokens = 1024\n\n# Usage display in chat responses\n# usage_footer = \"Full\"               # Off, Tokens, Cost, Full\n\n# Channel adapters (tokens via env vars)\n[telegram]\nbot_token_env = \"TELEGRAM_BOT_TOKEN\"\nallowed_users = []                     # Empty = allow all\n\n[discord]\nbot_token_env = \"DISCORD_BOT_TOKEN\"\n# guild_ids = []\n\n[slack]\nbot_token_env = \"SLACK_BOT_TOKEN\"\napp_token_env = \"SLACK_APP_TOKEN\"\n\n# MCP server connections\n[[mcp_servers]]\nname = \"filesystem\"\ncommand = \"npx\"\nargs = [\"-y\", \"@modelcontextprotocol/server-filesystem\", \"/tmp\"]\n```\n\n### Environment variables\n\nCopy `.env.example` to `~/.rustyhand/.env` and fill in the keys you need:\n\n```bash\n# LLM providers — set ANY key and RustyHand auto-detects the provider.\n# Priority order: Anthropic → Kimi → DeepSeek → Zhipu → MiniMax → OpenRouter.\nANTHROPIC_API_KEY=sk-ant-...       # Claude Opus / Sonnet / Haiku (default)\nKIMI_API_KEY=sk-kimi-...            # Kimi Code — Anthropic-compat, 256K ctx\nDEEPSEEK_API_KEY=sk-...             # DeepSeek V4 Flash / V4 Pro (V3/R1 legacy, deprecated 2026-07-24)\nZHIPU_API_KEY=...                   # Zhipu GLM-4.6\nMINIMAX_API_KEY=eyJ...              # MiniMax M1 / M2.7 (1M context)\nOPENROUTER_API_KEY=sk-or-...        # Universal gateway (GPT/Gemini/Grok/etc.)\n\n# Local LLM — no key needed, just run `ollama serve`\n# (Base URL defaults to http://localhost:11434/v1 — override only if needed)\n\n# Embedding-only upstreams (independent of LLM provider)\nVOYAGE_API_KEY=pa-...                # Voyage AI (voyage-3-lite, code, legal, ...)\n# OPENAI_API_KEY can also be used for text-embedding-3-* — not for LLM completion.\n\n# Channel tokens\nTELEGRAM_BOT_TOKEN=123456:ABC-...\nDISCORD_BOT_TOKEN=...\nSLACK_BOT_TOKEN=xoxb-...\nSLACK_APP_TOKEN=xapp-...\n\n# Log level\nRUST_LOG=info\n# RUST_LOG=rusty_hand=debug            # Debug RustyHand only\n```\n\n### Manage config from the CLI\n\n```bash\nrustyhand config show                              # Print current config\nrustyhand config edit                              # Open in $EDITOR\nrustyhand config get default_model.provider        # Read a key\nrustyhand config set default_model.provider kimi   # Switch provider\nrustyhand config set-key kimi                      # Interactively save API key\nrustyhand config test-key kimi                     # Verify connectivity\n```\n\n---\n\n## CLI Reference\n\n### Core commands\n\n| Command | Description |\n|---------|-------------|\n| `rustyhand init` | Initialize `~/.rustyhand/` and default config |\n| `rustyhand start` | Start the daemon (API server + kernel) |\n| `rustyhand stop` | Stop the running daemon |\n| `rustyhand status [--json]` | Show kernel status |\n| `rustyhand health [--json]` | Quick daemon health check |\n| `rustyhand doctor [--repair]` | Run diagnostic checks |\n| `rustyhand tui` | Launch interactive TUI dashboard |\n| `rustyhand dashboard` | Open web dashboard in browser |\n| `rustyhand chat [agent]` | Quick chat with an agent |\n| `rustyhand message \u003cagent\u003e \u003ctext\u003e` | Send a one-shot message |\n| `rustyhand logs [--follow] [--lines N]` | Tail the log file |\n| `rustyhand reset [--confirm]` | Reset local config and state |\n\n### Agents\n\n| Command | Description |\n|---------|-------------|\n| `rustyhand agent new [template]` | Spawn from a template (interactive picker if omitted) |\n| `rustyhand agent spawn \u003cmanifest.toml\u003e` | Spawn from a manifest file |\n| `rustyhand agent list [--json]` | List running agents |\n| `rustyhand agent chat \u003cid\u003e` | Interactive chat with an agent by ID |\n| `rustyhand agent kill \u003cid\u003e` | Kill an agent |\n\n### Channels\n\n| Command | Description |\n|---------|-------------|\n| `rustyhand channel list` | List configured channels and status |\n| `rustyhand channel setup [name]` | Interactive channel setup wizard |\n| `rustyhand channel test \u003cname\u003e` | Send a test message |\n| `rustyhand channel enable \u003cname\u003e` | Enable a channel |\n| `rustyhand channel disable \u003cname\u003e` | Disable a channel |\n\n### Models\n\n| Command | Description |\n|---------|-------------|\n| `rustyhand models list [--provider X]` | Browse available models |\n| `rustyhand models aliases` | Show model shorthand names |\n| `rustyhand models providers` | List providers and their auth status |\n| `rustyhand models set [model]` | Set the default model |\n\n### Skills\n\n| Command | Description |\n|---------|-------------|\n| `rustyhand skill install \u003csource\u003e` | Install from ClawHub, local path, or git URL |\n| `rustyhand skill list` | List installed skills |\n| `rustyhand skill search \u003cquery\u003e` | Search ClawHub marketplace |\n| `rustyhand skill remove \u003cname\u003e` | Remove a skill |\n| `rustyhand skill create` | Scaffold a new skill |\n\n### Workflows \u0026 scheduling\n\n| Command | Description |\n|---------|-------------|\n| `rustyhand workflow list` | List workflows |\n| `rustyhand workflow create \u003cfile.json\u003e` | Create from JSON |\n| `rustyhand workflow run \u003cid\u003e \u003cinput\u003e` | Run a workflow |\n| `rustyhand trigger list [--agent-id X]` | List event triggers |\n| `rustyhand trigger create \u003cagent-id\u003e \u003cpattern-json\u003e` | Create a trigger |\n| `rustyhand cron list` | List scheduled jobs |\n\n### Integrations (MCP)\n\n| Command | Description |\n|---------|-------------|\n| `rustyhand add \u003cname\u003e [--key TOKEN]` | Install an integration (e.g., `github`, `notion`) |\n| `rustyhand remove \u003cname\u003e` | Remove an integration |\n| `rustyhand integrations [query]` | List / search integrations |\n\n### Security \u0026 vault\n\n| Command | Description |\n|---------|-------------|\n| `rustyhand vault init` | Initialize the credential vault (AES-256-GCM) |\n| `rustyhand vault set \u003ckey\u003e` | Store a credential |\n| `rustyhand vault list` | List stored keys (values hidden) |\n| `rustyhand vault remove \u003ckey\u003e` | Remove a credential |\n| `rustyhand security audit` | View the audit trail |\n| `rustyhand security rbac` | Manage access control |\n\n### Other\n\n| Command | Description |\n|---------|-------------|\n| `rustyhand mcp` | Start MCP server over stdio |\n| `rustyhand sessions [agent]` | List conversation sessions |\n| `rustyhand approvals list` | List pending approval requests |\n| `rustyhand qr` | Generate device pairing QR code |\n| `rustyhand onboard` | Interactive onboarding wizard |\n| `rustyhand completion \u003cshell\u003e` | Generate shell completions (bash/zsh/fish/powershell) |\n| `rustyhand new skill\\|integration` | Scaffold a new skill or integration |\n\nAll list/status commands support `--json` for scripting.\n\n---\n\n## Autonomous Templates\n\nRustyHand ships autonomous templates as agent presets in the dashboard. They are not a separate runtime entity: each template creates a normal agent, and you can optionally attach a cron schedule during creation.\n\nEach autonomous template bundles:\n- **Agent preset** — model, profile, prompt, and capabilities\n- **Schedule defaults** — suggested cron expression and trigger message\n- **Operational playbook** — multi-phase prompt for recurring work\n- **Guardrails** — approval and tool constraints where needed\n\n### Bundled Autonomous Templates\n\n| Template | What It Does |\n|------|-------------|\n| **GitHub Monitor** | Monitors repositories, runs tests, detects regressions, and files issues on a schedule. |\n| **Web Researcher** | Runs recurring research sweeps, cross-references sources, and produces structured reports. |\n| **Content Clipper** | Processes long-form video into short clips with captions and packaging. |\n| **Lead Generator** | Discovers and enriches qualified leads on a recurring schedule. |\n| **Intel Collector** | Monitors targets, detects changes, and updates a living knowledge base. |\n| **Predictor** | Collects signals, updates forecasts, and tracks prediction accuracy. |\n| **Twitter Manager** | Creates, schedules, and reviews social content with approval controls. |\n| **Web Browser** | Executes recurring browser automation tasks with strict purchase approval gates. |\n\nUse the dashboard to launch one: **Agents → Templates** or **Create Agent → enable schedule**.\n\n---\n\n## 40 Pre-built Agent Templates\n\nSpawn any template with `rustyhand agent new \u003cname\u003e`:\n\n| Template | Description |\n|----------|-------------|\n| `analyst` | Data analysis and reporting |\n| `api-monitor` | API endpoint monitoring |\n| `architect` | System design and architecture |\n| `assistant` | General-purpose assistant |\n| `capability-builder` | **Meta-agent** — writes new skills at runtime via privileged `skill_install` tool |\n| `ci-monitor` | CI/CD pipeline monitoring |\n| `code-reviewer` | Code review and feedback |\n| `coder` | Software development |\n| `coordinator` | **Meta-agent** — delegates work across other agents via `agent_send` |\n| `customer-support` | Customer support |\n| `dag-monitor` | DAG/workflow monitoring |\n| `data-scientist` | Data science and ML |\n| `db-reporter` | Database reporting |\n| `debugger` | Bug investigation |\n| `devops-lead` | DevOps and infrastructure |\n| `diagnostic` | **Meta-agent** — read-only observability (self-history, metrics, audit log) |\n| `doc-writer` | Documentation |\n| `email-assistant` | Email drafting and management |\n| `health-tracker` | Health and fitness tracking |\n| `hello-world` | Starter agent for new users |\n| `home-automation` | Smart home control |\n| `legal-assistant` | Legal document review |\n| `log-analyzer` | Log analysis and alerting |\n| `meeting-assistant` | Meeting notes and follow-ups |\n| `ops` | Operations management |\n| `orchestrator` | Multi-agent orchestration |\n| `personal-finance` | Financial tracking |\n| `planner` | Project planning |\n| `recruiter` | Recruiting and screening |\n| `researcher` | Research and analysis |\n| `sales-assistant` | Sales support |\n| `security-auditor` | Security analysis |\n| `slack-notifier` | Slack notification automation |\n| `social-media` | Social media management |\n| `test-engineer` | Testing and QA |\n| `translator` | Multi-language translation |\n| `travel-planner` | Travel planning |\n| `tutor` | Education and tutoring |\n| `weekly-digest` | Weekly summary reports |\n| `writer` | Content writing |\n\n### Agent manifest format (`agent.toml`)\n\n```toml\nname = \"hello-world\"\nversion = \"0.1.0\"\ndescription = \"A friendly greeting agent\"\nauthor = \"rusty-hand\"\nmodule = \"builtin:chat\"\n\n[model]\nprovider = \"anthropic\"\nmodel = \"claude-sonnet-4-20250514\"\nmax_tokens = 4096\ntemperature = 0.6\nsystem_prompt = \"\"\"Your system prompt here...\"\"\"\n\n[resources]\nmax_llm_tokens_per_hour = 100000\n\n[capabilities]\ntools = [\"file_read\", \"file_list\", \"web_fetch\", \"web_search\", \"memory_store\", \"memory_recall\"]\nnetwork = [\"*\"]\nmemory_read = [\"*\"]\nmemory_write = [\"self.*\"]\nagent_spawn = false\n```\n\n---\n\n## Channel Adapters\n\nRustyHand ships three messaging adapters — the ones whose APIs work without\na public webhook URL, which is what most users actually run:\n\n- **Telegram** — long-polling Bot API (`@BotFather` token).\n- **Discord** — Gateway WebSocket (Developer Portal bot token).\n- **Slack** — Socket Mode (`xapp-` app token + `xoxb-` bot token).\n\nEach adapter supports per-channel model overrides, DM/group policies, rate\nlimiting, and output formatting.\n\n\u003e v0.7.4 and earlier shipped 38 adapters (Matrix, WhatsApp, Signal, Teams,\n\u003e IRC, ...). They were dropped in v0.7.5 — most were webhook-only and broken\n\u003e in typical localhost / home-Docker setups, and many were sprint fillers\n\u003e without real usage. Pin to v0.7.4 if you need them, or open an issue and\n\u003e we'll discuss a route.\n\n### Channel policies\n\nConfigure each channel under the `[channels.*]` table in `config.toml`:\n\n```toml\n[channels.telegram]\nbot_token_env = \"TELEGRAM_BOT_TOKEN\"\nallowed_users = [123456789]            # Restrict to specific users\ndefault_agent = \"assistant\"            # Route inbound messages here\n\n[channels.telegram.overrides]\ndm_policy = \"Respond\"                  # Respond | AllowedOnly | Ignore\ngroup_policy = \"MentionOnly\"           # All | MentionOnly | CommandsOnly | Ignore\noutput_format = \"TelegramHtml\"         # Markdown | TelegramHtml | SlackMrkdwn | PlainText\n```\n\n### Zero-config Telegram on Docker\n\nSince v0.7.10, the Docker entrypoint generates `default_agent = \"assistant\"`\nunder each `[channels.*]` section automatically (override with the\n`RUSTYHAND_{TELEGRAM,DISCORD,SLACK}_DEFAULT_AGENT` env var, or set it to\nan empty string to leave it blank). The bundled `assistant` manifest uses\n`provider = \"anthropic\"`, so a fresh container with `ANTHROPIC_API_KEY`\nplus a bot token replies to the first message without any extra config or\n`rustyhand init` step.\n\nIf the router can't resolve a target at message time (no\n`default_agent`, no bindings, no direct routes), the bridge tries to\nauto-route to a running agent first, then to spawn one of the bundled\nmeta-agents (`assistant` → `coordinator` → `coder`). The user only sees\na config-pointing error message when every fallback fails.\n\n---\n\n## 7 LLM Providers\n\nRustyHand v0.7.0 ships with a deliberately lean set of 7 providers, driven by 2 wire protocols (Anthropic Messages API + OpenAI-compatible Chat Completions). Anthropic and **Kimi Code** are the two first-class coding providers:\n\n| Provider | Env var | Role |\n|---|---|---|\n| **Anthropic** (default) | `ANTHROPIC_API_KEY` | Claude Opus/Sonnet/Haiku — best-in-class tool use + extended thinking |\n| **Kimi (Moonshot)** | `KIMI_API_KEY` | Kimi Code — Anthropic-compatible, 256K ctx, vision, reasoning |\n| **DeepSeek** | `DEEPSEEK_API_KEY` | V4 Flash + V4 Pro — fast \u0026 reasoning (V3/R1 deprecated 2026-07-24). Also exposes an Anthropic-compatible endpoint at `/anthropic` |\n| **Zhipu GLM** | `ZHIPU_API_KEY` | GLM-4.6 — Chinese frontier |\n| **MiniMax** | `MINIMAX_API_KEY` | M1/M2 — 1M context |\n| **OpenRouter** | `OPENROUTER_API_KEY` | Universal gateway — any model via one key |\n| **Ollama** | (no key) | Local on `localhost:11434` |\n\nDefault auto-detect order: Anthropic → Kimi → DeepSeek → Zhipu → MiniMax → OpenRouter. Set whichever key you have; RustyHand picks the first one found.\n\nPrefer Kimi? Set `KIMI_API_KEY` and auto-detect will route to `kimi-for-coding` on the Kimi Code endpoint (`api.kimi.com/coding`). Change anytime via `rustyhand config set default_model.provider \u003cname\u003e`.\n\n\u003e v0.6.x shipped 27 providers (OpenAI, Gemini, Groq, xAI, Copilot, Mistral, Together, Fireworks, Perplexity, Cohere, AI21, Cerebras, SambaNova, HuggingFace, Replicate, vLLM, LM Studio, Moonshot, Qwen, Qianfan, Bedrock). They were removed in v0.7.0 — use `openrouter` to reach any of those models through one gateway.\n\nFeatures:\n- Intelligent routing with task complexity scoring\n- Automatic fallback between providers\n- Per-model pricing and cost tracking\n- Per-agent budget limits\n\n### Embedding providers\n\nVector embeddings power semantic memory recall. The catalog is independent of\nthe LLM provider list — `OPENAI_API_KEY` is still usable for text-embedding-3-*\neven though OpenAI is not a first-class LLM provider in v0.7.0.\n\nAuto-detected at boot (first available wins):\n\n| Provider | Models | Key required |\n|----------|--------|-------------|\n| **Voyage AI** | voyage-3, voyage-3-lite, voyage-code-3, voyage-finance-2, voyage-law-2, voyage-multilingual-2 | `VOYAGE_API_KEY` |\n| **OpenAI** (embedding-only) | text-embedding-3-small, text-embedding-3-large, text-embedding-ada-002 | `OPENAI_API_KEY` |\n| **Ollama** | nomic-embed-text, all-MiniLM-L6-v2, mxbai-embed-large | No |\n| **Any OpenAI-compat endpoint** | whatever the server exposes | provider-specific |\n\nConfigure explicitly in `config.toml`:\n\n```toml\n[memory]\nembedding_provider = \"voyage\"              # or \"openai\", \"ollama\", \"\u003ccustom\u003e\"\nembedding_api_key_env = \"VOYAGE_API_KEY\"\n```\n\nOr let RustyHand auto-detect: it probes Voyage → OpenAI → Ollama at boot and uses the first available provider. Falls back to text search (SQLite LIKE) when no embedding driver is found.\n\n```bash\nrustyhand models list                 # Browse all models\nrustyhand models list --provider kimi # Filter by provider\nrustyhand models set claude-sonnet    # Set default model\n```\n\n---\n\n## Architecture\n\n10 Rust crates with a modular kernel design:\n\n```\nrusty-hand-types       Core types, traits, config, taint tracking, Ed25519 manifest signing\n    |\n    +-- rusty-hand-memory      SQLite persistence, vector embeddings (Voyage/OpenAI/Ollama), session compaction\n    +-- rusty-hand-wire        RHP P2P protocol (JSON-RPC over TCP, HMAC-SHA256 auth)\n    +-- rusty-hand-channels    Telegram + Discord + Slack adapters with rate limiting\n    +-- rusty-hand-skills      Skill system + ClawHub marketplace\n    +-- rusty-hand-extensions  25 MCP integrations, AES-256-GCM credential vault, OAuth2\n    |\n    +-- rusty-hand-runtime     Agent loop, 2 LLM drivers (Anthropic + OpenAI-compat), 53+ tools, WASM sandbox, MCP, A2A\n    |\n    +-- rusty-hand-kernel      Orchestration: lifecycle, scheduling, metering, RBAC, workflows\n    |\n    +-- rusty-hand-api         Axum HTTP daemon, 120+ endpoints, WebSocket, SSE, OpenAI-compat\n    |\n    +-- rusty-hand-cli         CLI binary + TUI dashboard (ratatui)\n```\n\n### Key internals\n\n| Concept | Implementation |\n|---------|---------------|\n| **Agent loop** | `rusty-hand-runtime` — iterative LLM call → tool execution → response cycle |\n| **Kernel** | `RustyHandKernel` struct (40+ fields) — central orchestration for all subsystems |\n| **AppState** | Bridges kernel to HTTP routes via `Arc\u003cRustyHandKernel\u003e` in Axum state |\n| **Sandbox** | WASM (wasmtime) with fuel metering + epoch interruption + watchdog thread |\n| **Memory** | SQLite + vector embeddings (Voyage AI, OpenAI, Ollama) for semantic search + knowledge graph |\n| **Metering** | Per-agent token/cost tracking with budget enforcement and alerts |\n| **P2P** | RHP (RustyHand Protocol) — JSON-RPC over TCP, Ed25519 identity, nonce-based auth |\n| **A2A** | Agent-to-Agent protocol for cross-instance agent communication |\n\n---\n\n## API Endpoints\n\nDefault: `http://127.0.0.1:4200`. All endpoints return JSON. Authenticate with `Authorization: Bearer \u003capi_key\u003e` when `api_key` is set in config.\n\n### Health \u0026 status\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/api/health` | GET | Health check |\n| `/api/status` | GET | Full kernel status |\n\n### Agents\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/api/agents` | GET | List all agents |\n| `/api/agents` | POST | Spawn a new agent |\n| `/api/agents/{id}` | GET | Agent details |\n| `/api/agents/{id}` | DELETE | Kill an agent |\n| `/api/agents/{id}/message` | POST | Send message (triggers LLM) |\n\n### Budget\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/api/budget` | GET | Global budget status |\n| `/api/budget` | PUT | Update budget settings |\n| `/api/budget/agents` | GET | Per-agent cost ranking |\n| `/api/budget/agents/{id}` | GET | Single agent budget detail |\n\n### Network \u0026 P2P\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/api/network/status` | GET | RHP network status |\n| `/api/peers` | GET | Connected peers |\n\n### A2A (Agent-to-Agent)\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/api/a2a/agents` | GET | External A2A agents |\n| `/api/a2a/discover` | POST | Discover agent at URL |\n| `/api/a2a/send` | POST | Send task to external agent |\n| `/api/a2a/tasks/{id}/status` | GET | Check task status |\n\n### OpenAI-compatible\n\nDrop-in replacement for OpenAI API:\n\n```bash\ncurl -X POST http://localhost:4200/v1/chat/completions \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model\": \"researcher\",\n    \"messages\": [{\"role\": \"user\", \"content\": \"Analyze Q4 market trends\"}],\n    \"stream\": true\n  }'\n```\n\nFull REST/WS/SSE endpoints cover agents, memory, workflows, channels, models, skills, sessions, approvals, triggers, crons, security, and more (120+ total).\n\n---\n\n## Dashboard\n\nThe web dashboard is served at `http://localhost:4200` when the daemon is running. Since v0.7.45 it's a React 18 control panel (industrial-rust palette, 15 pages); React + ReactDOM UMD bundles and the precompiled JSX are inlined into the binary at compile time, so the dashboard ships single-binary like before — no CDN, no `node_modules` at runtime.\n\n### Sections\n\n| Section | What you see |\n|---------|-------------|\n| **Overview** | Live tiles (running agents, cost, audit entries, errors), recent activity, approvals waiting, demo-seed shortcuts, providers, audit chain head |\n| **Agents** | Spawn (template or custom), kill / restart, drawer with Info / Config / Identity / Activity tabs editing the agent's manifest live |\n| **Chat** | WebSocket streaming with HTTP fallback, markdown rendering, tool-trace cards, sessions list per agent |\n| **Workflows** | Visual step builder with HTML5 drag-and-drop reorder, fan-out / collect / conditional / loop modes, runs history, run-with-JSON-input |\n| **Automation** | Cron jobs (3 schedule × 3 action variants), triggers (9 pattern variants), toggle / run-now / delete |\n| **Channels** | Configure modal generated from `/api/channels` field metadata, test / reload / disconnect |\n| **Skills** | Custom install via inline editor, ClawHub browse + search + install, uninstall |\n| **Analytics** | Cost, requests, cache hit-rate, p95 latency, top agents, provider state, CSV export |\n| **Knowledge** | Live graph viz + mini-cypher query (`source:foo relation:works_at depth:3` → POST `/api/knowledge/query`) |\n| **Memory** | Sessions list with label edit + delete, export to markdown, full backup / restore via `/api/memory/{export,import}` |\n| **Approvals** | Pending decisions with one-click approve / reject |\n| **Audit log** | Recent + chain-verify + JSON export |\n| **MCP servers** | Configured + connected MCP bridges from `/api/mcp/servers` |\n| **Network** | RHP P2P status + known peers (`/api/network/status`, `/api/peers`) |\n| **Bindings** | Agent → channel/trigger bindings (`/api/bindings`) |\n| **Settings** | Provider key set / delete / test, demo-mode info, build info |\n\nOther niceties: ⌘K / Ctrl-K command palette, toast notifications, tweaks fab (theme dark/light, accent rust/copper/amber/forest/electric, density), `AuthGate` + `LoginScreen` for remote deployments, error boundary so a component crash shows a recovery card instead of a blank `#root`.\n\n### Maintaining the panel\n\nJSX sources live in `crates/rusty-hand-api/static/js/panel/src/*.jsx`; compiled outputs sit one level up at `static/js/panel/*.js`. After editing JSX, recompile via:\n\n```bash\ncd crates/rusty-hand-api/static/js/panel/src \u0026\u0026 ./build.sh\n```\n\nThe build needs Node + esbuild (`npm i -g esbuild` or use `ESBUILD=\"npx --yes esbuild@0.24.0\" ./build.sh`). The Rust build itself doesn't touch Node — it `include_str!`s the `.js` files. A `build.rs` checks JSX/JS mtimes and emits a `cargo:warning=` if you forget to recompile.\n\nTests pinning the panel contract:\n- `tests/panel_dashboard_test.rs` — 10 tests asserting HTML response, React inlined, every page component + endpoint wired, no Alpine residue, bundle size 100 KB ≤ x ≤ 1 MB\n- `tests/panel_jsx_smoke.rs` — runs the compiled bundle under Node with a React shim and asserts every page component instantiates without throwing (catches JSX runtime errors that string-match tests miss)\n\n---\n\n## Security\n\n16 independent security layers — defense in depth, no single point of failure.\n\n| # | System | Description |\n|---|--------|-------------|\n| 1 | **WASM Dual-Metered Sandbox** | Tool code runs in WebAssembly with fuel metering + epoch interruption. Watchdog kills runaway code. |\n| 2 | **Merkle Hash-Chain Audit Trail** | Every action cryptographically linked. Tamper with one entry and the chain breaks. |\n| 3 | **Taint Tracking** | Information flow labels propagate through execution — secrets tracked from source to sink. |\n| 4 | **Ed25519 Signed Manifests** | Agent identity and capabilities are cryptographically signed. |\n| 5 | **SSRF Protection** | Blocks private IPs, cloud metadata endpoints, DNS rebinding. |\n| 6 | **Secret Zeroization** | `Zeroizing\u003cString\u003e` auto-wipes API keys from memory when no longer needed. |\n| 7 | **RHP Mutual Auth** | HMAC-SHA256 nonce-based, constant-time verification for P2P. |\n| 8 | **Capability Gates** | Role-based access control — agents declare tools, kernel enforces. |\n| 9 | **Security Headers** | CSP, X-Frame-Options, HSTS, X-Content-Type-Options on every response. |\n| 10 | **Health Redaction** | Public health check returns minimal info. Full diagnostics require auth. |\n| 11 | **Subprocess Sandbox** | `env_clear()` + selective passthrough. Process tree isolation with cross-platform kill. |\n| 12 | **Prompt Injection Scanner** | Detects override attempts, data exfiltration patterns, shell injection in skills. |\n| 13 | **Loop Guard** | SHA256-based tool call loop detection with circuit breaker. |\n| 14 | **Session Repair** | 7-phase message history validation and automatic recovery. |\n| 15 | **Path Traversal Prevention** | Canonicalization with symlink escape prevention. |\n| 16 | **GCRA Rate Limiter** | Cost-aware token bucket rate limiting with per-IP tracking. |\n\n---\n\n## Deployment\n\n### Systemd\n\nA service file is provided in `deploy/rustyhand.service`:\n\n```bash\nsudo cp deploy/rustyhand.service /etc/systemd/system/rustyhand.service\n# Edit ExecStart path and user as needed\nsudo systemctl daemon-reload\nsudo systemctl enable --now rustyhand\n```\n\nThe service includes security hardening: `NoNewPrivileges`, `ProtectSystem=strict`, `ProtectHome`, `PrivateTmp`, and resource limits.\n\n### Docker Environment Variables\n\nThe Docker entrypoint generates `config.toml` from environment variables automatically — no config file needed. If you mount your own `config.toml`, env vars are ignored.\n\nSet `RUSTYHAND_FORCE_ENV_CONFIG=1` to always regenerate config from env vars (overrides mounted file).\n\n#### Core\n\n| Env var | Default | Description |\n|---------|---------|-------------|\n| `RUSTYHAND_API_KEY` | *(none)* | **Bearer auth token.** When set, all API endpoints require `Authorization: Bearer \u003ctoken\u003e` header. Strongly recommended for non-local access. |\n| `RUSTYHAND_API_LISTEN` | `0.0.0.0:4200` | HTTP bind address |\n| `RUSTYHAND_LOG_LEVEL` | `info` | Log level: `trace`, `debug`, `info`, `warn`, `error` |\n\n#### LLM Provider\n\n| Env var | Default | Description |\n|---------|---------|-------------|\n| `RUSTYHAND_PROVIDER` | `anthropic` | LLM provider: `anthropic`, `kimi`, `deepseek`, `zhipu`, `minimax`, `openrouter`, `ollama` |\n| `RUSTYHAND_MODEL` | `claude-sonnet-4-20250514` | Model identifier |\n| `RUSTYHAND_MODEL_KEY_ENV` | `ANTHROPIC_API_KEY` | Which env var holds the LLM API key |\n| `RUSTYHAND_MODEL_BASE_URL` | *(auto)* | Override provider API endpoint |\n| `RUSTYHAND_FALLBACK_PROVIDER` | *(none)* | Fallback provider if primary fails |\n| `RUSTYHAND_FALLBACK_MODEL` | *(none)* | Fallback model |\n| `RUSTYHAND_FALLBACK_KEY_ENV` | *(none)* | Env var for fallback API key |\n\n#### LLM API Keys (pass through to agents)\n\n| Env var | Provider |\n|---------|----------|\n| `ANTHROPIC_API_KEY` | Anthropic Claude (default) |\n| `KIMI_API_KEY` | Kimi Code (Moonshot) |\n| `DEEPSEEK_API_KEY` | DeepSeek V4 Flash / V4 Pro (V3/R1 legacy, deprecated 2026-07-24) |\n| `ZHIPU_API_KEY` | Zhipu GLM-4.6 |\n| `MINIMAX_API_KEY` | MiniMax M1 / M2 |\n| `OPENROUTER_API_KEY` | OpenRouter gateway (any upstream model) |\n\n#### Budget\n\n| Env var | Default | Description |\n|---------|---------|-------------|\n| `RUSTYHAND_BUDGET_HOURLY` | `0.0` | Max spend per hour in USD (0 = unlimited) |\n| `RUSTYHAND_BUDGET_DAILY` | `0.0` | Max spend per day in USD |\n| `RUSTYHAND_BUDGET_MONTHLY` | `0.0` | Max spend per month in USD |\n\n#### Memory \u0026 Embeddings\n\n| Env var | Default | Description |\n|---------|---------|-------------|\n| `RUSTYHAND_MEMORY_DECAY` | `0.05` | Memory confidence decay rate |\n| `RUSTYHAND_EMBEDDING_PROVIDER` | *(auto)* | Embedding provider: `voyage`, `openai`, `ollama` |\n| `RUSTYHAND_EMBEDDING_KEY_ENV` | *(auto)* | Env var for embedding API key |\n| `VOYAGE_API_KEY` | *(none)* | Voyage AI embeddings key |\n\n#### Channels\n\n| Env var | Description |\n|---------|-------------|\n| `TELEGRAM_BOT_TOKEN` | Telegram bot — auto-enables `[telegram]` section |\n| `DISCORD_BOT_TOKEN` | Discord bot — auto-enables `[discord]` section |\n| `SLACK_BOT_TOKEN` | Slack bot — auto-enables `[slack]` section |\n| `SLACK_APP_TOKEN` | Slack app-level token (for Socket Mode) |\n| `RUSTYHAND_TELEGRAM_USERS` | Comma-separated Telegram user IDs to allow (e.g. `123456789,987654321`). Brackets and quotes tolerated. Negative IDs (channels) supported. Unset = open to ANY Telegram user — **strongly recommended to set**. |\n\n#### Other\n\n| Env var | Description |\n|---------|-------------|\n| `RUSTYHAND_EXEC_MODE` | Shell exec policy: `deny`, `allowlist`, `full` |\n| `RUSTYHAND_A2A_ENABLED` | Enable A2A protocol: `true` / `1` |\n| `RUSTYHAND_USAGE_FOOTER` | Response footer: `Off`, `Tokens`, `Cost`, `Full` |\n| `RUSTYHAND_FORCE_ENV_CONFIG` | Set to `1` to always regenerate config from env vars |\n\n#### Example: full Docker run\n\n```bash\ndocker run -d --name rustyhand \\\n  -p 4200:4200 \\\n  -e RUSTYHAND_API_KEY=my-secret-token \\\n  -e RUSTYHAND_PROVIDER=anthropic \\\n  -e RUSTYHAND_MODEL=claude-sonnet-4-20250514 \\\n  -e RUSTYHAND_MODEL_KEY_ENV=ANTHROPIC_API_KEY \\\n  -e ANTHROPIC_API_KEY=sk-ant-... \\\n  -e RUSTYHAND_BUDGET_DAILY=5.0 \\\n  -e TELEGRAM_BOT_TOKEN=123456:ABC... \\\n  -v rustyhand-data:/data \\\n  ghcr.io/ginkida/rustyhand:latest\n```\n\n### Cross-compilation\n\nCross-compilation to `aarch64-unknown-linux-gnu` is supported via `Cross.toml`:\n\n```bash\ncross build --release --target aarch64-unknown-linux-gnu -p rusty-hand-cli\n```\n\n---\n\n## Development\n\n### Prerequisites\n\n- Rust 1.75+ (stable) — `rust-toolchain.toml` auto-selects\n- Components: `rustfmt`, `clippy` (included in toolchain)\n\n### Build \u0026 verify\n\n```bash\n# Compile all crates (use --lib if the daemon binary is locked)\ncargo build --workspace --lib\n\n# Run all tests (1,481 as of v0.7.10)\ncargo test --workspace\n\n# Lint — must be 0 warnings\ncargo clippy --workspace --all-targets -- -D warnings\n\n# Format check\ncargo fmt --all -- --check\n```\n\n### Release build\n\n```bash\ncargo build --release -p rusty-hand-cli\n# Binary: target/release/rustyhand (~32 MB)\n# LTO + single codegen unit + stripped symbols + opt-level 3\n```\n\n### Project structure\n\n```\nrustyhand/\n  Cargo.toml                # Workspace manifest (10 member crates)\n  Cargo.lock\n  rust-toolchain.toml       # Rust stable + rustfmt + clippy\n  .env.example              # Environment variable template\n  Dockerfile                # Multi-stage build\n  docker-compose.yml\n  Cross.toml                # Cross-compilation config\n  agents/                   # 37 pre-built agent templates (agent.toml each)\n  deploy/                   # systemd service, Docker scripts\n  scripts/                  # install.sh, install.ps1\n  crates/\n    rusty-hand-types/       # Core types (config.rs is the master config struct)\n    rusty-hand-memory/      # SQLite + vector embeddings (Voyage AI, OpenAI, Ollama)\n    rusty-hand-runtime/     # Agent loop + LLM drivers + tools + sandbox\n    rusty-hand-wire/        # RHP P2P protocol\n    rusty-hand-api/         # Axum HTTP server + routes + dashboard\n      src/\n        server.rs           # Router setup, middleware, AppState\n        routes.rs           # All API endpoint handlers (~7600 LOC)\n      static/\n        index_body.html     # Dashboard SPA (Alpine.js)\n        index_head.html     # CSS + fonts\n    rusty-hand-kernel/      # Central kernel (~5300 LOC, 40+ fields)\n    rusty-hand-cli/         # CLI + TUI binary\n    rusty-hand-channels/    # Telegram + Discord + Slack adapters\n    rusty-hand-skills/      # Skill system + ClawHub + OpenClaw compat\n    rusty-hand-extensions/  # MCP + vault + OAuth2\n```\n\n### Key files for contributors\n\n| File | What it does |\n|------|-------------|\n| `crates/rusty-hand-kernel/src/kernel.rs` | The kernel — 40+ fields, central orchestration |\n| `crates/rusty-hand-api/src/routes.rs` | All API handlers (~7600 LOC) |\n| `crates/rusty-hand-api/src/server.rs` | Router, middleware, `AppState` struct |\n| `crates/rusty-hand-types/src/config.rs` | Master config struct (`KernelConfig`) |\n| `crates/rusty-hand-api/static/index_body.html` | Dashboard SPA |\n| `crates/rusty-hand-api/src/channel_bridge.rs` | Channel adapter wiring |\n| `crates/rusty-hand-runtime/src/drivers/` | LLM drivers (anthropic.rs for Anthropic + Kimi; openai.rs for DeepSeek/Zhipu/MiniMax/OpenRouter/Ollama) |\n\n### Common gotchas\n\n- `rustyhand.exe` may be locked if the daemon is running — use `--lib` flag or kill daemon first\n- New config fields need: struct field + `#[serde(default)]` + `Default` impl entry\n- New routes must be registered in `server.rs` router AND implemented in `routes.rs`\n- Dashboard tabs need both HTML in `index_body.html` and JS data/methods\n- `AgentLoopResult` field is `.response` not `.response_text`\n- CLI daemon command is `start` (not `daemon`)\n\n---\n\n## Benchmarks\n\nAll data from official documentation and public repositories — April 2026.\n\n| Metric | RustyHand | ZeroClaw | LangGraph | CrewAI | AutoGen | OpenClaw |\n|--------|----------|----------|-----------|--------|---------|----------|\n| **Cold start** | 180 ms | 10 ms | 2.5 s | 3.0 s | 4.0 s | 5.98 s |\n| **Idle memory** | 40 MB | 5 MB | 180 MB | 200 MB | 250 MB | 394 MB |\n| **Install size** | 32 MB | 8.8 MB | 150 MB | 100 MB | 200 MB | 500 MB |\n| **Security layers** | 16 | 6 | 2 | 1 | 2 | 3 |\n| **Channel adapters** | 3 | 15 | 0 | 0 | 0 | 13 |\n| **LLM providers** | 7 (+ OpenRouter gateway) | 28 | 15 | 10 | 8 | 10 |\n| **Language** | Rust | Rust | Python | Python | Python | TypeScript |\n\n---\n\n## MCP Integration (for AI Agents)\n\nRustyHand exposes itself as an **MCP server** over stdio, giving any MCP-compatible AI agent (Claude Desktop, Cursor, Windsurf, Claude Code, etc.) full control over the agent OS.\n\n### Setup\n\nAdd to your MCP client config (e.g. `claude_desktop_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"rustyhand\": {\n      \"command\": \"rustyhand\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\nThat's it. The AI agent now has 30+ tools to manage the entire system.\n\n### Available MCP Tools\n\n| Tool | What it does |\n|------|-------------|\n| **System** | |\n| `rustyhand_system_health` | Check daemon health and DB connectivity |\n| `rustyhand_system_status` | Uptime, agent count, default provider/model |\n| `rustyhand_config_get` | Read current config (secrets redacted) |\n| `rustyhand_config_set` | Set config field by dotted path (e.g. `default_model.provider`) |\n| `rustyhand_config_reload` | Hot-reload config from `~/.rustyhand/config.toml` |\n| **Agents** | |\n| `rustyhand_agent_list` | List all agents (ID, name, state, model) |\n| `rustyhand_agent_get` | Full agent details by ID |\n| `rustyhand_agent_spawn` | Spawn new agent from TOML manifest |\n| `rustyhand_agent_kill` | Stop and remove agent |\n| `rustyhand_agent_message` | Send message, get LLM-powered response |\n| `rustyhand_agent_session` | Get conversation history |\n| `rustyhand_agent_set_model` | Change agent's LLM model at runtime |\n| `rustyhand_agent_session_reset` | Clear conversation history |\n| **Models \u0026 Providers** | |\n| `rustyhand_provider_list` | All 7 providers with auth status |\n| `rustyhand_model_list` | Available models (tier, context window, cost) |\n| **Budget** | |\n| `rustyhand_budget_status` | Global spend vs limits (hourly/daily/monthly) |\n| `rustyhand_budget_agents` | Per-agent cost ranking |\n| **Workflows** | |\n| `rustyhand_workflow_list` | List workflow definitions |\n| `rustyhand_workflow_run` | Execute workflow with input |\n| `rustyhand_workflow_runs` | List past workflow runs |\n| **Cron** | |\n| `rustyhand_cron_list` | List all scheduled jobs |\n| `rustyhand_cron_create` | Schedule recurring agent task (cron expression) |\n| `rustyhand_cron_delete` | Remove scheduled job |\n| **Approvals** | |\n| `rustyhand_approval_list` | List pending/approved/rejected requests |\n| `rustyhand_approval_approve` | Approve a pending execution |\n| `rustyhand_approval_reject` | Reject a pending execution |\n| **Other** | |\n| `rustyhand_channel_list` | Channel adapters and their status |\n| `rustyhand_template_list` | Available agent templates |\n| `rustyhand_tool_list` | All built-in tools available to agents |\n\nPlus: every running agent automatically becomes an MCP tool named `rusty_hand_agent_{name}`, so the AI agent can delegate tasks to specialized RustyHand agents.\n\n### Example: AI agent workflow via MCP\n\nAn AI agent (Claude, GPT, etc.) can autonomously:\n\n1. `rustyhand_agent_spawn` — create a researcher agent with web access\n2. `rustyhand_agent_message` — ask it to research a topic\n3. `rustyhand_agent_spawn` — create a writer agent\n4. `rustyhand_agent_message` — pass research results to the writer\n5. `rustyhand_cron_create` — schedule the researcher to update weekly\n6. `rustyhand_budget_status` — check how much it all cost\n\n### Why an AI agent should use RustyHand\n\n- **Delegate work** — spawn specialized agents instead of doing everything yourself\n- **Persistent memory** — agents remember context across sessions (vector search + knowledge graph)\n- **3 channels** — reach users on Telegram, Discord, and Slack without building integrations\n- **Budget control** — set spending limits so agents can't run up costs\n- **7 LLM providers** — Anthropic, Kimi, DeepSeek, Zhipu, MiniMax, OpenRouter, Ollama — plus OpenRouter gateway to any other model\n- **Autonomous scheduling** — cron jobs run agents on schedule, no human needed\n- **60 bundled skills** — instant expertise in Kubernetes, AWS, PostgreSQL, Git, Python, etc.\n- **Approval gates** — dangerous actions require human approval before executing\n- **Audit trail** — every action is logged in a Merkle hash chain\n\n## REST API for Programmatic Access\n\nWhen `api_key` is configured, add `-H \"Authorization: Bearer \u003ctoken\u003e\"` to all requests (except `/api/health`).\n\n```bash\n# Health check (always public)\ncurl http://localhost:4200/api/health\n\n# List agents\ncurl http://localhost:4200/api/agents\n\n# Spawn an agent\ncurl -X POST http://localhost:4200/api/agents \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"manifest_toml\": \"name = \\\"my-agent\\\"\\nmodule = \\\"builtin:chat\\\"\\n[model]\\nprovider = \\\"kimi\\\"\\nmodel = \\\"kimi-for-coding\\\"\\napi_key_env = \\\"KIMI_API_KEY\\\"\\nsystem_prompt = \\\"You are a helpful assistant.\\\"\"}'\n\n# Send a message (triggers LLM call, returns full response)\ncurl -X POST http://localhost:4200/api/agents/{id}/message \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"message\": \"Hello, what can you do?\"}'\n\n# Stream a response (SSE)\ncurl -N -X POST http://localhost:4200/api/agents/{id}/message/stream \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"message\": \"Write a haiku about Rust\"}'\n\n# OpenAI-compatible endpoint (drop-in replacement for any OpenAI client)\ncurl -X POST http://localhost:4200/v1/chat/completions \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"model\": \"coder\", \"messages\": [{\"role\": \"user\", \"content\": \"Fix this bug\"}]}'\n\n# Budget status\ncurl http://localhost:4200/api/budget\n\n# Memory — store and recall\ncurl -X PUT http://localhost:4200/api/memory/agents/{id}/kv/project_name \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"value\": \"rustyhand\"}'\ncurl http://localhost:4200/api/memory/agents/{id}/kv/project_name\n\n# With auth enabled:\ncurl -H \"Authorization: Bearer my-secret-token\" http://localhost:4200/api/agents\n```\n\nSDKs for Python and JavaScript are included in `sdk/python/` and `sdk/javascript/`.\n\n---\n\n## How It Works — Data Flow\n\n```\nUser message (CLI / API / Telegram / Discord / ...)\n    |\n    v\n[Channel Adapter] --- converts platform message to unified ChannelMessage\n    |\n    v\n[Kernel Router] --- resolves target agent via bindings/broadcast rules\n    |\n    v\n[Agent Registry] --- looks up AgentManifest + Session\n    |\n    v\n[Agent Loop] (rusty-hand-runtime/src/agent_loop.rs)\n    |\n    +-- 1. Recall memories (vector similarity via Voyage/OpenAI/Ollama, or text LIKE)\n    +-- 2. Build system prompt (SOUL.md + USER.md + TOOLS.md + MEMORY.md + recalled context)\n    +-- 3. Call LLM (driver: Anthropic or OpenAI-compat)\n    |       |-- retry on rate limit (3x, exponential backoff)\n    |       |-- fallback to next provider on failure\n    |       |-- model routing by complexity (simple/medium/complex)\n    +-- 4. If tool_use → execute tool → append result → goto 3 (max 50 iterations)\n    |       |-- built-in: file_read, file_write, shell_exec, web_search, web_fetch,\n    |       |             memory_store, memory_recall, agent_send, agent_spawn, browser_*\n    |       |-- MCP tools: GitHub, Notion, Slack, PostgreSQL, ... (25+ integrations)\n    |       |-- skills: 60 prompt-only + Python/WASM/Node.js executable skills\n    +-- 5. Extract response text + reply directives\n    |\n    v\n[Metering] --- record token usage + cost, check budget limits\n    |\n    v\n[Session Save] --- persist messages to SQLite, append daily memory log\n    |\n    v\n[Channel Adapter] --- format response for platform, send back\n    |\n    v\nUser receives response\n```\n\n### Key Types\n\n| Type | File | Purpose |\n|------|------|---------|\n| `KernelConfig` | `crates/rusty-hand-types/src/config.rs` | Master config (50+ fields, all with `#[serde(default)]`) |\n| `AgentManifest` | `crates/rusty-hand-types/src/agent.rs` | Agent definition (model, tools, capabilities, resources) |\n| `RustyHandKernel` | `crates/rusty-hand-kernel/src/kernel.rs` | Central orchestrator (40+ subsystem fields) |\n| `LlmDriver` | `crates/rusty-hand-runtime/src/llm_driver.rs` | Trait: `complete()` + `complete_stream()` |\n| `KernelHandle` | `crates/rusty-hand-runtime/src/kernel_handle.rs` | Trait: inter-agent ops (spawn, send, kill, memory, tasks) |\n| `AppState` | `crates/rusty-hand-api/src/routes.rs` | Axum state: `Arc\u003cRustyHandKernel\u003e` + bridge manager |\n| `AgentLoopResult` | `crates/rusty-hand-runtime/src/agent_loop.rs` | Result: `.response`, `.total_usage`, `.cost_usd`, `.silent` |\n| `MemorySubstrate` | `crates/rusty-hand-memory/src/substrate.rs` | Unified memory API (structured + semantic + knowledge graph) |\n| `Event` | `crates/rusty-hand-types/src/event.rs` | Event bus payload (Message, ToolResult, Lifecycle, System) |\n| `ToolDefinition` | `crates/rusty-hand-types/src/tool.rs` | Tool schema for LLM (name, description, JSON Schema input) |\n\n### Extending RustyHand\n\n**Add a new LLM provider:**\n1. Add base URL constant to `crates/rusty-hand-types/src/model_catalog.rs`\n2. Add match arm to `crates/rusty-hand-runtime/src/drivers/mod.rs` `provider_defaults()`\n3. Most providers use the OpenAI-compatible driver — no new driver code needed\n\n**Add a new API endpoint:**\n1. Add handler function in `crates/rusty-hand-api/src/routes.rs`\n2. Register route in `crates/rusty-hand-api/src/server.rs` `build_router()`\n3. Add request/response types in `crates/rusty-hand-api/src/types.rs` if needed\n\n**Add a new config field:**\n1. Add field with `#[serde(default)]` to struct in `crates/rusty-hand-types/src/config.rs`\n2. Add default value to the `Default` impl\n3. Add to custom `Debug` impl (redact secrets)\n\n**Add a new built-in tool:**\n1. Add `ToolDefinition` to `builtin_tool_definitions()` in `crates/rusty-hand-runtime/src/tool_runner.rs`\n2. Add execution handler in the same file's `execute_tool()` match\n\n**Add a new channel adapter:**\n1. Create `crates/rusty-hand-channels/src/\u003cname\u003e.rs`\n2. Add `pub mod \u003cname\u003e` to `crates/rusty-hand-channels/src/lib.rs`\n3. Wire into `crates/rusty-hand-api/src/channel_bridge.rs`\n\n---\n\n## License\n\nMIT — use it however you want.\n\n---\n\n## Links\n\n- [GitHub](https://github.com/ginkida/rustyhand)\n- [Quick Start](https://github.com/ginkida/rustyhand#quick-start)\n- [API Reference](https://github.com/ginkida/rustyhand#api-endpoints)\n- [Python SDK](https://github.com/ginkida/rustyhand/tree/main/sdk/python)\n- [JavaScript SDK](https://github.com/ginkida/rustyhand/tree/main/sdk/javascript)\n\n---\n\n## Acknowledgments\n\nRustyHand is a fork of [OpenFang](https://github.com/RightNow-AI/openfang), originally built by [Jaber](https://x.com/Akashi203) at [RightNow](https://www.rightnowai.co/).\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eBuilt with Rust. Secured with 16 layers. Agents that actually work for you.\u003c/strong\u003e\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fginkida%2Frustyhand","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fginkida%2Frustyhand","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fginkida%2Frustyhand/lists"}