-
Notifications
You must be signed in to change notification settings - Fork 3
cli
Pre-Alpha. This page describes behavior that may change.
The CLI is a network OS shell, not a Unix wrapper. You connect over SSH, you get tab completion driven by the YANG schema, and the workflow is the one operators of JunOS or Cisco IOS already know: edit, diff, commit, rollback. This is the long version of the CLI tour.
ze cli # Interactive shell
ze cli -c "show bgp peer list" # One-shot command, exits after
ze show bgp peer upstream detail # Read-only query, safe in scripts
ze start --cli # Start daemon + interactive CLI attached
ze show debug | ze pipe match reactor # Offline pipe formatting
ze start --web-only # Start daemon with web UI only (no SSH CLI)
ze cli is the interactive path. ze cli -c runs a single command and exits, with a non-zero exit code on error so it composes with shell pipelines. ze show is the read-only subset: it cannot mutate state, which is exactly what you want in a monitoring script. ze start --cli starts the daemon and immediately drops into an interactive CLI session attached to it. ze pipe (formerly ze format) brings the YANG pipe operators (json, table, match, count, resolve, origin, first, last) to any command's output offline: pipe through ze pipe json or ze pipe match <pattern>. ze start --web-only starts the daemon with the web UI but without the SSH CLI server.
Every command that takes a filename argument treats - as stdin (reading) or stdout (writing), so configs stream through pipes without temp files: generate | ze config show -, ze config migrate -o - old.conf. stdin is consumed once (a second - in one command fails cleanly), a file literally named - is ./-, and the TTY-bound editor commands (ze config edit, ze config rollback, ze config history) reject it.
Operational commands read verb first: the action comes first, then the object, then any filters. One registry holds the whole vocabulary, and it holds twelve verbs. Both the grammar gate and the plugin registration gate derive their verb set from it, so there is no second list.
| Role | Verbs | What the role means |
|---|---|---|
| Read |
show, monitor, resolve
|
Reads state and changes nothing. |
| Config-tree mutation |
set, delete
|
The only verbs allowed to target an object in the config YANG tree, in path form. |
| Runtime action |
clear, request, commit, update, cache, create, debug
|
Acts on live state. create and delete also manipulate live kernel resources such as netlink interfaces. debug perturbs live protocol state for introspection, which is why it is not a read. |
A small, learnable verb set is the point, so adding a verb is a vocabulary decision rather than a convenience.
Two surfaces are deliberately outside the verb-first grammar. The text-bridge compatibility verbs announce, withdraw, peer, and help mirror a legacy line protocol whose grammar that protocol fixes. stop, restart, and reboot are answered by the SSH exec middleware before the dispatcher, which registers no key for them.
show host # read-only query
show crashes # read-only query
show event list # read-only query
show metrics pool # read-only query
monitor traffic stat # live stream
request config archive backup-2026 # runtime action
request l2tp outgoing-call remote lns1 called 5551234
announce flowspec destination 192.0.2.0/24 discardAfter the verb comes the object, which is the component or plugin that owns the command (host, crashes, ddos, anomaly, traffic, l2tp, and so on), so the command tree mirrors the plugin tree. After the object come positional keyword filters. Address family and other qualifiers are keywords in the grammar (show neighbor ipv6, show traffic usage name eth0), never --flags. The --flag spelling belongs only to the offline ze ... shell tooling, not to the command model.
The grammar is now uniform: the last noun-first reads were nested under show (event list became show event list, command list/help/complete became show command ...), enabling debug for a subsystem became set debug module <name> and disabling it delete debug module <name>, and clear interface counters [<name>] puts the action ahead of the interface name.
The bare forms are gone, not deprecated. The migration removed the spellings below from the command tree, so the dispatcher answers unknown command for the left column.
| Removed | Type instead |
|---|---|
daemon reload |
request reload |
daemon status |
show status |
daemon quit |
request halt |
daemon shutdown |
request shutdown |
bgp summary |
show bgp summary |
bgp health |
show bgp health |
bgp monitor |
monitor bgp |
bgp metrics values / bgp metrics list
|
show metrics values / show metrics list
|
peer list |
show bgp peer list |
rib routes received / rib routes sent
|
show bgp rib received / show bgp rib sent
|
rib clear-in / rib clear-out
|
clear bgp rib in / clear bgp rib out
|
rib inject / rib withdraw
|
request bgp rib inject / request bgp rib withdraw
|
cache list |
show cache |
cache forward <id> <peer> |
request cache forward <id> <selector> |
cache retain <id> / cache release <id> / cache expire <id>
|
request cache retain <id>, request cache release <id>, request cache expire <id>
|
commit start <name> and its siblings |
request commit start <name> |
rpki status and the rest of the family |
show bgp rpki status, show bgp rpki cache, show bgp rpki roa, show bgp rpki summary, show bgp rpki aspa
|
route-refresh <family> |
request peer <sel> refresh <family> |
subscribe / unsubscribe
|
request subscribe / request unsubscribe
|
command-list / command-help <name>
|
show command list / show command help <name>
|
del bgp peer <name> |
delete bgp peer <sel> |
system memory / system platform / system sockets tcp / system update
|
show system memory, show system platform, show system sockets tcp, show system update
|
system profile heap / system goroutines summary / system file-descriptors summary
|
show system profile heap, show system goroutines summary, show system file-descriptors summary
|
system file-descriptors max <n> |
set system file-descriptors max <n> |
system kernel-log count <n> / system memory-map
|
show system kernel-log count <n> / show system memory
|
interface rate [<name>] |
show interface rate [<name>] |
show interface detail <name> / show interface counters <name>
|
show interface name <name> detail / show interface name <name> counters
|
capture interface [<name>] |
show capture interface [<name>] |
runtime memory |
show runtime memory |
traceroute <target> / tcp-check <host> <port>
|
show traceroute <target> / show tcp-check <host> <port>
|
set bgp peer <name> with <config> / set bgp peer <name> save
|
Removed with no replacement. Peer config goes through the editor. |
Two notes on that table. cache stays in the verb vocabulary above while no operator command registers a path under it: the cache commands moved under show and request, and the command tree carries no top-level cache node. The commit row is about the BGP commit windows below, which live under request commit. It says nothing about the config editor's own commit, which is unchanged.
Hyphen names one thing; a space opens a namespace. A hyphen inside a token joins words that name a single indivisible thing, so graceful-restart, as-set, max-prefix, and show class-of-service keep their hyphens. When the left part is an object with members, it becomes its own token so completion can enumerate the members and the command tree keeps mirroring the plugin tree. Several commands moved to this namespace form: show traffic stat (was show traffic-stat), show traffic feature, monitor traffic stat, show bgp health (was show bgp-health), show flow export / show flow recent, show policy routes, show runtime memory (Go allocator) and show system memory (OS process, was show system memory-map), ze pipe (was ze format), and ze isis decode (was ze isis-decode). If you have muscle memory for the old hyphenated spellings, retype them with a space.
Run ze with no arguments in an interactive terminal and it opens a hierarchical, navigable menu of every command instead of printing static help. The launcher groups commands by section, lets you drill into subcommands, and returns the command you select so you can run it.
ze # Interactive command menu (TTY only)| Behaviour | Detail |
|---|---|
| TTY detection | The menu opens only when stdin is a terminal. When piped or scripted, ze prints static help and exits with status 1. |
| Grouping | Commands are listed under section headers. The Operations section also folds in YANG-dispatched verbs, sorted alphabetically. |
| Drill-down | Entries with subcommands show a > arrow; selecting one descends a level. A breadcrumb at the top shows where you are. |
| Type-to-filter | Typing narrows the visible entries by name prefix. The filter is shown at the bottom. |
| Keys | Up/Down navigate, Enter selects (or descends), Left/Backspace go back a level, Esc clears the filter then quits. |
The launcher renders in an alternate screen and uses the semantic color system below (structure magenta for the ze title and section headers, identity cyan for command names, blue for the breadcrumb, gray for descriptions and hints).
Every terminal surface (the launcher, help output, autocomplete, the config editor, the BGP dashboard, ping and traceroute monitors, and structured logs) shares one semantic palette. The rule is consistency: the same color always means the same thing, so you read meaning, not decoration. Hierarchy comes from weight (normal, dim, bold), not hue.
There are seven foreground roles, the practical ceiling before colors stop carrying meaning. The palette is dark-terminal-first and uses ANSI 256-color codes (not true-color) for maximum compatibility, including SSH sessions over constrained links. It degrades automatically: 16-color terminals get the base ANSI mapping, monochrome terminals get bold and dim only.
| Role | Meaning | Color | Used for |
|---|---|---|---|
| structure | "what kind of thing am I looking at?" | 205 magenta | Headers, section titles, prompt path, mode indicators |
| identity | "what can I type or act on?" | 73 cyan | Commands, keywords, completion entries |
| value | "what is the system telling me?" | 82 green | Data values, counts, addresses, ASNs, route counts |
| caution | "something is off, not broken" | 214 orange | Warnings, flags, non-default or degraded state |
| danger | "something is broken, act now" | 196 red | Errors, down state, validation failures |
| muted | "background info, skip on fast scan" | 241 gray | Descriptions, secondary text, timestamps, hints |
| context | "where am I?" | 33 blue | Navigation breadcrumb, current path, positional info |
Two modifiers layer on top of a role rather than acting as roles: bold for emphasis (selected row, active state) and a paired dark background for inline validation and selected-row highlight.
SSH sessions render the same TUI as local sessions. The Wish middleware detects terminal capabilities per connection and the 256-color codes degrade automatically, so no separate palette is needed.
A handful of ze show subcommands run locally without touching the daemon at all (version, bgp decode, bgp encode, env, schema, yang, data (ls, cat, registered), config (dump, diff, history, ls, cat, fmt), interface). The rest go through the SSH server built into the Ze process.
The SSH server is part of the daemon. ze init walks you through username, password, host, and port the first time. Defaults are 127.0.0.1:2222 with an auto-generated ED25519 host key. Credentials live in the Ze database (database.zefs) with bcrypt-hashed passwords.
Override the host or port from the environment when you talk to a remote daemon:
export ZE_SSH_HOST=10.0.0.1
export ZE_SSH_PORT=2222
ze cliThe full list lives in reference/command-reference.md. The most-used groups are these.
show bgp peer list
show bgp peer <selector> detail
show bgp peer <selector> capabilities
show bgp peer <selector> statistics
show bgp peer <selector> history
show bgp peer <selector> rib
show bgp summary [<afi>/<safi>]
show bgp health
request peer <selector> teardown <code> [message]
request peer <selector> pause
request peer <selector> resume
request peer <selector> flush
request peer <selector> clear soft
request peer <selector> refresh <family>
delete bgp peer <selector>
The peer selector takes * (all peers), an exact IP, a peer name, an ASN (as65001), a prefix, an exclusion (!edge1), or a comma-separated list.
A peer-scoped destructive command takes one peer and refuses anything else. request peer <sel> teardown, pause, resume, flush, clear soft, peer <sel> raw, and delete bgp peer <sel> share one resolver, which accepts a name, an address, an ASN, or a prefix. It refuses * and an empty selector, because the command needs one specific peer. It refuses every exclusion form (!edge1, !as65001, !10.0.0.0/24), because an exclusion names a set: in a two-peer topology it would resolve to one peer and tear down the other, then start failing the day a third peer is configured. It refuses any selector that matches more than one peer. A selector that resolves to nothing is an error, not a silent success reported as done.
peer <sel> update text <attrs> nlri <family> <op> <prefix>
peer <sel> update hex <hex>
show bgp rib [received | sent | in | out] [filters...]
show bgp rib best [filters...]
show bgp rib best status
show bgp rib status
clear bgp rib in <selector>
clear bgp rib out <selector> [family]
request bgp rib inject <peer> <family> <prefix> [attrs...]
request bgp rib withdraw <peer> <family> <prefix>
show bgp rib rpf <family> <source-addr> # reverse-path LPM lookup in the Loc-RIB (CIDR families)
request bgp rib inject takes a peer label, not a live session, so you can prime the Adj-RIB-In without anyone connected. show bgp rib filters on family, prefix, path, community, large-community, first N, and last N, and count and graph change the shape of the answer.
The commit workflow lets you batch multiple route operations into one named transaction.
request commit start <name>
request commit end <name>
request commit eor <name>
request commit rollback <name>
request commit show <name>
request commit withdraw <name> route <prefix>
request commit list
deactivate <path> # Mark a node inactive (kept in file, skipped at apply)
activate <path> # Clear inactive flag
insert <path> before <ref> # Insert into an ordered list
rename <old> <new> # Rename a keyed list entry
copy <src> <dst> # Copy a keyed list entry
deactivate and activate work on both containers and leaf nodes. An inactive node is kept in the config file but skipped at apply time.
In edit mode, show | compare diffs the candidate against the committed config and prints only the parts that differ, not the whole tree with a few changed lines buried in it, so a large config still shows a small, readable change set before you commit.
show host [cpu|nic|memory|dmi|thermal|storage|kernel|platform|all]
show health # Component health registry
show policy list # BGP filter types and named instances
show policy chain peer <peer> # Effective BGP filter chain for a peer
show policy routes # Policy-based routing rules (PBR)
show static # Static routes with BFD status
show rib # Protocol RIB (route-type marks a discard route)
show interface # Every interface, full detail
show interface brief # One line each: name, state, IP, MTU
show interface scan # Discover and classify every OS interface
show interface type <type> # Only interfaces of that type
show interface errors # Only interfaces with a non-zero error or drop counter
show interface rate [<name>] # Per-interface rate tracking
show interface name <n> detail # Full detail for one interface
show interface name <n> counters # Counters for one interface
show bmp sessions # BMP receiver sessions
show bmp peers # BMP monitored peers
show bmp collectors # BMP sender collector status
show bmp rib # BMP monitored routes
show rr status # Route reflector running state
show rr peers # Route reflector peer states
show vpn ipsec status # IPsec engine status
show vpn ipsec sa # Active IKE and Child SA details, with byte and packet counters
show vpn ipsec peer name <name> # One IPsec peer, full detail
show vpn ipsec dataplane sa [spi <spi>] # Kernel SAD read back
show vpn ipsec dataplane policy # Kernel SPD read back
show vpn ipsec dataplane drift # Child SAs the kernel does not hold; exits non-zero on drift
show pki certificates # Loaded certificates with expiry
show bgp rpki status
show bgp rpki cache
show bgp rpki roa [<prefix>]
show bgp rpki summary
show bgp rpki aspa # ASPA records and validation state
request bgp rpki validate <prefix> <origin-asn>
show dns lookup <name> # DNS resolution
show dns cache list # Cache entries with TTL
show dns cache stats # Hit/miss statistics
clear dns cache # Flush the DNS cache
show system sockets # TCP/UDP socket state (replaces ss)
show system kernel-log # Kernel log (replaces dmesg)
show system goroutines # Goroutine dump
show system file-descriptors # FD counts and limits
show system profile cpu # CPU pprof profile
show system profile heap # Heap pprof profile
show runtime memory # Go allocator: alloc, heap, GC (runtime.MemStats)
show system memory # OS process memory (VmRSS/VmSize) from /proc/self/status
show tcp-check <ip> <port> # TCP connectivity probe
show traceroute <target> # ICMP path trace
show capture interface <iface> # Live packet capture (replaces tcpdump)
show crashes # Panic crash reports
show debug # Live debug module state (YANG-dispatched)
show class-of-service # CoS profiles and assignments
show bgp irr # IRR filter status per ASN
show traffic stat # Aggregated traffic snapshot (top talkers, ports)
show traffic usage # Per-interface eBPF byte accounting
show traffic feature # Neutral per-source traffic signals (facts, not verdicts)
show anomaly detect # Behavioral anomaly incidents (report-only)
show anomaly shape # Anomaly responder mode and armed sources
show ddos status # DDoS observation status
show ddos incidents # Recent DDoS incident ring (newest first)
show metrics pool # Per-attribute-pool occupancy and dedup rates
monitor ping <target> # Continuous ping with live stats (count, size, interval)
monitor traceroute <target> # mtr-style continuous traceroute
monitor system netlink all # Kernel route/link/address changes
monitor interface rate # Live interface rate tracking
monitor traffic stat # Full-screen live traffic monitor
monitor bgp # Live event stream (see Monitoring)
monitor bgp peer <addr> event update direction received
monitor vpn ipsec # Live IPsec event stream
request reload # Re-read the configuration
request shutdown # Graceful shutdown
request halt # Goroutine dump and immediate exit
request peer <sel> refresh <family> # ROUTE-REFRESH toward one peer (RFC 2918)
show status # Daemon status dump
show reload-status # Result of the last reload
help
help command # Self-documenting command catalog
help command --json # Machine-readable catalog
show command list
show command help <name>
show host and show crashes are served by the daemon when it is running and fall back to the same in-process detection when it is not, so both work whether or not the daemon is up. That matters most for show crashes: you inspect a crash exactly when the process has died. The traffic-visibility verbs (show traffic stat, show traffic usage, show traffic feature), the report-only show anomaly detect and show anomaly shape, and show ddos status / show ddos incidents are all read-only and safe in scripts.
On-demand route origination uses its own verbs: announce flowspec <match> (rate-limit <bps> | discard) [tag <k> <v>] [for <dur>] originates a tracked FlowSpec rule (with siblings announce unicast and announce blackhole), withdraw removes announcements by tag, id, or all, and show announcements lists the active set.
The shell understands a small set of network OS pipe operators. They are not Unix pipes.
| Pipe | Effect |
|---|---|
| json |
Render the structured response as JSON. |
| table |
Render as a table. |
| match <regex> |
Drop rows that do not match. |
| count |
Just the row count. |
| no-more |
Disable paging on long output. |
| log |
Scrollback output for streaming commands (monitor ping, monitor traceroute). |
| first N |
Keep only the first N items. Server-side early termination when supported by the command. |
| last N |
Keep only the last N items (trailing window). |
| origin |
Annotate IP addresses with ASN names via Team Cymru. Useful with traceroute. |
| resolve |
Annotate IP addresses with reverse DNS hostnames. |
| json is the one that matters most for scripting. The output is the same JSON envelope every other Ze surface produces, so you can pipe it through jq and get the same fields you would see from the REST API. Pipes compose: monitor traceroute <target> | log | origin adds one line per round with ASN annotations.
The display format pipes (| text, | table, | json, | yaml, | ndjson) override the default for one command. You can change the default itself. The config sets it once for all sessions:
environment {
cli {
format {
default text; # text (default), table, json, yaml, or ndjson
}
}
}
A session override is set cli format <value> in operational mode; set cli format with no argument prints the current format. An explicit display pipe on a command always wins over the configured or session default, so show bgp peer list | json is JSON regardless of the default.
Some pipe segments are owned by the command rather than the shell. show bgp rib | received, show bgp rib | advertised, and show bgp rib | peer <selector> are folded into server-side arguments so the daemon does the filtering and streams only the matching rows, instead of the shell filtering a full response after the fact. Display and transform pipes (json, table, resolve, origin, and so on) stay client-side. In interactive mode the whole pipe chain is validated up front against each command's declared filter metadata, so an unsupported or misspelled filter is rejected before the command runs rather than after it has already produced output.
In ze cli, tab completion works on every position: command verbs, peer names, address families, log levels. Plugin-provided commands are included too: the interactive completer asks the running daemon for the live plugin command set per request, so a command a plugin registers appears in tab-completion, not just when typed blind. (Offline shell completion from ze completion bash|zsh|fish|nushell stays YANG-only, since it runs without a daemon.) History is persisted across sessions. Ctrl-C cancels the current command, Ctrl-D exits. The prompt reflects your current edit context (ze[bgp peer upstream]#).
Operational command arguments are YANG-typed. The schema that drives completion also declares the type, range, and pattern of each argument, so the same validation that catches a bad value in the config editor catches a bad value typed at an operational command. A family argument that no peer has negotiated, or a port outside 1-65535, is rejected against the schema before the command is dispatched.
Read-only queries follow the show <noun> ... convention with the selector inside the path: show bgp peer <selector> detail, show bgp peer <selector> capabilities, show bgp summary, and show bgp summary <afi>/<safi> for a per-family summary. The family argument on show bgp summary is checked against the families peers have actually negotiated, and an unknown or un-negotiated family rejects with the set of families currently reachable on the running daemon.
Ze can record a local transcript of ze cli and ze config edit sessions, capturing both the commands you type and their output. Transcripts are written to $XDG_DATA_HOME/ze/transcripts/, which is useful for recovering what you did after a disconnect. Writes are best-effort and never block the CLI: if the transcript cannot be written, the session continues normally.
Enable it in config or via the environment:
environment {
cli {
transcript enabled;
}
}
The equivalent environment variable is ze.cli.transcript.
ze signal is the SSH-based control surface for the daemon process itself, separate from the in-shell commands above.
| Command | Effect |
|---|---|
ze signal reload |
Reload the on-disk config. |
ze signal stop |
Graceful shutdown without the GR marker. |
ze signal restart |
Graceful restart with the GR marker. |
ze signal reboot |
Graceful shutdown, then an OS reboot. Needs root on Linux. |
ze signal status |
Dump daemon status. |
ze signal quit |
Goroutine dump and exit. |
ze signal reload, ze signal status, and ze signal quit send the verb-first daemon commands request reload, show status, and request halt. ze signal stop, ze signal restart, and ze signal reboot send the bare words stop, restart, and reboot, which the SSH exec middleware answers before the dispatcher.
The same actions are available as Unix signals: SIGHUP reloads, SIGTERM and SIGINT shut down gracefully, SIGUSR1 triggers a status callback logged at Warn level via the structured logger, SIGQUIT dumps goroutines (mapped to ze signal quit).
- CLI tour for the five-minute version.
- Show commands for the operator's day-2 quick reference.
- Command reference for the long list.
- Web UI for the same operations through a browser.
Adapted from main/docs/guide/cli.md, main/docs/features/api-commands.md, main/docs/guide/operations.md, main/docs/guide/command-reference.md, and main/docs/architecture/cli/color-system.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
- 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