-
Notifications
You must be signed in to change notification settings - Fork 2
commands
Pre-Alpha. This page describes behavior that may change.
A plugin exposes commands by declaring them in its Registration at startup and handling them with OnExecuteCommand at runtime. Once declared, the command is visible on every operator surface automatically: the CLI shell, ze cli -c, the MCP server, the REST API, and the Looking Glass (if it is read-only). You do not wire it up five times. You declare it once.
This page covers the author side. The consumer side (how commands flow from the CLI through the dispatcher to the plugin) is in the architecture reference.
Commands go in the Commands field of sdk.Registration. The engine learns about them during stage 1 (declare-registration).
err := p.Run(ctx, sdk.Registration{
Commands: []sdk.CommandDecl{
{Name: "my-plugin status", Description: "Show current status"},
{Name: "my-plugin check", Description: "Trigger immediate check", Args: []string{"target"}},
},
})| Field | Purpose |
|---|---|
Name |
The full command name. Use spaces to group (my-plugin status). |
Description |
One line shown in help and command-list. |
Args |
The expected positional arguments. Used for tab completion and help text. |
Register OnExecuteCommand before calling Run(). The handler receives the command serial (a correlation id for the request), the command name, the arguments, and the peer selector if one was provided.
p.OnExecuteCommand(func(serial, command string, args []string, peer string) (status, data string, err error) {
switch command {
case "my-plugin status":
return "done", `{"status":"running","uptime":3600}`, nil
case "my-plugin check":
if len(args) < 1 {
return "error", "usage: my-plugin check <target>", nil
}
result := performCheck(args[0])
return "done", result, nil
default:
return "error", "unknown command: " + command, nil
}
})OnExecuteCommand returns (status, data, error).
Success with data. Return a short status string ("done" is the usual choice) and the structured result as a JSON string.
return "done", `{"count":42,"items":["a","b"]}`, nilSuccess without data. Return "done" and an empty data string.
return "done", "", nilHandler error. Return a non-nil error. The SDK sends an error response and the status and data values are ignored.
return "", "", fmt.Errorf("operation failed: database timeout")User-facing validation failure. Return "error" as the status with an explanatory message in data, and nil for the error. The engine treats the response as a successful RPC but the operator sees the error message.
return "error", "usage: my-plugin check <target>", nilThe distinction matters: a Go error from the handler is a plugin bug, and the engine logs it. A "error" status is an expected failure that the user should see.
Commands are delivered as execute-command RPCs over the plugin connection.
#17 ze-plugin-callback:execute-command {"serial":"abc123","command":"my-plugin status","args":[],"peer":""}
#17 ok {"status":"done","data":"{\"status\":\"running\"}"}
On a handler error:
#17 error {"message":"operation failed: database timeout"}
| Field | Type | Purpose |
|---|---|---|
serial |
string | Correlation id for the request. |
command |
string | Command name (e.g. "my-plugin status"). |
args |
[]string |
Additional arguments. May be empty. |
peer |
string | Peer selector. May be empty. |
The peer field is the selector from the CLI (e.g. *, a peer name, or an IP). Use it to narrow your command's effect to the peers the operator targeted.
Forward to a worker. The handler runs on the plugin's event loop. If the command does real work, push the request onto a channel and return a status that says "accepted" or "in progress". The operator can poll for the result with a separate command.
JSON all the way. data is a string, but everything else in Ze treats the contents as JSON. Return JSON even when the output is trivial. It plays better with ze cli ... | json and with the MCP tools.
Tab completion. The Args field gives Ze a hint for tab completion. For dynamic completion (peer names, family names), the engine generates candidates from its own registry, so you usually do not need to do anything extra.
-
Handlers for the full
OnExecuteCommandsignature. - Go plugins for the surrounding SDK.
- Interfaces: CLI for the operator side of the pipe.
- In-tree commands reference for the full version.
Adapted from main/docs/plugin-development/commands.md.
Unreviewed draft. This wiki was authored in bulk and has not been reviewed. File corrections on the issue tracker.
- Overview
- YANG Model
- Editor Workflow
- Archive and Rollback
- System
- Interfaces
- VRRP
- BFD
- FIB
- OSPF
- IS-IS
- MPLS / LDP / RSVP-TE
- RSVP-TE
- SRv6
- Static Routes
- Policy Routing
- Firewall
- Traffic Control
- Class of Service
- L2TP/PPP
- PPPoE
- VPP Data Plane
- RPKI
- IPsec VPN
- TACACS+ AAA
- RADIUS AAA
- AS112 DNS
- Authorization
- Fleet
- BGP
- Starting and Stopping
- Show Commands
- Monitoring
- Flow Export
- DDoS Mitigation
- Anomaly Detection
- Health Checks
- Audit Trail
- Production Diagnostics
- Logging
- Operational Reports
- Healthcheck
- Self-Update
- Zero-Touch Provisioning
- MRT Analysis
- Upgrade and Restart
- Storage
- Policy
- Core
- Resilience
- Validation
- Capabilities
- Address Families
- Protocol
- Subsystems
- Infrastructure
- Route Server at an IXP
- Transit Edge with RPKI
- Public Looking Glass
- ExaBGP Migration Walkthrough
- FlowSpec Injection
- Chaos-Tested Peering
- AS Path Topology