nutdart

A powerful Flutter FFI plugin built on libnut-core for desktop automation that provides comprehensive mouse control, keyboard automation, and screen capture capabilities across Windows, macOS, and Linux platforms.

Developed by Telosnex for integrating with Anthropic's Claude LLM computer use tool.

🚀 Features

🖱️ Mouse Control

  • Cursor Movement: Move mouse to precise coordinates or points
  • Clicking: Left, middle, and right-click with single or double-click support
  • Dragging: Drag operations between any two points
  • Scrolling: Horizontal and vertical scrolling with custom deltas
  • Press & Hold: Independent mouse button press and release control
  • Position Tracking: Get current mouse cursor position

⌨️ Keyboard Automation

  • Key Tapping: Send individual key presses with full key name support
  • Modifier Keys: Support for Cmd/Ctrl, Alt, Shift, Meta, and Fn combinations
  • String Typing: Type complete strings.
  • Key States: Hold keys down and release them independently
  • Built-in Shortcuts: Pre-built methods for common operations (copy, paste, save, etc.)
  • Navigation Keys: Arrow keys, Enter, Escape, Tab, Backspace, Delete, and more

📸 Screen Capture

  • Full Screen: Capture entire desktop with optional JPEG compression
  • Region Capture: Capture specific rectangular areas
  • Smart Resizing: Automatic image resizing with max dimension constraints
  • JPEG Compression: Configurable quality settings (0-100)
  • Memory Efficient: Direct JPEG encoding without intermediate bitmap storage

🎯 Cross-Platform Support

  • macOS: Native ScreenCaptureKit integration for optimal performance
  • Windows: Windows API-based implementation with full feature support
  • Linux: X11-based implementation for comprehensive desktop control
  • Graceful Degradation: Stub implementations for unsupported platforms (web, mobile)

📦 Installation

Add nutdart to your pubspec.yaml file:

dependencies:
  nutdart: ^0.0.1

Then run:

flutter pub get

🔧 Usage

Basic Mouse Control

import 'package:nutdart/nutdart.dart';

// Move mouse to specific coordinates
Mouse.moveTo(500, 300);

// Click at current position
Mouse.click(); // Left click by default
Mouse.click(MouseButton.right); // Right click

// Click at specific coordinates
Mouse.clickAt(100, 200);

// Double-click
Mouse.doubleClick();

// Drag from one point to another
Mouse.drag(Point(100, 100), Point(300, 300));

// Scroll
Mouse.scrollVertical(-3); // Scroll up
Mouse.scrollHorizontal(2); // Scroll right

// Get current mouse position
Point position = Mouse.getPosition();
print('Mouse is at: ${position.x}, ${position.y}');

Keyboard Automation

// Type a string
Keyboard.type("Hello, World!");

// Tap individual keys
Keyboard.tap("enter");
Keyboard.tap("escape");
Keyboard.tab();

// Use modifier keys
Keyboard.tapWithModifiers("c", ["cmd"]); // Cmd+C
Keyboard.tapWithModifiers("z", ["cmd", "shift"]); // Cmd+Shift+Z

// Built-in shortcuts
Keyboard.copy();
Keyboard.paste();
Keyboard.save();
Keyboard.selectAll();

// Navigation
Keyboard.arrowUp();
Keyboard.arrowDown();
Keyboard.enter();
Keyboard.backspace();

// Hold and release keys
Keyboard.keyDown("shift");
Keyboard.tap("a"); // Types "A" while shift is held
Keyboard.keyUp("shift");

Screen Capture

// Get screen dimensions
Size screenSize = Screen.getSize();
print('Screen: ${screenSize.width}x${screenSize.height}');

// Capture full screen
Uint8List? screenshot = Screen.capture();

// Capture with JPEG compression and resizing
Uint8List? compressed = Screen.capture(
  maxSmallDimension: 800,  // Resize smaller dimension to max 800px
  quality: 85,             // JPEG quality (0-100)
);

// Capture specific region
Uint8List? region = Screen.captureRegion(
  100, 100,     // x, y
  800, 600,     // width, height
  quality: 90,
);

// Save screenshot to file
if (screenshot != null) {
  File('screenshot.jpg').writeAsBytesSync(screenshot);
}

Complete Example

import 'package:nutdart/nutdart.dart';
import 'dart:io';

void automateTask() async {
  // Get screen center
  final screenSize = Screen.getSize();
  final center = Point(screenSize.width ~/ 2, screenSize.height ~/ 2);
  
  // Move to center and click
  Mouse.moveToPoint(center);
  Mouse.click();
  
  // Type some text
  Keyboard.type("Automated with nutdart!");
  
  // Select all and copy
  Keyboard.selectAll();
  await ComputerUse.sleep(100); // Brief pause
  Keyboard.copy();
  
  // Take a screenshot
  final screenshot = Screen.capture(maxSmallDimension: 1200, quality: 90);
  if (screenshot != null) {
    File('automation_result.jpg').writeAsBytesSync(screenshot);
    print('Screenshot saved!');
  }
}

🔒 Platform Availability

This plugin is designed exclusively for desktop platforms:

Platform Support Notes
macOS ✅ Full Uses ScreenCaptureKit
Windows ✅ Full Uses Win32 API
Linux ✅ Full ⚠️ X11 only, Wayland doesn't have sufficient APIs
Web ⚠️ Stub Compiles but functions are no-ops
Android ⚠️ Stub Compiles but functions are no-ops
iOS ⚠️ Stub Compiles but functions are no-ops

Architecture

  • FFI: Direct communication with native C libraries for maximum performance
  • Graceful Degradation: Automatic fallback to no-op stubs on unsupported environments (web, mobile)
  • Screen Capture: JPEG compression happens in native code for maximum efficiency

🔧 Developming on the plugin

Building Native Code

The plugin automatically builds native libraries for each platform:

  • macOS/iOS: Uses Xcode and CocoaPods
  • Windows: Uses CMake and MSVC
  • Linux: Uses CMake and GCC
  • Android: Uses Gradle and NDK (stub only)

Regenerating FFI Bindings

dart run ffigen --config ffigen.yaml

Running Example

cd example
flutter run

🤝 Contributing

Contributions are welcome! Please feel free to submit pull requests, report bugs, or suggest new features.

🙏 Acknowledgments

Wouldn't be possible without nut.js, its C libraries are the core of the plugin. libnut-core has been upgraded to support the most recent macOS API required for screen capture, ScreenCaptureKit.

Libraries

nutdart
Nutdart public API. On unsupported platforms (web, Android, iOS) this becomes a set of no-op placeholders so that dependent applications can still compile. On desktop platforms (macOS, Windows, Linux) the full FFI implementation is used.
nutdart_bindings_generated