Introduction
Note: This page is in English. Pages not yet translated are shown in Portuguese.
πΊπΈ English Β· π§π· PortuguΓͺs
GarraIA
The secure, lightweight open-source framework for AI agents β written in Rust, born in Brazil.
Quick Start Β· Why GarraIA? Β· Features Β· Memory Β· Security Β· Architecture Β· Migrate from OpenClaw Β· Contributing
A personal AI assistant that runs on your machine. One self-contained native binary runs your agents on Telegram, Discord, Slack, WhatsApp and iMessage β with an AES-256-GCM encrypted credential vault, hot config reload, a full memory system with local embeddings, and a warm Brazilian Portuguese persona as the default voice (fully configurable, including a neutral English mode).
Every performance and comparison number in this README is measured, not
asserted: the reproducible harness, the scenario definitions, and the
raw evidence live in
benches/agent-framework-comparison/.
If a number has no committed measurement behind it, it does not appear here.
Local-first. All state β conversations, memory, config, credentials β
is stored on your machine, and there is no telemetry or analytics
phone-home. Your prompts go only to the LLM provider you configure; run
Ollama for a fully offline setup (set
GARRAIA_NO_UPDATE_CHECK=1 to also silence the once-a-day release check
against the GitHub API β the only other outbound call garra start makes).
πΎ Meet Garraβ
Garra is not just an API endpoint β it is a personal assistant with a
personality. From the first garra start it introduces itself by name and
speaks warm, direct, first-person Brazilian Portuguese (no sycophancy).
When something breaks, it explains what happened and what to do next
instead of dumping raw error codes.
"Oi! π Eu sou o Garra, seu assistente pessoal. Pode falar comigo como vocΓͺ falaria com um amigo."
The persona is the default, not a cage: set agent.system_prompt for
a custom personality or agent.persona = "neutral" for a fully neutral
tone in any language. See ADR 0012.
Quick Startβ
# Requires Rust 1.97+ (matches the MSRV declared in Cargo.toml)
cargo build --release -p garraia
# Interactive setup β pick your LLM provider; optionally store API keys
# in the encrypted vault (the wizard's default is config.yml, mode 0600)
./target/release/garra init
# Start
./target/release/garra start
# Bare `garra` opens the chat REPL. On a clean install that is OpenRouter
# with `z-ai/glm-5.3-flash` (issue #1180). With no `agent.default_provider`
# in config, autodetect uses the first cloud provider you have a credential
# for (Anthropic > OpenAI > OpenRouter) and only falls back to local Ollama
# when none exists.
./target/release/garra
# Local Ollama is the second option β ask for it explicitly by naming a tag.
# A tag that is not pulled yet prompts to download it; `-y` downloads
# without asking.
./target/release/garra --model qwen3.8
# One-shot non-interactive ask β great for scripts and CI
./target/release/garra ask --provider openrouter \
--json --timeout-secs 30 "Reply with exactly: OK"
# MCP server over stdio β exposes `garra_ask` to Claude Desktop / Claude Code
./target/release/garra mcp-server
Install via script (Linux, macOS) β uses published release binaries
curl -fsSL https://garraia.org/install.sh | sh
Mirrors of the same script: GitHub release CDN
https://github.com/michelbr84/GarraRUST/releases/latest/download/install.sh
(most robust against IP rate limits; a snapshot taken at each release),
https://raw.githubusercontent.com/michelbr84/GarraRUST/main/install.sh and
https://cdn.jsdelivr.net/gh/michelbr84/GarraRUST@main/install.sh (both
track main).
The installer downloads the binary for your platform, verifies it against
the release's SHA256SUMS, then chains into init and start. It leaves two
names on your PATH: garraia (the release asset) and the alias garra (a
relative symlink to it), so the garra β¦ commands used throughout this
README and in the CLI's own hints work as written; a cargo build produces
garra directly.
Flags (usable through the pipe with sh -s --) and their equivalent env
toggles: --skip-setup (GARRAIA_SKIP_INIT=1 + GARRAIA_SKIP_START=1),
--skip-init, --skip-start, --no-local (GARRAIA_BOOTSTRAP_LOCAL=0),
--version <tag>, --install-dir <dir>, --help. An env var set by the
caller wins over the matching flag. For a fully unattended install:
curl -fsSL https://garraia.org/install.sh | sh -s -- --skip-setup
# The project default β OpenRouter primary, local Ollama as the backup.
# The key is read from stdin, never from argv.
printf '%s\n' "$OPENROUTER_API_KEY" | garraia config set-routing \
--primary-provider openrouter --primary-model z-ai/glm-5.3-flash \
--backup-provider ollama --backup-model qwen3.8:latest --api-key-stdin
garraia start
In TTY-less contexts (Docker build, CI) the installer prints next steps and exits 0 instead of blocking.
Releases ship 6 prebuilt CLI binaries: Linux x86_64/aarch64,
macOS x86_64/aarch64, Windows x86_64/aarch64 (the three aarch64 builds
are best-effort) β plus, from v0.3.6, an Android aarch64 build for
Termux (best-effort; see the Android section below) β each also as a .tar.gz
(.zip on Windows) containing the binary named plainly garraia,
plus LICENSE and README.md. From v0.3.4 they also carry Linux
packages β garraia-linux-{x86_64,aarch64}.deb/.rpm and a portable
garraia-linux-x86_64.AppImage (all best-effort; see
docs/installation.md). The bare binaries stay
published unchanged because garra update and both installers resolve
assets by exact name. The Linux binaries are built against glibc 2.35,
so they need Ubuntu 22.04+ / Debian 12+; older distros and musl-based
systems (Alpine) have to build from source. The installer checks
this before downloading.
Separately from the CLI, the Garra Desktop app (a Tauri tray app with
the parrot overlay and the Chat Bar on Ctrl+Space, bundling the CLI as a
sidecar) is published best-effort as
garraia-desktop-windows-x86_64.msi / -setup.exe (from v0.3.4) and
garraia-desktop-linux-x86_64.deb / .AppImage (from v0.3.5). Do not
confuse the two AppImages: garraia-linux-x86_64.AppImage is the
terminal CLI only. See docs/installation.md
Β§"Garra Desktop on Linux".
Once it is installed, garra desktop opens it from the terminal β
--status reports whether it is installed and where, --no-launch just
prints the resolved path for scripts. The CLI only locates and spawns the
app: it embeds no GUI and takes no Tauri dependency, so headless installs
(Termux, RunPod, Docker) are unaffected
(ADR 0021).
Install via script (Windows) β irm | iex
irm https://garraia.org/install.ps1 | iex
The Windows sibling of install.sh, at behavioral parity with it: detects the
platform, resolves the latest release, verifies the download against
SHA256SUMS, installs garraia.exe under %LOCALAPPDATA%\Programs\GarraIA
together with a garra.cmd shim (so garra works too), puts the directory on
your user PATH, then chains into init and start. No administrator rights
needed.
Mirrors (same script, auto-synced): raw.githubusercontent.com, jsDelivr, and
the GitHub release CDN
https://github.com/michelbr84/GarraRUST/releases/latest/download/install.ps1
β the release CDN mirror only resolves from v0.3.4 onward, since install.ps1
landed after the v0.3.3 tag. See docs/installation.md.
irm | iex cannot receive arguments β there is no PowerShell equivalent of
sh -s --. To pass flags, invoke the downloaded text as a scriptblock:
& ([scriptblock]::Create((irm https://garraia.org/install.ps1))) -SkipSetup
Flags mirror the shell installer (-SkipSetup, -SkipInit, -SkipStart,
-NoLocal, -Version <tag>, -InstallDir <dir>, -NoModifyPath, -Help),
each paired with a GARRAIA_* environment variable. GARRAIA_VERSION and
GARRAIA_INSTALL_DIR set by the caller win over -Version/-InstallDir;
for the on/off switches, env var and flag are OR-ed β either one enables
the behaviour.
On Windows ARM64 the installer picks the native
garraia-windows-aarch64.exe (published from v0.3.4, best-effort);
pinning GARRAIA_VERSION to anything older on ARM64 fails with a 404, since
those releases only served ARM64 via the x86_64 binary under emulation.
The binaries and installers are not code-signed, so SmartScreen shows "Windows protected your PC" on first run of the desktop MSI β expected, not tampering. See docs/installation.md for the full Windows section.
Install on Android (Termux) β curl | bash inside Termux
From v0.3.6 the installer has a Termux branch: run it inside the
Termux app (the
F-Droid or GitHub build β the Play Store fork is unsupported) and it
detects Termux via $TERMUX_VERSION / $PREFIX, skips the glibc preflight,
and installs garraia into $PREFIX/bin (on your PATH, no sudo):
pkg install curl
curl -fsSL https://garraia.org/install.sh | bash
garraia doctor # platform, dirs, config, providers, daemon β sysexits
garraia doctor whatsapp # the personal-WhatsApp path end to end: link, key, gateway, access, profile, workspace, MCP, provider
garraia chat # cloud provider, or --url http://PC-LAN:8080 for a LAN LLM
The Android binary targets bionic (aarch64-linux-android, API 21+,
built with cargo-ndk in the build-android-arm64 release job, best-effort)
β static musl builds are deliberately not shipped because they break DNS
on Android. garra update resolves the garraia-android-aarch64 asset
inside Termux. Your LLM can live in the cloud or on your LAN: any
OpenAI-compatible server (llama.cpp / LM Studio / vLLM / Ollama) works via
--url, and --provider llamacpp talks to a llama-server on
localhost:8080. Keep the Termux session in the foreground (or acquire a
wakelock) β Android's phantom process killer and battery optimization can
stop long-running background daemons. Strategy and the Termux β native
roadmap live in ADR 0016.
Update an existing install β garra update
garra update # interactive
garra update --yes # non-interactive (CI)
garra rollback # restore the previous binary if anything goes wrong
Self-update downloads the platform binary, verifies it against the release's per-asset SHA-256 checksum (aborts on mismatch or missing checksum), and swaps the executable atomically.
Build the desktop app (Tauri)
Prebuilt bundles are on the Releases page (see above); build from source
only if you need to. scripts/build-desktop-linux.sh (Linux: .deb +
AppImage, prerequisites listed in its header) and
scripts/build-installer.ps1 (Windows: MSI + NSIS) wrap these steps:
cargo build --release -p garraia
mkdir -p crates/garraia-desktop/src-tauri/binaries
cp target/release/garra crates/garraia-desktop/src-tauri/binaries/garraia-$(rustc -vV | grep host | cut -d' ' -f2)
cargo tauri build --manifest-path crates/garraia-desktop/src-tauri/Cargo.toml
# `cargo build --release -p garraia-desktop` gives the bare binary, no bundle
Why GarraIA?β
Measured, reproducible numbersβ
Measured with the versioned harness in
benches/agent-framework-comparison/
(scenarios 001,
002,
003;
raw logs committed under
results/).
Performance was measured on openclaw@2026.7.1-2 (npm latest at run
time) and a fresh ZeroClaw master clone (d355e3b); hardware and
versions recorded in environment.txt. The security-audit scenarios
below use separate commit-pinned inspection checkouts.
| Metric | GarraIA | OpenClaw (Node.js) | ZeroClaw (Rust) |
|---|---|---|---|
| Installed footprint | 47 MiB single binary (LTO, stripped) | 370 MiB node_modules + Node.js β₯ 22.22.3 runtime | 40 MiB binary (default lean-bundle build) |
Peak RSS, --help | 8.6 MiB (8,756 KiB) | 49.2 MiB (50,388 KiB) | 15.3 MiB (15,704 KiB) |
Cold start, --help (mean of 20) | 4.1 ms | 46.2 ms | 8.5 ms |
Yes, ZeroClaw's default binary is 7 MiB smaller than ours β the table reports what the harness measured, including where we lose.
These are CLI-floor measurements, not idle-server memory β the harness says exactly what it measures and what it does not. Numbers above are from
results/2026-08-28-vm/(x86_64 Linux container); the dedicated 1 vCPU / 1 GB droplet run is the reference target and lands in a follow-up results directory.
Audited security posture β all three frameworks, pinned commitsβ
Verified by mechanical inspection of pinned checkouts (OpenClaw
343252a, ZeroClaw d5617f1) β every row has a
reproducible check in scenarios
004
and 005,
with per-claim evidence in results/:
| GarraIA | OpenClaw | ZeroClaw | |
|---|---|---|---|
| Credentials at rest | AES-256-GCM vault (PBKDF2, 600k iters) available; opt-in β the init wizard's default is config.yml at mode 0600. MCP secrets auto-move to the vault when a passphrase is set | Not encrypted at rest (their docs' own words) β POSIX 0600/0700 perms; SecretRefs + 1Password/Vault are opt-in | ChaCha20-Poly1305 by default β the only default-encrypted posture of the three. Caveats: master key sits on the same filesystem; 1Password refs opt-in |
| Default bind | 127.0.0.1 | loopback | 127.0.0.1 |
| Gateway auth default | Messaging channels are deny-by-default (pairing codes). Local API is open on loopback; token/session auth is opt-in | Token required out of the box; fails closed without one | Pairing required by default; public bind is warn-only |
| Dependency tree | 1,061 crates (Cargo.lock) | 66 direct prod npm deps; npm install -g resolved 300 packages on the measured run | 1,265 crates (Cargo.lock) |
| Plugin isolation | WASM sandbox (wasmtime): memory caps + execution deadlines, opt-in feature | In-process, plugins are trusted code (their threat model says so) | WASM component model; Ed25519 signing exists but defaults to disabled |
Feature comparisonβ
| GarraIA | OpenClaw | ZeroClaw | |
|---|---|---|---|
| Chat channels | 11 wired in the default build (Telegram, Discord, Slack, WhatsApp, iMessageΒ·macOS, Google Chat, Teams, LINE, Matrix, IRC, Signal) + web chat + OpenAI-compatible API; the first 5 also have gateway integration tests | 27 bundled channel plugins | ~40 adapters (default build bundles 6) |
| LLM providers | 15 built-in (Anthropic, OpenAI, Ollama native + 12 OpenAI-compatible presets); 100+ models via OpenRouter; any endpoint via base_url | plugin providers | multiple, feature-gated |
| MCP | client: stdio (default build) + Streamable HTTP (mcp-http feature); also serves MCP over stdio (garra mcp-server, one garra_ask tool) | client: stdio/SSE/Streamable HTTP; also serves MCP | client: stdio/http/sse, per-agent fail-closed scoping |
| Memory | SQLite + local vector search (sqlite-vec) + LLM fact extraction, auto-injected into context | Markdown files + SQLite FTS5/vector | sqlite/postgres/qdrant backends |
| Config hot reload | file watch β most settings apply live (channels/providers wire at boot) | file watch (hybrid mode) | explicit reload endpoint only |
| Scheduling | one-shot heartbeats (up to 30 days ahead) and cron recurrence with IANA timezones, delivered to the originating channel; retries failed runs with backoff | full cron + automations | cron + SOP engine |
| Multi-tenant group workspace | in active development β Postgres 16 + pgvector, 42 tables across 36 migrations, 36 of them under FORCE Row-Level Security (Phase 3) | explicit non-goal (single trusted operator) | no |
| Native PT-BR assistant persona | yes β first-class, default | no | no |
| Prebuilt binaries + self-update | 6 targets (3 x86_64 required, 3 aarch64 best-effort), SHA-256-verified atomic self-update | npm package (needs Node runtime) | 10 targets, SLSA provenance |
Where the others win, honestly: OpenClaw has the broadest channel and plugin ecosystem (27 channels, 150+ extensions) plus a mature cron system, and its gateway requires auth out of the box β GarraIA's local API auth is still opt-in. ZeroClaw encrypts secrets by default, ships 10 prebuilt targets with SLSA provenance, and has OS-level exec sandboxing. We compare against their strengths on purpose: if this table ever reads like marketing, open an issue with the scenario ID and we will fix the table, not the finding.
Featuresβ
LLM providersβ
3 native providers β Anthropic Claude (SSE streaming, tool use),
OpenAI (GPT-4o, Azure, any compatible endpoint via base_url),
Ollama (local models + local embeddings) β plus 12 OpenAI-compatible
presets: OpenRouter (100+ models), DeepSeek, Mistral, Gemini, Qwen, Yi,
Cohere, MiniMax, Moonshot, Falcon, Jais, Sansa. Automatic provider
fallback on 429/5xx with exponential backoff and a circuit breaker.
Channelsβ
Wired end-to-end today: Telegram (streaming, MarkdownV2, bot
commands, pairing), Discord (slash commands, sessions), Slack
(Socket Mode), WhatsApp (Meta Cloud API webhooks, and β since v0.4.3 β
personal WhatsApp by linked device: garra whatsapp scans a QR code, keeps
the session encrypted on disk and runs a Node/Baileys bridge over stdio;
needs Node.js 20+ and npm on that path only β
docs/whatsapp.md,
ADR 0023; since v0.4.6,
who may talk to it and how far each one goes is
Access Policy v2
β explicit admission, a declared default for strangers, a per-principal
ceiling (chat Β· read Β· full, file writes separate) and a per-group
policy, driven by one engine shared by the CLI
(garra whatsapp access|level|write|block|unblock|users|remove|owner|unowner),
the admin API and the Web Console's WhatsApp Access page; the level is a
ceiling that composes with the session mode, so it only ever removes, never
grants, and garra doctor whatsapp walks the whole path end to end),
iMessage
(macOS, chat.db polling + AppleScript). Also: web chat console, an
OpenAI-compatible API (/v1/chat/completions) for VS Code
(Continue et al.) sharing the same session history, and an
Anthropic-compatible POST /v1/messages shim so Claude Code can point
at the gateway (ADR 0014).
garra agents setup|status|link|rollback|web provisions GarraIA,
OpenClaw, Hermes and Claude Code with one provider + model via AgentDeck.
Six more channels ship wired in the
default build: Google Chat and Teams (RS256-JWT webhooks),
LINE (HMAC webhook), and Matrix (federated, E2EE), IRC and
Signal (via signal-cli), which connect at boot with backoff retry.
They carry unit coverage in garraia-channels but no gateway integration
test yet, so the badge counts them as wired, not as CI-guarded.
Agent runtimeβ
Tool-execution loop (bash, file read/write, web fetch/search, repo
search, git diff, scheduling) with per-task tool-call budget; sliding
context window plus automatic background summarization for long sessions;
execution modes (ask / code / debug / architect / review / orchestrator
/ custom) with per-mode tool policies, selected via /mode, header, or
deterministic auto-routing. Since v0.3.9 those policies are enforced in
the executor β before that they were only asked for in the system prompt,
so a mode advertised as read-only did not actually stop file_write or
bash.
Voiceβ
STT via Whisper (local whisper.cpp or OpenAI API); TTS via Chatterbox
(GPU, multilingual), Hibiki, or any OpenAI-compatible /v1/audio/speech
endpoint (LM Studio) β ElevenLabs and Kokoro adapters exist in
garraia-channels::voice_channel but are not wired to the gateway yet;
garra start --with-voice; automatic audio replies on Telegram; format
conversion via ffmpeg.
MCP (Model Context Protocol)β
Connect any MCP server: stdio for local processes (default build), plus
Streamable HTTP for remote ones behind the mcp-http feature (in
config.yml/mcp.json use transport: stdio or transport: http; the
admin API additionally accepts sse/streamableHttp, all mapped to the
Streamable HTTP client; legacy SSE-only servers are not supported, and
the prebuilt binaries currently ship stdio-only). Tools appear
namespaced (server.tool); MCP prompts become slash commands
automatically; marketplace with one-click install via the web console
(/api/mcp/marketplace); admin API adds/removes servers without
restart; CLI: garra mcp list|inspect|resources|prompts. Config in
config.yml or mcp.json, both in the active config directory β
~/.config/garraia by default; see
Configuration (mcp.json is Claude
Desktop-compatible).
Skills & pluginsβ
Markdown skills (SKILL.md + YAML frontmatter) auto-discovered from
<config-dir>/skills/, with a visual editor and full CRUD API. Optional
WASM plugin sandbox (wasmtime, --features plugins) with per-plugin
memory caps and execution deadlines.
Web console "Garra Glass"β
A no-build-step SPA served at GET / β dashboard, chat, providers,
channels, sessions, settings, diagnostics, logs. Security invariant: no
secret is ever returned by any /api/* endpoint (write-only settings
report configured: true|false). Design system in
ADR 0009.
Infrastructureβ
Hot config reload (watched config.yml), daemonization with PID
management, garra restart, runtime provider switching, structured logs
(request_id, session_id, JSON via GARRAIA_LOG_FORMAT=json),
configurable timeouts per subsystem, per-IP rate limiting, health checks
(GET /api/health + boot table + background probes), AI-transparency
headers (X-AI-Model, X-AI-Provider) on every response.
Memory and self-learningβ
<config-dir>/ # ~/.config/garraia by default (see Configuration)
βββ memoria/fatos.json # LLM-extracted facts
βββ data/memory.db # SQLite + vector search (sqlite-vec)
βββ data/sessions.db # persistent conversation sessions (today under ~/.garraia/data/ unless `data_dir` is set)
βββ credentials/vault.json # AES-256-GCM encrypted credentials
After conversations, a dedicated LLM extractor identifies durable facts and stores them with context and date; local embeddings (Ollama β nomic-embed-text, mxbai-embed-large, β¦) power semantic search; relevant facts are injected into the agent's context automatically.
Memory is managed from three places. The CLI covers the most ground β
garra memory has stats, list, add, search, reindex, backup,
pin, ttl, delete and compact. The web console and the gateway
API cover the read paths plus a clear: GET /api/memory/recent,
GET /api/memory/search and DELETE /api/memory.
memory:
enabled: true
embedding_provider: ollama-embed # key of the `embeddings` entry below
embeddings:
ollama-embed:
provider: ollama
model: nomic-embed-text
base_url: "http://localhost:11434"
Securityβ
Built for the requirements of always-on agents that touch private data. Wording below matches what the code does β audited claim by claim (see the comparison section above for the evidence trail).
- Encrypted credential vault (opt-in) β AES-256-GCM at
<config-dir>/credentials/vault.json, key derived via PBKDF2-HMAC-SHA256 (600k iterations) fromGARRAIA_VAULT_PASSPHRASE. Stated plainly: thegarra initwizard's recommended default stores provider keys inconfig.yml(mode 0600, plaintext); choose the vault option and export the passphrase on every start to get encryption at rest. Making the vault the default is a roadmap item. - MCP secrets vault-protected β sensitive env vars of MCP servers are
auto-moved to the vault on save;
mcp.jsonkeeps onlyvault:mcp.<server>.<key>references. No passphrase β plaintext with a loud warning, never a broken boot. - Channels are deny-by-default β per-channel allowlists; unknown users must present a pairing code; unauthorized messages are dropped.
- Local API binds 127.0.0.1 by default β
gateway.api_keygates the/wsWebSocket handshake (and only it); the REST surface has no api-key auth today, so protect it with topology (loopback, firewall, reverse proxy).session_tokens_requiredis NOT implemented and the gateway refuses to start with it set, rather than claim a protection that does not exist. Hardening these defaults is tracked on the roadmap. TheHOSTenv var can override the bind β mind your container config. - 256-bit session tokens β HttpOnly, SameSite=Strict cookie (or
Bearer/
X-Session-Key), rotated on resume, TTL + idle timeout. - Two auth stacks, stated plainly β Auth v1 (
/v1/auth/*): 15-minute HS256 access tokens + opaque HMAC-signed refresh tokens, Argon2id hashing with PBKDF2 lazy upgrade. Legacy mobile endpoints (/auth/*): 30-day JWTs, Argon2id (legacy PBKDF2 rows upgraded on first login) β being migrated to v1. - Risky-command confirmation β opt-in
tool_confirmation_enabledpauses before destructive bash (rm -r,git reset --hard, β¦). - MCP process resource limits β optional per-server virtual-memory cap (setrlimit, Unix), startup timeout, auto-restart with exponential backoff. These are resource limits, not a sandbox: MCP processes keep filesystem/network access.
- MCP child environment isolation β a stdio MCP server is spawned with
an environment built from scratch: a minimal allowlist (
PATH,HOME, locale, temp dir) plus that server's ownenvmap. Gateway secrets (GARRAIA_JWT_SECRET, provider API keys, vault passphrase) never reach a third-party MCP binary. Per-serverinherit_env: truerestores the old behaviour and warns on every connect. - WASM plugin sandbox β optional (
--features plugins): per-plugin memory caps and execution deadlines via wasmtime. - Heuristic input filtering β control-character sanitization plus a keyword screen for common prompt-injection phrases on chat channels and the WebSocket. It is a heuristic, not a guarantee β treat prompt injection as unsolved, like every framework should.
- TLS (source builds) β compile with
cargo build -p garraia --features garraia-gateway/tls(the feature lives on the gateway crate; thegarraiabinary has notlspassthrough yet) and pointtls_cert_path/tls_key_pathat your certs (e.g. issued via certbot/Let's Encrypt). No built-in ACME client. Honest caveats: the prebuilt release binaries do not include the TLS feature today, and with certs configured but the feature absent the gateway logs a warning and serves plain HTTP β both are open hardening items on the roadmap. For production, a TLS-terminating reverse proxy in front of the loopback bind is the recommended setup.
Execution profilesβ
Everything above is the standard profile β the posture for a shared
machine. For a disposable pod (RunPod, Docker) that exists precisely so
the agent can act with full autonomy, declare it β the profile is never
inferred from container markers, and an invalid value refuses to boot:
execution:
profile: isolated-pod # or GARRAIA_EXECUTION_PROFILE=isolated-pod (wins)
pod_root: /workspace # optional, absolute; MCP filesystem root
channels:
whatsapp_linked:
type: whatsapp_linked
enabled: true
owners: ["5511999998888"] # only declared owners, only in 1:1 chats
Full power inside the isolated pod; no implicit access outside the pod.
The WhatsApp owner gets the code floor (bash, file_write, MCP tools);
groups and paired-only contacts never inherit it; the bash risky-command
gate and file jail stay on; a mounted host filesystem, the Docker socket or
host secrets are not isolated by the profile. Guide:
docs/execution-profiles.md,
ADR 0024.
Migrating from OpenClaw?β
garra migrate openclaw # --dry-run to preview, --source <dir> for custom paths
Imports your skills and channel configurations. Credential files are
detected and listed but not copied β re-enter API keys via
garra init (pick the vault option there to store them encrypted).
Configurationβ
GarraIA reads config.yml from its config directory, resolved as
$GARRAIA_CONFIG_DIR β ~/.config/garraia (the default on new
installs) β ~/.garraia (legacy, only when the XDG dir does not
exist). Run garraia config check to see which directory and file are
active. Details in docs/installation.md:
# The bind comes from --host/HOST and --port/PORT (default 127.0.0.1:3888);
# gateway.host/gateway.port are deprecated and never bound the socket (#1261).
llm:
claude:
provider: anthropic
model: claude-sonnet-4-5
# api_key resolution: vault > config > ANTHROPIC_API_KEY env var
ollama-local:
provider: ollama
model: qwen3.8:latest
base_url: "http://localhost:11434"
channels:
telegram:
type: telegram
enabled: true
bot_token: "your-bot-token" # or TELEGRAM_BOT_TOKEN
agent:
max_tokens: 4096
fallback_providers: [openrouter, ollama-local]
max_history_messages: 20
summarize_threshold: 40
memory:
enabled: true # embeddings + `embedding_provider`: see "Memory and self-learning"
Run garra config check to validate the effective configuration with
precedence reporting. Full reference β including Discord, Slack,
WhatsApp, iMessage, voice, embeddings, MCP, timeouts, rate limiting and
.garraignore β in docs/ and the
Portuguese README.
Architectureβ
A Rust workspace of 22 crates, each with a single responsibility:
crates/
βββ garraia-cli/ # CLI, init wizard, daemon management, self-update
βββ garraia-gateway/ # WebSocket gateway, HTTP API, web console, REST v1
βββ garraia-agents/ # LLM providers, tools, MCP client, agent runtime
βββ garraia-channels/ # 11 wired: Telegram, Discord, Slack, WhatsApp, iMessage, Google Chat, Teams, LINE, Matrix, IRC, Signal
βββ garraia-auth/ # Auth v1: Argon2id, JWT HS256, RBAC, RLS-backed identity
βββ garraia-workspace/ # Postgres 16 + pgvector multi-tenant (42 tables / 36 migrations, 36 under FORCE RLS)
βββ garraia-security/ # Credential vault, allowlists, pairing, validation
βββ garraia-db/ # SQLite memory, vector search, sessions
βββ garraia-config/ # YAML/TOML config, hot reload, `config check`
βββ garraia-voice/ # Whisper STT β LLM β Chatterbox/Hibiki TTS
βββ garraia-plugins/ # WASM plugin sandbox (wasmtime)
βββ garraia-embeddings/ # EmbeddingProvider / VectorStore traits
βββ garraia-learning/ # Self-improving skills (mining, safety gate, versioning)
βββ garraia-hardware/ # Physical devices: Device trait, R0-R5 risk gate, MQTT/Home Assistant/serial/GPIO adapters
βββ garraia-desktop-core/ # Tauri-free core of the Desktop Control Center (state, detect, supervise, locate)
βββ ... # telemetry, media, skills, storage, common, glob, desktop
apps/
βββ garraia-mobile/ # Flutter client (Riverpod, go_router) β Garra Cloud Alpha
Deep dives: runtime flow & voice pipeline, ADRs, wiki.
Documentation site (generated from this repo's markdown): https://michelbr84.github.io/GarraRUST/.
Roadmapβ
Development follows a 7-phase plan in ROADMAP.md β currently
deep in Phase 3: Group Workspace, a multi-tenant family/team space
(files, chats, AI memory, Notion-like tasks) on Postgres 16 + pgvector
with FORCE Row-Level Security. Recent milestones: auth v1 (Argon2id +
15-min JWTs + refresh tokens), the 37-table RLS schema, tus resumable
uploads, object storage (local + S3), OpenTelemetry baseline, the Garra
Learning agent, this benchmark harness, and the v0.3.x distribution wave
(AugβSep 2026): install.sh/install.ps1, Linux .deb/.rpm/AppImage,
native Windows ARM64, garra agents setup with the Anthropic-compatible
/v1/messages shim, and Garra Desktop for Linux with the Chat Bar.
v0.4.9 (Oct 2026) landed two big fronts and a security sweep. Data-subject
rights went live: GET /v1/me/export now returns a user's personal content
across every group they belong to (messages, mentions, files, memories,
tasks) and declares what it left out, PATCH /v1/me changes an email through
a safe out-of-band flow instead of blindly, and DELETE /v1/me queues a
30-day-grace erasure run by a dedicated-credential worker. The gateway also
became an MCP server over HTTP with task delegation β garra_ask,
garra_agent, external orchestrators with their own identity, policy, and
per-orchestrator audit, and operator-defined regex redaction β all off by
default and fail-closed. Alongside: 24 RUSTSEC advisories closed in one pass,
verifiable provenance attestation on every release asset, and the request path
now rejects unwrap()/expect().
See What's New in v0.4.9.
Contributingβ
GarraIA is MIT-licensed open source. Join the
Discord, check
CONTRIBUTING.md, and filter by
good first issue.
Support channels are listed in SUPPORT.md; security reports
go through SECURITY.md.
Licenseβ
MIT