Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
roswire

Language / 语言: English | 简体中文
roswire is a lightweight, JSON-first command-line bridge for AI agents and automation scripts that need to operate MikroTik RouterOS devices.
Unlike traditional CLIs designed for human interaction, roswire does not emit colors, spinners, pagers, or interactive prompts. Its contract is simple: successful results go to stdout; structured errors and diagnostics go to stderr.
Project status: MVP / beta candidate. The core JSON-first CLI, configuration, protocol routing, self-description APIs, SSH file transfer, file workflows, and release engineering are in place. Production-stable status is still gated by the real RouterOS / CHR acceptance matrix. See
docs/production-readiness.mdfor production gates anddocs/develop-plan.mdfor the development plan.
Key features
- JSON-first contract: machine-readable output is the stable interface for agents and scripts.
- Strict stream separation:
stdoutcontains successful results only;stderrcontains errors, debug logs, and diagnostics. - Non-interactive by default: missing inputs fail with structured JSON errors instead of waiting for user input.
- Protocol and dialect layering: supports RouterOS native API (
8728/8729) with v6/v7 dialects plus RouterOS v7 REST API. - Single native binary: distributed as one Rust binary; no Node.js, Python, Go, or other runtime required.
- Agent-friendly self-correction: errors include stable error codes, redacted context, and optional repair hints.
Installation
Prebuilt binaries are published through GitHub Releases, with a checksums.txt file attached to each release.
Linux quick install:
|
The installer detects Linux x86_64 / arm64, downloads the matching latest release artifact, verifies checksums.txt, and installs roswire to /usr/local/bin. To install a pinned version or a user-local path:
| ROSWIRE_VERSION=v0.0.3 ROSWIRE_INSTALL_DIR="/.local/bin"
If Rust is already installed, crates.io installation is also supported after the crate is published:
For manual installation steps, Cargo installation notes, Windows PowerShell checksum verification, source builds, and uninstall instructions, see docs/installation.md. Maintainer release procedures are documented in docs/release.md.
Quick start
This path starts with a fresh install, checks the local environment, creates one profile, stores the password outside shell history, and runs the first read-only RouterOS command.
- Install and run local diagnostics
|
doctor only checks the local machine by default. It does not contact RouterOS unless --include-remote is passed.
- Initialize local configuration
- Create and inspect a RouterOS profile
- Store the password without putting it in shell history
The env secret backend stores only the environment variable name in config.toml; the secret value stays in the current process environment.
;
For production hosts, prefer an OS keychain or encrypted secret backend when available. Store the secret with your platform keychain tool first, then save only the reference in roswire:
- Run the first read-only RouterOS command
Output (stdout) is structured JSON; errors go to stderr as one structured JSON object.
Common tasks
| Intent | Command |
|---|---|
| Check local setup | roswire doctor --json |
| Create or inspect profiles | roswire config init --json, roswire config profiles --json, roswire --profile studio config inspect --json |
| Store credentials safely | roswire config secret set studio password type=env env=ROSWIRE_STUDIO_PASSWORD --json or type=keychain |
| Inventory interfaces, addresses, routes, and resources | roswire --profile studio interface print --json, ip address print, ip route print, system resource print |
| Run unsupported read-only RouterOS print commands | roswire --profile studio raw /system/resource/print --json |
| Preview file transfers safely | roswire --profile studio file upload ./setup.rsc flash/setup.rsc --dry-run --ssh-host-key SHA256:replace-with-routeros-host-key --allow-from 203.0.113.10/32 --json |
Command usage examples
Local diagnostics:
Profile creation and inspection:
Secret setup without command-line password values:
;
;
Common read-only RouterOS commands:
Raw read-only print commands for advanced RouterOS paths:
Transfer dry runs with explicit SSH safety inputs:
CLI contract
roswire [global-options] <path...> <action> [key=value ...]
Configuration precedence is intentionally simple:
- Command-line options, including global options such as
--profile,--host,--user,--protocol, and--routeros-version - Profile values in
~/.roswire/config.toml - Protocol defaults
The local configuration directory is ~/.roswire/ by default. It contains config.toml, local logs under ~/.roswire/logs/, and keeps logs for up to 30 days. Passwords should preferably be stored in the local keychain or referenced through a secret backend; config files should store secret references only.
Device fields map to these profile keys: host, user, protocol, routeros_version, transfer, port, ssh_port, ssh_user, ssh_key, ssh_host_key, and allow_from. These device fields do not come from single-device ROS_* environment variables. Environment variables are process-level settings or secret-backend inputs only.
Process-level environment variables and secret-backend variables:
| Variable | Purpose |
|---|---|
ROSWIRE_HOME |
Override the default ~/.roswire directory, mainly for tests or portable environments. |
ROSWIRE_DEBUG |
Enable redacted debug diagnostics. |
ROSWIRE_MASTER_KEY |
Default master key for encrypted secrets; a secret key_id can point to another variable. |
Custom variables referenced by profile secrets with type=env |
For example ROSWIRE_STUDIO_PASSWORD; read only through the secret backend and never used for device field precedence. |
Passwords and SSH key passphrases use profile secrets: password, ssh_password, and ssh_key_passphrase.
Detailed docs: docs/installation.md, docs/release.md, docs/routeros-acceptance-matrix.md, and docs/production-readiness.md.
Agent self-description APIs
roswire is intended for agent use, so all important help and configuration inspection surfaces provide stable JSON. Agents do not need to parse human help text.
Common self-description commands:
Conventions:
help --jsonis machine-readable help with the command catalog, argument shape, examples, output schemas, error codes, and repair hints;--helpremains for humans.config inspect --jsonreports the active profile, resolved field sources, and secret status, but always redacts passwords, tokens, and private key paths.doctor --jsonruns local checks by default; it reaches RouterOS only when--include-remoteis passed.- Static help and schemas come from
roswire's built-in catalog by default.--remoteconnects to RouterOS and overlays real device version, protocol capabilities, observable fields, and runtime enum values. - Remote schema discovery can cache results under
~/.roswire/cache/, but cache invalidation must include RouterOS version, build time, packages, and protocol capability; caches must never contain secrets or full local paths. - Self-description outputs include
schema_versionso agents can make compatibility decisions.
Protocol selection
When protocol=auto (the default), roswire performs read-only probing on first connection to determine the RouterOS version and available protocols, then routes the actual command to the best backend.
Fixed precedence:
- If
--protocolor profileprotocolexplicitly sets a non-autoprotocol, use it strictly and do not auto-reroute. - In automatic mode, probe
restfirst, thenapi-ssl, thenapi. - If the device is RouterOS v7, REST is available, and the current action has a REST mapping, prefer REST.
- If REST is unavailable or the action has no REST mapping, fall back to the RouterOS v7 native API dialect.
- If the device is RouterOS v6, use only the native API v6 dialect; REST is not part of v6 routing.
Probe failure handling is stable: network unreachable or disabled service errors continue to the next candidate; authentication failure is terminal and does not silently retry another protocol, because doing so could hide credential problems.
Native API dialects
RouterOS v6 and v7 both support the native API, but they differ in login flows, menu fields, error returns, and available commands. roswire uses this implementation strategy:
- Share TCP/TLS connections, RouterOS sentence encoding/decoding, and
!re/!done/!trapparsing. - Keep v6 and v7 login compatibility, field normalization, action mappings, and test fixtures separate.
- Default to
routeros_version=autoprobing; use--routeros-versionor a profile value to forcev6/v7in controlled environments. - Allow some deliberate duplication in dialect code to keep behavior clear and tests stable, but do not duplicate the low-level transport and encoding logic.
Protocol mappings
| CLI command | Native API (v6/v7 dialects) | REST API |
|---|---|---|
roswire ip address print |
/ip/address/print |
GET /rest/ip/address |
roswire ip address add address=1.1.1.1 interface=ether1 |
/ip/address/add |
PUT /rest/ip/address |
roswire ip address set .id=*1 disabled=true |
/ip/address/set |
PATCH /rest/ip/address/*1 |
roswire ip address remove .id=*1 |
/ip/address/remove |
DELETE /rest/ip/address/*1 |
Client-side file upload and download
roswire supports local-client-to-RouterOS file workflows such as uploading .rsc scripts, importing configuration, generating backups, and downloading artifacts. These workflows have two layers:
- Control plane: API/REST commands such as
/import,/export file=...,/system/backup/save, and/file print. - Data plane: actual file-byte transfer; API sentences and REST JSON must not be treated as a general large-file transport.
Target command shapes:
Recommended strategy:
- Plain file upload: use the SSH transfer backend to place a local file on the RouterOS filesystem, then run follow-up commands if needed.
- Upload and execute
.rsc: upload to a temporary path, execute/import file-name=...through API/REST, and optionally delete the temporary file after success. - Create and download backups: run
/system/backup/save name=..., then download the resulting.backupfile through SSH transfer. - Create and download exports: run
/export file=..., then download the generated.rscfile. - Write
/system/script: when the source is local text, API/REST can writesource=@local-filecontents directly without creating a RouterOS file; size limits and binary rejection still apply.
File transfer uses SSH only. roswire can inspect and configure /ip service ssh through API/REST: enable SSH, set the port, and merge --allow-from or profile allow_from into the service address whitelist. It never opens SSH implicitly; it may modify the device service only when --ensure-ssh is explicitly provided. Transfer cleanup can restore the original SSH service state according to policy.
Note: profile host or --host must be a routable IP address or DNS name. RouterOS MAC addresses are for Layer 2 neighbor discovery and are not supported by the current API, REST, or SSH connection paths.
The SSH transfer backend must validate the actual SSH file-transfer subprotocols supported by the target RouterOS version. Do not assume REST multipart upload support, and do not keep FTP, /tool fetch, or other transfer backends.
Architecture
flowchart TD
agent[Agent / LLM]
subgraph roswire[roswire]
parser[Argument parser<br/>clap]
context[Context engine<br/>CLI / profile / config loading]
schema[Self-description and schema engine<br/>static catalog / remote overlay / cache]
router[Protocol router<br/>select API / REST from config]
discovery[First-connection probing<br/>version / capability / precedence]
classic[Native API transport<br/>TCP / TLS + sentence codec]
v6[RouterOS v6 dialect]
v7[RouterOS v7 dialect]
transfer[SSH file-transfer layer<br/>upload / download]
sshPrep[SSH service preparation<br/>enable / whitelist / restore]
parser --> context
parser --> schema
parser --> router
context --> router
context --> schema
schema -->|--remote| discovery
router --> discovery
router --> transfer
discovery -->|api / api-ssl| classic
classic --> v6
classic --> v7
transfer --> sshPrep
end
legacy6[RouterOS v6 native API]
legacy7[RouterOS v7 native API]
rest[RouterOS v7 REST API]
ssh[RouterOS SSH service]
agent -->|CLI call<br/>for example roswire ip address print --json| parser
v6 -->|raw TCP / TLS| legacy6
v7 -->|raw TCP / TLS| legacy7
discovery -->|HTTP / JSON| rest
sshPrep -->|API / REST sets /ip service ssh| discovery
transfer -->|SSH / 22| ssh
Development roadmap
The implementation plan lives in docs/develop-plan.md. Current priorities:
- Rust project scaffolding and CLI parsing.
- Stable JSON error model and output stream separation.
- First-connection probing, protocol precedence, and automatic routing.
- RouterOS native API shared transport plus v6/v7 dialects.
- RouterOS v7 REST protocol implementation.
- Integration tests using RouterOS CHR or dedicated test devices.