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
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:
import { config } from "dotenv";
config();Connecting to the Remote Machine
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
.envfile — never hardcode them. TheignoreCertificateoption 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:
// 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:
// 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:
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:
// 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:
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 functionsuseRemote()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 activedisconnect()closes the connection — always call it in afinallyblock- 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.