Examples

RDP Automation

Automate a remote desktop session via RDP with nut.js

rdpremote-desktopimage-searchautomation

This example demonstrates using @nut-tree/plugin-rdp to automate a remote Windows machine via RDP. The plugin redirects nut.js operations to the remote session, enabling image-based automation, keyboard input, mouse control, and clipboard access over the connection.

Setup

typescript
import "@nut-tree/nl-matcher";
import {
    centerOf,
    clipboard,
    imageResource,
    Key,
    keyboard,
    mouse,
    screen,
    sleep,
    straightTo,
} from "@nut-tree/nut-js";
import { connect } from "@nut-tree/plugin-rdp";

Load credentials from environment variables:

typescript
import { config } from "dotenv";

config();

Connecting to the Remote Machine

typescript
screen.config.confidence = 0.87;
screen.config.resourceDirectory = "./resources";

const remote = await connect({
    hostname: process.env.REMOTE_HOSTNAME,
    port: parseInt(process.env.REMOTE_PORT),
    username: process.env.REMOTE_USERNAME,
    password: process.env.REMOTE_PASSWORD,
    ignoreCertificate: true,
});

console.log(`Connected: ${remote.isConnected()}`);

Important: Store credentials in environment variables or a .env file — never hardcode them. The ignoreCertificate option should only be used in development or trusted environments.

Redirecting Providers

After connecting, call useRemote() to redirect all nut.js operations to the remote machine. You can also activate providers individually:

typescript
// Redirect all at once
remote.useRemote();

// Or activate individually
remote.useRemoteScreen();
remote.useRemoteKeyboard();
remote.useRemoteMouse();
remote.useRemoteClipboard();

Automating the Remote Desktop

Once providers are redirected, use the standard nut.js APIs. All operations happen on the remote machine:

typescript
// Allow the remote desktop to fully render
await sleep(3000);

// Wait for the Windows start button to appear
await screen.waitFor(imageResource("start.png"), 10000, 1000, {
    providerData: { validateMatches: true },
});

// Open Notepad via the Start menu
await keyboard.type(Key.LeftWin);
await sleep(1000);
await keyboard.type("notepad");
await keyboard.type(Key.Enter);

// Type some text
await keyboard.type("Hello world! nut.js ❤️ you!");

Image-Based Interaction

Use screen.waitFor() and mouse.move() to find and click elements visually:

typescript
const target = await screen.waitFor(
    imageResource("helo.png"),
    10000,
    1000,
    { providerData: { validateMatches: true } },
);
await mouse.move(straightTo(centerOf(target)));

Clipboard Operations

With useRemoteClipboard(), the clipboard API operates on the remote machine:

typescript
// Select all and copy on the remote machine
await keyboard.type(Key.LeftControl, Key.A);
await keyboard.type(Key.LeftControl, Key.C);

// Read from the remote clipboard
const clip = await clipboard.getContent();
console.log(`Clipboard: ${clip}`);

// Write to the remote clipboard and paste
await clipboard.setContent("We ❤️ you too, nut.js!");
await keyboard.type(Key.LeftControl, Key.A);
await keyboard.type(Key.LeftControl, Key.V);

Error Handling and Cleanup

Always disconnect in a finally block. Combine with screen recording to capture failures:

typescript
import { useScreenRecorder } from "@nut-tree/plugin-screenrecording";

useScreenRecorder();

const remote = await connect({ /* ... */ });
remote.useRemote();

await screen.startRecording({ fps: 30, bufferSeconds: 5 });

try {
    // ... automation steps ...
} catch (e) {
    console.error(e);
    await screen.stopRecording({ outputPath: "./error.mp4" });
} finally {
    remote.disconnect();
}

await screen.discardRecording();

Key Points

  • connect() establishes the RDP session and returns provider registration functions
  • useRemote() redirects all nut.js operations (screen, keyboard, mouse, clipboard) to the remote machine
  • Individual useRemoteScreen(), useRemoteKeyboard(), useRemoteMouse(), useRemoteClipboard() allow selective redirection
  • isConnected() checks whether the RDP session is still active
  • disconnect() closes the connection — always call it in a finally block
  • Works with other plugins like @nut-tree/nl-matcher (image matching) and @nut-tree/plugin-screenrecording (recording)
  • Store credentials in environment variables, not in source code

For complete API documentation, see the RDP plugin docs.

Was this page helpful?