openclaw-release/skills/mesh-api/SKILL.md
Interact with a Meshtastic LoRa mesh network through MESH-API — list nodes, read messages, send texts, and check connection status.
npx skillsauth add mr-tbot/mesh-api mesh-apiInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You can interact with a Meshtastic LoRa mesh network through a running MESH-API instance. MESH-API exposes a REST API (default port 5000) that lets you list online nodes, read recent messages, send texts to specific nodes or broadcast to channels, and check device connectivity.
MESH_API_URL — Base URL of the MESH-API instance (e.g. http://192.168.1.50:5000). Required.MESH_API_KEY — Optional bearer token for future authentication support. If set, include it as Authorization: Bearer <token> on every request. If empty or unset, omit the header entirely — MESH-API has no auth by default.List all mesh nodes the MESH-API instance can see.
Request:
curl -s "$MESH_API_URL/nodes"
Response: JSON array of node objects.
[
{"id": "!a1b2c3d4", "shortName": "TBot", "longName": "TBot Base Station"},
{"id": "!e5f6a7b8", "shortName": "Hike", "longName": "Hiker Node"}
]
id is the Meshtastic hex node ID (always starts with ! followed by 8 hex characters).shortName is a 4-character display name.longName is the full node name.Retrieve recent messages from the mesh.
Request:
curl -s "$MESH_API_URL/messages"
Response: JSON array of message objects. Each message contains sender info, text, timestamp, and channel.
Send a message to a specific node (direct) or broadcast to a channel.
Direct message to a node:
curl -s -X POST "$MESH_API_URL/send" \
-H "Content-Type: application/json" \
-d '{"message": "Hello from OpenClaw", "node_id": "!a1b2c3d4", "direct": true}'
Broadcast to a channel:
curl -s -X POST "$MESH_API_URL/send" \
-H "Content-Type: application/json" \
-d '{"message": "Hello mesh!", "channel_index": 0}'
Body parameters:
message (string, required) — The text to send.node_id (string, required for direct) — Target node hex ID (e.g. !a1b2c3d4).direct (boolean) — Set true for a direct message to node_id.channel_index (integer) — Channel index for broadcast (default 0 = LongFast).Response:
{"status": "sent", "to": "!a1b2c3d4", "direct": true, "message": "Hello from OpenClaw"}
Broadcast a message to a channel (form-encoded, primarily used by the web UI).
Request:
curl -s -X POST "$MESH_API_URL/ui_send" \
-d "message=Hello+mesh!&channel_index=0"
Parameters (form-encoded):
message (string, required) — The text to send.channel_index (integer) — Channel index (default 0).destination_node (string, optional) — If provided, sends a direct message instead of broadcast.For programmatic use, prefer POST /send with JSON. Use /ui_send only when mimicking the web UI.
Check whether MESH-API is connected to its Meshtastic radio device.
Request:
curl -s "$MESH_API_URL/connection_status"
Response:
{"status": "connected", "error": null}
status will be "connected" or "disconnected".error contains an error description string if disconnected, otherwise null.List all available slash commands registered on the mesh (including extension commands).
Request:
curl -s "$MESH_API_URL/commands_info"
Response: JSON array of command objects.
[
{"command": "/ping", "description": "Check if the bot is online"},
{"command": "/ai-9z", "description": "Ask the AI a question"},
{"command": "/nodes", "description": "List online mesh nodes"}
]
When the user says something like the phrases below, map their intent to the corresponding API call:
| User says | Action |
|-----------|--------|
| "Who is online on the mesh?" | GET /nodes — list all visible nodes and summarize who is online. |
| "What nodes are on the mesh network?" | GET /nodes |
| "Send 'hello' to TBot" | GET /nodes first to resolve the name "TBot" to a node ID, then POST /send with {"message": "hello", "node_id": "<resolved_id>", "direct": true}. |
| "Send a message to !a1b2c3d4" | POST /send with {"message": "<user's message>", "node_id": "!a1b2c3d4", "direct": true}. |
| "What's been said on the mesh recently?" | GET /messages — retrieve and summarize the recent messages. |
| "Show me mesh messages" | GET /messages |
| "Is the mesh connected?" | GET /connection_status — report whether the radio link is up. |
| "Check mesh connection" | GET /connection_status |
| "Broadcast 'weather alert' to the mesh" | POST /send with {"message": "weather alert", "channel_index": 0}. |
| "Broadcast on channel 2: meeting at noon" | POST /send with {"message": "meeting at noon", "channel_index": 2}. |
| "What commands does the mesh bot support?" | GET /commands_info — list and describe available slash commands. |
When resolving a node by name (e.g. "send to TBot"), always call GET /nodes first to find the matching id. Never guess a node ID.
Character limit. Meshtastic mesh messages have a strict practical limit. Keep any message you send via POST /send under 200 characters unless the user explicitly requests a longer message. MESH-API will chunk longer messages automatically, but each chunk is a separate radio transmission — warn the user it will arrive as multiple packets and may take time.
No unsolicited long messages. Never send AI-generated text directly to the mesh without user confirmation if the text exceeds one chunk (200 characters). Always ask the user first: "This response is X characters and will be sent as N packets — proceed?"
Bot-loop prevention. Messages prefixed with m@i- are AI-generated mesh messages. If you see this prefix on an inbound mesh message (via GET /messages), do not relay it back to the mesh. Doing so creates an infinite loop between AI agents on the network.
Node ID format. Meshtastic node IDs are hex strings matching the pattern ! followed by exactly 8 hexadecimal characters (e.g. !a1b2c3d4). Always validate a node ID matches this format before using it in POST /send. If the user provides a name instead, resolve it via GET /nodes.
Connection check. Before sending messages, it is good practice to call GET /connection_status to verify the mesh radio is connected. If status is "disconnected", inform the user and do not attempt to send.
No auth by default. MESH-API does not require authentication in its default configuration. The MESH_API_KEY env var is optional future-proofing. Only include the Authorization header if MESH_API_KEY is set and non-empty.
Rate awareness. Meshtastic is a low-bandwidth LoRa network. Do not send rapid bursts of messages. If you need to send multiple messages, space them out and inform the user about the delay.
tools
# MESH-API Skill — MOVED > **This file has moved to [`openclaw-release/skills/mesh-api/SKILL.md`](../../openclaw-release/skills/mesh-api/SKILL.md).** > > It ships as part of the `@mesh-api/openclaw-meshtastic` OpenClaw plugin package. ## Manual install (without the plugin) ```bash cp openclaw-release/skills/mesh-api/SKILL.md ~/.openclaw/skills/mesh-api/SKILL.md ```
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.