Skip to content

CLI transports

Daniel Frantík edited this page Oct 25, 2026 · 5 revisions

CLI transports

Five transports drive the router's command line instead of the binary API: Telnet, SSH, MAC-Telnet, WinBox CLI and WinBox CLI over MAC. They differ only in how they reach the console; above that they behave the same, and this page describes what they share. Use one when the router's API service is off but a console is reachable — which is almost always.

using tik4net;
using tik4net.Objects;
using tik4net.Objects.Interface;
using tik4net.Telnet;

using ITikCliConnection connection = new TikConnectionSetup(HOST, USER, PASS).CreateTelnetConnection();

foreach (var iface in connection.LoadAll<Interface>())    // the same code as over the API
    Console.WriteLine(iface.Name);
Transport Reaches the console over Encrypted Page
Telnet TCP 23 no Telnet connection
Ssh TCP 22, SSH shell yes SSH connection
WinboxCli TCP 8291, WinBox channel yes WinBox CLI connection
MacTelnet UDP 20561, MAC layer no (login is) MAC-Telnet connection
WinboxCliMac UDP 20561, MAC layer yes WinBox CLI over MAC

Same code as over the API

  • The O/R mapper, ITikCommand and the async surface work unchanged: tik4net turns each command into a console line and parses the answer back into rows.
  • Errors arrive as the same exception types the API raises (TikNoSuchItemException, …).
  • A filter runs on the router (where …); only the matching rows come back.
  • Secret fields (keys, passwords) are read with show-sensitive, so they come back as over the API — when the user's group has the sensitive policy.
  • Values that contain ;, = or line breaks (comments, scripts, file contents) are read intact on RouterOS 7.
  • What each call becomes on the wire: Command translation.

Two dialects

A CLI connection also takes native console syntax, sent unchanged — for scripting, /export, or a menu tik4net has no entity for:

var lines = connection.CallCommandSync(":put [/ip address print as-value where interface=ether1]");

Tab completion

CompleteCli types a partial line followed by Tab and returns what the router offers — sub-menus and verbs after a path, the settable parameters after add / set , the accepted words after name=:

IReadOnlyList<string> verbs = connection.CompleteCli("/interface ");
string completed = connection.CompleteCliRaw("/interface/bridge add frame-types=");   // "... frame-types=admit-"
IReadOnlyList<string> values = connection.CompleteCli(completed);                     // admit-all, …
  • When the candidates share a prefix, RouterOS completes in place instead of listing: CompleteCli returns no tokens and CompleteCliRaw returns the completed line — complete that line again to see what follows.
  • On RouterOS 6 write the path with spaces (/interface bridge add …); after the slash form it completes nothing.
  • For a structured answer use Describing menus.

What the type gives you

ITikCliConnection (ITikMacCliConnection on the MAC-layer two) carries, on top of ITikConnection:

  • CallCommandSync / CallCommandAsync — native console lines (Low-level API);
  • SafeModeTake / SafeModeRelease / SafeModeUnroll — Safe Mode;
  • CompleteCli — the router's Tab completion;
  • CancellationMode — what a cancel after sending costs (below).

Limits compared with the API

  • One command at a time per connection. Calls from several threads are safe but queue. For parallel commands open a second connection — see Threading and concurrency.
  • No Streaming — ExecuteListWithDuration is API-only; ExecuteListUntilDone works, its timeout ended according to CancellationMode. Snapshot helpers (Ping, GetInterfaceMonitorTrafficSnapshot) and callback monitors work — see Monitors and streaming.
  • Listen is polled, not pushed — and a change made on the same connection can be missed; see Threading.
  • No CancelInFlight — a cancel after sending waits for the reply to end, unless you choose AbandonAndClose (below).
  • Slower per command than the API: a command is a console line and its printed answer.

Options

Option Default Meaning
CancellationMode Cooperative AbandonAndClose cuts a cancelled read and closes the connection — see Async and cancellation
CliReadPageSize 100 on the MAC layer, off elsewhere read big tables in windows of N rows; 0 = one command — see MAC-layer transports
CliFieldSeparator ~^~ the separator RouterOS 7 writes between values, so a value keeps its ;; null reads plain as-value
CatalogCachePath %TEMP%\tik4net where the menu grammar learned from the router is cached; null = nothing on disk
var setup = new TikConnectionSetup(HOST, USER, PASS)
{
    CliReadPageSize = 200,
    CancellationMode = TikCancellationMode.AbandonAndClose,
};

RouterOS versions

The console changed more between versions than the API did; the translation absorbs it without asking the router for its version:

  • RouterOS 6 — no :serialize, so a value containing ; is not read intact; secrets are printed anyway.
  • Before 7.13 — free-text fields are read row by row with get (line breaks read as LF).
  • Before 7.18 — no scriptable /safe-mode: SafeModeUnroll closes the connection (which rolls back); open a new one to continue.
  • Before 7.20 — flags are read with a separate query; row ids are normalised to the API's spelling.

More in RouterOS versions.

Troubleshooting

  • The login fails or times out — check that the service is enabled (/ip service, or /tool mac-server for the MAC layer) and that the user's group has the matching policy (telnet — also for MAC-Telnet — ssh, winbox); a missing policy often reads like a wrong password. See services and policies.
  • TikConnectionResponseIncompleteException — the router's count of rows did not match what arrived, so the read was refused rather than returned short. On the MAC layer keep paging on; elsewhere retry.
  • A raw read returns nothing — a bare print as-value prints nothing at a terminal; wrap it in :put [ … ].

See also

Clone this wiki locally