Skip to content

editor workflow

Thomas Mangin edited this page Apr 11, 2026 · 3 revisions

Pre-Alpha. This page describes behavior that may change.

The config editor is the piece of Ze that turns "edit a text file and hope" into the network-OS workflow operators actually expect. You edit in a draft session, you run diff to see what you are about to change, you commit atomically, and you rollback if you were wrong. commit confirmed is the safety net for changes that might lock you out.

This page covers the operational workflow: the commands, the draft-session model, the five operations, and the rollback story. The underlying YANG model is on YANG model. The archive story (how every committed config is kept) is on Archive and rollback.

Starting the editor

ze config edit                      # Edit the default config
ze config edit myconfig.conf        # Edit a specific file

The editor starts an ephemeral Ze instance in the background that serves the schema validators and the completion engine. You do not need a running daemon to edit a file, and the background instance terminates when the editor exits.

Inside the interactive shell (ze cli), the editor runs against the live tree instead of a file. The draft lives in the daemon.

The draft-session model

Every user gets their own draft on top of the committed tree. You can disconnect, come back, and pick up where you left off. Other users see their own drafts and the last committed version. They do not see yours.

A draft is cheap. You can abandon it with discard if you change your mind. You can edit half a change, leave it open, and come back to it the next day. The editor persists the draft state between sessions.

The five operations

set and delete

ze[bgp peer upstream]# set timer hold-time 180
ze[bgp peer upstream]# delete md5-password

set writes a leaf value, delete removes one. Both validate against the YANG schema at the time of the command. If the value is invalid (wrong type, out of range, pattern mismatch), the command returns an error immediately and the change does not enter the draft.

set also creates missing containers and list entries on the way in. set bgp peer new-peer remote ip 10.0.0.1 creates the peer if it does not exist. delete walks back out: removing the last leaf of a container removes the container.

show

ze# show bgp peer upstream
peer upstream {
    connection { remote { ip 10.0.0.1; } }
    session    { asn { local 65000; remote 65001; } }
    timer      { hold-time 180; }
    ...
}

show without arguments prints the whole tree. show <path> prints one subtree. It prints the committed tree plus your draft changes applied, which is usually what you want: you see what the config would look like if you committed right now.

diff

ze# diff
+ bgp peer upstream timer hold-time 180
- bgp peer upstream timer hold-time 90

diff shows your draft against the committed tree. Additions are prefixed with +, removals with -, changes are shown as a remove plus an add. This is the command you run every time before you commit, because it is the one that catches "wait, I did not mean to touch that".

commit

ze# commit
Commit successful.

commit runs every validator on the draft, applies the draft atomically to the committed tree, notifies every subsystem of the change, and writes an archive revision. If validation fails, the commit is rejected and the draft stays as it was. If application fails (which is rare, because the validators caught the common cases), the change is rolled back and the commit is rejected.

Commit is atomic at the tree level. Either the entire draft applies or none of it does. You cannot land a half-applied config.

rollback

ze# rollback 1
Rolled back to revision N-1.

rollback <N> restores the tree to N commits ago. rollback 1 is "undo the last commit". rollback 5 jumps back five commits. The archive keeps every committed version and show archive lists what is available. See Archive and rollback for the archive model.

Editing list entries

Beyond set and delete, the editor has four verbs for manipulating list entries and ordered leaf-lists: insert, rename, copy, and the pair deactivate / activate.

insert for ordered leaf-lists

ze# insert bgp peer upstream filter import rpki:validate first
ze# insert bgp peer upstream filter import reject-bogons before rpki:validate
ze# insert bgp peer upstream filter import aspath:prepend last
ze# insert bgp peer upstream filter import community:scrub after rpki:validate

insert places a value into an ordered leaf-list at a specific position. The four position tokens are first, last, before <ref>, and after <ref>. Positions that reference a value not in the list are rejected.

Ambiguity gotcha. A value literally named first, last, before, or after collides with the position keywords. Quote the value if you are inserting one of those.

The canonical use case is the filter chain on a peer (see route filters), but the verb works on any YANG leaf-list marked as ordered.

rename for list entries

ze# rename bgp peer old-name to new-name

rename changes the key of an existing list entry in place, keeping every leaf and every child container attached, and preserving the entry's position in the list order. The syntax is JunOS-style: rename <path> <old-key> to <new-key> — the to keyword is mandatory and fixes ambiguity when a list key is literally to.

rename rejects attempts to overwrite an existing entry: if new-key already exists, the command fails and the draft is unchanged.

Note that rename is a config-tree operation. What happens to runtime state (session state, statistics) on a live peer is up to how the reactor reconciles the post-commit config against the running peer set — do not assume the daemon treats the post-rename peer as identical to the pre-rename one. Use rename during preparatory config edits, not as a way to rename a session mid-flight.

copy for list entries

ze# copy bgp peer template-peer to new-peer

copy is the mirror of rename: it creates a new list entry at <dst-key> that is a deep copy of <src-key>, leaving the source intact. Useful for spinning up a new peer off a template without retyping every leaf. Same to keyword syntax as rename.

deactivate and activate

ze# deactivate bgp peer special filter import no-self-as
ze# activate   bgp peer special filter import no-self-as

deactivate marks a specific value in a leaf-list as inactive, without removing it. The result in the committed config is the value with an inactive: prefix. activate clears the prefix. Neither verb reorders the list.

The main use is suppressing a default filter on one peer without disturbing its order in the chain — see route filters — deactivating a default filter.

Commit confirmed

ze# commit confirmed 60
Commit applied. Auto-rollback in 60s if not confirmed.

ze# commit confirm          # Make the change permanent before the timer fires
ze#

commit confirmed <N> applies the change and starts a rollback timer. If you do not type commit confirm within <N> seconds, Ze reverts the change automatically. <N> accepts values from 1 to 3600.

This is the safety net for changes you suspect might lock you out. Tightening authentication on the peer you are connected through. Restricting the SSH listener to a specific source IP. Rewriting firewall rules. If the change kills your connection, you wait, the timer fires, Ze reverts, and your connection comes back.

abort rolls back a pending confirmed commit immediately instead of waiting for the timer.

The command reference

Full list of editor commands:

Command Description
set <path> <value> Set a configuration value.
delete <path> Delete a value or a subtree.
insert <path> <value> <position> Insert into an ordered leaf-list at first, last, before <ref>, or after <ref>.
rename <path> <old-key> to <new-key> Rename a list entry in place, preserving all children and position.
copy <path> <src-key> to <dst-key> Deep-copy a list entry to a new key.
deactivate <path> <value> Mark a leaf-list value as inactive (adds inactive: prefix).
activate <path> <value> Re-activate a deactivated leaf-list value.
show Display the current configuration.
show <path> Display a specific subtree.
diff Show uncommitted changes.
commit Apply the draft.
commit confirmed <N> Commit with an N-second auto-revert timer.
confirm Make a pending confirmed commit permanent.
abort Roll back a pending confirmed commit immediately.
rollback <N> Restore revision N.
top Navigate to the tree root.
up Navigate up one level.
edit <path> Navigate into a subtree.
discard Throw away the draft.
exit Exit the editor.

The prompt reflects the current edit context: ze[bgp peer upstream]# means you are inside bgp/peer[name='upstream'], and set commands operate relative to that context.

Draft conflicts

When two users edit the same leaf in parallel, the second commit detects the conflict and reports it. The conflict report names the path and shows both values. The user resolves the conflict (by accepting one of the two values, or by setting a third) and tries again.

Conflict detection happens at commit time, not at edit time. You can have an active draft on the same leaf as another user for as long as you like. The conflict only matters when you try to apply your draft.

Web UI equivalence

Everything described above is available in the web UI too. The Finder-style column browser is the edit/up/top/show part. The pending-changes bar is diff. The Review and Commit button is commit. The SSE notification banner is the multi-user awareness. The model is identical because both surfaces drive the same underlying editor.

See also

Adapted from main/docs/guide/config-editor.md.

Home

About

First Steps

Configuration

Operation

Interfaces

Plugins

Plugin Development

Chaos Testing

Blueprints

Development

Reference

Clone this wiki locally