Help us shape the future of Go! Take the 2026 Go Developer Survey

iterm2

package module
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 5, 2026 License: GPL-2.0 Imports: 19 Imported by: 0

README

iterm2-go

A Go client for iTerm2's API — the same API its Python scripting library uses, spoken directly over the WebSocket. No Python, no bundled runtime, no script installed into iTerm2's scripts folder.

CI Go Reference

Read UPSTREAM.md before depending on this. The protocol definition is pinned and verified byte-identical to iTerm2's own. The connection to a real iTerm2 is not yet verified by any automated run — every test drives a fake that implements the protocol as read from iTerm2's source. See what is and is not verified.

Install

go get github.com/taumatix/iterm2-go@v0.9.0

Requires Go 1.27 or newer, macOS, and iTerm2 with the API enabled in Settings → General → Magic → Enable Python API. The setting's name says Python; it governs the socket, not the language.

Use

package main

import (
	"context"
	"fmt"
	"log"

	iterm2 "github.com/taumatix/iterm2-go"
)

func main() {
	ctx := context.Background()

	conn, err := iterm2.Connect(ctx, iterm2.WithAdvisoryName("my-tool"))
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	h, err := conn.ListSessions(ctx)
	if err != nil {
		log.Fatal(err)
	}
	for _, s := range h.Sessions() {
		fmt.Printf("%s\t%s\n", s.ID, s.Title)
	}

	tab, err := conn.CreateTab(ctx, iterm2.CreateTabOptions{})
	if err != nil {
		log.Fatal(err)
	}
	if err := conn.SendText(ctx, tab.SessionID, "echo hello\n", false); err != nil {
		log.Fatal(err)
	}
}

The first connection raises a permission prompt in iTerm2, because the library asks the running application for a cookie over AppleScript. A program iTerm2 launched itself is handed ITERM2_COOKIE and ITERM2_KEY in its environment and is not prompted.

How a tab's panes are arranged

Tab.Sessions lists a tab's panes in order: left to right, top to bottom. Tab.SplitTree() keeps the arrangement, as iTerm2 reports it. Each node is either a pane (Session set) or a split whose Children sit side by side (Vertical) or stacked. Its panes are the same *Session values as in Sessions, and each carries its own Frame.

func describe(n *iterm2.SplitNode, depth int) {
	pad := strings.Repeat("  ", depth)
	switch {
	case n.Session != nil:
		fmt.Printf("%spane %s\n", pad, n.Session.ID)
	case n.Vertical:
		fmt.Printf("%sside by side:\n", pad)
	default:
		fmt.Printf("%sstacked:\n", pad)
	}
	for _, c := range n.Children {
		describe(c, depth+1)
	}
}
A panel in the toolbelt

RegisterTool puts a web page in iTerm2's toolbelt: serve it from your program (on loopback) and register its URL.

err := conn.RegisterTool(ctx, iterm2.Tool{
	Name:       "My panel",
	Identifier: "com.example.mypanel",
	URL:        "http://127.0.0.1:8080/",
	Reveal:     true, // show it even if it was registered, and hidden, before
})

iTerm2 forgets the tool when it quits. On a Persistent, RegisterTool also registers it again on every new connection, without revealing it, and reports a refusal in Reconnect.ToolErr.

Functions iTerm2 can call

RegisterRPC registers a function iTerm2 can invoke by name: from a key binding, a trigger, or a toolbelt page. Its arguments arrive as JSON, and what it returns goes back as JSON. An error goes back as an exception iTerm2 can show.

reg, err := conn.RegisterRPC(ctx, iterm2.RPC{
	Name:      "greet",
	Arguments: []string{"who", "session_id"},
	Defaults:  map[string]string{"session_id": "session.id"}, // filled from an iTerm2 variable
	Handler: func(ctx context.Context, args map[string]json.RawMessage) (any, error) {
		var who string
		if err := json.Unmarshal(args["who"], &who); err != nil {
			return nil, err
		}
		return "hello " + who, nil
	},
})

On a Persistent the function is registered again on every new connection.

RegisterTitleProvider registers one as a session-title provider: it appears among the title choices in a profile's settings under its DisplayName, and a session using it shows the string its handler returns. Map an argument to a variable in Defaults, such as user.gitBranch; iTerm2 describes title providers as called again when such a variable changes, which this library's tests (against a stand-in, not iTerm2) cannot show.

reg, err := conn.RegisterTitleProvider(ctx, iterm2.TitleProvider{
	RPC: iterm2.RPC{
		Name:      "branch_title",
		Arguments: []string{"branch"},
		Defaults:  map[string]string{"branch": "user.gitBranch"},
		Handler: func(ctx context.Context, args map[string]json.RawMessage) (any, error) {
			var branch string
			_ = json.Unmarshal(args["branch"], &branch)
			return "⎇ " + branch, nil
		},
	},
	DisplayName: "Git branch",
	Identifier:  "com.example.branch-title",
})

RegisterContextMenuItem adds one to a session's context menu, labelled DisplayName; map Defaults to variables such as session.path to act on the session the menu was opened on.

Status-bar components are not typed yet.

Watching for changes
sub, err := conn.SubscribeNewSessions(ctx)
if err != nil {
	return err
}
defer sub.Unsubscribe(ctx)

for n := range sub.C() {
	fmt.Println("new session:", n.GetNewSessionNotification().GetSessionId())
}

Notifications are dropped rather than blocking when a consumer falls behind — the read loop delivers them, so a blocked reader would stall every request on the connection. sub.Dropped() counts what was lost, and WithSubscriptionBuffer sets how much slack there is.

Staying connected

A Conn cannot come back once iTerm2 quits or restarts, which it does on every update: the cookie that authorised it was spent on the handshake, and iTerm2 forgets every cookie when it restarts. ConnectPersistent does the reconnecting for you. It dials again when iTerm2 is back, re-makes your subscriptions on the new connection, and tells you it did:

p, err := iterm2.ConnectPersistent(ctx)
if err != nil {
	return err // the first connection failed: is the Python API enabled?
}
defer p.Close()

sub, err := p.SubscribeNewSessions(ctx) // its channel stays open across reconnects
if err != nil {
	return err
}
for {
	select {
	case n, ok := <-sub.C():
		if !ok {
			return sub.Err() // nil after Unsubscribe or Close
		}
		fmt.Println("new session:", n.GetNewSessionNotification().GetSessionId())
	case r := <-p.Reconnects():
		// Anything iTerm2 posted while it was away is lost. Resynchronise here:
		// subscriptions are already back, so nothing after this is missed.
		_, _ = p.ListSessions(ctx)
		log.Printf("reconnected (%d so far): %v", r.Count, r.Cause)
	}
}

A Persistent has every typed method a Conn has (ListSessions, CreateTab, SendText, SplitPane, Activate, Close*, the variables, and each Subscribe* helper returning a DurableSubscription), each made on whichever connection is current. A Session, Tab or Window it lists acts through the Persistent too, so one you held across a restart still works. Both satisfy iterm2.Client, so code written against that takes either.

While iTerm2 is away, every call returns ErrReconnecting, which also matches ErrClosed. A per-session subscription whose session did not survive the restart is closed with sub.Err() saying why.

If you would rather write the loop yourself, conn.Done() closes when a Conn ends and conn.Err() says why; a fresh Connect then makes a new one.

Either way, with the default credentials this works in a process iTerm2 launched as well as in one it did not. The ITERM2_COOKIE iTerm2 handed the process is used for the first connection only, and later ones ask iTerm2 for a fresh cookie over AppleScript. That second path needs the process to be allowed to send Apple Events to iTerm2, so macOS may ask the user once.

Anything else in the API

The hand-written surface covers the session hierarchy, sending text, creating tabs and splits, closing things, variables and notifications. Everything else iTerm2 can do — profiles, screen contents, transactions, registering a toolbelt tool — goes through Conn.Do:

resp, err := conn.Do(ctx, &apipb.ClientOriginatedMessage{
	Submessage: &apipb.ClientOriginatedMessage_RegisterToolRequest{
		RegisterToolRequest: &apipb.RegisterToolRequest{
			Name:       proto.String("My Tool"),
			Identifier: proto.String("com.example.mytool"),
			URL:        proto.String("http://localhost:8080/"),
		},
	},
})

apipb is generated from iTerm2's api.proto, so every request in the protocol is reachable without waiting for a typed wrapper here.

Errors

Error Means
ErrUnauthorized iTerm2 refused the handshake: the API is off, or the cookie was already spent. Cookies are single use.
ErrClosed The connection is gone, whether through Close or because iTerm2 quit. After a drop the error wraps ErrClosed and carries the cause, so errors.Is(err, ErrClosed) holds either way.
*APIError iTerm2 could not parse the request, or answered with something this package cannot read.
*StatusError A well-formed request iTerm2 declined. Status carries api.proto's own spelling, so it can be looked up there.

Testing

go test ./...                       # the whole suite, no iTerm2 needed
go test -race ./...
ITERM2_LIVE=1 go test -run TestLive ./...   # against your real iTerm2: opens and closes a tab

The suite runs against internal/fakeiterm, which is not a mock of this package's internals: it listens on a real unix socket, performs a real WebSocket upgrade, checks the same handshake headers iTerm2 checks, and exchanges real protobuf. That is why it can run on Linux in CI.

What it cannot prove is that iTerm2 agrees with it, since both sides were written from the same documents by the same author. TestLive is the test that closes that gap and it has never run green — see UPSTREAM.md. Treat the connection layer as unverified against the real application.

Contributing

ROADMAP.md is ordered by how much each entry limits real use; the top of it is the next thing worth doing. Regenerating apipb/ after the protocol moves needs buf: buf generate. Never edit proto/api.proto — it is upstream's file, kept byte-identical so its digest can be checked.

License

GPL-2.0-or-later — copyleft. Linking this library into your program brings the GPL's obligations with it, so read the licence before depending on it.

This is not a preference; it follows from what the library is. proto/api.proto is copied verbatim from iTerm2, which is GPL-2.0, and iTerm2's own client bindings — the iterm2 Python package, the direct equivalent of this library — are published as GPLv2+. Relicensing a copy of someone else's protocol definition more permissively is not ours to do.

Documentation

Overview

Package iterm2 is a Go client for the iTerm2 API.

iTerm2 exposes the same API its Python scripting library uses: a WebSocket carrying protocol-buffer messages over a unix domain socket in the application's support directory. This package speaks that protocol directly, so nothing here needs Python, iTerm2's bundled runtime, or a script installed into iTerm2's scripts folder.

Enabling the API

iTerm2 rejects every connection until the API is switched on in Settings > General > Magic > Enable Python API. The name says Python; the setting governs the socket, not the language.

Connecting

conn, err := iterm2.Connect(ctx)
if err != nil {
	return err
}
defer conn.Close()

h, err := conn.ListSessions(ctx)
if err != nil {
	return err
}
for _, s := range h.Sessions() {
	fmt.Println(s.ID, s.Title)
}

Connect authorises the connection with a single-use cookie. It reads ITERM2_COOKIE and ITERM2_KEY if they are set — which they are for a process iTerm2 launched itself — and otherwise asks the running iTerm2 for a fresh pair over AppleScript, which requires macOS. Pass WithCredentials to supply them yourself.

Two layers

The hand-written surface — Conn, Hierarchy, Window, Tab, Session and their methods — is the stable one, and covers the session hierarchy, sending text, creating tabs and splits, closing things, variables and notifications.

Everything else iTerm2 can do is reachable through Conn.Do, which sends one ClientOriginatedMessage from the apipb package and returns its response. That includes profiles, the screen contents, transactions, registering a toolbelt tool and the rest of api.proto. apipb is generated from iTerm2's api.proto and tracks it: UPSTREAM.md records the commit it came from, what is verified, and what is not.

Concurrency

A Conn is safe for concurrent use. Requests from many goroutines are serialised onto the socket and matched to their responses by message id, so one slow request does not block another.

Notifications are delivered to a Subscription's channel and are dropped rather than blocking when the consumer falls behind, because the read loop delivers them and a blocked reader would stall every request on the connection. Subscription.Dropped counts what was lost.

Index

Constants

View Source
const (
	// Subprotocol is the WebSocket subprotocol iTerm2 requires. iTerm2 refuses
	// the upgrade unless sec-websocket-protocol matches it exactly
	// (iTermWebSocketConnection.m, kProtocolName).
	Subprotocol = "api.iterm2.com"

	// LibraryVersion is reported in the x-iterm2-library-version header as
	// "go <LibraryVersion>".
	//
	// iTerm2 requires the header to be two space-separated fields and compares
	// the second against a per-language minimum. It publishes a minimum for
	// "python" only, so "go" is not version-gated today — iTerm2's own Swift
	// client sends "swift 1.0" on the same basis. The value is a plain decimal
	// rather than this module's semantic version because that is what the
	// comparison parses; it is not a promise about anything else, and it moves
	// only if iTerm2 starts gating Go clients.
	LibraryVersion = "0.1"

	// LegacyTCPAddress is the loopback address iTerm2 listened on before the
	// unix domain socket, and still accepts. [Connect] falls back to it when the
	// socket is absent, which is what iTerm2's Python library does.
	LegacyTCPAddress = "localhost:1912"
)
View Source
const (
	// SessionAll addresses every session at once.
	SessionAll = "all"

	// SessionActive addresses whichever session currently has keyboard focus.
	SessionActive = "active"
)

Session identifiers that iTerm2 accepts in place of a real one, documented at the top of api.proto. Not every request accepts them; the comment on each request message in api.proto says which do.

View Source
const AllVariables = "*"

AllVariables is the name that asks for every variable in one JSON object instead of a single value, as api.proto's "special value" for the get field.

Variables

View Source
var ErrClosed = errors.New("iterm2: connection closed")

ErrClosed is returned by every operation on a Conn whose connection has gone away, whether because Conn.Close was called or because iTerm2 quit.

View Source
var ErrNoCredentials = errors.New("iterm2: ITERM2_COOKIE and ITERM2_KEY are not set")

ErrNoCredentials is returned by EnvCredentials when neither ITERM2_COOKIE nor ITERM2_KEY is set.

View Source
var ErrNotSupported = errors.New("iterm2: not supported by this iTerm2")

ErrNotSupported reports a request iTerm2 understood but declined as unavailable, such as a notification type this iTerm2 version does not post.

View Source
var ErrReconnecting = fmt.Errorf("iterm2: reconnecting to iTerm2: %w", ErrClosed)

ErrReconnecting is returned by a Persistent connection while it has lost iTerm2 and is dialling again. It wraps ErrClosed, so code that already checks for a closed connection keeps working.

View Source
var ErrUnauthorized = errors.New("iterm2: unauthorized")

ErrUnauthorized wraps a handshake iTerm2 refused. The usual causes are the Python API being switched off in Settings > General > Magic, and a cookie that has already been used — iTerm2 consumes each one exactly once.

Functions

func DefaultSocketPath

func DefaultSocketPath() string

DefaultSocketPath returns the unix domain socket a running iTerm2 listens on.

It honours IT2_SUITE, which iTerm2 uses to keep parallel builds — a nightly alongside a release — from sharing one support directory.

Types

type APIError

type APIError struct {
	Message string
}

APIError is iTerm2's report that a request could not be understood. It corresponds to the `error` field of ServerOriginatedMessage, which iTerm2 sets only for a malformed request — never as an ordinary outcome.

func (*APIError) Error

func (e *APIError) Error() string

type ActivateOptions

type ActivateOptions struct {
	// OrderWindowFront raises the window containing the target.
	OrderWindowFront bool

	// SelectTab selects the target's tab. Valid for a tab or a session.
	SelectTab bool

	// SelectSession selects the target pane within its tab. Valid for a session.
	SelectSession bool

	// ActivateApp brings iTerm2 itself to the front.
	ActivateApp bool

	// RaiseAllWindows and IgnoringOtherApps apply only with ActivateApp, and
	// correspond to ActivateRequest.App in api.proto.
	RaiseAllWindows   bool
	IgnoringOtherApps bool
}

ActivateOptions asks for more than the default of bringing one object forward.

type Client added in v0.4.0

type Client interface {
	Do(ctx context.Context, req *apipb.ClientOriginatedMessage) (*apipb.ServerOriginatedMessage, error)

	ListSessions(ctx context.Context) (*Hierarchy, error)
	CreateTab(ctx context.Context, opts CreateTabOptions) (*NewTab, error)
	SendText(ctx context.Context, sessionID, text string, suppressBroadcast bool) error
	SplitPane(ctx context.Context, sessionID string, opts SplitPaneOptions) ([]string, error)
	Activate(ctx context.Context, opts ActivateOptions) error
	CloseSessions(ctx context.Context, force bool, ids ...string) error
	CloseTabs(ctx context.Context, force bool, ids ...string) error
	CloseWindows(ctx context.Context, force bool, ids ...string) error

	GetVariables(ctx context.Context, scope VariableScope, identifier string, names ...string) (map[string]json.RawMessage, error)
	GetStringVariable(ctx context.Context, scope VariableScope, identifier, name string) (value string, ok bool, err error)
	SetVariables(ctx context.Context, scope VariableScope, identifier string, values map[string]string) error
	SetStringVariable(ctx context.Context, scope VariableScope, identifier, name, value string) error
}

Client is the request surface *Conn and *Persistent share, so code can be written once and handed either. Subscriptions are not part of it: a Persistent's outlive a reconnect and are a different type.

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

Conn is a connection to a running iTerm2.

A Conn is safe for concurrent use: requests from many goroutines are serialised onto the socket and matched to their responses by message id.

Every method takes a context. Cancelling one abandons that request only — a response arriving afterwards is discarded. To tear the connection down, call Conn.Close.

func Connect

func Connect(ctx context.Context, opts ...Option) (*Conn, error)

Connect dials a running iTerm2 and completes the API handshake.

It prefers the unix domain socket at DefaultSocketPath and falls back to LegacyTCPAddress when that socket does not exist, matching iTerm2's own Python library.

The API must be enabled in iTerm2 (Settings > General > Magic > Enable Python API) or the handshake fails with an error wrapping ErrUnauthorized.

func (*Conn) Activate

func (c *Conn) Activate(ctx context.Context, opts ActivateOptions) error

Activate brings iTerm2 to the front without selecting anything in particular.

func (*Conn) Close

func (c *Conn) Close() error

Close shuts the connection down and waits for its reader to finish.

Requests in flight fail with ErrClosed, and every Subscription channel is closed. Calling it more than once is harmless, and calling it on a connection iTerm2 already dropped returns nil.

func (*Conn) CloseSessions

func (c *Conn) CloseSessions(ctx context.Context, force bool, ids ...string) error

CloseSessions closes panes by id.

force skips the confirmation iTerm2 would otherwise show for a session with a running job; without it, a user who declines leaves that session open and the call reports USER_DECLINED for it.

iTerm2 answers with one status per target, so closing several can partly succeed. The returned error joins one *StatusError per target that failed, naming it, and is nil only when every one closed.

func (*Conn) CloseTabs

func (c *Conn) CloseTabs(ctx context.Context, force bool, ids ...string) error

CloseTabs closes tabs by id. See Conn.CloseSessions for force and the per-target statuses.

func (*Conn) CloseWindows

func (c *Conn) CloseWindows(ctx context.Context, force bool, ids ...string) error

CloseWindows closes windows by id. See Conn.CloseSessions for force and the per-target statuses.

func (*Conn) CreateTab

func (c *Conn) CreateTab(ctx context.Context, opts CreateTabOptions) (*NewTab, error)

CreateTab opens a new tab, or a new window when opts.WindowID is empty.

func (*Conn) Do

Do sends one request and returns iTerm2's response to it.

This is the whole API: every request type in api.proto is a field of apipb.ClientOriginatedMessage, and the typed methods on Conn are built on this one. req is not modified — Do sends a copy carrying the message id.

A response whose `error` field is set comes back as an *APIError, because iTerm2 sets it only for a request it could not parse. Per-request status enums are left in the response for the caller to read; the typed methods turn a non-OK status into a *StatusError.

func (*Conn) Done added in v0.2.0

func (c *Conn) Done() <-chan struct{}

Done is closed when the connection ends, whether through Conn.Close or because iTerm2 went away. Conn.Err then says which.

A program that only listens has no request in flight to fail, so without this it cannot tell iTerm2 has quit. A connection cannot be revived — its cookie is spent — so the response to Done is a fresh Connect:

for {
	conn, err := iterm2.Connect(ctx)
	if err != nil { /* back off and retry */ }
	// subscribe to what you need; notifications posted while
	// disconnected are gone, so resynchronise any state here
	<-conn.Done()
}

func (*Conn) Err added in v0.2.0

func (c *Conn) Err() error

Err is nil while the connection is up. Once Conn.Done is closed it reports why: ErrClosed after Conn.Close, or the error that ended the connection when iTerm2 dropped it.

func (*Conn) GetStringVariable

func (c *Conn) GetStringVariable(ctx context.Context, scope VariableScope, identifier, name string) (value string, ok bool, err error)

GetStringVariable reads one variable and decodes it as a string.

It returns ok false when the variable is unset. A variable holding something other than a string — a number, or the object AllVariables returns — is an error, because silently rendering it would hide the mismatch.

func (*Conn) GetVariables

func (c *Conn) GetVariables(ctx context.Context, scope VariableScope, identifier string, names ...string) (map[string]json.RawMessage, error)

GetVariables reads variables from one object.

identifier names the session, tab or window, and is ignored for ScopeApp. The returned values are JSON, exactly as iTerm2 sends them: a string variable arrives quoted. Use Conn.GetStringVariable when a string is what is wanted.

The result is keyed by the requested name and omits any variable iTerm2 reported as unset, which it does by sending JSON null.

iTerm2 refuses to read more than one variable at once from SessionAll and answers MULTI_GET_DISALLOWED.

func (*Conn) ListSessions

func (c *Conn) ListSessions(ctx context.Context) (*Hierarchy, error)

ListSessions returns a snapshot of every window, tab and session.

func (*Conn) RegisterContextMenuItem added in v0.9.0

func (c *Conn) RegisterContextMenuItem(ctx context.Context, m ContextMenuItem) (*RPCRegistration, error)

RegisterContextMenuItem adds m to iTerm2's session context menu and answers its calls until it is unregistered or the connection ends.

func (*Conn) RegisterRPC added in v0.7.0

func (c *Conn) RegisterRPC(ctx context.Context, fn RPC) (*RPCRegistration, error)

RegisterRPC registers fn and answers iTerm2's calls to it until it is unregistered or the connection ends.

func (*Conn) RegisterTitleProvider added in v0.8.0

func (c *Conn) RegisterTitleProvider(ctx context.Context, t TitleProvider) (*RPCRegistration, error)

RegisterTitleProvider registers t in iTerm2's session-title role and answers its calls until it is unregistered or the connection ends.

func (*Conn) RegisterTool added in v0.6.0

func (c *Conn) RegisterTool(ctx context.Context, t Tool) error

RegisterTool adds a web-view panel to iTerm2's toolbelt.

iTerm2 forgets the tool when it quits. Persistent.RegisterTool registers it again on every new connection.

func (*Conn) SendText

func (c *Conn) SendText(ctx context.Context, sessionID, text string, suppressBroadcast bool) error

SendText types text into the session, as though the user had.

The session may be SessionAll or SessionActive. suppressBroadcast keeps the text out of other sessions when the user has broadcasting switched on.

func (*Conn) SetStringVariable

func (c *Conn) SetStringVariable(ctx context.Context, scope VariableScope, identifier, name, value string) error

SetStringVariable writes one string variable, doing the JSON quoting.

The name must begin with "user." — see Conn.SetVariables.

func (*Conn) SetVariables

func (c *Conn) SetVariables(ctx context.Context, scope VariableScope, identifier string, values map[string]string) error

SetVariables writes variables on one object.

Values must be JSON, so a string needs its quotes. iTerm2 rejects any name not beginning with "user." and answers INVALID_NAME, which arrives as a *StatusError: the built-in variables are iTerm2's to write, not a script's.

func (*Conn) SplitPane

func (c *Conn) SplitPane(ctx context.Context, sessionID string, opts SplitPaneOptions) ([]string, error)

SplitPane divides a session and returns the ids of the sessions created.

More than one id comes back when sessionID is SessionAll. api.proto warns that a tmux integration session reports none, because the split happens only if and when the tmux server acts on it.

func (*Conn) Subscribe

func (c *Conn) Subscribe(ctx context.Context, req *apipb.NotificationRequest) (*Subscription, error)

Subscribe asks iTerm2 to post notifications and returns them on a channel.

req must set NotificationType. Everything else api.proto allows — the session to watch, a VariableMonitorRequest, a KeystrokePattern filter — is passed through untouched, so this covers notification types this package has no named helper for. Subscribe sets Subscribe itself.

The returned Subscription must be released with Subscription.Unsubscribe, or iTerm2 keeps posting for the life of the connection.

func (*Conn) SubscribeFocusChanges

func (c *Conn) SubscribeFocusChanges(ctx context.Context) (*Subscription, error)

SubscribeFocusChanges posts a notification when the application, window, tab or pane with focus changes. api.proto warns that duplicates are normal; ignore the ones that report no change.

func (*Conn) SubscribeLayoutChanges

func (c *Conn) SubscribeLayoutChanges(ctx context.Context) (*Subscription, error)

SubscribeLayoutChanges posts a notification whenever windows, tabs or panes move. Each carries a full hierarchy snapshot, the same shape Conn.ListSessions returns.

func (*Conn) SubscribeNewSessions

func (c *Conn) SubscribeNewSessions(ctx context.Context) (*Subscription, error)

SubscribeNewSessions posts a notification whenever a session is created, or a closed one is restored by undo. Read the id from apipb.Notification.GetNewSessionNotification.

func (*Conn) SubscribeTerminatedSessions

func (c *Conn) SubscribeTerminatedSessions(ctx context.Context) (*Subscription, error)

SubscribeTerminatedSessions posts a notification whenever a session ends.

func (*Conn) SubscribeVariableChanges

func (c *Conn) SubscribeVariableChanges(ctx context.Context, scope VariableScope, identifier, name string) (*Subscription, error)

SubscribeVariableChanges posts a notification when a variable changes.

identifier names the session, tab or window to watch and is ignored for ScopeApp. name is the variable, such as "jobName" or "user.myVariable".

type ContextMenuItem added in v0.9.0

type ContextMenuItem struct {
	RPC

	// DisplayName is the menu item's label.
	DisplayName string

	// Identifier must be unique among context-menu items; api.proto asks for a
	// reverse-DNS name, such as com.example.copy-path.
	Identifier string
}

ContextMenuItem is an RPC offered as an item in a session's context menu, labelled DisplayName. Choosing it calls the Handler; map arguments to session variables in Defaults, such as "session.path", to act on the session the menu was opened on. iTerm2 does not show the result.

type CreateTabOptions

type CreateTabOptions struct {
	// ProfileName selects the profile. Empty uses the default profile.
	ProfileName string

	// WindowID puts the tab in an existing window. Empty creates a new window.
	WindowID string

	// TabIndex is the position for the new tab, and is valid only with WindowID.
	// nil lets iTerm2 choose. An index iTerm2 cannot honour still creates the
	// tab — it answers INVALID_TAB_INDEX, which arrives as a [*StatusError]
	// even though the tab now exists.
	TabIndex *uint32

	// SelectTab, when pointed at false, creates the tab in the background
	// without selecting it or raising its window. nil keeps iTerm2's default of
	// selecting it.
	SelectTab *bool

	// CustomProfileProperties overrides profile settings for this session only.
	// Each value must be JSON, matching ProfileProperty.json_value in
	// api.proto — a string setting therefore needs its quotes, as in
	// `{"Command": "\"/bin/zsh\""}`.
	CustomProfileProperties map[string]string
}

CreateTabOptions configures Conn.CreateTab.

It is a struct rather than a list of functional options so that a field added later is an additive change for callers who construct it with field names.

type CredentialSource

type CredentialSource interface {
	Credentials(ctx context.Context) (Credentials, error)
}

CredentialSource supplies credentials for one connection attempt.

It is called once per attempt rather than once per Conn, because a cookie is consumed by the attempt whether or not the attempt succeeds.

func AppleScriptCredentials

func AppleScriptCredentials(advisoryName string) CredentialSource

AppleScriptCredentials asks a running iTerm2 for a fresh single-use cookie.

advisoryName is shown to the user in iTerm2's script console and in the permission prompt, so it should name the program rather than the library.

This requires macOS and a running iTerm2: it drives /usr/bin/osascript, and on any other platform it fails without running anything. The user may be asked to approve the connection the first time a given key appears.

IT2_APP_PATH, if set, selects which iTerm2 build to ask — matching the behaviour of iTerm2's own it2 CLI, and needed only when several are running.

func DefaultCredentials

func DefaultCredentials(advisoryName string) CredentialSource

DefaultCredentials uses the environment when iTerm2 has provided credentials there, and otherwise asks iTerm2 for a fresh cookie over AppleScript.

The environment's cookie is used once per process. iTerm2 issues it single use and forgets every cookie when it restarts, so presenting it a second time can only be refused; after the first attempt this source asks over AppleScript instead, which is what lets a program reconnect. And when the environment's cookie is refused outright — inherited from a parent that already spent it — Connect asks for a fresh one and tries once more. Both match iTerm2's Python library, which deletes ITERM2_COOKIE after a refusal; this one leaves the environment alone and remembers the spent value instead.

func EnvCredentials

func EnvCredentials() CredentialSource

EnvCredentials reads ITERM2_COOKIE and ITERM2_KEY from the environment.

iTerm2 sets both for processes it launches itself, including scripts run from its Scripts menu. It returns ErrNoCredentials when neither is set, so it can be chained ahead of AppleScriptCredentials — which is what DefaultCredentials does.

func StaticCredentials

func StaticCredentials(cookie, key string) CredentialSource

StaticCredentials returns a source that always yields the same values.

Because a cookie is single use, a Conn built on this source can connect once. It is meant for a process iTerm2 launched — which is handed a cookie in its environment — and for tests.

type CredentialSourceFunc

type CredentialSourceFunc func(ctx context.Context) (Credentials, error)

CredentialSourceFunc adapts a function to CredentialSource.

func (CredentialSourceFunc) Credentials

func (f CredentialSourceFunc) Credentials(ctx context.Context) (Credentials, error)

Credentials calls f.

type Credentials

type Credentials struct {
	Cookie string
	Key    string
}

Credentials authorise a connection to iTerm2's API.

The cookie is single use: iTerm2 consumes it during the WebSocket handshake (iTermWebSocketCookieJar consumeCookie), so a second connection needs a second cookie. The key is a stable identity for the client — iTerm2 reuses it to recognise a reconnecting script and offer the same authorisation, and invents one if it is absent.

type DurableSubscription added in v0.3.0

type DurableSubscription struct {
	// contains filtered or unexported fields
}

DurableSubscription is a Subscription that a Persistent connection re-makes on every new connection, so DurableSubscription.C stays open across iTerm2 restarts. What iTerm2 posted while it was away is lost; a Reconnect says when that happened.

func (*DurableSubscription) C added in v0.3.0

func (d *DurableSubscription) C() <-chan *apipb.Notification

C is the channel notifications arrive on. It is closed by DurableSubscription.Unsubscribe, by Persistent.Close, or when the subscription cannot be re-made after a reconnect, in which case DurableSubscription.Err says why.

func (*DurableSubscription) Dropped added in v0.3.0

func (d *DurableSubscription) Dropped() uint64

Dropped counts notifications discarded because C was full, across every connection this subscription has had.

func (*DurableSubscription) Err added in v0.3.0

func (d *DurableSubscription) Err() error

Err is nil until the channel closes, and nil after an Unsubscribe or a Close. It is set when iTerm2 refused the subscription on a new connection — a per-session subscription whose session did not survive the restart, for one.

func (*DurableSubscription) Unsubscribe added in v0.3.0

func (d *DurableSubscription) Unsubscribe(ctx context.Context) error

Unsubscribe stops the subscription for good: it is not re-made at the next reconnect, and C is closed.

type Hierarchy

type Hierarchy struct {
	Windows []*Window

	// BuriedSessions are sessions iTerm2 is holding without a tab. They have no
	// frame or grid size, and no tab or window to reach them through.
	BuriedSessions []*Session
}

Hierarchy is a snapshot of every window, tab and session iTerm2 had open when Conn.ListSessions was called.

It is a snapshot, not a live view: sessions open and close, so an id taken from here can be gone by the time it is used. Requests naming a vanished session come back as a *StatusError with a NOT_FOUND status.

func (*Hierarchy) Session

func (h *Hierarchy) Session(id string) *Session

Session finds a session by id, returning nil when the snapshot has no such session.

func (*Hierarchy) Sessions

func (h *Hierarchy) Sessions() []*Session

Sessions returns every session in the hierarchy, buried ones last.

It is the flat view most callers want: finding a session by its title or a variable does not usually care which window it is in.

func (*Hierarchy) Tab

func (h *Hierarchy) Tab(id string) *Tab

Tab finds a tab by id, returning nil when the snapshot has no such tab.

func (*Hierarchy) Tabs

func (h *Hierarchy) Tabs() []*Tab

Tabs returns every tab in the hierarchy.

func (*Hierarchy) Window

func (h *Hierarchy) Window(id string) *Window

Window finds a window by id, returning nil when the snapshot has no such window.

type NewTab

type NewTab struct {
	WindowID string

	// TabID is rendered as a decimal string because that is the form the rest of
	// the API uses: api.proto types CreateTabResponse.tab_id as int32 while
	// ListSessionsResponse.Tab.tab_id is a string. That the two are the same
	// namespace is inferred from api.proto, not yet confirmed against a running
	// iTerm2 — see ROADMAP.md.
	TabID string

	SessionID string
}

NewTab identifies what Conn.CreateTab created.

type Option

type Option func(*config)

Option configures Connect.

func ForceTCP

func ForceTCP() Option

ForceTCP connects over loopback TCP even when a unix socket exists.

func WithAdvisoryName

func WithAdvisoryName(name string) Option

WithAdvisoryName sets the name iTerm2 shows for this client in its script console and its authorisation prompt. It should name the program, not this library. The default is the running program's filename.

func WithCredentialSource

func WithCredentialSource(src CredentialSource) Option

WithCredentialSource replaces how credentials are obtained. The default is DefaultCredentials.

func WithCredentials

func WithCredentials(cookie, key string) Option

WithCredentials supplies a cookie and key directly, instead of reading the environment or asking iTerm2 over AppleScript. Use it when something else in the program already holds a cookie, and in tests.

func WithReconnectBackoff added in v0.3.0

func WithReconnectBackoff(min, max time.Duration) Option

WithReconnectBackoff sets how long a Persistent connection waits between attempts while iTerm2 is away: min after the first failure, doubling to max. The default is one second to thirty. Connect ignores it.

func WithSocketPath

func WithSocketPath(path string) Option

WithSocketPath overrides the unix domain socket to connect to. The default is DefaultSocketPath.

func WithSubscriptionBuffer

func WithSubscriptionBuffer(n int) Option

WithSubscriptionBuffer sets how many notifications a Subscription buffers before it starts dropping them. The default is 64.

Notifications are dropped rather than blocking, because iTerm2 posts screen updates and keystrokes faster than most consumers read them, and a blocked reader would stall every other request on the connection. See Subscription.Dropped.

func WithTCPAddress

func WithTCPAddress(addr string) Option

WithTCPAddress overrides the loopback address used when no unix socket is present. The default is LegacyTCPAddress.

type Persistent added in v0.3.0

type Persistent struct {
	// contains filtered or unexported fields
}

Persistent is a connection to iTerm2 that survives iTerm2 restarting, which it does on every update.

A Conn cannot come back: its cookie is spent. Persistent dials a fresh one when the current one ends, re-makes every DurableSubscription on it, and reports each replacement on Persistent.Reconnects. Between the two, calls return ErrReconnecting.

It is the loop the README used to ask every program to write.

func ConnectPersistent added in v0.3.0

func ConnectPersistent(ctx context.Context, opts ...Option) (*Persistent, error)

ConnectPersistent connects to iTerm2 as Connect does, with the same options, and keeps reconnecting with them until Persistent.Close.

ctx bounds the first connection only. Its error is returned as Connect's would be, so a program started with the API switched off finds out at once. Every attempt obtains fresh credentials from the configured source, which with the default credentials means asking iTerm2 for a new cookie.

func (*Persistent) Activate added in v0.4.0

func (p *Persistent) Activate(ctx context.Context, opts ActivateOptions) error

Activate is Conn.Activate on whichever connection is current. It returns ErrReconnecting while iTerm2 is away; see Persistent.

func (*Persistent) Close added in v0.3.0

func (p *Persistent) Close() error

Close stops reconnecting, closes the current connection and every DurableSubscription. Calling it twice is harmless.

func (*Persistent) CloseSessions added in v0.4.0

func (p *Persistent) CloseSessions(ctx context.Context, force bool, ids ...string) error

CloseSessions is Conn.CloseSessions on whichever connection is current. It returns ErrReconnecting while iTerm2 is away; see Persistent.

func (*Persistent) CloseTabs added in v0.4.0

func (p *Persistent) CloseTabs(ctx context.Context, force bool, ids ...string) error

CloseTabs is Conn.CloseTabs on whichever connection is current. It returns ErrReconnecting while iTerm2 is away; see Persistent.

func (*Persistent) CloseWindows added in v0.4.0

func (p *Persistent) CloseWindows(ctx context.Context, force bool, ids ...string) error

CloseWindows is Conn.CloseWindows on whichever connection is current. It returns ErrReconnecting while iTerm2 is away; see Persistent.

func (*Persistent) Conn added in v0.3.0

func (p *Persistent) Conn() (*Conn, error)

Conn returns the current connection, for the typed methods on Conn. It returns ErrReconnecting while iTerm2 is away and ErrClosed after Close. Do not keep the result: it is replaced at the next reconnect.

func (*Persistent) CreateTab added in v0.4.0

func (p *Persistent) CreateTab(ctx context.Context, opts CreateTabOptions) (*NewTab, error)

CreateTab is Conn.CreateTab on whichever connection is current. It returns ErrReconnecting while iTerm2 is away; see Persistent.

func (*Persistent) Do added in v0.3.0

Do sends one request on the current connection. See Conn.Do.

func (*Persistent) GetStringVariable added in v0.4.0

func (p *Persistent) GetStringVariable(ctx context.Context, scope VariableScope, identifier, name string) (value string, ok bool, err error)

GetStringVariable is Conn.GetStringVariable on whichever connection is current. It returns ErrReconnecting while iTerm2 is away; see Persistent.

func (*Persistent) GetVariables added in v0.4.0

func (p *Persistent) GetVariables(ctx context.Context, scope VariableScope, identifier string, names ...string) (map[string]json.RawMessage, error)

GetVariables is Conn.GetVariables on whichever connection is current. It returns ErrReconnecting while iTerm2 is away; see Persistent.

func (*Persistent) ListSessions added in v0.4.0

func (p *Persistent) ListSessions(ctx context.Context) (*Hierarchy, error)

ListSessions is Conn.ListSessions on whichever connection is current. It returns ErrReconnecting while iTerm2 is away; see Persistent.

func (*Persistent) Reconnects added in v0.3.0

func (p *Persistent) Reconnects() <-chan Reconnect

Reconnects delivers a Reconnect each time the connection is replaced. It holds only the latest; see Reconnect.Count.

func (*Persistent) RegisterContextMenuItem added in v0.9.0

func (p *Persistent) RegisterContextMenuItem(ctx context.Context, m ContextMenuItem) (*RPCRegistration, error)

RegisterContextMenuItem is Conn.RegisterContextMenuItem on a Persistent: the item is registered again on every new connection.

func (*Persistent) RegisterRPC added in v0.7.0

func (p *Persistent) RegisterRPC(ctx context.Context, fn RPC) (*RPCRegistration, error)

RegisterRPC is Conn.RegisterRPC on a Persistent: the registration is a DurableSubscription, so the function is registered again on every new connection and answers on whichever connection is current.

func (*Persistent) RegisterTitleProvider added in v0.8.0

func (p *Persistent) RegisterTitleProvider(ctx context.Context, t TitleProvider) (*RPCRegistration, error)

RegisterTitleProvider is Conn.RegisterTitleProvider on a Persistent: it is registered again on every new connection.

func (*Persistent) RegisterTool added in v0.6.0

func (p *Persistent) RegisterTool(ctx context.Context, t Tool) error

RegisterTool is Conn.RegisterTool, and the tool is registered again on every new connection, before the Reconnect is announced. iTerm2 forgets a tool when it quits, so without this a panel vanishes at every restart.

Re-registration does not reveal the tool, whatever Reveal says: a restart of iTerm2 should not pop the toolbelt open. A tool iTerm2 refuses then is reported in Reconnect.ToolErr. Registering a tool with the same Identifier again replaces it, here as in iTerm2.

Like every call, it returns ErrReconnecting while iTerm2 is away, and the tool is then not remembered.

func (*Persistent) SendText added in v0.4.0

func (p *Persistent) SendText(ctx context.Context, sessionID, text string, suppressBroadcast bool) error

SendText is Conn.SendText on whichever connection is current. It returns ErrReconnecting while iTerm2 is away; see Persistent.

func (*Persistent) SetStringVariable added in v0.4.0

func (p *Persistent) SetStringVariable(ctx context.Context, scope VariableScope, identifier, name, value string) error

SetStringVariable is Conn.SetStringVariable on whichever connection is current. It returns ErrReconnecting while iTerm2 is away; see Persistent.

func (*Persistent) SetVariables added in v0.4.0

func (p *Persistent) SetVariables(ctx context.Context, scope VariableScope, identifier string, values map[string]string) error

SetVariables is Conn.SetVariables on whichever connection is current. It returns ErrReconnecting while iTerm2 is away; see Persistent.

func (*Persistent) SplitPane added in v0.4.0

func (p *Persistent) SplitPane(ctx context.Context, sessionID string, opts SplitPaneOptions) ([]string, error)

SplitPane is Conn.SplitPane on whichever connection is current. It returns ErrReconnecting while iTerm2 is away; see Persistent.

func (*Persistent) Subscribe added in v0.3.0

Subscribe asks iTerm2 to post notifications, as Conn.Subscribe does, and re-asks on every new connection.

func (*Persistent) SubscribeFocusChanges added in v0.4.0

func (p *Persistent) SubscribeFocusChanges(ctx context.Context) (*DurableSubscription, error)

SubscribeFocusChanges is Conn.SubscribeFocusChanges on a Persistent.

func (*Persistent) SubscribeLayoutChanges added in v0.4.0

func (p *Persistent) SubscribeLayoutChanges(ctx context.Context) (*DurableSubscription, error)

SubscribeLayoutChanges is Conn.SubscribeLayoutChanges on a Persistent.

func (*Persistent) SubscribeNewSessions added in v0.3.0

func (p *Persistent) SubscribeNewSessions(ctx context.Context) (*DurableSubscription, error)

SubscribeNewSessions is Conn.SubscribeNewSessions on a Persistent.

func (*Persistent) SubscribeTerminatedSessions added in v0.3.0

func (p *Persistent) SubscribeTerminatedSessions(ctx context.Context) (*DurableSubscription, error)

SubscribeTerminatedSessions is Conn.SubscribeTerminatedSessions on a Persistent.

func (*Persistent) SubscribeVariableChanges added in v0.4.0

func (p *Persistent) SubscribeVariableChanges(ctx context.Context, scope VariableScope, identifier, name string) (*DurableSubscription, error)

SubscribeVariableChanges is Conn.SubscribeVariableChanges on a Persistent.

type RPC added in v0.7.0

type RPC struct {
	// Name is what iTerm2 calls it by.
	Name string

	// Arguments are the argument names, which with Name make the signature
	// iTerm2 matches a call against.
	Arguments []string

	// Defaults fills an argument the caller left out from an iTerm2 variable,
	// by path: {"session_id": "session.id"}. Each key must be in Arguments.
	Defaults map[string]string

	// Timeout is how long iTerm2 waits for an answer. Zero leaves it to iTerm2.
	Timeout time.Duration

	// Handler answers one call. Each argument arrives as the JSON iTerm2 sent;
	// the result is sent back as JSON, and an error as an exception iTerm2 can
	// show. ctx ends when the registration does.
	Handler func(ctx context.Context, args map[string]json.RawMessage) (any, error)
}

RPC is a function iTerm2 can call in this program: from a key binding, a trigger, a toolbelt panel's page, or anything else that invokes a script function by name, such as `greet(who: "you")`.

This registers it in iTerm2's generic role. The status-bar, session-title and context-menu roles take attributes of their own and are not covered yet.

type RPCRegistration added in v0.7.0

type RPCRegistration struct {
	// contains filtered or unexported fields
}

RPCRegistration is a registered RPC. Unregister it to stop answering.

func (*RPCRegistration) Unregister added in v0.7.0

func (r *RPCRegistration) Unregister(ctx context.Context) error

Unregister stops the function. Calls already running are cancelled and waited for.

type Reconnect added in v0.3.0

type Reconnect struct {
	// Count is how many reconnects this Persistent has made, this one included.
	// The channel keeps only the latest, so a caller that fell behind sees the
	// count jump rather than every event.
	Count int
	// Cause is why the previous connection ended. It wraps ErrClosed.
	Cause error
	// At is when the new connection was ready.
	At time.Time
	// ToolErr joins the errors of the tools that could not be registered again
	// on the new connection (see [Persistent.RegisterTool]), or is nil.
	ToolErr error
}

Reconnect reports that a Persistent connection was replaced.

Notifications iTerm2 posted between the old connection ending and the new one subscribing are gone, and nothing replays them. Treat a Reconnect as "my view of iTerm2 may be stale": resynchronise, for instance with Conn.ListSessions. It is sent only once every subscription is back, so a change made after the resynchronisation is delivered.

type Rect

type Rect struct {
	X      int32
	Y      int32
	Width  int32
	Height int32
}

Rect is a position and size in screen points, as iTerm2 reports window and pane frames.

type Session

type Session struct {
	ID    string
	Title string

	// Frame and GridSize are unset for a buried session, because it is not on
	// screen to have either.
	Frame    Rect
	GridSize Size

	// Buried reports whether iTerm2 is holding this session without a tab.
	Buried bool
	// contains filtered or unexported fields
}

Session is one pane.

func (*Session) Activate

func (s *Session) Activate(ctx context.Context, opts ActivateOptions) error

Activate selects this session and, with ActivateOptions, raises its tab, window and application.

func (*Session) Close

func (s *Session) Close(ctx context.Context, force bool) error

Close closes this pane.

func (*Session) SendText

func (s *Session) SendText(ctx context.Context, text string) error

SendText types text into this session.

func (*Session) SetVariable

func (s *Session) SetVariable(ctx context.Context, name, value string) error

SetVariable writes one of this session's variables. The name must begin with "user.".

func (*Session) SplitPane

func (s *Session) SplitPane(ctx context.Context, opts SplitPaneOptions) ([]string, error)

SplitPane divides this session.

func (*Session) Variable

func (s *Session) Variable(ctx context.Context, name string) (string, bool, error)

Variable reads one of this session's variables as a string, such as "jobName", "path" or "user.something".

type Size

type Size struct {
	Width  int32
	Height int32
}

Size is a width and height in character cells.

type SplitDirection

type SplitDirection int32

SplitDirection is which way a pane divides.

const (
	// SplitVertical puts the new pane beside the old one, divided by a vertical
	// line. api.proto names the divider, not the arrangement.
	SplitVertical SplitDirection = SplitDirection(apipb.SplitPaneRequest_VERTICAL)

	// SplitHorizontal puts the new pane above or below the old one.
	SplitHorizontal SplitDirection = SplitDirection(apipb.SplitPaneRequest_HORIZONTAL)
)

type SplitNode added in v0.5.0

type SplitNode struct {
	// Session is set when this node is a pane, and nil when it is a split.
	Session *Session

	// Vertical is the direction of this split's dividers: true when they are
	// vertical, so Children sit side by side, left to right; false when they
	// are horizontal, so Children are stacked, top to bottom.
	Vertical bool

	// Children are the areas this split divides, in order. Empty for a pane.
	Children []*SplitNode
}

SplitNode is one node of a tab's split tree, as api.proto's SplitTreeNode lays it out: either a pane, or a divided area holding further nodes.

It carries no geometry of its own. Each pane's Frame and GridSize are on its Session, and anything more (proportions, divider positions) is not something iTerm2 reports.

func (*SplitNode) Panes added in v0.5.0

func (n *SplitNode) Panes() []*Session

Panes returns the panes under n, depth first in link order, which is the order Tab.Sessions has.

type SplitPaneOptions

type SplitPaneOptions struct {
	Direction SplitDirection

	// Before puts the new pane above or to the left of the one being split.
	Before bool

	// ProfileName selects the profile. Empty uses the default profile.
	ProfileName string

	// CustomProfileProperties overrides profile settings for the new session
	// only. Values are JSON; see [CreateTabOptions.CustomProfileProperties].
	CustomProfileProperties map[string]string
}

SplitPaneOptions configures Conn.SplitPane.

type StatusError

type StatusError struct {
	Op     string
	Status string
	Code   int32
}

StatusError reports a well-formed request that iTerm2 declined, carrying the status enum it answered with.

Op names the operation as this package spells it, so the error reads in Go terms; Status is iTerm2's own enum value name, so it can be looked up in api.proto.

func (*StatusError) Error

func (e *StatusError) Error() string

type Subscription

type Subscription struct {
	// contains filtered or unexported fields
}

Subscription delivers one kind of notification from iTerm2.

iTerm2 posts every notification a connection has subscribed to down the one socket, with nothing tying a notification back to the request that asked for it. A Subscription therefore remembers what it asked for and delivers only the notifications that match, so two subscriptions on one Conn do not see each other's traffic.

iTerm2 refuses a second subscription to the same notification type and session on one connection, answering ALREADY_SUBSCRIBED; Conn.Subscribe surfaces that as a *StatusError. Fan one Subscription out in your own code, or use a second Conn.

func (*Subscription) C

func (s *Subscription) C() <-chan *apipb.Notification

C is the channel notifications arrive on. It is closed when the subscription ends, whether through Subscription.Unsubscribe or because the connection went away.

func (*Subscription) Dropped

func (s *Subscription) Dropped() uint64

Dropped counts notifications discarded because the buffer was full. A non-zero value means the consumer is slower than iTerm2 is posting; see WithSubscriptionBuffer.

func (*Subscription) Unsubscribe

func (s *Subscription) Unsubscribe(ctx context.Context) error

Unsubscribe tells iTerm2 to stop posting this notification and closes Subscription.C.

The channel is closed even when the request fails — there is nothing left to deliver either way — so the returned error reports what iTerm2 said and is safe to log rather than handle. Calling it twice is harmless.

type Tab

type Tab struct {
	ID string

	// WindowID is the window this tab was found in. api.proto does not carry it
	// on the tab; it is filled in from the enclosing window while parsing, so
	// that a *Tab is usable on its own.
	WindowID string

	// ActiveSessionID is the pane with focus within this tab. Reported from
	// protocol 1.18; empty on older versions.
	ActiveSessionID string

	// TmuxWindowID and TmuxConnectionID are set only for a tab belonging to a
	// tmux integration session.
	TmuxWindowID     string
	TmuxConnectionID string

	// Group describes the tab group this tab belongs to, or nil when it belongs
	// to none. Reported from protocol 1.19.
	Group *TabGroup

	// Sessions are the tab's panes, flattened from api.proto's split tree in
	// left-to-right, top-to-bottom order. [Tab.SplitTree] keeps the tree's
	// shape.
	Sessions []*Session

	// MinimizedSessions are panes the user has collapsed. They are not in
	// Sessions.
	MinimizedSessions []*Session
	// contains filtered or unexported fields
}

Tab is one tab within a window.

func (*Tab) Activate

func (t *Tab) Activate(ctx context.Context, opts ActivateOptions) error

Activate selects this tab.

func (*Tab) ActiveSession

func (t *Tab) ActiveSession() *Session

ActiveSession returns the tab's focused pane, or nil when iTerm2 did not say which it is — which is what an iTerm2 older than protocol 1.18 does.

func (*Tab) Close

func (t *Tab) Close(ctx context.Context, force bool) error

Close closes this tab and every pane in it.

func (*Tab) SplitTree added in v0.5.0

func (t *Tab) SplitTree() *SplitNode

SplitTree returns how the tab's panes are arranged, or nil when iTerm2 sent no layout for it. Its panes are the same *Session values as in Sessions.

type TabGroup

type TabGroup struct {
	ID string

	Name string

	// Color is a hex string as iTerm2 produces it: "#rrggbb" for sRGB, or
	// "p3#rrggbbrrggbb" for Display P3.
	Color string

	Collapsed bool
}

TabGroup is the group a tab belongs to.

A group has no central record in iTerm2: its identity is a UUID carried by each member tab, and every member reports the same name, colour and collapsed state. Two tabs are in the same group exactly when their IDs match.

type TitleProvider added in v0.8.0

type TitleProvider struct {
	RPC

	// DisplayName is how iTerm2 lists the provider in its settings.
	DisplayName string

	// Identifier must be unique among title providers; api.proto asks for a
	// reverse-DNS name, such as com.example.branch-title.
	Identifier string
}

TitleProvider is an RPC iTerm2 calls to compute a session's title. Once registered it appears among the title choices in a profile's settings, under DisplayName, and a session using it shows whatever its Handler returns.

Defaults is how a title follows the session: map an argument to a variable such as "session.path" or "user.gitBranch", and iTerm2 calls the provider again when that variable changes.

type Tool added in v0.6.0

type Tool struct {
	// Name is shown to the user.
	Name string

	// Identifier must be unique to the tool. api.proto asks for a reverse-DNS
	// name, such as com.example.mytool. Registering the same identifier again
	// replaces the tool.
	Identifier string

	// URL is the page the panel loads.
	URL string

	// Reveal shows the tool even if it was registered before. iTerm2 adds a
	// tool to the visible set by itself only the first time; it does not open
	// a hidden toolbelt either way.
	Reveal bool
}

Tool is a panel in iTerm2's toolbelt, showing a web page.

type VariableScope

type VariableScope int32

VariableScope selects which object a variable belongs to.

The values mirror api.proto's VariableScope enum, which starts at 1 — there is no zero value, so a VariableScope left at its Go zero is invalid and the methods taking one reject it rather than defaulting to a scope the caller did not choose.

func (VariableScope) String

func (s VariableScope) String() string

String names the scope as api.proto spells it.

type Window

type Window struct {
	ID     string
	Number int32
	Frame  Rect

	// SelectedTabID is the tab on top. iTerm2 began reporting it in protocol
	// 1.18 and leaves it empty on older versions.
	SelectedTabID string

	Tabs []*Tab
	// contains filtered or unexported fields
}

Window is one iTerm2 window.

func (*Window) Activate

func (w *Window) Activate(ctx context.Context, opts ActivateOptions) error

Activate brings this window forward.

func (*Window) Close

func (w *Window) Close(ctx context.Context, force bool) error

Close closes this window.

Directories

Path Synopsis
internal
fakeiterm
Package fakeiterm is a stand-in for a running iTerm2, used by this module's tests.
Package fakeiterm is a stand-in for a running iTerm2, used by this module's tests.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL