Developers
Tool protocol
The local NDJSON socket protocol that the CLI, plugins, and agents use to reach the registry.
meith exposes its tool registry over a local newline-delimited JSON socket. The renderer uses Electron IPC, but it calls the same ToolRegistry and receives the same ToolResult shape.
Transport
The socket protocol is NDJSON: each line is one complete JSON frame. The runtime writes its socket path to ~/.meith/config.json and publishes live instance records in ~/.meith/instances/. Every message may include protocol; the current value is PROTOCOL_VERSION = 1. A mismatched version returns a transport error with PROTOCOL_ERROR.
Client messages
tool_call
Calls a registered tool. The response is zero or more tool_event frames, then one final tool_result frame.
{
"type": "tool_call",
"protocol": 1,
"requestId": "req_ab12cd34",
"toolName": "open_browser_tab",
"arguments": { "url": "http://localhost:3000" },
"clientInfo": {
"caller": "cli",
"cwd": "/work/project",
"spaceId": "space_1",
"tabId": "btab_1"
},
"timeoutMs": 30000
}list_tools returns serializable tool descriptors, and cancel_tool_call cancels an in-flight call by request id. Cancellation is cooperative — the registry aborts the call signal and races execution against it so a cancelled call always resolves with a structured failure.
The ToolResult envelope
Every tool resolves to this envelope:
interface ToolResult<T = unknown> {
ok: boolean
content?: T
meta?: Record<string, unknown>
diagnostics?: Array<{
level: "info" | "warn" | "error"
message: string
}>
error?: {
code: ToolErrorCode
message: string
details?: unknown
}
}Tools may return either a raw value or a full ToolResult.
- Raw values become
{ ok: true, content: value }. okResult()anderrorResult()create explicit envelopes.- Throwing
ToolErrorcontrols the returned error code; any other throw becomesTOOL_FAILED.
Error codes: UNKNOWN_TOOL, VALIDATION_ERROR, PERMISSION_DENIED, TIMEOUT, TOOL_FAILED, RUNTIME_SHUTTING_DOWN, CANCELLED, and PROTOCOL_ERROR.
Capabilities
Each tool can declare safety metadata that PermissionService treats as authorization inputs.
| Capability | Meaning |
|---|---|
read-only | Reads state, files, or metadata without mutating. |
writes-files | Creates, modifies, deletes, or persists files or config. |
controls-browser | Opens, navigates, clicks, types, or screenshots tabs. |
starts-process | Starts or controls processes, terminals, or dev servers. |
accesses-network | Causes network access directly or indirectly. |
destructive | Performs high-impact, irreversible actions. |
Caller identity
The socket is a local but untrusted boundary. ToolSocketService does not trust security-relevant caller claims from socket peers:
- socket clients can assert
cliorplugin, - attempts to assert
renderer,agent, orinternalare downgraded, - client-provided session ids are replaced by a server-assigned per-connection id.
Why it matters
caller: "renderer", and agents call the registry in-process with their real session id.Timeouts and auditing
Timeout order is tool_call.timeoutMs, then the tool definition's timeoutMs, then DEFAULT_TOOL_TIMEOUT_MS. Every registry call is logged and passed to PermissionService.auditToolCall; argument and result summaries redact likely secrets and large payloads before writing to audit.jsonl.