Sikuli is now named SikuliX:
SikuliX automates anything you see on the screen of your desktop computer running Windows, Mac or some Linux/Unix. It uses image recognition powered by OpenCV to identify and control GUI components. This is handy in cases when there is no easy access to a GUI's internals or the source code of the application or web page you want to act on.
SikuliX supports below scripting languages
  • Python language level 2.7 (supported by Jython)
  • Ruby language level 1.9 and 2.0 (supported by JRuby)

… and you can use it in Java programming and programming/scripting with any Java aware programming/scripting language (Jython, JRuby, Scala, Clojure, …).
Though SikuliX is currently not available on any mobile device, it can be used with the respective emulators on a desktop computer or based on VNC solutions.
Besides locating images on a screen SikuliX can run the mouse and the keyboard to interact with the identified GUI elements. This is available for multi monitor environments and even for remote systems with some restrictions.
SikuliX comes with basic text recognition (OCR) and can be used to search text in images. This feature is powered by Tesseract.
SikuliX is a Java application, that works on Windows XP+, Mac 10.6+ and most Linux/Unix systems. For Windows, Mac and Ubuntu 12.04+ it is complete and should normally work out of the box. For other Linux/Unix systems there usually are a few prerequisites to be setup.
SikuliX is the follow up of Sikuli Script with it's last version from 2011 as Sikuli-X-1.0rc3.
Though it is no longer supported: here you find valuable information for the 
installation.

RESTful SikuliX:

The idea of using SikuliX in a remote context appeared due to automation architecture chosen for the project I'm currently working on. As we scale our tests between number of environments, there was a necessity in resolving some complicated tasks, that couldn't be done with common libraries like Selenium, on remote VMs. SikuliX had everything we needed, except remote platform we could use in a context of existing architecture.

RESTful has a built a client-server platform, that included latest SikuliX API and several useful utility classes for interacting with remote file system. After some period of time I've realized that this approach could be useful for others, so now I'm happy to anounce new experimental features, that are already pushed into SikuliX repository - RemoteServer andRESTClient.

These modules are not fully tested yet, but you can give it a try and report all issues you'll find or push appropriate pull requests. There're some tests written for Windows / Linux OS, that could be a start point for you.
And now let's take a look at provided functionality.
RemoteServer module is based on Grizzly Http Sever and contains the following endpoints:
  • http://ip:port/sikuli/cmd/execute - uses apache commons exec library for running command line on a remote VM.
  • http://ip:port/sikuli/file/upload - uploads a list of provided files to the given remote path.
  • http://ip:port/sikuli/file/download - downloads a single file from remote path (multiple file download feature is not implemented yet).
  • http://ip:port/sikuli/file/delete - removes file or directory by a given remote path (quick note: file system operations were implemented using apache commons iolibrary).
  • http://ip:port/sikuli/file/exists - checks a list of inputs, if appropriate files or directories exist.
  • http://ip:port/sikuli/file/createFolder - creates directory by a given remote path.
  • http://ip:port/sikuli/file/cleanFolder- removes content of a given remote directory.
  • http://ip:port/sikuli/file/copyFolder- copies 1 folder's content to another.
  • http://ip:port/sikuli/image/click - uses SikuliX API for clicking provided image with a given wait timeout on a remote VM.
  • http://ip:port/sikuli/image/setText - uses SikuliX API to print some text into appropriate control with a given wait timeout on a remote VM.
  • http://ip:port/sikuli/image/exists - uses SikuliX API for checking if image is present on a screen or not on a remote VM.
  • http://ip:port/sikuli/image/dragAndDrop - uses SikuliX API for dragging and dropping objects on remote VM.

If you take a look at code, you'll find it pretty straightforward, e.g. here's a delete processor:

    @POST
    @Path("/delete")
    public Response delete(@QueryParam("path") final String path) {
        return Response.status(FileUtility.delete(path) ? 
               Response.Status.OK : Response.Status.NOT_FOUND)
               .build();
    }
As you may saw above, common SikuliX APIs provides us a way of setting wait timeout. This functionality is implemented via observers mechanism, that uses onAppear event to process requested actions:

    private RemoteDesktop onAppear(final Pattern element, 
            final SikuliAction action, final String text) {
        desktop.onAppear(element, new ObserverCallBack() {
            public void appeared(ObserveEvent e) {
                switch (action) {
                    case CLICK:
                        e.getMatch().click();
                        break;
                    case TYPE:
                        e.getMatch().click();
                        e.getMatch().type(text);
                        break;
                }

                desktop.stopObserver();
            }
        });

        return this;
    }
Before moving to client's part, let's take a look at one more interesting block, related to remote command line execution. As I've mentioned above, we use apache commons exec library for this purpose. And I must say, it provides a fantastic feature, that I struggled with for a while - delayed exit from main thread by timeout. You may know that common java command line executor will stuck forever, if started process waits for user input or it's just a simple server application. Let's look what commons exec can provide for this particular case:

    public static int executeCommandLine(final Command command) {
        if (command.getProcess() == null) {
            CMD_LOGGER.severe("There's nothing to execute.");
            return -1;
        }

        CMD_LOGGER.info("Processing the following command: " +
                command.getProcess() + (command.getArgs() != null ?
                " " + command.getArgs() : ""));

        final long timeout = (command.getTimeout() > 0 ?
                command.getTimeout() : 0) * 1000;
        final CommandLine commandLine = new CommandLine(
                separatorsToSystem(quoteArgument(
                    command.getProcess())));

        if (command.getArgs() != null) {
            for (String arg : command.getArgs()) {
                commandLine.addArgument(quoteArgument(arg));
            }
        }

        final ExecutionResultsHandler resultHandler =
                new ExecutionResultsHandler();
        final PumpStreamHandler streamHandler =
                new PumpStreamHandler(
                    new ExecutionLogger(CMD_LOGGER, Level.INFO),
                    new ExecutionLogger(CMD_LOGGER, Level.SEVERE));
        final DefaultExecutor executor = new DefaultExecutor();

        executor.setStreamHandler(streamHandler);
        executor.setProcessDestroyer(
                new ShutdownHookProcessDestroyer());

        try {
            executor.execute(commandLine, resultHandler);
            resultHandler.waitFor(timeout);
        } catch (InterruptedException | IOException e) {
            CMD_LOGGER.severe("Command execution failed: "
                + e.getMessage());
            return -1;
        }

        return resultHandler.getExitValue();
    }
ExecutionResultsHandler will let process be released by a given timeout.

That's almost pretty much related to server side. To build remote server, use the following command:

mvn clean install
It will create a jar with all necessary dependencies in your target folder.

To start server, use the following command:

java -jar sikulixremoteserver-1.1.0-jar-with-dependencies.jar port
Port is optional. You can skip it, if you want to use default one - 4041.

Now it's time to look at client side, that is located inside RESTClient module.

There's nothing specific. Code is pretty straightforward, as it only takes care about sending necessary objects to listed above endpoints. Client implements SikuliX interface. Besides that, you may find some other interfaces used as an input methods' arguments. We decided to leave them in project to allow users overriding client's methods and common sending containers. It was done for number of reasons. One of them is incompatible Jersey 1.x and 2.x versions. If your project uses Jersey 1.x dependencies, you won't be able to use new SikuliX REST client, as it's based on Jersey 2.x. In such case you will need to implement your own client using SikuliX remote interfaces.

As a simple example of REST call implementation, let's take a look at multiple files upload API:

    public void uploadFile(final List filesPath,
            final String saveToPath) {
        final MultiPart multiPart =
            new MultiPart(MediaType.MULTIPART_FORM_DATA_TYPE);

        for (String path : filesPath) {
            multiPart.bodyPart(new FileDataBodyPart("file",
                new File(separatorsToSystem(path)),
                MediaType.APPLICATION_OCTET_STREAM_TYPE));
        }

        final Response response = service.path("file")
                .path("upload")
                .queryParam("saveTo", separatorsToSystem(saveToPath))
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.entity(multiPart,
                    multiPart.getMediaType()));

        if (response.getStatus() ==
                Response.Status.OK.getStatusCode()) {
            CLIENT_LOGGER.info("File(-s) " + filesPath +
                " has been saved to " +
                separatorsToSystem(saveToPath) + " on " + ip);
        } else {
            CLIENT_LOGGER.severe("Unable to save file(-s) " +
                filesPath + " to " + separatorsToSystem(saveToPath) +
                " on " + ip);
        }

        response.close();
    }
As you see, we can pass a list of files' paths for uploading. It's pretty useful when we need to copy expected images we want to allow SikuliX interact with on a remote VM.

Provided tests were created for Windows OS and haven't been tested on Unix or Mac yet. If you're going to give it a try, you'll need to install and start remote server first. By default all the tests are disabled to avoid build failures, as such verifications are very platform and configuration specific. To enable them, just change the following option in a pom.xml:

skipTests=false
To choose classes to be included into test run, you need to modify suites.xml located in resources folder. Actually, you should carefully explore resources before execution. Batches' extensions should be renamed to .bat. And you may also need to provide your own images, as they are very OS specific.

When you finish with resources, you'll need to update BaseTest configuration:
SIKULIX_SERVER_IP field must refer your newly raised remote server IP address.
WAIT_TIMEOUT will tell SikuliX to wait until expected image is appeared on a screen.
SIMILARITY level will be used while images comparison.
As we've already mentioned file upload scenario, let's take a look at appropriate test:

    @Test
    public void uploadFilesToServer() {
        getClient().uploadFile(Arrays.asList(
                BATCH_RUNNER_SCRIPT.getPath(),
                BATCH_SAMPLE_SCRIPT.getPath()),
                SERVER_PATH.getPath());

        assertTrue(getClient().exists(Arrays.asList(
                SERVER_PATH.getPath() + "/" +
                    BATCH_RUNNER_SCRIPT.getName(),
                SERVER_PATH.getPath() + "/" +
                    BATCH_SAMPLE_SCRIPT.getName())));
    }
To perform common SikuliX actions, you can use the following example:

    @Test
    public void callCommandLineFromStartMenu() {
        getClient().click(new ImageBox(
                getResource(RESOURCE_BUTTON_START_IMAGE).getPath(),
                SIMILARITY), WAIT_TIMEOUT);

        getClient().setText(new ImageBox(
                getResource(RESOURCE_INPUT_FIND_FILES_IMAGE)
                    .getPath(), SIMILARITY),
                "cmd" + Key.ENTER, WAIT_TIMEOUT);

        assertTrue(getClient().exists(new ImageBox(
                getResource(RESOURCE_INPUT_CMD_IMAGE).getPath(),
                SIMILARITY), WAIT_TIMEOUT));
    }
You can find more examples in official SikuliX 2014 GitHub repository.