Headless Desktop Lua Automation

The headless Desktop Lua runner lets RTFMv2.Console execute Desktop-compatible Lua scripts without opening the CoordOps Desktop UI. It is designed for automation, smoke tests, CI checks, and repeatable validation of Desktop script behavior.

Unlike interactive console Lua scripts, this feature runs scripts against a virtual Desktop window runtime. Scripts can inspect the Desktop script metadata catalog, open virtual window runtimes by window_id, set control values, click run buttons, and receive command callbacks.

Command Syntax

RTFMv2.Console.exe desktop-lua run --file <script.lua> [options]

Options

Option Required Description
--file <path> Yes Path to the Desktop Lua script to execute.
--new-session <name> No Create a new local session before the script runs.
--target <host-or-range> With --new-session Target host, range, or domain for the new session.
--load-session <path> No Load an existing session file or session directory before the script runs.
--password <value> No Session database password for creating or loading a session.
--dry-run No Generate commands and callbacks without launching external tools.
--fail-fast No Return a non-zero exit code when a generated command fails.
--timeout <seconds> No Maximum script runtime. Defaults to 300.
--output text|json No Output format. Defaults to text.

Common Examples

Run a metadata smoke test in dry-run mode:

RTFMv2.Console.exe desktop-lua run ^
  --file "Assets\Scripts\LUA\11_window_metadata_showcase.lua" ^
  --new-session Headless_Metadata_Test ^
  --target 127.0.0.1 ^
  --password test ^
  --dry-run ^
  --timeout 30

Run a Desktop Nmap automation script without launching Nmap:

RTFMv2.Console.exe desktop-lua run ^
  --file "Assets\Scripts\LUA\automation_test_1.lua" ^
  --new-session Headless_Nmap_Test ^
  --target 192.168.0.100 ^
  --password test ^
  --dry-run ^
  --timeout 30

Load an existing session and emit JSON for CI tooling:

RTFMv2.Console.exe desktop-lua run ^
  --file "Assets\Scripts\LUA\11_window_metadata_showcase.lua" ^
  --load-session "C:\CoordOps\Sessions\Assessment1" ^
  --password "session-password" ^
  --output json

On Linux, use the same command with dotnet RTFMv2.Console.dll and Unix-style paths:

dotnet RTFMv2.Console.dll desktop-lua run \
  --file ./Assets/Scripts/LUA/11_window_metadata_showcase.lua \
  --new-session Headless_Metadata_Test \
  --target 127.0.0.1 \
  --password test \
  --dry-run \
  --timeout 30

Runtime Model

The runner starts in a virtual Main Window runtime:

  • rtfm.window_meta.window_id is main.window.
  • rtfm.session is available when a session was created or loaded.
  • rtfm.commands exposes the current framework command catalog.
  • rtfm.windows is available from the Main Window runtime for catalog and cross-window automation.

Use rtfm.windows.open_by_window_id() to create a virtual runtime for a Desktop window:

rtfm.windows.open_by_window_id("scanner.nmap")

for _, runtime in ipairs(rtfm.windows.runtime_list()) do
  if runtime.window_id == "scanner.nmap" then
    rtfm.windows.execute(runtime.runtime_key, [[
      rtfm.set_text("txtHost", "192.168.0.100")
      rtfm.set_is_checked("sS", true)
      rtfm.set_is_checked("sV", true)
      rtfm.set_is_checked("T4", true)
      rtfm.click("btnRun")
    ]])
  end
end

Headless Lua API

The virtual runtime supports the Desktop rtfm table used by bundled Desktop Lua scripts.

API Description
rtfm.print(message) Writes output with the current virtual window title.
rtfm.has_session() Returns whether a session is active.
rtfm.create_session(name, target, password) Creates a local session.
rtfm.load_session(path, password) Loads a session file and returns success/error values.
rtfm.close_session() Clears the current session.
rtfm.session Current session object, or nil if no session is active.
rtfm.commands Current framework command catalog.
rtfm.cancel_requested() Always returns false in the current headless runner.
rtfm.window Virtual controls for the current runtime.
rtfm.window_meta Runtime metadata, including runtime_key, window_id, and window_title.
rtfm.get_text(control) / rtfm.set_text(control, value) Read or write text controls.
rtfm.get_is_checked(control) / rtfm.set_is_checked(control, value) Read or write checkbox controls.
rtfm.get_selected_index(control) / rtfm.set_selected_index(control, index) Read or write selected indexes.
rtfm.control_type(control) Returns the virtual control kind.
rtfm.control_description(control) Returns control description metadata.
rtfm.control_meta(control) Returns available metadata for a control.
rtfm.click(control) Simulates a supported button click.

The Main Window runtime also supports:

API Description
rtfm.windows.catalog() Returns catalog metadata for known Desktop windows.
rtfm.windows.list() Alias for catalog().
rtfm.windows.get_meta(window_id) Returns metadata for a specific window id.
rtfm.windows.runtime_list() Returns currently registered virtual runtimes.
rtfm.windows.open_by_window_id(window_id) Creates a virtual runtime for a Desktop window.
rtfm.windows.open(runtime_key) Returns whether a runtime exists.
rtfm.windows.close(runtime_key) Removes a virtual runtime.
rtfm.windows.execute(runtime_key, script_text) Executes Lua inside another virtual runtime.

Command Generation

When a script clicks a supported run button, the headless runtime generates a command from the virtual controls:

  • If txtMain has text, that text is used as the command.
  • For scanner.nmap, the runtime can compose an nmap command from txtHost and flags such as sS, sV, sC, Pn, T4, and T3.
  • If txtTarget has text, the runtime falls back to <window_id> <target>.

With --dry-run, generated commands are printed and callbacks are invoked, but external processes are not launched.

Callbacks

Desktop Lua scripts can define command callbacks:

function on_command_generated(ctx)
  rtfm.print("Generated: " .. tostring(ctx.command_string))
end

function on_command_output(ctx)
  rtfm.print(tostring(ctx.stream) .. ": " .. tostring(ctx.line))
end

function on_command_done(ctx)
  rtfm.print("Exit code: " .. tostring(ctx.exit_code))
end

The callback context includes fields such as command_id, command_string, stream, line, exit_code, success, source_window_id, and source_window_title, depending on the callback.

Exit Codes

Code Meaning
0 Script completed successfully.
1 Script file, syntax, or Lua runtime error.
2 Session setup error.
3 Timeout.
4 Generated command failure when --fail-fast is enabled.

Limitations

  • This is a true headless runtime. It does not launch Avalonia windows.
  • rtfm.ui.prompt() and rtfm.ui.prompt_credentials() return an unavailable result in headless mode.
  • Virtual controls are based on script metadata and common control names. They are not full visual UI controls.
  • Use --dry-run for CI and smoke tests when external scanners should not be executed.
  • Scripts that require interactive prompts should provide defaults or branch when prompts are unavailable.

For CI or release validation, run fast Desktop Lua smoke tests in dry-run mode:

RTFMv2.Console.exe desktop-lua run ^
  --file "Assets\Scripts\LUA\11_window_metadata_showcase.lua" ^
  --new-session Headless_CI ^
  --target 127.0.0.1 ^
  --password test ^
  --dry-run ^
  --timeout 30 ^
  --output json

This validates session setup, the Desktop script catalog, Lua execution, and virtual window metadata without depending on the desktop UI or third-party tools.