# Attach and send keys

Source: https://libtmux.org/en/go/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/go/latest/guides/attaching-to-tmux/).

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

```go file="examples/quickstart/main.go"
// Command quickstart runs a command in tmux and prints what it showed.
package main

import (
	"context"
	"errors"
	"fmt"
	"log"
	"os"

	"github.com/libtmux/libtmux-go/tmux"
)

func main() {
	if err := run(context.Background()); err != nil {
		log.Fatal(err)
	}
}

func run(ctx context.Context) (err error) {
	// A private server: a socket and an empty config of its own, so this
	// neither touches nor is changed by a tmux you already use.
	server, err := tmux.NewServer(tmux.ServerOptions{
		SocketName: "libtmux-quickstart",
		ConfigFile: os.DevNull,
	})
	if err != nil {
		return fmt.Errorf("configure tmux: %w", err)
	}
	session, err := server.NewSession(ctx, tmux.NewSessionRequest{Name: "demo"})
	if err != nil {
		return fmt.Errorf("create session: %w", err)
	}
	// Cleanup runs even when ctx is the reason the program is leaving.
	defer func() {
		err = errors.Join(err, server.Kill(context.WithoutCancel(ctx)))
	}()

	// The command runs in a window of its own, with a terminal.
	result, err := session.Run(ctx, "echo hello from tmux", tmux.RunOptions{})
	if err != nil {
		return fmt.Errorf("run command: %w", err)
	}
	for _, line := range result.Lines {
		fmt.Println(line)
	}
	fmt.Println("exit status:", result.Status)
	return nil
}
```

## 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/go/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/go/latest/guides/querying-and-filtering/) covers absent and ambiguous matches.

## Where this comes from

**Source:** [`examples/quickstart/main.go`](<https://github.com/libtmux/libtmux-go/blob/2de249b600d65218ee8b8fdc07c6b2b919242151/examples/quickstart/main.go>)

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

**Checked by:** the whole file runs against a real tmux server as
`TestQuickstart`; the `docs:quickstart` region inside it is additionally
mirrored into README.md by `go generate ./tmux`, and CI fails if the two drift

### 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.
