{"id":49562320,"url":"https://github.com/garudust-org/garudust-agent","last_synced_at":"2026-06-06T05:00:36.631Z","repository":{"id":354030243,"uuid":"1221723996","full_name":"garudust-org/garudust-agent","owner":"garudust-org","description":"🦅 Open-source AI agent runtime in Rust — Self-hostable with persistent memory, self-improving skills, MCP support, built-in cron, multi-platform messaging \u0026 production gateway.","archived":false,"fork":false,"pushed_at":"2026-06-03T07:56:38.000Z","size":8845,"stargazers_count":22,"open_issues_count":5,"forks_count":6,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-03T09:26:08.304Z","etag":null,"topics":["ai-agent","anthropic","cli","discord-bot","llm","mcp","ollama","openrouter","rag","rust","self-hosted","self-improvement","self-learning","telegram-bot","tui"],"latest_commit_sha":null,"homepage":"https://garudust-org.github.io/garudust-agent/","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/garudust-org.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","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":null,"dco":null,"cla":null}},"created_at":"2026-04-26T15:47:17.000Z","updated_at":"2026-06-03T07:56:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/garudust-org/garudust-agent","commit_stats":null,"previous_names":["ninenox/garudust","garudust-org/garudust","garudust-org/garudust-agent"],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/garudust-org/garudust-agent","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garudust-org%2Fgarudust-agent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garudust-org%2Fgarudust-agent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garudust-org%2Fgarudust-agent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garudust-org%2Fgarudust-agent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/garudust-org","download_url":"https://codeload.github.com/garudust-org/garudust-agent/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garudust-org%2Fgarudust-agent/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33907694,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"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":["ai-agent","anthropic","cli","discord-bot","llm","mcp","ollama","openrouter","rag","rust","self-hosted","self-improvement","self-learning","telegram-bot","tui"],"created_at":"2026-05-03T10:05:16.280Z","updated_at":"2026-06-06T05:00:36.619Z","avatar_url":"https://github.com/garudust-org.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"assets/logo-agent.jpg\" alt=\"Garudust\"/\u003e\n\n  \u003ca href=\"README.md\"\u003e\u003cimg src=\"https://img.shields.io/badge/🇺🇸-English-blue?style=flat-square\" alt=\"English\"/\u003e\u003c/a\u003e\n  \u003ca href=\"docs/i18n/th/README.md\"\u003e\u003cimg src=\"https://img.shields.io/badge/🇹🇭-ภาษาไทย-red?style=flat-square\" alt=\"ภาษาไทย\"/\u003e\u003c/a\u003e\n  \u003ca href=\"docs/i18n/zh/README.md\"\u003e\u003cimg src=\"https://img.shields.io/badge/🇨🇳-简体中文-yellow?style=flat-square\" alt=\"简体中文\"/\u003e\u003c/a\u003e\n\u003c/div\u003e\n\n# Garudust Agent\n\n[![CI](https://github.com/garudust-org/garudust-agent/actions/workflows/ci.yml/badge.svg)](https://github.com/garudust-org/garudust-agent/actions/workflows/ci.yml)\n[![crates.io](https://img.shields.io/crates/v/garudust-agent.svg)](https://crates.io/crates/garudust-agent)\n[![Downloads](https://img.shields.io/crates/d/garudust-agent.svg)](https://crates.io/crates/garudust-agent)\n[![Release](https://img.shields.io/github/v/release/garudust-org/garudust-agent)](https://github.com/garudust-org/garudust-agent/releases/latest)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n![Rust 1.87+](https://img.shields.io/badge/rust-1.87+-orange.svg)\n[![Discord](https://img.shields.io/badge/Discord-Join%20Community-5865F2?logo=discord\u0026logoColor=white\u0026style=flat-square)](https://discord.com/channels/1501414298449088745/1501414298893942877)\n\n**Your AI agent. Your server. Your rules.**\n\nA self-improving AI agent runtime written in Rust — ~10 MB binary, no runtime dependencies. Chat in the terminal, reply across 7 platforms, open the web dashboard, run the desktop app, or expose a REST + WebSocket API. Connect any MCP server, swap LLM providers with one env var. No telemetry. No lock-in.\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"assets/demo.svg\" alt=\"Garudust demo\"/\u003e\n\u003c/div\u003e\n\n---\n\n## Quick Start\n\n**01 — Install**\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/garudust-org/garudust-agent/main/scripts/install.sh | sh\n```\n\nmacOS \u0026 Linux, any arch (ARM, Raspberry Pi, WSL). Windows: `irm .../scripts/install.ps1 | iex`. Override with `GARUDUST_VERSION` / `GARUDUST_BIN_DIR`.\n\n\u003cdetails\u003e\n\u003csummary\u003eManual download or build from source\u003c/summary\u003e\n\nGrab a pre-built binary from [GitHub Releases](https://github.com/garudust-org/garudust-agent/releases/latest):\n\n| OS | Architecture | Binary |\n|----|-------------|--------|\n| macOS | Apple Silicon (M1/M2/M3/M4) | `garudust-*-aarch64-apple-darwin.tar.gz` |\n| macOS | Intel | `garudust-*-x86_64-apple-darwin.tar.gz` |\n| Linux | x86_64 | `garudust-*-x86_64-unknown-linux-musl.tar.gz` |\n| Linux | ARM64 (Raspberry Pi 4/5, Jetson) | `garudust-*-aarch64-unknown-linux-musl.tar.gz` |\n| Windows | x86_64 | `garudust-*-x86_64-pc-windows-msvc.zip` |\n\nOr build from source (Rust 1.87+): `git clone https://github.com/garudust-org/garudust-agent \u0026\u0026 cargo build --release`\n\n\u003c/details\u003e\n\n---\n\n**02 — Configure**\n\n```bash\ngarudust setup    # interactive wizard — picks provider, writes config.yaml + .env\n```\n\nOr set your key directly in `~/.garudust/.env` (e.g. `ANTHROPIC_API_KEY=sk-ant-...`). See [LLM Providers](#llm-providers) for all supported keys.\n\n---\n\n**03 — Run**\n\n```bash\ngarudust                           # interactive TUI\ngarudust \"summarise git log\"       # one-shot task\ngarudust --hint fast \"check this\"  # route to a cheaper model\ngarudust-server --port 3000        # headless REST + WebSocket server (+ web dashboard, see below)\ndocker compose up -d\n\n# Management subcommands\ngarudust setup                     # interactive first-time setup wizard\ngarudust doctor                    # check environment and configuration\ngarudust config show               # view current configuration\ngarudust config set \u003ckey\u003e \u003cvalue\u003e # set a configuration value\ngarudust model [\u003cname\u003e]            # get or switch the active model\n# Script tools\ngarudust tool list                 # list installed + available hub tools\ngarudust tool install \u003cname\u003e       # install a tool from the hub\ngarudust tool uninstall \u003cname\u003e     # remove an installed tool\ngarudust tool update [\u003cname\u003e]      # update one tool (omit to update all)\n\n# Skills\ngarudust skill list                # list installed + available hub skills\ngarudust skill install \u003csource\u003e    # install from hub / GitHub / URL / well-known\ngarudust skill uninstall \u003cname\u003e    # remove an installed skill\ngarudust skill update [\u003cname\u003e]     # update one skill (omit to update all)\ngarudust skill validate [\u003cpath\u003e]   # validate SKILL.md frontmatter\n```\n\n---\n\n## Desktop app \u0026 web dashboard\n\nThe recommended way to use Garudust with a UI is the **native desktop app** — a\npure-Rust ([egui](https://github.com/emilk/egui)) app with the agent embedded\nin-process (no webview, no separate server). Just download and run.\n\n\u003cdiv align=\"center\"\u003e\n\n### ⬇ Download Garudust Desktop\n\n[**🍎 macOS**](https://github.com/garudust-org/garudust-agent/releases/latest/download/Garudust-macOS-universal.dmg) \u0026nbsp;·\u0026nbsp;\n[**🪟 Windows**](https://github.com/garudust-org/garudust-agent/releases/latest/download/Garudust-Windows-x64-setup.exe) \u0026nbsp;·\u0026nbsp;\n[**🐧 Linux (AppImage)**](https://github.com/garudust-org/garudust-agent/releases/latest/download/Garudust-Linux-x86_64.AppImage) \u0026nbsp;·\u0026nbsp;\n[**📦 Debian/Ubuntu (.deb)**](https://github.com/garudust-org/garudust-agent/releases/latest/download/Garudust-Linux-x86_64.deb)\n\n\u003csub\u003emacOS is a universal build (Intel + Apple Silicon). Other archs / versions: [all releases](https://github.com/garudust-org/garudust-agent/releases/latest)\u003c/sub\u003e\n\n\u003cimg src=\"assets/desktop.png\" alt=\"Garudust desktop app\" width=\"760\"/\u003e\n\n\u003c/div\u003e\n\n| OS | Install |\n|----|---------|\n| macOS | open the `.dmg`, drag **Garudust** to Applications |\n| Windows 10/11 | run the `.exe` installer |\n| Linux | `chmod +x Garudust_*.AppImage \u0026\u0026 ./Garudust_*.AppImage` |\n| Debian / Ubuntu | `sudo dpkg -i Garudust_*.deb` |\n\n\u003e Builds are not yet code-signed, so on first launch macOS Gatekeeper\n\u003e (right-click → **Open**) and Windows SmartScreen (**More info → Run anyway**)\n\u003e will warn — expected for unsigned apps.\n\nOn first run, set your LLM key on the **Secrets** page (or in `~/.garudust/.env`).\nThe Secrets page is masked + write-only; the agent runs inside the app itself.\n\nBuild from source: `cargo run -p garudust-desktop-native --release` (see\n[`apps/desktop-native/README.md`](apps/desktop-native/README.md)).\n\n**Prefer the browser?** The same UI (Rust/[Leptos](https://leptos.dev) → WASM) is\nserved by the server with the `web-ui` feature:\n\n```bash\ncd web \u0026\u0026 trunk build --release          # one-time: cargo install trunk + rustup target add wasm32-unknown-unknown\ncargo run -p garudust-server --features web-ui --port 3000   # → open http://localhost:3000\n```\n\n---\n\n## Features\n\n🪶 **Tiny footprint** — ~10 MB statically linked binary, \u003c 20 ms cold start, zero runtime dependencies. Runs on a Raspberry Pi without Docker.\n\n🧠 **Self-improving** — remembers your preferences and facts across every session. Automatically writes reusable skills after complex multi-step workflows. Cross-session goals stay injected until you mark them done — you never repeat yourself.\n\n🔀 **24 LLM providers, one config line** — Anthropic, OpenAI, Gemini, Groq, Mistral, DeepSeek, Ollama, AWS Bedrock, vLLM, and 15 more. Route tasks to cheaper models with `--hint`, rotate fallback keys automatically on auth failure.\n\n📡 **7 platforms in one process** — Telegram, Discord, Slack, Matrix, LINE, WhatsApp, Webhook. Per-platform RBAC, mention gate, per-user session isolation — each adapter activates the moment its token is in `.env`.\n\n⚡ **Parallel tool execution** — independent tool calls run concurrently; conflict-prone calls serialized by key. 15+ built-in tools: web search, file I/O, browser automation (CDP), terminal, RAG, sub-agent delegation. Connect any MCP server or drop a custom script tool in any language.\n\n🔒 **Secure by design** — three sandbox modes for the terminal tool: direct host, Docker container, or SSH remote host. Hardline blocks on the most destructive commands regardless of sandbox. Approval modes (`auto` / `smart` / `deny`) gate destructive operations. Secrets are redacted from all tool output before the model sees them.\n\n🌐 **Headless API** — `garudust-server` exposes `/chat`, `/stream`, and a WebSocket endpoint — embed in any app or script. Cron-scheduled autonomous tasks run without a user present.\n\n🖥️ **Web dashboard \u0026 native desktop app** — a Rust/Leptos (WASM) dashboard served straight from the binary (`web-ui` feature) for the browser, plus a pure-Rust native [egui](https://github.com/emilk/egui) desktop app with the agent embedded in-process (DMG / EXE / AppImage / deb). No JS/TS; secrets stay masked and server-side.\n\n---\n\n## Platforms\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://core.telegram.org/bots\"\u003e\u003cimg src=\"https://img.shields.io/badge/Telegram-2CA5E0?logo=telegram\u0026logoColor=white\u0026style=for-the-badge\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://discord.com/developers/applications\"\u003e\u003cimg src=\"https://img.shields.io/badge/Discord-5865F2?logo=discord\u0026logoColor=white\u0026style=for-the-badge\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://api.slack.com/apps\"\u003e\u003cimg src=\"https://img.shields.io/badge/Slack-4A154B?logo=slack\u0026logoColor=white\u0026style=for-the-badge\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://matrix.org\"\u003e\u003cimg src=\"https://img.shields.io/badge/Matrix-000000?logo=matrix\u0026logoColor=white\u0026style=for-the-badge\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://developers.line.biz/console/\"\u003e\u003cimg src=\"https://img.shields.io/badge/LINE-00C300?logo=line\u0026logoColor=white\u0026style=for-the-badge\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://developers.facebook.com/docs/whatsapp/cloud-api\"\u003e\u003cimg src=\"https://img.shields.io/badge/WhatsApp-25D366?logo=whatsapp\u0026logoColor=white\u0026style=for-the-badge\"/\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Webhook-6E7681?style=for-the-badge\"/\u003e\n\u003c/div\u003e\n\nAll adapters run in the same `garudust-server` process. Set the token in `~/.garudust/.env` and the adapter activates automatically.\n\n---\n\n## LLM Providers\n\nSet `providers.default.name` in `config.yaml` and the corresponding key in `~/.garudust/.env`:\n\n| Provider | `name` | `.env` key |\n|----------|--------|------------|\n| Anthropic | `anthropic` | `ANTHROPIC_API_KEY` |\n| OpenAI | `openai` | `OPENAI_API_KEY` |\n| Google Gemini | `gemini` | `GEMINI_API_KEY` |\n| Groq | `groq` | `GROQ_API_KEY` |\n| Mistral | `mistral` | `MISTRAL_API_KEY` |\n| DeepSeek | `deepseek` | `DEEPSEEK_API_KEY` |\n| xAI (Grok) | `xai` | `XAI_API_KEY` |\n| OpenRouter | `openrouter` | `OPENROUTER_API_KEY` |\n| AWS Bedrock | `bedrock` | `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY` |\n| Ollama | `ollama` | *(none — add `url:` for custom endpoint)* |\n| vLLM | `vllm` | `VLLM_API_KEY` |\n| ThaiLLM | `thaillm` | `THAILLM_API_KEY` |\n| Together AI | `together` | `TOGETHER_API_KEY` |\n| Fireworks AI | `fireworks` | `FIREWORKS_API_KEY` |\n| Cerebras | `cerebras` | `CEREBRAS_API_KEY` |\n| Perplexity | `perplexity` | `PERPLEXITY_API_KEY` |\n| Cohere | `cohere` | `COHERE_API_KEY` |\n| NVIDIA NIM | `nvidia` | `NVIDIA_API_KEY` |\n| Alibaba DashScope | `alibaba` | `DASHSCOPE_API_KEY` |\n| ByteDance Doubao | `doubao` | `ARK_API_KEY` |\n| Zhipu AI (GLM) | `zhipu` | `ZHIPU_API_KEY` |\n| Moonshot (Kimi) | `moonshot` | `MOONSHOT_API_KEY` |\n| Baidu ERNIE | `baidu` | `QIANFAN_API_KEY` |\n| Any OpenAI-compat | *(omit `name:`, set `url:` in profile)* | relevant key |\n\nFallback keys: set `LLM_FALLBACK_API_KEYS=key2,key3` in `.env` — rotated automatically on auth failure.\n\n---\n\n## Architecture\n\n```\n┌──────────────────────────────────────────────────────────────────────┐\n│  bin/garudust (CLI)              bin/garudust-server (Daemon)        │\n└────────────────────┬─────────────────────────┬───────────────────────┘\n                     │                         │\n                     │          ┌──────────────┴───────────────────────┐\n                     │          │  garudust-gateway  (server-only)     │\n                     │          │  POST /chat · POST /stream · GET /ws │\n                     │          │  RBAC · /join · /invite · Metrics    │\n                     │          ├──────────────────────────────────────┤\n                     │          │  garudust-platforms  (server-only)   │\n                     │          │  Telegram · Discord · Slack          │\n                     │          │  LINE · Matrix · WhatsApp · Webhook  │\n                     │          ├──────────────────────────────────────┤\n                     │          │  garudust-cron  (server-only)        │\n                     │          │  cron-scheduled autonomous tasks     │\n                     │          └──────────────┬───────────────────────┘\n                     │                         │\n                     ▼                         ▼\n┌──────────────────────────────────────────────────────────────────────┐\n│                    garudust-agent  (run-loop)                        │\n│  load memory → build prompt → LLM call → tool dispatch → repeat     │\n└──────┬──────────────┬─────────────────┬─────────────────────────────┘\n       ▼              ▼                 ▼\n  garudust-      garudust-        garudust-\n  transport      tools            memory\n  (24 LLMs +    (built-in +      (memory.md +\n  key rotation)  hub + MCP)       SQLite + RAG)\n\ngarudust-core — shared types · config · traits (used by every crate above)\n```\n\n---\n\n## Configuration\n\nSecrets → `~/.garudust/.env`. Everything else → `~/.garudust/config.yaml`.\n\n### `~/.garudust/.env`\n\n```bash\n# LLM provider — set one (auto-detected from env when no config.yaml)\nANTHROPIC_API_KEY=sk-ant-...\n# OPENAI_API_KEY=sk-...\n# GEMINI_API_KEY=AIza...\n# GROQ_API_KEY=gsk_...\n\n# Fallback keys — rotated automatically on auth failure\n# LLM_FALLBACK_API_KEYS=sk-ant-backup1,sk-ant-backup2\n\n# Platform adapters — set only what you use\nTELEGRAM_TOKEN=123456789:AAFxxx\nDISCORD_TOKEN=\u003cbot-token\u003e\nSLACK_BOT_TOKEN=xoxb-...\nSLACK_APP_TOKEN=xapp-...\nLINE_CHANNEL_TOKEN=\u003cchannel-access-token\u003e\nLINE_CHANNEL_SECRET=\u003c32-char-hex\u003e\nWHATSAPP_ACCESS_TOKEN=EAAxxxxx\nWHATSAPP_PHONE_NUMBER_ID=123456789012345\nWHATSAPP_VERIFY_TOKEN=my_verify_token\n\n# Search (optional — falls back to DuckDuckGo)\nBRAVE_SEARCH_API_KEY=BSA...\nSERPER_API_KEY=...\n\n# Gateway auth\nGARUDUST_API_KEY=my-gateway-secret\n```\n\n### `~/.garudust/config.yaml`\n\n```yaml\nproviders:\n  default:\n    name: anthropic          # see LLM Providers table above for all 24 options\n    key: ${ANTHROPIC_API_KEY}\n    model: claude-sonnet-4-6\n\nsecurity:\n  approval_mode: smart       # auto | smart | deny\n  terminal_sandbox: none     # none | docker | ssh\n  rate_limit_rpm: ~          # per-IP limit (~ = unlimited)\n  rate_limit_rpm_per_user: ~ # per-(platform, user_id) limit\n\n  # ── SSH sandbox (terminal_sandbox: ssh) ──────────────────────────────\n  # ssh_host: \"192.168.1.50\"              # required\n  # ssh_user: \"pi\"                        # optional — defaults to current OS user\n  # ssh_port: 22                          # optional — default 22\n  # ssh_key_path: ~/.ssh/garudust_pi      # optional — uses ~/.ssh/id_* if unset\n  # ssh_jump_host: \"bastion.example.com\"  # optional — ProxyJump for hosts behind NAT\n  # ssh_remote_cwd: \"/home/pi/scripts\"    # optional — cd here before every command\n  # ssh_options: [\"IdentitiesOnly=yes\"]   # optional — extra -o flags (escape hatch)\n\n# Route a single task to a different model without changing the default:\nrouting:\n  fast: groq-fast/llama-3.1-8b-instant\n  # then: garudust --hint fast \"quick question\"\n\n# Use a cheap model for background skill-reflection (defaults to main model):\nreflection_model: groq/llama-3.1-8b-instant\n\n# Conversation window per session — pairs of (user, assistant) turns (default 20):\nmax_history_pairs: 20\n```\n\nFor the full config reference (cron, MCP, RBAC, compression, etc.) see [CONTRIBUTING.md](CONTRIBUTING.md).\n\n---\n\n## Tools\n\nBuilt-in, no configuration needed:\n\n`web_fetch` · `web_search` · `http_request` · `browser` (CDP) · `read_file` · `write_file` · `list_directory` · `terminal` · `memory` · `session_search` · `delegate_task` · `skill_view` · `write_skill` · `doc_ingest` · `doc_search`\n\n**Hub** — community tools and skills from [garudust-hub](https://github.com/garudust-org/garudust-hub):\n\n```bash\ngarudust tool install hash_text    # script tool → ~/.garudust/tools/hash_text/\ngarudust tool install read_qr\ngarudust skill install weather     # Markdown instruction, no subprocess\ngarudust skill install fetch-title\n```\n\n**MCP** — connect any [Model Context Protocol](https://modelcontextprotocol.io) server:\n\n```yaml\nmcp_servers:\n  - name: filesystem\n    command: npx\n    args: [\"-y\", \"@modelcontextprotocol/server-filesystem\", \"/tmp\"]\n```\n\n**Custom tools** — drop a `tool.yaml` + script in `~/.garudust/tools/\u003cname\u003e/`. Any language. See [garudust-hub](https://github.com/garudust-org/garudust-hub) for examples.\n\n---\n\n## Access Control\n\nRole-based access via `roles:` in `config.yaml`. The first person to DM the bot is auto-promoted to `admin` when no users are assigned yet.\n\n```yaml\nroles:\n  default_role: member\n  definitions:\n    admin:  { approval_mode: auto }\n    member: { approval_mode: smart, allowed_toolsets: [web, files, memory], denied_tools: [bash] }\n    readonly: { approval_mode: deny }\n  users:\n    telegram:\n      \"123456789\": admin\n```\n\nRuntime commands: `/whoami` · `/join [code]` · `/invite \u003crole\u003e [max_uses]` · `/role list|add|approve|remove`\n\n\u003e **Production:** set `terminal_sandbox: docker` (local container) or `terminal_sandbox: ssh` (remote host) to sandbox shell execution, and `max_delegation_depth: 0` to prevent sub-agent chains.\n\n\u003e **Note:** setting `platform.session_per_user: false` causes all users to share one conversation context. The server logs a `WARN` at startup as a reminder. Only safe for single-user deployments.\n\n---\n\n## Terminal Sandbox\n\nThe `terminal` tool supports three execution backends:\n\n| Mode | `terminal_sandbox` | Runs on | Requires |\n|---|---|---|---|\n| Direct host | `none` | Local machine | Nothing |\n| Docker container | `docker` | Isolated container | Docker daemon |\n| Remote SSH host | `ssh` | Any host with sshd | SSH key auth |\n\nAll modes share the same hardline blocks (fork bomb, `rm -rf /`, `mkfs`, etc.) and the same approval gate — the sandbox only controls *where* the command runs.\n\n### SSH Sandbox\n\nCommands are forwarded via the system `ssh` binary to a remote host. Useful for managing a remote server, Raspberry Pi, or build machine without exposing any port to the internet — the agent SSHes *out*, the remote host just needs port 22 open.\n\n**Config fields** (all under `security:` in `config.yaml`):\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `ssh_host` | string | — | **Required.** Remote hostname or IP |\n| `ssh_user` | string | current OS user | Login username |\n| `ssh_port` | integer | `22` | SSH port |\n| `ssh_key_path` | path | `~/.ssh/id_*` | Private key file |\n| `ssh_jump_host` | string | — | ProxyJump bastion (`user@host:port`) for hosts behind NAT |\n| `ssh_remote_cwd` | string | — | `cd \u003cdir\u003e \u0026\u0026` prepended to every command; must be an absolute path with no shell metacharacters (e.g. `/home/pi/scripts`) |\n| `ssh_options` | list | `[]` | Extra `-o key=value` flags (appended after hardened defaults) |\n\n**Environment variable overrides** — no config.yaml required:\n\n```bash\nGARUDUST_TERMINAL_SANDBOX=ssh\nGARUDUST_SSH_HOST=192.168.1.50\nGARUDUST_SSH_USER=pi\nGARUDUST_SSH_PORT=22\nGARUDUST_SSH_KEY_PATH=/home/user/.ssh/garudust_pi\n```\n\n**Minimal working example** — Raspberry Pi behind a home router:\n\n```yaml\nsecurity:\n  terminal_sandbox: ssh\n  ssh_host: \"192.168.1.50\"\n  ssh_user: \"pi\"\n  ssh_key_path: ~/.ssh/garudust_pi\n```\n\n**With a bastion** — Pi is reachable only through a public jump server:\n\n```yaml\nsecurity:\n  terminal_sandbox: ssh\n  ssh_host: \"pi.internal\"\n  ssh_user: \"pi\"\n  ssh_key_path: ~/.ssh/garudust_pi\n  ssh_jump_host: \"bastion.example.com\"\n```\n\n**Security properties applied automatically:**\n\n- `BatchMode=yes` — no interactive prompts; fails immediately if key auth is rejected\n- `StrictHostKeyChecking=accept-new` — auto-trusts first contact, rejects changed host keys (MITM protection)\n- `ConnectTimeout` capped at 30 s — no indefinite TCP hangs\n- `ServerAliveInterval=10 ServerAliveCountMax=3` — detects dead connections in ~30 s rather than hanging until the command timeout fires\n- `--` before the command — prevents a command starting with `-` from being misread as an SSH flag\n- `env_clear()` before spawning `ssh` — API keys and secrets never reach the remote host\n- `ssh_remote_cwd` is validated as a safe absolute path before use — values containing shell metacharacters (`;` `\u0026` `|` `` ` `` `$` `\u003e` `\u003c` quotes, whitespace, etc.) are rejected at command time, not silently forwarded to the remote shell\n- `ssh_options` are appended *after* hardened defaults — `BatchMode` and `StrictHostKeyChecking` cannot be overridden by caller config\n\n---\n\n## Memory \u0026 Skills\n\nThe agent saves everything it learns to `~/.garudust/memory/` and loads it at the start of every session — you never need to repeat yourself. Repeating workflows are automatically written as reusable skills in `~/.garudust/skills/` after `auto_skill_threshold` iterations. Set `reflection_model` in `config.yaml` to use a cheaper model for this background pass and keep costs down.\n\n---\n\n## Contributing\n\nGarudust is Rust and designed to be extended. Pick your area:\n\n| Area | Where | Effort |\n|------|-------|--------|\n| Hub tool or skill | [garudust-hub](https://github.com/garudust-org/garudust-hub) — `tool.yaml` + script | Low — no Rust needed |\n| Bug reports / docs | [Issues](https://github.com/garudust-org/garudust-agent/issues) | Minimal |\n| New LLM provider | `crates/garudust-transport/src/` — impl `ProviderTransport` (2 methods) | Medium |\n| New platform adapter | `crates/garudust-platforms/src/` — impl `PlatformAdapter` (2 methods) | Medium |\n| Built-in tool | `crates/garudust-tools/src/toolsets/` — impl `Tool`, register in `ToolRegistry::new()` | Medium (~100 lines) |\n| Core features | Agent loop, memory, compression, gateway | High |\n\n```bash\ngit clone https://github.com/garudust-org/garudust-agent\ncd garudust-agent\ngit config core.hooksPath .githooks   # enable pre-push checks (fmt + tests)\ncargo build \u0026\u0026 cargo test --workspace \u0026\u0026 cargo clippy --workspace\n```\n\nStep-by-step guides for each area: [CONTRIBUTING.md](CONTRIBUTING.md)\n\n**Community:** [Discord](https://discord.com/channels/1501414298449088745/1501414298893942877) · [Issues](https://github.com/garudust-org/garudust-agent/issues) · [Discussions](https://github.com/garudust-org/garudust-agent/discussions) · [dev.to/garudust](https://dev.to/garudust)\n\n---\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n\n---\n\n## Contributors\n\n[![](https://contrib.rocks/image?repo=garudust-org/garudust-agent)](https://github.com/garudust-org/garudust-agent/graphs/contributors)\n\n---\n\n## Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=garudust-org/garudust-agent\u0026type=Date)](https://star-history.com/#garudust-org/garudust-agent\u0026Date)\n\n---\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://visitor-badge.laobi.icu/badge?page_id=garudust-org.garudust-agent\u0026style=flat\" alt=\"visitors\"/\u003e\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgarudust-org%2Fgarudust-agent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgarudust-org%2Fgarudust-agent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgarudust-org%2Fgarudust-agent/lists"}