routeros-cli

command module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 29, 2026 License: MIT Imports: 2 Imported by: 0

README

routeros-cli

A fast, structured CLI for MikroTik RouterOS — for network engineers and AI agents

CI Release Go Report Card

Docs · Agents · Troubleshooting · Issues


What it is

ros (routeros-cli macro) talks to MikroTik RouterOS devices over the native API (8728 / 8729 by default).

It is not SSH scraping — it speaks the binary RouterOS API, returns tables or JSON, and is safe for humans and agents.

For technicians For AI agents
Multi-router inventory by name --read-only + JSON envelope
Interactive or scripted device add Bundled skills (ros skills install)
Safe sessions with rollback audit instead of pasting full /export
ros -d router-edge --read-only audit -o json
{
  "ok": true,
  "data": {
    "firewall_filter": [ { ".id": "*1", "chain": "forward", "action": "fasttrack-connection", ... } ],
    ...
  },
  "meta": { "device": "router-edge", "command": "audit", "timestamp": "..." }
}

Install

Homebrew (macOS / Linux)

brew tap nic0der-im/tap
brew install ros

Linux / macOS (install.sh)

curl -sSL https://raw.githubusercontent.com/nic0der-im/routeros-cli/main/install.sh | sh

Windows — download the zip for your arch from the latest release, extract ros.exe, and put it on your PATH.

Scoop (Windows)

# After adding a scoop bucket that vendors scoop/ros.json from this repo:
scoop install ros

AUR (Arch) — package template: aur/PKGBUILD (routeros-cli-bin). Publish/update via your AUR account.

OS Arch Asset
macOS Apple Silicon ros_*_darwin_arm64.tar.gz
macOS Intel ros_*_darwin_amd64.tar.gz
Linux x86_64 ros_*_linux_amd64.tar.gz
Linux aarch64 ros_*_linux_arm64.tar.gz
Windows x86_64 ros_*_windows_amd64.zip
Windows ARM64 ros_*_windows_arm64.zip

Checksums ship as ros_*_checksums.txt in the same release.

Requires RouterOS 7.x with API enabled:

/ip/service/set api disabled=no address=192.168.88.0/24

For API-SSL (8729):

/ip/service/set api-ssl disabled=no

Build from source

Needs Go 1.26+ (see go.mod). The module root builds a single binary named ros.

All platforms (happy path)

git clone https://github.com/nic0der-im/routeros-cli.git
cd routeros-cli
go test ./...
go build -o ros .
./ros version

Optional version stamping (same as release builds):

go build -ldflags "-s -w -X main.version=0.2.0 -X main.commit=$(git rev-parse --short HEAD) -X main.date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" -o ros .

Or without cloning:

go install github.com/nic0der-im/routeros-cli@latest
# binary lands in $(go env GOPATH)/bin — ensure that dir is on PATH

macOS

# Apple Silicon or Intel — Go from Homebrew is fine
brew install go
git clone https://github.com/nic0der-im/routeros-cli.git
cd routeros-cli
go build -o ros .
sudo install -m 755 ros /usr/local/bin/ros
# or: mkdir -p ~/bin && mv ros ~/bin && echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrc

Cross-compile from macOS if needed:

GOOS=linux   GOARCH=amd64 CGO_ENABLED=0 go build -o ros-linux-amd64 .
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -o ros.exe .

Linux

# Debian/Ubuntu
sudo apt update && sudo apt install -y golang-go git
# Fedora
# sudo dnf install golang git
# Arch
# sudo pacman -S go git

git clone https://github.com/nic0der-im/routeros-cli.git
cd routeros-cli
go build -o ros .
sudo install -m 755 ros /usr/local/bin/ros
sudo ln -sf /usr/local/bin/ros /usr/local/bin/routeros-cli   # optional legacy alias

Static binary (useful for containers / minimal hosts):

CGO_ENABLED=0 go build -trimpath -ldflags "-s -w" -o ros .

Windows (PowerShell)

# Install Go from https://go.dev/dl/ then:
git clone https://github.com/nic0der-im/routeros-cli.git
cd routeros-cli
go test ./...
go build -o ros.exe .
# Put ros.exe somewhere on PATH, e.g.:
# Copy-Item .\ros.exe $env:USERPROFILE\bin\

Cross-compile from Windows to Linux:

$env:CGO_ENABLED=0; $env:GOOS="linux"; $env:GOARCH="amd64"; go build -o ros-linux-amd64 .

Verify

ros version
ros device list
ros 0.2.0          # "dev" when built without ldflags
  commit: abc1234
  built:  2026-07-29T04:40:00Z

Shell completions

Cobra ships ros completion for bash, zsh, fish, and PowerShell:

# zsh (Homebrew formula also installs completions automatically)
ros completion zsh > "${fpath[1]}/_ros"

# bash
ros completion bash > /usr/local/etc/bash_completion.d/ros

# fish
ros completion fish > ~/.config/fish/completions/ros.fish

# powershell
ros completion powershell | Out-String | Invoke-Expression

Quick start — add a router

Passwords go to the OS keyring, never to config.toml.

ros device add

Prompts for: name, host, port, username, password, TLS, optional id/tags.

Agentic / scripted (pipes & secrets)

echo "$PASS" | ros device add "central-hub-buenos-aires" \
  --address 10.0.0.1:8728 \
  --username admin \
  --id central-hub-ba \
  --password-stdin

Then

ros device use "central-hub-buenos-aires"
ros device test
ros device list
Connected to "central-hub-buenos-aires" (identity: central-hub-buenos-aires)

DEFAULT  NAME                         ID               ADDRESS              USERNAME  TLS
*        central-hub-buenos-aires     central-hub-ba   10.0.0.1:8728        admin     false
         router-edge                  router-edge      192.168.88.1:8728    admin     false
         edge-node-west               edge-west        10.10.20.1:8728      admin     false
Tip Detail
Port 8728 Plain API (TLS inferred off)
Port 8729 API-SSL (TLS inferred on)
Lookup -d accepts name, id, or IP
Winbox list ros device import --from winbox --dry-run

Rotate password later:

ros device auth set "central-hub-buenos-aires"    # interactive prompt

How commands are grouped

Everything follows:

ros -d <DEVICE> <VERB> <DOMAIN|/path> [params...]

Verbs

Verb Use
get Read
create Add
set Update
delete Remove (needs .id=*N)
enable / disable Toggle
audit Read-only multi-domain snapshot
session Safe apply journal
diag log / ping / neighbors
exec Raw API escape hatch

Domains (curated aliases)

ros domains
dhcp/lease                 → /ip/dhcp-server/lease
firewall/filter            → /ip/firewall/filter
firewall/nat               → /ip/firewall/nat
interface/wireguard        → /interface/wireguard
ip/address                 → /ip/address
user                       → /user
...
Domain API path
firewall/filter /ip/firewall/filter
firewall/nat /ip/firewall/nat
dhcp/lease /ip/dhcp-server/lease
user /user
radius /radius
interface/bridge /interface/bridge

Raw paths always work: ros get /ip/firewall/address-list

Params

key=value     →  =key=value
.id=*1        →  target row
?=disabled=false   →  query filter

Everyday examples

Read

ros -d router-edge get system info
IDENTITY         BOARD    PLATFORM  VERSION          UPTIME         CPU LOAD  MEMORY FREE/TOTAL
Edge Router Lab  CCR2004  MikroTik  7.18.2 (stable)  1w4d6h36m30s   6%        27738112/67108864
ros -d router-edge get ip/address
.ID  NETWORK         INTERFACE    ADDRESS              DYNAMIC  DISABLED
*2   192.168.88.0    dhcpSwitch   192.168.88.1/24      false    false
*67  100.68.176.0    ether1       100.68.178.110/20    true     false
ros -d router-edge get firewall/filter
DYNAMIC  COMMENT                         .ID  CHAIN    ACTION                  BYTES         PACKETS
false    FastTrack Established/Related   *1   forward  fasttrack-connection    2273138543    12394696
false    Accept Established/Related      *3   forward  accept                  2273138543    12394696
false    Drop all other input            *A   input    drop                    38249427      269466
...
ros -d router-edge get dhcp/lease
ACTIVE-ADDRESS  HOST-NAME    COMMENT      ADDRESS         MAC-ADDRESS        STATUS  SERVER
192.168.88.29   laptop-ops   Ops laptop   192.168.88.29   FC:B2:14:81:B3:AD  bound   dhcpNetwork
192.168.88.39   lab-server   Lab server   192.168.88.39   E0:B9:A5:D5:18:19  bound   dhcpNetwork
...
ros -d router-edge get user
GROUP  DISABLED  .ID  NAME   LAST-LOGGED-IN
full   false     *2   admin  2026-07-29 01:46:52
ros -d router-edge get system info -o json
{
  "ok": true,
  "data": [
    {
      "Identity": "Edge Router Lab",
      "Board": "CCR2004",
      "Version": "7.18.2 (stable)",
      "Uptime": "1w4d6h36m40s",
      "CPU Load": "5%"
    }
  ],
  "meta": {
    "device": "router-edge",
    "command": "/system/resource/print",
    "count": 1
  }
}
ros -d router-edge --read-only audit --profile network
Audit of "router-edge" (profile=network)
  interfaces:          14 item(s)
  ip_addresses:        3 item(s)
  ip_routes:           3 item(s)
  dns:                 1 item(s)
  dhcp_leases:         8 item(s)
  dhcp_servers:        1 item(s)

Profiles: full · network · security

Write (always prefer a safe session)

ros -d router-edge session begin --safe
Session 1785300485258875000 started on "router-edge" (safe=true)
ros -d router-edge create firewall/filter chain=forward action=accept protocol=tcp dst-port=443
ros -d router-edge set dhcp/server .id=*1 lease-time=1d
ros -d router-edge delete dhcp/lease .id=*F9

ros -d router-edge session status
Session 1785300485258875000
  Device:     router-edge
  Status:     active
  Safe:       true
  Started:    2026-07-29T04:48:05Z
  Updated:    2026-07-29T04:48:05Z
  Changes:    3
ros -d router-edge session commit
# or: ros -d router-edge session rollback
Session 1785300485258875000 committed on "router-edge" (3 change(s))

Diagnostics

ros -d router-edge diag ping 1.1.1.1 --count 3
SENT  RECEIVED  PACKET-LOSS  AVG-RTT    SEQ  HOST     SIZE  MIN-RTT    MAX-RTT    TTL  TIME
1     1         0            30ms808us  0    1.1.1.1  56    30ms808us  30ms808us  58   30ms808us
2     2         0            30ms482us  1    1.1.1.1  56    30ms157us  30ms808us  58   30ms157us
3     3         0            30ms411us  2    1.1.1.1  56    30ms157us  30ms808us  58   30ms268us
ros -d router-edge diag log
.ID  TIME                 TOPICS                 MESSAGE
*0   2026-07-17 02:04:45  system,error,critical  router was rebooted without proper shutdown
*3   2026-07-17 02:05:03  dhcp,info              dhcp-client on ether1 got IP address 100.68.178.110
...
ros -d router-edge diag neighbors

Backup

ros -d router-edge backup export --file ~/router-edge-$(date +%F).rsc
Configuration exported to "/Users/you/router-edge-2026-07-29.rsc" from "router-edge"
# Creates .backup on the router only (local download is still on the roadmap)
ros -d router-edge backup binary --file routeros-cli-backup
Backup "routeros-cli-backup.backup" created on "router-edge" (size: 123456)

Full reference: docs/COMMANDS.md


AI agents & skills

ros ships LLM skills that teach agents the safe workflow (read-only audit first; writes only via safe sessions).

ros skills list
ros
ros-safe-apply
# Install into Cursor, Codex, Claude Code, OpenCode
ros skills install --agent all --scope user
Pack Purpose
ros Inventory, audit, read-only get
ros-safe-apply Firewall / DHCP / users / etc. inside session begin
export ROS_READ_ONLY=1
export ROS_DEFAULT_OUTPUT=json

ros -d "central-hub-buenos-aires" audit --profile full -o json

Details: docs/AGENTS.md

Exit codes

Code Meaning
0 OK
1 Command / API error
2 Connection / auth
3 Config
4 Read-only violation

JSON shape: { "ok", "data" \| "error", "meta" } — add --raw for .id fields.


Config & secrets

What Where
Inventory ~/.config/ros/config.toml
Passwords OS Keychain (ros service)
Sessions ~/.config/ros/sessions/

Legacy ~/.config/routeros-cli/ is migrated automatically.


Roadmap

Done (v0.2.0)

  • Binary rename to ros (+ routeros-cli alias) and config migration to ~/.config/ros/
  • Multi-device inventory + OS keyring (never passwords in TOML)
  • Verb + domain API surface + ros domains curated aliases
  • --read-only / ROS_READ_ONLY=1, exit code 4, JSON envelope
  • ros audit profiles (full / network / security)
  • Safe sessions (begin / commit / rollback / status) with best-effort inverse journal
  • Winbox import (v3 .WBX / v4 Addresses.cdb on macOS, Linux, Windows)
  • Bundled agent skills + ros skills install|uninstall|list|path
  • Diagnostics (diag log|ping|neighbors), text backup export
  • Cross-platform release assets (linux/darwin/windows × amd64/arm64)

Done (v0.3.0)

  • Pre-state journaling for set / delete (+ curated helpers)
  • session watch heartbeat + auto-rollback on link loss (auto_rollback_pending)
  • backup binary --output + file get (API contents or FTP)
  • Homebrew tap (nic0der-im/homebrew-tap) + GoReleaser brews
  • AUR PKGBUILD/.SRCINFO with real checksums (live AUR push is maintainer-side)
  • Completions documented + Homebrew formula installs them
  • Stable apperr kinds in JSON error.code
  • Expanded domains + nat / lease helpers + richer diag
  • Opt-in integration tests (ROS_INTEGRATION_DEVICE)
  • Scoop + Chocolatey package templates

Still maintainer-side / ongoing

  • Push AUR package live (routeros-cli-bin on aur.archlinux.org)
  • Publish Scoop bucket / Chocolatey.org package from templates
  • Expand capa linda further as field needs appear
  • Harden skill packs after more production apply workflows

Not planned soon

  • Emulating Winbox GUI parity end-to-end
  • Storing passwords in config files or CLI flags
  • Targeting RouterOS 6.x as a first-class platform

Contributing

See CONTRIBUTING.md. PRs welcome.

go test ./...
go build -o ros .

License

MIT — see LICENSE.

Contact

nic0der-im · github.com/nic0der-im/routeros-cli

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internal
apperr
Package apperr defines stable machine-readable error kinds for ros.
Package apperr defines stable machine-readable error kinds for ros.
client
Package client provides an abstraction over the go-routeros library for communicating with RouterOS devices via the native API protocol.
Package client provides an abstraction over the go-routeros library for communicating with RouterOS devices via the native API protocol.
config
Package config handles loading, saving, and validating the ros TOML configuration file stored at ~/.config/ros/config.toml.
Package config handles loading, saving, and validating the ros TOML configuration file stored at ~/.config/ros/config.toml.
device
Package device manages the device inventory, building on top of the config package to provide higher-level operations for adding, removing, listing, and resolving RouterOS devices.
Package device manages the device inventory, building on top of the config package to provide higher-level operations for adding, removing, listing, and resolving RouterOS devices.
domains
Package domains maps friendly resource names to RouterOS API paths.
Package domains maps friendly resource names to RouterOS API paths.
filexfer
Package filexfer downloads RouterOS /file contents to the local workstation.
Package filexfer downloads RouterOS /file contents to the local workstation.
policy
Package policy enforces access modes such as read-only for agent workflows.
Package policy enforces access modes such as read-only for agent workflows.
rosapi
Package rosapi provides typed mapping of RouterOS API response sentences to Go structs and implements the Renderable interface for output formatting.
Package rosapi provides typed mapping of RouterOS API response sentences to Go structs and implements the Renderable interface for output formatting.
session
Package session provides safe-mode style change journals with rollback.
Package session provides safe-mode style change journals with rollback.
skills
Package skills embeds and installs agent skill packs for ros.
Package skills embeds and installs agent skill packs for ros.
winbox
Package winbox parses MikroTik Winbox address-book files (WBX / CDB) for import into the ros device inventory.
Package winbox parses MikroTik Winbox address-book files (WBX / CDB) for import into the ros device inventory.
pkg
schema
Package schema provides JSON Schema definitions for routeros-cli structured output types.
Package schema provides JSON Schema definitions for routeros-cli structured output types.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL