代理规则
一个用于AI代理控制Windows远程桌面会话的 CLI 工具,该工具建立在 铁RDP。 。 。 .
这是佩斯维护的叉子 此昵称/ 代理,作为 @foundationallabs/agent-rdp. 它是独立开发的,不跟踪上游.
演示
Claude Code 通过 RDP 实现 SQLite 数据库和表格创建自动化 :
特征
- 连接到 RDP 服务器 - 通过TLS和CredSSP认证,全面支持RDP协议
- 抓取截图 - 将远程桌面抓取为 PNG 或 JPEG
- 鼠标控制 - 点击、双击、右击、拖放、滚动
- 键盘输入 - 文本类型,按键组合(Ctrl+C、Alt+Tab等)
- 剪贴板同步 - 复制/粘贴本地机器和远程视窗之间的文本
- 驱动映射 - 将本地目录映射为远程机器上的网络驱动器
- UI 自动化 - 通过访问API与 Windows 应用程序互动(单击、选择、切换、扩展)
- OCR 文本位置 - 在无法使用UI自动化时使用OCR在屏幕上查找文本
- JSON 输出 - AI剂消费结构化产出
- 会话管理 - 多个命名会话,自动守护进程生命周期
安装
从 npm
npm install -g @foundationallabs/agent-rdp
作为克洛德密码的技巧
npx add-skill https://github.com/foundationallabs/agent-rdp
从源
git clone https://github.com/foundationallabs/agent-rdp
cd agent-rdp
pnpm install
pnpm build # Build native binary
pnpm build:ts # Build TypeScript
使用量
连接到 RDP 服务器
# Using command line (password visible in process list - not recommended)
agent-rdp connect --host 192.168.1.100 --username Administrator --password 'secret'
# Using environment variables (recommended)
export AGENT_RDP_USERNAME=Administrator
export AGENT_RDP_PASSWORD=secret
agent-rdp connect --host 192.168.1.100
# Using stdin (most secure)
echo 'secret' | agent-rdp connect --host 192.168.1.100 --username Administrator --password-stdin
截图
# Save to file
agent-rdp screenshot --output desktop.png
# Output as base64 (for AI agents)
agent-rdp screenshot --base64
# With JSON output
agent-rdp --json screenshot --base64
鼠标操作
# Click at position
agent-rdp mouse click 500 300
# Right-click
agent-rdp mouse right-click 500 300
# Double-click
agent-rdp mouse double-click 500 300
# Move cursor
agent-rdp mouse move 100 200
# Drag from (100,100) to (500,500)
agent-rdp mouse drag 100 100 500 500
键盘操作
# Type text (supports Unicode)
agent-rdp keyboard type "Hello, World!"
# Press key combinations
agent-rdp keyboard press "ctrl+c"
agent-rdp keyboard press "alt+tab"
agent-rdp keyboard press "ctrl+shift+esc"
# Press single keys (use press command)
agent-rdp keyboard press enter
agent-rdp keyboard press escape
agent-rdp keyboard press f5
滚动
agent-rdp scroll up --amount 3
agent-rdp scroll down --amount 5
agent-rdp scroll left
agent-rdp scroll right
地点(OCR)
使用 OCR( 由 坐标) (中文(简体) ). 当UI自动化无法访问某些元素(WebView内容,一些对话框)时有用.
# Find lines containing text
agent-rdp locate "Cancel"
# Pattern matching (glob-style)
agent-rdp locate "Save*" --pattern
# Get all text on screen
agent-rdp locate --all
# JSON output
agent-rdp locate "OK" --json
返回带有坐标的文本行以单击 :
Found 1 line(s) containing 'Cancel':
'Cancel Button' at (650, 420) size 80x14 - center: (690, 427)
To click the first match: agent-rdp mouse click 690 427
剪贴板
# Set clipboard text (available when you paste on Windows)
agent-rdp clipboard set "Hello from CLI"
# Get clipboard text (after copying on Windows)
agent-rdp clipboard get
# With JSON output
agent-rdp --json clipboard get
驱动绘图
将本地目录映射为远程Windows机上的网络驱动. 驱动器必须在连接时间映射 。 多盘可以指定.
# Map local directories during connection
agent-rdp connect --host 192.168.1.100 -u Administrator -p secret \
--drive /home/user/documents:Documents \
--drive /tmp/shared:Shared
# List mapped drives
agent-rdp drive list
在远程Windows机上,映射出驱动器在"文件探索"中作为网络位置出现.
候补贝壳
通过通过一个 RDP 替代 shell 启动一个特定的程序而不是桌面 。 例如, CyberArk PSM 期待这里的连接字符串 :
agent-rdp connect --host psm.example.com -u user -p secret \
--alternate-shell 'psm /u user@domain /a target /c PSM-RDP'
值也可以来自 AGENT_RDP_ALTERNATE_SHELL 环境变量。 需要国家解放军关闭(仅限TLS安全)的PSM部署可以添加 --no-nla (SDK: ) (韩语) enableNla: false) (中文(简体) ). 关闭 NLA 后, Windows 检查会话内部的密码, 所以 connect 发送证书给服务器确认登录后等待最多 20 s authentication_failed (理由 logon_unconfirmed若无. 在证书发送后和确认失败前结束的连接,因为服务器可能已经计算了尝试. 在证书离开客户端之前失败 connection_failed,或 certificate_mismatch 针头不匹配。 A 类 SESSION_CONTINUE 登录通知,Windows在良好登录时随会话ID发送,不会确认或失败登录.
代理-rdp不跟随Server Rediction,从不发布支持广告. 因此,一个 RD Connect Broker 农场将会话放在您拨打的主机上, 而不在另一个主机上重新连接断开的会话 .
UI 自动化
通过Windows UI自动化API在程序上与Windows应用程序互动,使用本地模式(InvokePattern,ChoiceProjectPattern,ToglePattern等). 当启用时, PowerShell 代理被注入到远程会话中, 用于捕捉访问树并进行动作 。 CLI与代理机之间的通信使用动态虚拟通道(DVC)来进行快速双向IPC.
详细文件见 终止.md。 。 。 .
# Connect with automation enabled
agent-rdp connect --host 192.168.1.100 -u Admin -p secret --enable-win-automation
# Take an accessibility tree snapshot (refs are always included)
agent-rdp automate snapshot
# Snapshot filtering options (like agent-browser)
agent-rdp automate snapshot -i # Interactive elements only
agent-rdp automate snapshot -c # Compact (remove empty structural elements)
agent-rdp automate snapshot -d 3 # Limit depth to 3 levels
agent-rdp automate snapshot -s "~*Notepad*" # Scope to a window/element
agent-rdp automate snapshot -i -c -d 5 # Combine options
# Pattern-based element operations (refs use @eN format)
agent-rdp automate click "#SaveButton" # Click button
agent-rdp automate click "@e5" # Click by ref number from snapshot
agent-rdp automate click "@e5" -d # Double-click (for file list items)
agent-rdp automate select "@e10" # Select item (SelectionItemPattern)
agent-rdp automate toggle "@e7" # Toggle checkbox (TogglePattern)
agent-rdp automate expand "@e3" # Expand menu (ExpandCollapsePattern)
agent-rdp automate context-menu "@e5" # Open context menu (Shift+F10)
# Fill text fields
agent-rdp automate fill ".Edit" "Hello World"
# Window operations
agent-rdp automate window list
agent-rdp automate window focus "~*Notepad*"
# Run PowerShell commands
agent-rdp automate run "Get-Process" --wait
agent-rdp automate run "Get-Process" --wait --process-timeout 5000 # With 5s timeout
选择者类型 :
@e5或者说@5- 快照的参考号码(建议使用前缀)#SaveButton- 自动化标识.Edit- Win32类名称~*pattern*- 通关卡名称匹配File- 元素名称(精确匹配)
快照输出格式 :
- Window "Notepad" [ref=e1, id=Notepad]
- MenuBar "Application" [ref=e2]
- MenuItem "File" [ref=e3]
- Edit "Text Editor" [ref=e5, value="Hello"]
会话管理
# List active sessions
agent-rdp session list
# Get current session info
agent-rdp session info
# Close a session
agent-rdp session close
# Use a named session
agent-rdp --session work connect --host work-pc.local ...
agent-rdp --session work screenshot
断开连接
agent-rdp disconnect
网页查看器
打开基于网络的查看器以查看浏览器中的远程桌面 :
# Open viewer (default streaming port 9224; the token comes from `connect`)
agent-rdp view --token <token>
# Specify a different port
agent-rdp view --port 9224 --token <token>
取景器需要启用WebSocket流线. 用流线启动会话 :
agent-rdp --stream-port 9224 connect --host 192.168.1.100 -u Admin -p secret
agent-rdp view --token <token printed by connect>
溪流需要打印符号 connect (单位:千美元)Stream: ws://127.0.0.1:9224/?token=...,或 stream_token 内 --json (产出).
JSON 输出
所有命令支持 --json 结构化产出:
agent-rdp --json screenshot --base64
成功响应 :
{
"success": true,
"data": {
"type": "screenshot",
"width": 1920,
"height": 1080,
"format": "png",
"base64": "iVBORw0KGgo..."
}
}
错误响应 :
{
"success": false,
"error": {
"code": "not_connected",
"message": "Not connected to an RDP server"
}
}
环境变量
| 变量 | 说明 |
|---|---|
AGENT_RDP_HOST | RDP 服务器主机名或 IP |
AGENT_RDP_PORT | RDP 服务器端口( 默认: 3389) |
AGENT_RDP_USERNAME | RDP 用户名 |
AGENT_RDP_PASSWORD | RDP 密码 |
AGENT_RDP_ALTERNATE_SHELL | 要启动替代桌面的外壳 |
AGENT_RDP_SESSION | 会话名称( 默认: “ 默认 ” ) |
AGENT_RDP_STREAM_PORT | WebSocket 流口 (0 = 已禁用) |
AGENT_RDP_STATE_DIR | 会话状态的基础目录( 绝对路径; 默认) /tmp/agent-rdp(中文(简体) ) |
AGENT_RDP_STREAM_TOKEN | 流代码 agent-rdp view (与 --token; 符号来自 connect(中文(简体) ) |
AGENT_RDP_BINARY | 只有节点.js SDK: 绝对路径 agent-rdp 二进制来代替平台软件包; 如果不存在错误 |
国家目录权限
在Unix上,CLI和Node.js SDK拒绝使用其状态目录另一个用户可以控制的会话:状态目录必须是您拥有的真实目录或root所拥有(如果其他人可以写给它的话会粘住),会话目录是您拥有的真正目录,没有组或其他权限. 检查在运行中的守护进程 pidemon 文件或 socket 被信任之前运行,并在新的守护进程启动之后再次运行,因此连接请求(它携带了 RDP 密码)从未在这样的目录中发送给守护进程. SDK将它曝光为 verifySessionDirs(session, { stateDir })。 。 。 .
这不涵盖作为自己的用户运行的其他进程,也不涵盖其父目录被另一个用户控制的状态目录:在您或根目录下选择一个状态目录.
节点.js API
在程序上使用来自Node.js/TypeScript的代理文本:
import { RdpSession } from '@foundationallabs/agent-rdp';
const rdp = new RdpSession({ session: 'default' });
await rdp.connect({
host: '192.168.1.100',
username: 'Administrator',
password: 'secret',
width: 1280,
height: 800,
drives: [{ path: '/tmp/share', name: 'Share' }],
alternateShell: 'psm /u user@domain /a target /c PSM-RDP', // Optional: start this instead of the desktop
enableWinAutomation: true, // Enable UI Automation
});
// Screenshot
const { base64, width, height } = await rdp.screenshot({ format: 'png' });
// Mouse
await rdp.mouse.click({ x: 100, y: 200 });
await rdp.mouse.rightClick({ x: 100, y: 200 });
await rdp.mouse.doubleClick({ x: 100, y: 200 });
await rdp.mouse.move({ x: 150, y: 250 });
await rdp.mouse.drag({ from: { x: 100, y: 100 }, to: { x: 500, y: 500 } });
// Keyboard
await rdp.keyboard.type({ text: 'Hello World' });
await rdp.keyboard.press({ keys: 'ctrl+c' });
await rdp.keyboard.press({ keys: 'enter' }); // Single keys use press()
// Scroll
await rdp.scroll.up(); // Default amount: 3
await rdp.scroll.down({ amount: 5 }); // Custom amount
await rdp.scroll.up({ x: 500, y: 300 }); // Scroll at position
// Clipboard
await rdp.clipboard.set({ text: 'text to copy' });
const text = await rdp.clipboard.get();
// Locate text using OCR
const matches = await rdp.locate({ text: 'Cancel' });
if (matches.length > 0) {
await rdp.mouse.click({ x: matches[0].center_x, y: matches[0].center_y });
}
// Get all text on screen
const allText = await rdp.locate({ all: true });
// Automation (requires --enable-win-automation at connect)
const snapshot = await rdp.automation.snapshot({ interactive: true });
await rdp.automation.click('@e5'); // Click button by ref
await rdp.automation.click('@e5', { doubleClick: true }); // Double-click
await rdp.automation.select('@e10'); // Select item
await rdp.automation.toggle('@e7'); // Toggle checkbox
await rdp.automation.expand('@e3'); // Expand menu
await rdp.automation.contextMenu('@e5'); // Open context menu
await rdp.automation.fill('#input', 'text'); // Fill text field
await rdp.automation.run('notepad.exe'); // Run command
await rdp.automation.waitFor('#SaveButton', { timeout: 5000 });
// Window management
const windows = await rdp.automation.listWindows();
await rdp.automation.focusWindow('~*Notepad*');
await rdp.automation.maximizeWindow();
// Drives
const drives = await rdp.drives.list();
// Session info
const info = await rdp.getInfo();
// Disconnect
await rdp.disconnect();
WebSocket 流线
为实时屏幕捕获和双向剪贴板支持启用 WebSocket 流线 :
const rdp = new RdpSession({
session: 'viewer',
streamPort: 9224, // Enable streaming
});
await rdp.connect({...});
// Connect your WebSocket client to receive JPEG frames
const streamUrl = rdp.getStreamUrl(); // "ws://127.0.0.1:9224/?token=..." (null until connected)
溪流要求 ?token= 查询参数和答案 401 没有它。 符号在每个连接上都是新的,来自连接响应(stream_token),SDK's getStreamUrl(),或者CLI的连接输出。 它针对机器上的其他用户和网页进行保护(DNS重新绑定);它不针对作为同一位用户运行的其他进程进行保护,后者可以像任何客户端一样读取令牌.
关于完整的WebSocket协议规格(消息类型、剪贴板流量、输入处理),参见 韦贝克特.md。 。 。 .
建筑
author-rdp 使用守护进程每会话架构 :
- 国 际 (单位:千美元)
agent-rdp) - 解析命令并沟通守护进程 - 守护进程 - 维护 RDP 连接和进程命令
- 独立人权委员会 - unix sockets(macOS/Linux)或TCP(窗口)
守护进程在第一个命令上自动启动, 并持续到明确关闭或会话时间结束 .
限制
UI 自动化
- 网络视图:UI自动化无法与WebView内容交互(如Windows Start菜单搜索,Edge浏览器内容,Electronapps). 使用
Win+R或者说automate run直接启动程序,而不是通过菜单点击. - UAC 对话框:用户账户控制高程提示在安全的桌面上运行,无法通过UI自动化访问. 没有很好的变通办法——远程用户必须手动与UAC交互,或者UAC必须被禁用(出于安全原因不推荐).
OCR 倒计时
当UI自动化无法访问某些元素时 locate 命令提供基于OCR的文本检测 :
agent-rdp locate "Button Text" # Find text and get coordinates
agent-rdp mouse click <x> <y> # Click at returned coordinates
这不是非常可靠的(OCR可以错误地读取字符,丢失文本,或者返回不精确的坐标),但可能为像对话框按钮这样的简单案例工作.
屏幕截图坐标检测
克劳德模型 (非计算机使用模式,如克洛德代码)在从截图估计像素坐标时差. 不要要求克洛德查看一个截图并猜到在哪里点击 - 这很可能是不准确的 .
双子座模型 一般擅长从图像中进行像素坐标估计.
如果你需要与克洛德进行视觉坐标检测 使用克洛德的绳子 计算机使用工具 专为此目的设计的.
所需资源
- Rust 1.75 或晚点
- 目标 RDP 服务器, 启用网络级别认证( NLA)
许可证
MIT OR Apache-2.0 (同名: IronRDP)