Skills catalog

nexo-rs uses "skill" to mean two different things. Both are covered on this page; gating semantics for each live in Gating by env / bins.

  1. Extension skills — shipped under extensions/ in the repo, discovered and spawned like any other stdio extension. 22 of them landed in Phase 13.
  2. Local skills — markdown files under an agent's skills_dir/ that get injected into the system prompt at turn start.

The two overlap in name but not in mechanism:

Extension skillLocal skill
Where it livesextensions/<id>/ with plugin.tomlskills/<name>/SKILL.md
How it's loadedExtension discovery → stdio spawnSkillLoader at turn time
What it producesTools in ToolRegistryText injected into the prompt
GatingWarn + continue, tools still registeredWarn + skip entirely

Extension skills (Phase 13)

All shipped as stdio extensions written in Rust. _common is a shared Rust library (circuit-breaker primitives), not an extension itself.

Core utilities

IdPurposeRequires
weatherCurrent + forecast via Open-Meteo (no auth).
openstreetmapForward / reverse geocoding via Nominatim.
wikipediaArticle search + summaries.
fetch-urlHTTP GET / POST with SSRF guard, retries, circuit breaker.
rssFetch & parse RSS / Atom / JSON feeds.
dns-toolsA/AAAA/MX/TXT/NS/SOA/SRV + reverse + whois.
endpoint-checkHTTP probe (status + latency) + TLS cert inspection.
pdf-extractExtract text from PDFs.
translateLibreTranslate self-hosted or DeepL API.
summarizeChat-based text/file summary via OpenAI-compat endpoint.
openai-whisperAudio transcription via OpenAI-compat /audio/transcriptions.

Search & knowledge

IdPurposeRequires
brave-searchWeb search.env BRAVE_SEARCH_API_KEY
goplacesGoogle Places text search + details.
wolfram-alphaComputational queries (short + full pods).env WOLFRAM_APP_ID

Infra & ops

IdPurposeRequiresWrite-gate
githubREST API: PRs, checks, issues.env GITHUB_TOKEN
cloudflareDNS, zones, cache purge.env CLOUDFLARE_API_TOKEN
docker-apips, inspect, logs, stats, start, stop, restart.bin dockerenv DOCKER_API_ALLOW_WRITE
proxmoxProxmox VE: nodes, VMs, containers, lifecycle.env PROXMOX_TOKENenv PROXMOX_ALLOW_WRITE, env PROXMOX_INSECURE_TLS for self-signed certs
onepassword1Password secrets metadata; reveal gated.bin op, env OP_SERVICE_ACCOUNT_TOKENenv OP_ALLOW_REVEAL
ssh-execRemote command execution with host allowlist.bin ssh, scphost allowlist in config
tmux-remoteDrive tmux sessions (create, send keys, capture, kill).bin tmux

Media & content

IdPurposeRequires
msedge-ttsText-to-speech via Edge Read Aloud.
rtsp-snapshotFrames / clips from RTSP or HTTP camera streams.bin ffmpeg
video-framesExtract frames + audio from videos.bin ffmpeg, ffprobe
tesseract-ocrOCR with language packs + PSM modes.bin tesseract
yt-dlpDownload video / audio / metadata.bin yt-dlp
spotifyNow-playing, search, play, pause, skip.env SPOTIFY_ACCESS_TOKEN

Google (phase 13.18)

Single google extension covering 32 tools across Gmail, Calendar, Tasks, Drive, People, and Photos. Uses OAuth refresh-token flow. Writes gated by five independent env flags:

  • GOOGLE_ALLOW_SEND — Gmail send
  • GOOGLE_ALLOW_CALENDAR_WRITE
  • GOOGLE_ALLOW_DRIVE_WRITE
  • GOOGLE_ALLOW_TASKS_WRITE
  • GOOGLE_ALLOW_PEOPLE_WRITE

See Plugins — Google for the OAuth setup and the generic google_call tool that fronts the extension.

LLM providers (phase 13.19)

anthropic and gemini are native LLM clients living under crates/llm/, not extensions. See LLM providers and children.

Templates

IdPurposeLanguage
template-rustCopy-and-edit skeleton (ping, add).Rust
template-pythonstdlib-only skeleton.Python

See Extensions — Templates.

Local skills

Local skills are markdown files loaded by SkillLoader and injected into the system prompt at turn time. Defined in the agent config:

# agents.yaml
agents:
  - id: kate
    skills_dir: ./skills
    skills:
      - weather
      - github
      - summarize
      - google-auth

Each entry resolves to <skills_dir>/<name>/SKILL.md:

---
name: "Weather"
description: "Current conditions and forecasts"
requires:
  bins: ["curl"]
  env: ["WEATHER_API_KEY"]
max_chars: 5000
---
# Weather skill

Call `weather_forecast(city)` to get a 3-day forecast.
Use metric units. Default to the user's locale when unspecified.

Loading flow

flowchart TD
    CFG[agents.yaml skills: list] --> LOOP[for each name]
    LOOP --> READ[read skills_dir/name/SKILL.md]
    READ --> FM[parse YAML frontmatter]
    FM --> GATE{bins on PATH<br/>AND env set?}
    GATE -->|no| SKIP[warn + skip<br/>not injected]
    GATE -->|yes| RENDER[render into prompt:<br/>heading + blockquote + body]
    RENDER --> TRUNC[truncate to max_chars]
    TRUNC --> INJECT[inject into system prompt]

Why local skills skip-on-miss (vs extensions warn-and-continue)

A local skill is a text instruction to the LLM describing a capability. If the backing bin/env isn't available the tool will fail — but worse, the LLM was told the capability exists and will repeatedly try to use it. Skipping the skill prevents lying to the model.

An extension is a registered tool. If the LLM invokes it and the backing bin is missing, the tool returns an error — the LLM observes and adapts. Warn-and-continue is fine.

See Gating for the full semantics.

How to pick

  • Need the LLM to know how to do something (usage pattern, style rules, examples)? → local skill.
  • Need the LLM to do something (make a call, return data)? → extension skill.
  • Both? → ship the extension and write a local skill next to it that explains when to use it.