Tools

Mutating vs Read-Only Actions

Every tool declares one or more actions, each classified as either mutating or read-only. This classification drives the operator approval workflow and the read-only subagent wrapper.

Read-only actions have no external side effects (searches, reads, listing). Mutating actions create, modify, or delete resources (sending email, writing files, executing commands).

Tools with mutating actions

ToolMutating actions
execexecute
write_filewrite
edit_fileedit
httprequest
spawnspawn
image_gengenerate
google_mailsend, reply, modify_labels
google_calendarcreate_event, update_event, delete_event
google_taskscreate_task, update_task, delete_task, create_list, delete_list
githubcreate_issue, create_pr_review, trigger_workflow
todoistcreate_task, update_task, close_task, delete_task, create_project
cronadd, remove, toggle, update
browsernavigate, click, type_text, fill, eval, screenshot
obsidiancreate, append

When operator approval is enabled, mutating actions pause for an Approve/Deny button click before executing. Read-only actions always execute immediately.

Parallel Tool Execution

When the LLM issues multiple tool calls in a single turn, oxicrab groups them into waves based on each tool's concurrency classification. Tools within the same wave execute concurrently; waves run in order.

ConcurrencyBehaviorExamples
ReadOnlyRuns concurrently with other ReadOnly tools in the same waveread_file, list_dir, web_search, memory_search, weather
SideEffectRuns sequentially (one at a time), but can share a wave with ReadOnly tools that complete firstwrite_file, exec, google_mail (send), cron (add)
ExclusiveRuns alone in its own wave, no other tools execute concurrentlybrowser (navigate/eval)

Each tool declares its concurrency level via the concurrency field on ToolCapabilities. The wave scheduler groups compatible calls and executes them with tokio::join! for maximum throughput while preserving safety for tools with side effects.

Filesystem & Shell

read_file Core

Read the contents of a file at the given path. Includes path traversal protection to prevent access outside the workspace.

write_file Core

Write content to a file at the given path. Creates parent directories if needed. Saves versioned backups (up to 14) in ~/.oxicrab/backups/ before overwriting existing files.

edit_file Core

Edit a file by replacing old_text with new_text. The old_text must exist exactly in the file. Useful for surgical edits without rewriting entire files.

list_dir Core

List the contents of a directory. Returns file names, sizes, and types.

exec Core

Execute a shell command and return its output. Secured with configurable command allowlists, environment scrubbing, and output size limits. Dangerous patterns (rm -rf, raw device access, command substitution, netcat, hex decode piping) are blocked.

Security

Configuration

~/.oxicrab/config.toml
[tools]
restrictToWorkspace = true

[tools.exec]
timeout = 60
additionalAllowedCommands = ["python3", "node"]
# allowedCommands = ["ls", "grep", "git", "cargo"]  # full override (replaces defaults)

[tools.exec.sandbox]
enabled = true
additionalReadPaths = ["/opt/data"]
additionalWritePaths = ["/home/user/output"]
blockNetwork = true

The default allowlist includes 70+ commands: file ops (ls, find, tree), text processing (grep, awk, sed, jq), dev tools (git, cargo, npm), and networking (curl, wget, dig). Use additionalAllowedCommands to add commands without replacing defaults, or allowedCommands for a full override. A startup warning is emitted when allowedCommands is empty (unrestricted shell access).

Set restrictToWorkspace: true to restrict filesystem access to the workspace directory.

The sandbox block controls kernel-level process sandboxing. On Linux, uses Landlock LSM. On macOS, uses Seatbelt (sandbox_init). Default read-only: /usr, /lib, /lib64, /bin, /sbin, /etc (plus /System, /Library, /opt/homebrew, /usr/local on macOS). Default read-write: workspace dir, /tmp, /var/tmp (plus /private/tmp, /private/var/folders on macOS). Use additionalReadPaths/additionalWritePaths to extend. Set blockNetwork: false to allow outbound connections from shell commands.

tmux Core

Manage persistent tmux shell sessions. Create long-running sessions, send commands, and read output. Ideal for processes that outlive a single tool call (dev servers, builds, etc.).

Web & Network

web_fetch Core

Fetch a URL and extract readable content. Converts HTML to markdown/text. Binary responses (images, PDFs) are saved to ~/.oxicrab/media/.

web_fetch_summary Core

Fetch a URL and return a small-model summary instead of the full extracted text. Use when the user wants "what does this page say" rather than a quote or specific extraction. Avoids dragging tens of KB of HTML into the main agent context. Adopted from IronClaw PR #2959.

Parameters

ParameterDescription
urlRequired. http(s) URL to fetch.
promptOptional framing for the summariser (e.g. "what's the API rate limit?"). Defaults to a generic key-points instruction.
max_input_charsCap on extracted page chars sent to the summariser. Default 12000; clamped to [1000, 60000].
summary_max_tokensCap on summary length in tokens. Default 600; clamped to [64, 4096].

Model routing

The summariser uses the provider/model at agents.defaults.modelRouting.tasks.web_summary when set; otherwise the main provider. Configure to a cheap model (e.g. Haiku, Gemini Flash, Mistral small) to keep summary cost negligible.

[agents.defaults.modelRouting.tasks]
web_summary = "anthropic/claude-haiku-4-5"

Cache

Identical (url, prompt, summary_max_tokens) requests are cached for 15 minutes (in-memory LRU, 64 entries). Cache survives across LLM turns within a single process; clears at restart. Cache hits are flagged with a [cached] prefix in the output.

SSRF

The fetch step delegates to web_fetch's SSRF validator (no internal IPs, redirects bounded by MAX_REDIRECTS). The summariser only sees the extracted text, never the raw bytes.

http Core

Make HTTP requests (GET, POST, PUT, PATCH, DELETE). For REST APIs, webhooks, and external services. Supports custom headers and JSON bodies. Binary responses are saved to disk.

reddit Core

Browse Reddit. Get hot, new, or top posts from a subreddit, or search within a subreddit. Read-only, no authentication required.

rss Core

RSS/Atom feed reader with adaptive content recommendations. Subscribes to feeds, pre-filters articles using keyword matching and LinTS (Linear Thompson Sampling for binary rewards, trained on your accept/reject signals), and surfaces candidates for review. Uses an onboarding state machine to guide setup before scanning.

Actions

ActionDescription
onboardGuided setup wizard. Detects the current onboarding step (needs_profileneeds_feedsneeds_calibrationcomplete) and returns the next instruction. Call this first to get started.
set_profileSet or update your interest description (minimum 20 characters). Used to pre-filter articles before LinTS ranking.
add_feedSubscribe to an RSS or Atom feed by URL. Validates and parses the feed on add, rejecting invalid or unreachable URLs.
remove_feedUnsubscribe from a feed by ID. Cascades to all stored articles for that feed.
enable_feedRe-enable a feed that was auto-disabled after consecutive failures. Resets failure counter.
list_feedsList all subscribed feeds with fetch stats (last fetched, article counts, error counts).
scanFetch all feeds, pre-filter new articles by interest profile, rank candidates with the LinTS model, and return the top results for review. Call accept or reject on results to train the model.
get_articlesList articles with optional filters: status (new/accepted/rejected), feed_id. Supports limit and offset for pagination.
acceptMark one or more articles as accepted. Accepts a single article_id or an array of IDs. Each accepted article is used as a positive training signal for the LinTS model.
rejectMark one or more articles as rejected. Accepts a single article_id or an array of IDs. Each rejected article is used as a negative training signal for the LinTS model.
get_article_detailFetch the full page content for an article by ID. Downloads and extracts readable text from the article URL.
feed_statsAnalytics dashboard. Shows per-feed acceptance rates, overall LinTS model weights, total article counts, and current cron scan job status.
doneMark the current review batch as complete. Commits all pending accept/reject decisions and updates the LinTS model.

How it works

Getting started

  1. Call rss { action: "onboard" } — the tool walks you through setup.
  2. Describe your interests: rss { action: "set_profile", interests: "Rust, AI engineering, distributed systems" }
  3. Add feeds from the suggestions (or your own): rss { action: "add_feed", url: "https://this-week-in-rust.org/rss.xml" }
  4. Fetch articles: rss { action: "scan" }
  5. Review at least 5 articles with accept / reject to calibrate the model.
  6. Call rss { action: "onboard" } again — setup completes and a cron job is created to scan every 6 hours automatically.

After setup, articles arrive via cron. Use get_articles to browse, feed_stats for analytics, and accept/reject to keep training the model.

Configuration

FieldDefaultDescription
enabledtrueEnable or disable the RSS tool
scanTimeout15Per-feed HTTP fetch timeout in seconds
maxArticlesPerFeed50Maximum new articles ingested per feed per scan cycle
purgeDays90Delete articles older than this many days (all statuses)
candidatesPerScan20Number of top-ranked articles returned to the LLM per scan
covarianceInflation0.01Exploration parameter — inflates the model covariance each scan cycle to prevent over-fitting

No external API key required. Behind the tool-rss cargo feature flag (default enabled). Feed data is stored in SQLite tables (rss_feeds, rss_articles, rss_article_tags, rss_profile, rss_model) in the workspace memory database.

Communication & Agents

spawn Core

Spawn a subagent to handle a task in the background. Tools are filtered by capability metadata — each tool declares its own subagent access level. Concurrency is limited by a semaphore (default: 5 concurrent subagents).

Subagent tool access

Each tool declares one of three subagent access levels via its capability metadata:

Access LevelBehaviorTools
FullPassed through directlyread_file, write_file, edit_file, list_dir, exec, web_search, web_fetch
ReadOnlyWrapped — only read-only actions exposed, mutating actions hidden from schema and blocked at executiongithub, google_mail, google_calendar, google_tasks, cron, todoist, reddit, media, obsidian, browser, weather, memory_search, workspace
DeniedNot availablehttp, tmux, spawn, subagent_control, image_gen, stash_retrieve, tool_search, all MCP tools

When the exfiltration guard is enabled, tools with network_outbound capability are additionally blocked unless listed in allowTools. This affects web_search, web_fetch (Full) and most ReadOnly tools that make network calls.

subagent_control Core

List running subagents, check capacity, or cancel a subagent by ID.

cron Core

Schedule recurring or one-shot tasks. Two job types: agent (default) processes the message as a full LLM turn with all tools; echo delivers the message directly to channels without invoking the LLM.

Schedule types

Actions

ActionDescriptionSubagent
addCreate a new scheduled job
listList all scheduled jobs
removeDelete a job by ID
runManually trigger a job
pausePause (disable) a job by ID
resumeResume (re-enable) a paused job by ID
dlq_listList dead letter queue entries (failed job executions). Optional dlq_status filter.
dlq_replayRetry a failed job by DLQ entry ID (dlq_id)
dlq_clearPurge DLQ entries. Optional dlq_status filter.
tracesList recent execution traces. Optional job_id filter and limit (default 10).
trace_detailShow full execution trace by trace_id, including all events.

Optional limits: expires_at (auto-disable after datetime), max_runs (auto-disable after N executions).

Dead Letter Queue (DLQ): Failed cron job executions are automatically recorded in the DLQ with job ID, payload, error message, and timestamp. The DLQ auto-purges to keep the 100 most recent entries.

Execution Traces: Every cron job run is traced with structured events (started, tool calls, LLM requests/responses, errors, completion). Traces are stored in SQLite and auto-purged to keep the 200 most recent. Use traces to list and trace_detail to inspect individual runs.

finish_cron Core Deferred

Explicit completion signal for cron-driven agent runs. Adopted from IronClaw PR #2807. Without this tool, cron jobs end via the heuristic "LLM stopped calling tools" — which fails the moment a hallucination drives the model to claim success after a tool returned is_error=true. finish_cron flips the contract: the LLM signals completion explicitly, and the cron callback uses the supplied summary verbatim for the trace's Completed / Failed event.

Registered as deferred — invisible by default in interactive contexts (it's only meaningful inside scheduled jobs). Surfaces in the cron system prompt; discoverable via tool_search if explicitly requested.

Parameters

ParameterDescription
summaryRequired. One-paragraph description of what actually happened. Stored verbatim in the trace; capped at 1000 chars.
successDefault true. Set to false to mark the run as a failure — the trace transitions to the Failed state and a DLQ entry is written.
reasonRequired when success = false. Short reason field surfaced in the trace and DLQ for the operator.

Behavior

claim Core

Manage structured claims about the user, project, or world. Each claim has text, confidence (0.0–1.0), status (open/accepted/retracted/contradicted), and optional evidence pointers. Use this when you need to record a fact you'll re-quote later — the structure prevents low-confidence hedges from rounding to fact, and the lint action surfaces contradictions before they accumulate.

Pairs with the _Source: …_ trailer on memory_search results: citations cover retrieval grounding, claims cover ingestion grounding. Adopted from openclaw's claims/wiki_lint pattern.

Actions

ActionDescriptionSubagent
addAssert a claim with text + confidence + optional evidence pointers
listList claims, optionally filtered by status (open/accepted/retracted/contradicted)
getFetch one claim by id (with evidence). Bumps last_seen_ms — the re-observation signal that keeps the staleness lint accurate.
lintRun all three lint passes (contradictions, stale low-confidence, orphans) and return a markdown report
update_statusMove a claim through the lifecycle: open → accepted | retracted | contradicted

Confidence guidance

Evidence pointer kinds

Each evidence pointer has a kind + value. The kind is freeform but conventional values are:

Lint passes

query_activity Core

Search the activity journal — an append-only NDJSON timeline of every conversation turn (user/agent) at <workspace>/activity_journal.ndjson. Accepts free-form natural-language time expressions. Only registered when agents.defaults.activityJournal.enabled = true.

Actions

ActionDescriptionSubagent
queryReturn records within window_minutes of the resolved anchor time. Read-only.

Parameters

ParameterDescription
time_expressionRequired. NL anchor: 30 minutes ago, 2pm yesterday, this morning, three days ago, now, etc.
window_minutesHalf-window width; the search covers anchor ± window. Defaults to defaultWindowMinutes (60); clamped at maxWindowMinutes (1440).
session_onlyWhen true, restrict results to the current session_key.

Time expression grammar

Case-insensitive. Word numbers (one, two, ..., ten) are accepted in place of digits. The tool returns the resolved anchor in its response so the model can sanity-check the parser.

The journal is never auto-rotated — archive or delete the file manually if it grows beyond your taste.

workspace Core

Manage workspace files: list, search, organize, and clean up files in the workspace. Tracks files in a SQLite manifest with category, creation time, and access time for lifecycle management.

Actions

ActionDescriptionSubagent
listList tracked workspace files, optionally filtered by category
searchSearch workspace files by filename pattern
infoGet detailed info about a specific tracked file
treeShow workspace directory tree
moveMove a file to a different workspace category
deleteDelete a tracked workspace file
tagAdd or update tags on a tracked file
cleanupRun workspace cleanup to remove expired files based on TTL config
sendSend a workspace file to the current conversation

Pagination

The list action accepts limit (integer, default 50, max 200) and offset (integer, default 0) parameters for pagination.

File Organization

Files written via write_file to workspace category directories (code/, documents/, data/, images/, downloads/, temp/) are automatically tracked in the manifest. Categories are inferred from file extensions. Files are organized into date-based subdirectories ({category}/{YYYY-MM-DD}/{filename}).

Reserved directories (memory/, knowledge/, skills/, sessions/) are not managed by the workspace tool. TTL-based expiration is configured via agents.defaults.workspaceTtl.

stash_retrieve Core

Retrieve truncated tool output from the in-memory stash. When a tool produces output that exceeds the truncation limit, the full result is preserved in an LRU cache (32 entries, 32 MB). Use this tool to recover the truncated portion by key, with optional offset and limit for pagination.

Parameters

ParameterDescription
keyThe stash key (provided in truncation notices). Required.
offsetByte offset to start reading from. Default: 0.
limitMaximum bytes to return. Default: 50000.

add_buttons Core

Attach interactive buttons to the next assistant response. Works on Slack (Block Kit) and Discord (action rows). Buttons appear below the message text. When a user clicks a button, the agent receives [button:{id}] as a new message, followed by any context data that was attached to the button.

Parameters

ParameterTypeDescription
buttonsarrayArray of button objects (max 5). Each object: id (string, required), label (string, required), style (string, optional: "primary", "success", "danger", "secondary"; default "secondary"), context (string, optional: opaque data returned on click — use to carry task IDs or action parameters; max 2000 chars, carried via Slack value field).

Style mapping

StyleDiscordSlack
primaryBlurple (Primary)Green (primary)
successGreen (Success)Default (no style)
dangerRed (Danger)Red (danger)
secondaryGrey (Secondary)Default (no style)

collections Core

Manage structured data collections with typed schemas. Create collections, then use per-collection tools (registered dynamically and discoverable via tool_search) for CRUD and aggregation operations.

Actions (collections tool)

ActionDescriptionSubagent
createCreate a new collection with typed field schema
listList all collections with record counts
describeShow full schema and metadata for a collection
deleteDelete a collection and all its records
alter_schemaAdd or remove fields from a collection schema

Actions (per-collection data tools)

Each collection gets its own tool named after the collection (e.g. grocery_list). Discover it via tool_search.

ActionDescriptionSubagent
addInsert a record with typed data
querySearch records with filters, pagination
updateUpdate a record by ID
deleteDelete a record by ID
countCount records matching optional filters
aggregateRun count/sum/avg/min/max with optional group_by

Field types

text, number, bool, enum (with allowed values), date, datetime. Collection names must be alphanumeric + underscore, 1–64 chars, starting with a letter.

Dynamic registration

Per-collection data tools are registered as deferred tools at startup and dynamically when new collections are created. Auto-generated skill files provide schema context to the LLM. Data is stored in SQLite tables (collections, collection_records) in the workspace memory database.

Google Workspace

google_mail Requires config

Interact with Gmail. Search, read, send, reply, list labels, and apply labels.

Actions

ActionDescriptionSubagent
searchSearch emails with Gmail query syntax
readRead a specific email by ID
sendSend a new email
replyReply to an existing email thread
list_labelsList all Gmail labels
labelApply or remove labels from messages

Setup

  1. Create a Google Cloud project at console.cloud.google.com
  2. Enable the Gmail API
  3. Create OAuth 2.0 credentials (Desktop application)
  4. Copy Client ID and Client Secret to config
  5. Run ./oxicrab auth google to complete the OAuth flow
[tools.google]
clientId = "your-google-client-id"
clientSecret = "your-google-client-secret"
gmail = true
calendar = true
tasks = true

Each tool can be individually enabled/disabled. OAuth scopes are derived automatically from which tools are enabled. Tokens are stored in the workspace database and auto-refresh. Run oxicrab auth google to authenticate.

google_calendar Requires config

Interact with Google Calendar. List, create, update, and delete events across calendars.

Actions

ActionDescriptionSubagent
list_eventsList upcoming events
get_eventGet details of a specific event
create_eventCreate a new calendar event
update_eventUpdate an existing event
delete_eventDelete an event
rsvpSet attendance status (accepted, declined, tentative) for a calendar event
list_calendarsList available calendars

Parameters

Mutating actions (create_event, update_event, delete_event, rsvp) accept a send_updates parameter (string: "all", "externalOnly", or "none", default "all") to control who receives email notifications.

Setup

Uses the same Google OAuth config as google_mail. Set "calendar": true and enable the Google Calendar API in your Cloud project.

google_tasks Requires config

Interact with Google Tasks. Create, list, update, and complete tasks across task lists.

Actions

ActionDescriptionSubagent
list_task_listsList all task lists
list_tasksList tasks in a task list
get_taskGet details of a specific task
create_taskCreate a new task
update_taskUpdate a task (title, notes, status, due date)
delete_taskDelete a task

Pagination

list_task_lists and list_tasks automatically paginate through all results using Google's nextPageToken mechanism.

Setup

Uses the same Google OAuth config as google_mail. Set "tasks": true and enable the Google Tasks API in your Cloud project.

Integrations

github Requires config

Interact with GitHub. Issues, pull requests, file content, PR reviews, CI/CD workflows, and notifications.

Actions

ActionDescriptionSubagent
list_issuesList issues for a repository
create_issueCreate a new issue
get_issueGet issue details
list_prsList pull requests
get_prGet pull request details
get_pr_filesList files changed in a pull request
create_pr_reviewSubmit a PR review (approve, request changes, or comment)
get_file_contentGet file content from a repository
trigger_workflowTrigger a GitHub Actions workflow
get_workflow_runsList recent workflow runs
notificationsList recent notifications

Subagents get read-only access (8 of 11 actions). Mutating actions (create_issue, create_pr_review, trigger_workflow) are hidden from the schema and blocked at execution.

Pagination

List actions support page (integer, default 1) and per_page (integer, default 10, max 100) parameters. Pagination applies to: list_issues, list_prs, get_workflow_runs, notifications.

Setup

  1. Create a Personal Access Token at github.com/settings/tokens
  2. Select scopes: repo, read:user
  3. Add to config:
[tools.github]
enabled = true
token = "ghp_your-github-token"

weather Requires config

Get current weather or forecast for a location. Uses the OpenWeatherMap API.

Setup

  1. Sign up at openweathermap.org/api (free tier available)
  2. Copy your API key
  3. Add to config:
[tools.weather]
enabled = true
apiKey = "your-openweathermap-api-key"

todoist Requires config

Manage Todoist tasks and projects.

Actions

ActionDescriptionSubagent
list_tasksList tasks (optionally filtered by project or filter query)
get_taskGet detailed info for a single task
create_taskCreate a new task
update_taskUpdate a task's content, description, due date, priority, or labels
complete_taskMark a task as complete
delete_taskPermanently delete a task
add_commentAdd a comment to a task
list_commentsList all comments on a task
list_projectsList all projects

Setup

  1. Get your API token from todoist.com/app/settings/account
  2. Add to config:
[tools.todoist]
enabled = true
token = "your-todoist-api-token"

media Requires config

Manage movies and TV series via Radarr (movies) and Sonarr (TV).

Actions

ActionDescriptionSubagent
search_movieSearch for movies by name
add_movieAdd a movie by TMDB ID
get_movie / list_moviesView library movies
search_seriesSearch for TV series by name
add_seriesAdd a series by TVDB ID
get_series / list_seriesView library series
profilesList quality profiles
root_foldersList root folder paths

Setup

  1. Install Radarr and/or Sonarr
  2. Get API keys: Settings > General > API Key (in each app)
  3. Add to config:
[tools.media]
enabled = true

[tools.media.radarr]
url = "http://localhost:7878"
apiKey = "your-radarr-api-key"

[tools.media.sonarr]
url = "http://localhost:8989"
apiKey = "your-sonarr-api-key"

obsidian Requires config

Read, write, search, and list notes in an Obsidian vault via the Local REST API plugin.

Actions

ActionDescriptionSubagent
readRead a note by path
writeCreate or overwrite a note (auto-generates YAML frontmatter)
appendAppend content to an existing note
searchFull-text search across the vault
listList notes, optionally filtered by folder

Pagination

The list (default 100, max 500) and search (default 50, max 500) actions accept limit and offset parameters for pagination.

Setup

  1. Install the Local REST API plugin in Obsidian (Community Plugins > search "Local REST API")
  2. Enable the plugin
  3. Copy the API key from the plugin settings
  4. Add to config:
[tools.obsidian]
enabled = true
apiUrl = "https://127.0.0.1:27124"
apiKey = "your-obsidian-local-rest-api-key"
vaultName = "MyVault"
syncInterval = 300
timeout = 15
Note: Obsidian must be running with the plugin enabled for the tool to work. syncInterval controls background cache refresh in seconds.

browser Requires config

Control a headless browser for web automation via Chrome DevTools Protocol. Open pages, click elements, type text, take screenshots, and execute JavaScript.

Actions

ActionDescriptionSubagent
openOpen a URL in the browser
clickClick an element by selector
type_textType text into a focused element
fillFill an input element by selector
screenshotTake a screenshot of the current page
snapshotGet the accessibility tree of the page
evalExecute JavaScript in the page context
getGet page content as text or HTML
scrollScroll the page by a given amount
waitWait for an element or a timeout
closeClose the browser session
navigateNavigate back, forward, or reload

Setup

  1. Install Chrome or Chromium: sudo apt install chromium-browser
  2. Enable in config:
[tools.browser]
enabled = true
headless = true
timeout = 30

Set headless: false to see the browser window. Set chromePath if Chrome is not in the default location. Screenshots are saved to ~/.oxicrab/media/.

image_gen Requires config

Generate images from text prompts. Supports OpenAI gpt-image-1 (DALL-E) and Google Imagen 3.

Setup

Uses API keys from the providers section. At least one provider key is required:

[tools.imageGen]
enabled = true
defaultProvider = "openai"
External Tools

MCP External

Connect external tool servers via the Model Context Protocol. Tools are auto-discovered at startup from child processes and registered as native tools with full middleware pipeline support. MCP tools cannot shadow built-in tools (rejected if they share a name with a built_in tool) and are not available to subagents. Null parameters are automatically stripped from tool calls before forwarding to MCP servers. Environment variable values containing CRLF characters are rejected at startup.

Configuration

[tools.mcp.servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/documents"]
enabled = true

[tools.mcp.servers.git]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-git"]
enabled = true

[tools.mcp.servers.git.env]
GIT_DIR = "/path/to/repo"

[tools.mcp.servers.git.sandbox]
enabled = true
additionalReadPaths = ["/path/to/repo"]
blockNetwork = false

Server config fields

FieldDescription
commandThe executable to run (e.g. npx, python, a binary path)
argsCommand-line arguments
envEnvironment variables passed to the child process
enabledSet to false to skip without removing the config
trustTrust level: "local" (default, full tool access), "verified" (requires approval per call), or "community" (read-only safe tools only)
sandboxProcess sandbox config for the server process. Same fields as tools.exec.sandbox: enabled (default true), additionalReadPaths, additionalWritePaths, blockNetwork (default true). Restricts the MCP server's filesystem and network access at the kernel level (Landlock on Linux, Seatbelt on macOS).
Prerequisite: Node.js and npm are required for npx-based MCP servers. MCP tools are discovered at startup — restart oxicrab after changing server config.
Voice Transcription

Voice Transcription

Voice messages from channels are automatically transcribed to text. Not a tool itself, but a service that feeds into the agent. Supports dual backends with automatic fallback.

Local backend (whisper.cpp)

On-device inference. Requires ffmpeg and a GGML model file:

# Install ffmpeg
sudo apt install ffmpeg

# Download the model (~574 MB)
mkdir -p ~/.oxicrab/models
wget -O ~/.oxicrab/models/ggml-large-v3-turbo-q5_0.bin \
  https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo-q5_0.bin

Cloud backend (Whisper API)

Uses Groq, OpenAI, or any OpenAI-compatible transcription endpoint. Groq offers free inference and is recommended.

Configuration

[voice.transcription]
enabled = true
localModelPath = "~/.oxicrab/models/ggml-large-v3-turbo-q5_0.bin"
preferLocal = true
threads = 4
apiKey = "your-groq-or-openai-api-key"
apiBase = "https://api.groq.com/openai/v1/audio/transcriptions"
model = "whisper-large-v3-turbo"

preferLocal: true (default) tries local first, falls back to cloud. Set to false to prefer cloud. Either backend alone is sufficient.