# Attach and send keys

Source: https://libtmux.org/en/java/latest/examples/attach-and-send-keys/

> Get a session handle, send a command to a pane, and capture output.

Get a session handle, send a command to a pane, and capture output. These
examples use libtmux from your program; to attach your terminal interactively,
see [Attaching to tmux](https://libtmux.org/en/java/latest/guides/attaching-to-tmux/).

The examples include setup, error handling, and cleanup. [Source and
verification](https://libtmux.org/en/java/latest/examples/attach-and-send-keys/#where-this-comes-from) identifies their files and checks.

```java file="examples/src/main/java/io/github/libtmux/examples/BuildAWorkspace.java"
package io.github.libtmux.examples;

import io.github.libtmux.Layout;
import io.github.libtmux.Pane;
import io.github.libtmux.Server;
import io.github.libtmux.ServerConfig;
import io.github.libtmux.ServerEndpoint;
import io.github.libtmux.Session;
import io.github.libtmux.Window;
import io.github.libtmux.exception.ServerUnavailableException;
import java.nio.file.Path;
import java.util.Optional;

/**
 * Lays out a session the way you would set one up by hand before starting work.
 *
 * <pre>{@code
 * java BuildAWorkspace.java /tmp/libtmux-java-dev/demo/s
 * }</pre>
 */
public final class BuildAWorkspace {

    private BuildAWorkspace() {}

    public static void main(String[] args) {
        System.out.println(run(Path.of(args.length > 0 ? args[0] : "/tmp/libtmux-java-dev/demo/s")));
    }

    /** Separated from {@code main} so the suite can run exactly what a reader runs. */
    public static String run(Path socket) {
        ServerConfig config = ServerConfig.builder()
                .endpoint(ServerEndpoint.socketPath(socket))
                .configFile(Path.of("/dev/null"))
                .build();

        // Closing a server closes this client. The tmux server, and the session, outlive the program
        // — which is the whole point of tmux and the reason nothing here kills it.
        try (Server server = Server.open(config)) {
            // One read decides and answers. An absent daemon means the name cannot be taken, so
            // that specific failure is the other way this resolves to "not found".
            Optional<Session> existing;
            try {
                existing = server.session("work");
            } catch (ServerUnavailableException absent) {
                existing = Optional.empty();
            }
            Session session = existing.orElseGet(() -> server.newSession("work"));

            Window editor = session.newWindow(window -> window.named("editor").detached());
            Pane shell = editor.split(split -> split.toRight());
            shell.sendLine("git status --short");

            editor.selectLayout(Layout.MAIN_VERTICAL);

            return "session " + session.name() + " has "
                    + session.refresh().windows().size() + " windows";
        }
    }
}
```

## Finding an existing session instead

For a script that runs repeatedly, look up a session before creating it.
[Attaching to
tmux](https://libtmux.org/en/java/latest/guides/attaching-to-tmux/#finding-a-session-instead-of-always-creating-one)
shows that pattern, and [Filtering and querying, in
practice](https://libtmux.org/en/java/latest/guides/querying-and-filtering/) covers absent and ambiguous matches.

## Where this comes from

**Source:**
[`examples/src/main/java/io/github/libtmux/examples/BuildAWorkspace.java`](<https://github.com/libtmux/libtmux-java/blob/c067fced0dfd19bd6dd3d260e9d4c336becdb063/examples/src/main/java/io/github/libtmux/examples/BuildAWorkspace.java>)

**In this page:** read whole from the file

**Checked by:** run against real tmux by the `examples` module's own
`ExamplesRunTest`

### Source inclusion

A `file="..."` fence reads the named source during the site build. Hand-quoted
excerpts are copies; their source files and regions are listed above.
